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 }