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;
014
015 import org.mmtk.policy.Space;
016 import org.mmtk.utility.Constants;
017 import org.mmtk.utility.Log;
018 import org.mmtk.utility.options.*;
019 import org.mmtk.utility.statistics.Timer;
020 import org.mmtk.vm.VM;
021
022 import org.vmmagic.pragma.*;
023
024 /**
025 * This abstract class implements the core functionality for
026 * simple collectors.<p>
027 *
028 * This class defines the collection phases, and provides base
029 * level implementations of them. Subclasses should provide
030 * implementations for the spaces that they introduce, and
031 * delegate up the class hierarchy.<p>
032 *
033 * For details of the split between global and thread-local operations
034 * @see org.mmtk.plan.Plan
035 */
036 @Uninterruptible
037 public abstract class Simple extends Plan implements Constants {
038 /****************************************************************************
039 * Constants
040 */
041
042 /* Shared Timers */
043 private static final Timer refTypeTime = new Timer("refType", false, true);
044 private static final Timer scanTime = new Timer("scan", false, true);
045 private static final Timer finalizeTime = new Timer("finalize", false, true);
046
047 /* Phases */
048 public static final short SET_COLLECTION_KIND = Phase.createSimple("set-collection-kind", null);
049 public static final short INITIATE = Phase.createSimple("initiate", null);
050 public static final short PREPARE = Phase.createSimple("prepare");
051 public static final short PRECOPY = Phase.createSimple("precopy");
052 public static final short PREPARE_STACKS = Phase.createSimple("prepare-stacks", null);
053 public static final short STACK_ROOTS = Phase.createSimple("stacks");
054 public static final short ROOTS = Phase.createSimple("root");
055 public static final short CLOSURE = Phase.createSimple("closure", scanTime);
056 public static final short SOFT_REFS = Phase.createSimple("soft-ref", refTypeTime);
057 public static final short WEAK_REFS = Phase.createSimple("weak-ref", refTypeTime);
058 public static final short FINALIZABLE = Phase.createSimple("finalize", finalizeTime);
059 public static final short WEAK_TRACK_REFS = Phase.createSimple("weak-track-ref", refTypeTime);
060 public static final short PHANTOM_REFS = Phase.createSimple("phantom-ref", refTypeTime);
061 public static final short FORWARD = Phase.createSimple("forward");
062 public static final short FORWARD_REFS = Phase.createSimple("forward-ref", refTypeTime);
063 public static final short FORWARD_FINALIZABLE = Phase.createSimple("forward-finalize", finalizeTime);
064 public static final short RELEASE = Phase.createSimple("release");
065 public static final short COMPLETE = Phase.createSimple("complete", null);
066
067 /* Sanity placeholder */
068 public static final short PRE_SANITY_PLACEHOLDER = Phase.createSimple("pre-sanity-placeholder", null);
069 public static final short POST_SANITY_PLACEHOLDER = Phase.createSimple("post-sanity-placeholder", null);
070
071 /* Sanity phases */
072 public static final short SANITY_SET_PREGC = Phase.createSimple("sanity-setpre", null);
073 public static final short SANITY_SET_POSTGC = Phase.createSimple("sanity-setpost", null);
074 public static final short SANITY_PREPARE = Phase.createSimple("sanity-prepare", null);
075 public static final short SANITY_ROOTS = Phase.createSimple("sanity-roots", null);
076 public static final short SANITY_COPY_ROOTS = Phase.createSimple("sanity-copy-roots", null);
077 public static final short SANITY_BUILD_TABLE = Phase.createSimple("sanity-build-table", null);
078 public static final short SANITY_CHECK_TABLE = Phase.createSimple("sanity-check-table", null);
079 public static final short SANITY_RELEASE = Phase.createSimple("sanity-release", null);
080
081 // CHECKSTYLE:OFF
082
083 /** Ensure stacks are ready to be scanned */
084 protected static final short prepareStacks = Phase.createComplex("prepare-stacks", null,
085 Phase.scheduleCollector (PREPARE_STACKS),
086 Phase.scheduleMutator (PREPARE_STACKS),
087 Phase.scheduleGlobal (PREPARE_STACKS));
088
089 /** Trace and set up a sanity table */
090 protected static final short sanityBuildPhase = Phase.createComplex("sanity-build", null,
091 Phase.scheduleGlobal (SANITY_PREPARE),
092 Phase.scheduleCollector (SANITY_PREPARE),
093 Phase.scheduleComplex (prepareStacks),
094 Phase.scheduleCollector (SANITY_ROOTS),
095 Phase.scheduleGlobal (SANITY_ROOTS),
096 Phase.scheduleCollector (SANITY_COPY_ROOTS),
097 Phase.scheduleGlobal (SANITY_BUILD_TABLE));
098
099 /** Validate a sanity table */
100 protected static final short sanityCheckPhase = Phase.createComplex("sanity-check", null,
101 Phase.scheduleGlobal (SANITY_CHECK_TABLE),
102 Phase.scheduleCollector (SANITY_RELEASE),
103 Phase.scheduleGlobal (SANITY_RELEASE));
104
105 /** Start the collection, including preparation for any collected spaces. */
106 protected static final short initPhase = Phase.createComplex("init",
107 Phase.scheduleGlobal (SET_COLLECTION_KIND),
108 Phase.scheduleGlobal (INITIATE),
109 Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER));
110
111 /**
112 * Perform the initial determination of liveness from the roots.
113 */
114 protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null,
115 Phase.scheduleMutator (PREPARE),
116 Phase.scheduleGlobal (PREPARE),
117 Phase.scheduleCollector (PREPARE),
118 Phase.scheduleComplex (prepareStacks),
119 Phase.scheduleCollector (PRECOPY),
120 Phase.scheduleCollector (STACK_ROOTS),
121 Phase.scheduleCollector (ROOTS),
122 Phase.scheduleGlobal (ROOTS),
123 Phase.scheduleGlobal (CLOSURE),
124 Phase.scheduleCollector (CLOSURE));
125
126 /**
127 * Complete closure including reference types and finalizable objects.
128 */
129 protected static final short refTypeClosurePhase = Phase.createComplex("refType-closure", null,
130 Phase.scheduleCollector (SOFT_REFS),
131 Phase.scheduleGlobal (CLOSURE),
132 Phase.scheduleCollector (CLOSURE),
133 Phase.scheduleCollector (WEAK_REFS),
134 Phase.scheduleCollector (FINALIZABLE),
135 Phase.scheduleGlobal (CLOSURE),
136 Phase.scheduleCollector (CLOSURE),
137 Phase.schedulePlaceholder(WEAK_TRACK_REFS),
138 Phase.scheduleCollector (PHANTOM_REFS));
139
140 /**
141 * Ensure that all references in the system are correct.
142 */
143 protected static final short forwardPhase = Phase.createComplex("forward-all", null,
144 /* Finish up */
145 Phase.schedulePlaceholder(FORWARD),
146 Phase.scheduleCollector (FORWARD_REFS),
147 Phase.scheduleCollector (FORWARD_FINALIZABLE));
148
149 /**
150 * Complete closure including reference types and finalizable objects.
151 */
152 protected static final short completeClosurePhase = Phase.createComplex("release", null,
153 Phase.scheduleMutator (RELEASE),
154 Phase.scheduleCollector (RELEASE),
155 Phase.scheduleGlobal (RELEASE));
156
157
158 /**
159 * The collection scheme - this is a small tree of complex phases.
160 */
161 protected static final short finishPhase = Phase.createComplex("finish",
162 Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER),
163 Phase.scheduleCollector (COMPLETE),
164 Phase.scheduleGlobal (COMPLETE));
165
166 /**
167 * This is the phase that is executed to perform a collection.
168 */
169 public short collection = Phase.createComplex("collection", null,
170 Phase.scheduleComplex(initPhase),
171 Phase.scheduleComplex(rootClosurePhase),
172 Phase.scheduleComplex(refTypeClosurePhase),
173 Phase.scheduleComplex(forwardPhase),
174 Phase.scheduleComplex(completeClosurePhase),
175 Phase.scheduleComplex(finishPhase));
176
177 // CHECKSTYLE:ON
178
179 /**
180 * The current collection attempt.
181 */
182 protected int collectionAttempt;
183
184 /****************************************************************************
185 * Collection
186 */
187
188 /**
189 * Perform a (global) collection phase.
190 *
191 * @param phaseId The unique of the phase to perform.
192 */
193 @Inline
194 public void collectionPhase(short phaseId) {
195 if (phaseId == SET_COLLECTION_KIND) {
196 requiredAtStart = getPagesRequired();
197 collectionAttempt = VM.collection.maximumCollectionAttempt();
198 emergencyCollection = lastCollectionWasExhaustive() && collectionAttempt > 1;
199 if (collectionAttempt > MAX_COLLECTION_ATTEMPTS) {
200 VM.assertions.fail("Too many collection attempts. Suspect plan is not setting FullHeap flag");
201 }
202 if (emergencyCollection) {
203 if (Options.verbose.getValue() >= 1) Log.write("[Emergency]");
204 forceFullHeapCollection();
205 }
206 return;
207 }
208
209 if (phaseId == INITIATE) {
210 setGCStatus(GC_PREPARE);
211 return;
212 }
213
214 if (phaseId == PREPARE_STACKS) {
215 stacksPrepared = true;
216 return;
217 }
218
219 if (phaseId == PREPARE) {
220 loSpace.prepare(true);
221 nonMovingSpace.prepare(true);
222 if (USE_CODE_SPACE) {
223 smallCodeSpace.prepare(true);
224 largeCodeSpace.prepare(true);
225 }
226 immortalSpace.prepare();
227 VM.memory.globalPrepareVMSpace();
228 return;
229 }
230
231 if (phaseId == ROOTS) {
232 VM.scanning.resetThreadCounter();
233 setGCStatus(GC_PROPER);
234 return;
235 }
236
237 if (phaseId == RELEASE) {
238 loSpace.release(true);
239 nonMovingSpace.release();
240 if (USE_CODE_SPACE) {
241 smallCodeSpace.release();
242 largeCodeSpace.release(true);
243 }
244 immortalSpace.release();
245 VM.memory.globalReleaseVMSpace();
246 return;
247 }
248
249 if (phaseId == COMPLETE) {
250 setGCStatus(NOT_IN_GC);
251 Space.clearAllAllocationFailed();
252 awaitingAsyncCollection = false;
253 return;
254 }
255
256 if (Options.sanityCheck.getValue() && sanityChecker.collectionPhase(phaseId)) {
257 return;
258 }
259
260 Log.write("Global phase "); Log.write(Phase.getName(phaseId));
261 Log.writeln(" not handled.");
262 VM.assertions.fail("Global phase not handled!");
263 }
264
265 /**
266 * Replace a scheduled phase. Used for example to replace a placeholder.
267 *
268 * @param oldScheduledPhase The scheduled phase to replace.
269 * @param newScheduledPhase The new scheduled phase.
270 */
271 public void replacePhase(int oldScheduledPhase, int newScheduledPhase) {
272 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection);
273 cp.replacePhase(oldScheduledPhase, newScheduledPhase);
274 }
275
276 /**
277 * Replace a placeholder phase.
278 *
279 * @param placeHolderPhase The placeholder phase
280 * @param newScheduledPhase The new scheduled phase.
281 */
282 public void replacePlaceholderPhase(short placeHolderPhase, int newScheduledPhase) {
283 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection);
284 cp.replacePhase(Phase.schedulePlaceholder(placeHolderPhase), newScheduledPhase);
285 }
286 }