001/*
002 *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 *  This file is licensed to You under the Eclipse Public License (EPL);
005 *  You may not use this file except in compliance with the License. You
006 *  may obtain a copy of the License at
007 *
008 *      http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 *  See the COPYRIGHT.txt file distributed with this work for information
011 *  regarding copyright ownership.
012 */
013package org.mmtk.plan.markcompact;
014
015import org.mmtk.plan.*;
016import org.mmtk.policy.MarkCompactSpace;
017import org.mmtk.policy.Space;
018import org.mmtk.utility.heap.VMRequest;
019import org.mmtk.utility.sanitychecker.SanityChecker;
020
021import org.vmmagic.pragma.*;
022import org.vmmagic.unboxed.ObjectReference;
023
024/**
025 * This class implements the global state of a simple sliding mark-compact
026 * collector.<p>
027 *
028 * FIXME Need algorithmic overview and references.<p>
029 *
030 * All plans make a clear distinction between <i>global</i> and
031 * <i>thread-local</i> activities, and divides global and local state
032 * into separate class hierarchies.  Global activities must be
033 * synchronized, whereas no synchronization is required for
034 * thread-local activities.  There is a single instance of Plan (or the
035 * appropriate sub-class), and a 1:1 mapping of PlanLocal to "kernel
036 * threads" (aka CPUs).  Thus instance
037 * methods of PlanLocal allow fast, unsychronized access to functions such as
038 * allocation and collection.<p>
039 *
040 * The global instance defines and manages static resources
041 * (such as memory and virtual memory resources).  This mapping of threads to
042 * instances is crucial to understanding the correctness and
043 * performance properties of MMTk plans.
044 */
045@Uninterruptible public class MC extends StopTheWorld {
046
047  /****************************************************************************
048   * Class variables
049   */
050
051  /** The mark compact space itself */
052  public static final MarkCompactSpace mcSpace = new MarkCompactSpace("mc", VMRequest.fraction(0.6f));
053
054  /** The space descriptor */
055  public static final int MARK_COMPACT = mcSpace.getDescriptor();
056
057  /** Specialized method identifier for the MARK phase */
058  public static final int SCAN_MARK    = 0;
059
060  /** Specialized method identifier for the FORWARD phase */
061  public static final int SCAN_FORWARD = 1;
062
063  /* Phases */
064  public static final short PREPARE_FORWARD     = Phase.createSimple("fw-prepare");
065  public static final short FORWARD_CLOSURE     = Phase.createSimple("fw-closure");
066  public static final short RELEASE_FORWARD     = Phase.createSimple("fw-release");
067
068  /** Calculate forwarding pointers via a linear scan over the heap */
069  public static final short CALCULATE_FP        = Phase.createSimple("calc-fp");
070
071  /** Perform compaction via a linear scan over the heap */
072  public static final short COMPACT             = Phase.createSimple("compact");
073
074  // CHECKSTYLE:OFF
075
076  /**
077   * This is the phase that is executed to perform a mark-compact collection.
078   *
079   * FIXME: Far too much duplication and inside knowledge of StopTheWorld
080   */
081  public short mcCollection = Phase.createComplex("collection", null,
082      Phase.scheduleComplex  (initPhase),
083      Phase.scheduleComplex  (rootClosurePhase),
084      Phase.scheduleComplex  (refTypeClosurePhase),
085      Phase.scheduleComplex  (completeClosurePhase),
086      Phase.scheduleCollector(CALCULATE_FP),
087      Phase.scheduleGlobal   (PREPARE_FORWARD),
088      Phase.scheduleCollector(PREPARE_FORWARD),
089      Phase.scheduleMutator  (PREPARE),
090      Phase.scheduleCollector(STACK_ROOTS),
091      Phase.scheduleCollector(ROOTS),
092      Phase.scheduleGlobal   (ROOTS),
093      Phase.scheduleComplex  (forwardPhase),
094      Phase.scheduleCollector(FORWARD_CLOSURE),
095      Phase.scheduleMutator  (RELEASE),
096      Phase.scheduleCollector(RELEASE_FORWARD),
097      Phase.scheduleGlobal   (RELEASE_FORWARD),
098      Phase.scheduleCollector(COMPACT),
099      Phase.scheduleComplex  (finishPhase));
100
101  // CHECKSTYLE:ON
102
103  /****************************************************************************
104   * Instance variables
105   */
106
107  /** This trace sets the mark bit in live objects */
108  public final Trace markTrace;
109
110  /** This trace updates pointers with the forwarded references */
111  public final Trace forwardTrace;
112
113  /**
114   * Constructor.
115 */
116  public MC() {
117    markTrace = new Trace(metaDataSpace);
118    forwardTrace = new Trace(metaDataSpace);
119    collection = mcCollection;
120  }
121
122  /*****************************************************************************
123   *
124   * Collection
125   */
126
127
128  /**
129   * {@inheritDoc}
130   */
131  @Override
132  @Inline
133  public final void collectionPhase(short phaseId) {
134    if (phaseId == PREPARE) {
135      super.collectionPhase(phaseId);
136      markTrace.prepare();
137      mcSpace.prepare();
138      return;
139    }
140    if (phaseId == CLOSURE) {
141      markTrace.prepare();
142      return;
143    }
144    if (phaseId == RELEASE) {
145      markTrace.release();
146      mcSpace.release();
147      super.collectionPhase(phaseId);
148      return;
149    }
150
151    if (phaseId == PREPARE_FORWARD) {
152      super.collectionPhase(PREPARE);
153      forwardTrace.prepare();
154      mcSpace.prepare();
155      return;
156    }
157    if (phaseId == RELEASE_FORWARD) {
158      forwardTrace.release();
159      mcSpace.release();
160      super.collectionPhase(RELEASE);
161      return;
162    }
163
164    super.collectionPhase(phaseId);
165  }
166
167  /*****************************************************************************
168   *
169   * Accounting
170   */
171
172  /**
173   * {@inheritDoc}
174   * The superclass accounts for its spaces, we just
175   * augment this with the mark-sweep space's contribution.
176   */
177  @Override
178  public int getPagesUsed() {
179    return (mcSpace.reservedPages() + super.getPagesUsed());
180  }
181
182  @Override
183  public boolean willNeverMove(ObjectReference object) {
184    if (Space.isInSpace(MARK_COMPACT, object))
185      return false;
186    return super.willNeverMove(object);
187  }
188
189  @Override
190  public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
191    Space space = Space.getSpaceForObject(object);
192
193    // Nursery
194    if (space == MC.mcSpace) {
195      // We are never sure about objects in MC.
196      // This is not very satisfying but allows us to use the sanity checker to
197      // detect dangling pointers.
198      return SanityChecker.UNSURE;
199    }
200    return super.sanityExpectedRC(object, sanityRootRC);
201  }
202
203  @Override
204  @Interruptible
205  protected void registerSpecializedMethods() {
206    TransitiveClosure.registerSpecializedScan(SCAN_MARK, MCMarkTraceLocal.class);
207    TransitiveClosure.registerSpecializedScan(SCAN_FORWARD, MCForwardTraceLocal.class);
208    super.registerSpecializedMethods();
209  }
210}