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     */
013    package org.mmtk.plan.markcompact;
014    
015    import org.mmtk.plan.*;
016    import org.mmtk.policy.MarkCompactSpace;
017    import org.mmtk.policy.Space;
018    import org.mmtk.utility.heap.VMRequest;
019    import org.mmtk.utility.sanitychecker.SanityChecker;
020    
021    import org.vmmagic.pragma.*;
022    import org.vmmagic.unboxed.ObjectReference;
023    
024    /**
025     * This class implements the global state of a simple sliding mark-compact
026     * collector.
027     *
028     * FIXME Need algorithmic overview and references.
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.
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", DEFAULT_POLL_FREQUENCY, VMRequest.create(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       * Perform a (global) collection phase.
130       *
131       * @param phaseId Collection phase to execute.
132       */
133      @Override
134      @Inline
135      public final void collectionPhase(short phaseId) {
136        if (phaseId == PREPARE) {
137          super.collectionPhase(phaseId);
138          markTrace.prepare();
139          mcSpace.prepare();
140          return;
141        }
142        if (phaseId == CLOSURE) {
143          markTrace.prepare();
144          return;
145        }
146        if (phaseId == RELEASE) {
147          markTrace.release();
148          mcSpace.release();
149          super.collectionPhase(phaseId);
150          return;
151        }
152    
153        if (phaseId == PREPARE_FORWARD) {
154          super.collectionPhase(PREPARE);
155          forwardTrace.prepare();
156          mcSpace.prepare();
157          return;
158        }
159        if (phaseId == RELEASE_FORWARD) {
160          forwardTrace.release();
161          mcSpace.release();
162          super.collectionPhase(RELEASE);
163          return;
164        }
165    
166        super.collectionPhase(phaseId);
167      }
168    
169      /*****************************************************************************
170       *
171       * Accounting
172       */
173    
174      /**
175       * Return the number of pages reserved for use given the pending
176       * allocation.  The superclass accounts for its spaces, we just
177       * augment this with the mark-sweep space's contribution.
178       *
179       * @return The number of pages reserved given the pending
180       * allocation, excluding space reserved for copying.
181       */
182      @Override
183      public int getPagesUsed() {
184        return (mcSpace.reservedPages() + super.getPagesUsed());
185      }
186    
187      /**
188       * Calculate the number of pages a collection is required to free to satisfy
189       * outstanding allocation requests.
190       *
191       * @return the number of pages a collection is required to free to satisfy
192       * outstanding allocation requests.
193       */
194      @Override
195      public int getPagesRequired() {
196        return super.getPagesRequired() + mcSpace.requiredPages();
197      }
198    
199      /**
200       * @see org.mmtk.plan.Plan#willNeverMove
201       *
202       * @param object Object in question
203       * @return True if the object will never move
204       */
205      @Override
206      public boolean willNeverMove(ObjectReference object) {
207        if (Space.isInSpace(MARK_COMPACT, object))
208          return false;
209        return super.willNeverMove(object);
210      }
211    
212      /**
213       * Return the expected reference count. For non-reference counting
214       * collectors this becomes a true/false relationship.
215       * @param object The object to check.
216       * @param sanityRootRC The number of root references to the object.
217       *
218       * @return The expected (root excluded) reference count.
219       */
220      @Override
221      public int sanityExpectedRC(ObjectReference object, int sanityRootRC) {
222        Space space = Space.getSpaceForObject(object);
223    
224        // Nursery
225        if (space == MC.mcSpace) {
226          // We are never sure about objects in MC.
227          // This is not very satisfying but allows us to use the sanity checker to
228          // detect dangling pointers.
229          return SanityChecker.UNSURE;
230        }
231        return super.sanityExpectedRC(object, sanityRootRC);
232      }
233    
234      /**
235       * Register specialized methods.
236       */
237      @Override
238      @Interruptible
239      protected void registerSpecializedMethods() {
240        TransitiveClosure.registerSpecializedScan(SCAN_MARK, MCMarkTraceLocal.class);
241        TransitiveClosure.registerSpecializedScan(SCAN_FORWARD, MCForwardTraceLocal.class);
242        super.registerSpecializedMethods();
243      }
244    }