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; 014 015import org.mmtk.policy.Space; 016import org.mmtk.utility.Log; 017import org.mmtk.utility.alloc.Allocator; 018import org.mmtk.utility.options.*; 019import org.mmtk.utility.statistics.Timer; 020import org.mmtk.vm.VM; 021 022import 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 037public abstract class Simple extends Plan { 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 PREPARE_STACKS = Phase.createSimple("prepare-stacks", null); 052 public static final short STACK_ROOTS = Phase.createSimple("stacks"); 053 public static final short ROOTS = Phase.createSimple("root"); 054 public static final short CLOSURE = Phase.createSimple("closure", scanTime); 055 public static final short SOFT_REFS = Phase.createSimple("soft-ref", refTypeTime); 056 public static final short WEAK_REFS = Phase.createSimple("weak-ref", refTypeTime); 057 public static final short FINALIZABLE = Phase.createSimple("finalize", finalizeTime); 058 public static final short WEAK_TRACK_REFS = Phase.createSimple("weak-track-ref", refTypeTime); 059 public static final short PHANTOM_REFS = Phase.createSimple("phantom-ref", refTypeTime); 060 public static final short FORWARD = Phase.createSimple("forward"); 061 public static final short FORWARD_REFS = Phase.createSimple("forward-ref", refTypeTime); 062 public static final short FORWARD_FINALIZABLE = Phase.createSimple("forward-finalize", finalizeTime); 063 public static final short RELEASE = Phase.createSimple("release"); 064 public static final short COMPLETE = Phase.createSimple("complete", null); 065 066 /* Sanity placeholder */ 067 public static final short PRE_SANITY_PLACEHOLDER = Phase.createSimple("pre-sanity-placeholder", null); 068 public static final short POST_SANITY_PLACEHOLDER = Phase.createSimple("post-sanity-placeholder", null); 069 070 /* Sanity phases */ 071 public static final short SANITY_SET_PREGC = Phase.createSimple("sanity-setpre", null); 072 public static final short SANITY_SET_POSTGC = Phase.createSimple("sanity-setpost", null); 073 public static final short SANITY_PREPARE = Phase.createSimple("sanity-prepare", null); 074 public static final short SANITY_ROOTS = Phase.createSimple("sanity-roots", null); 075 public static final short SANITY_COPY_ROOTS = Phase.createSimple("sanity-copy-roots", null); 076 public static final short SANITY_BUILD_TABLE = Phase.createSimple("sanity-build-table", null); 077 public static final short SANITY_CHECK_TABLE = Phase.createSimple("sanity-check-table", null); 078 public static final short SANITY_RELEASE = Phase.createSimple("sanity-release", null); 079 080 // CHECKSTYLE:OFF 081 082 /** Ensure stacks are ready to be scanned */ 083 protected static final short prepareStacks = Phase.createComplex("prepare-stacks", null, 084 Phase.scheduleMutator (PREPARE_STACKS), 085 Phase.scheduleGlobal (PREPARE_STACKS)); 086 087 /** Trace and set up a sanity table */ 088 protected static final short sanityBuildPhase = Phase.createComplex("sanity-build", null, 089 Phase.scheduleGlobal (SANITY_PREPARE), 090 Phase.scheduleCollector (SANITY_PREPARE), 091 Phase.scheduleComplex (prepareStacks), 092 Phase.scheduleCollector (SANITY_ROOTS), 093 Phase.scheduleGlobal (SANITY_ROOTS), 094 Phase.scheduleCollector (SANITY_COPY_ROOTS), 095 Phase.scheduleGlobal (SANITY_BUILD_TABLE)); 096 097 /** Validate a sanity table */ 098 protected static final short sanityCheckPhase = Phase.createComplex("sanity-check", null, 099 Phase.scheduleGlobal (SANITY_CHECK_TABLE), 100 Phase.scheduleCollector (SANITY_RELEASE), 101 Phase.scheduleGlobal (SANITY_RELEASE)); 102 103 /** Start the collection, including preparation for any collected spaces. */ 104 protected static final short initPhase = Phase.createComplex("init", 105 Phase.scheduleGlobal (SET_COLLECTION_KIND), 106 Phase.scheduleGlobal (INITIATE), 107 Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER)); 108 109 /** 110 * Perform the initial determination of liveness from the roots. 111 */ 112 protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null, 113 Phase.scheduleMutator (PREPARE), 114 Phase.scheduleGlobal (PREPARE), 115 Phase.scheduleCollector (PREPARE), 116 Phase.scheduleComplex (prepareStacks), 117 Phase.scheduleCollector (STACK_ROOTS), 118 Phase.scheduleGlobal (STACK_ROOTS), 119 Phase.scheduleCollector (ROOTS), 120 Phase.scheduleGlobal (ROOTS), 121 Phase.scheduleGlobal (CLOSURE), 122 Phase.scheduleCollector (CLOSURE)); 123 124 /** 125 * Complete closure including reference types and finalizable objects. 126 */ 127 protected static final short refTypeClosurePhase = Phase.createComplex("refType-closure", null, 128 Phase.scheduleCollector (SOFT_REFS), 129 Phase.scheduleGlobal (CLOSURE), 130 Phase.scheduleCollector (CLOSURE), 131 Phase.scheduleCollector (WEAK_REFS), 132 Phase.scheduleCollector (FINALIZABLE), 133 Phase.scheduleGlobal (CLOSURE), 134 Phase.scheduleCollector (CLOSURE), 135 Phase.schedulePlaceholder(WEAK_TRACK_REFS), 136 Phase.scheduleCollector (PHANTOM_REFS)); 137 138 /** 139 * Ensure that all references in the system are correct. 140 */ 141 protected static final short forwardPhase = Phase.createComplex("forward-all", null, 142 /* Finish up */ 143 Phase.schedulePlaceholder(FORWARD), 144 Phase.scheduleCollector (FORWARD_REFS), 145 Phase.scheduleCollector (FORWARD_FINALIZABLE)); 146 147 /** 148 * Complete closure including reference types and finalizable objects. 149 */ 150 protected static final short completeClosurePhase = Phase.createComplex("release", null, 151 Phase.scheduleMutator (RELEASE), 152 Phase.scheduleCollector (RELEASE), 153 Phase.scheduleGlobal (RELEASE)); 154 155 156 /** 157 * The collection scheme - this is a small tree of complex phases. 158 */ 159 protected static final short finishPhase = Phase.createComplex("finish", 160 Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), 161 Phase.scheduleCollector (COMPLETE), 162 Phase.scheduleGlobal (COMPLETE)); 163 164 /** 165 * This is the phase that is executed to perform a collection. 166 */ 167 public short collection = Phase.createComplex("collection", null, 168 Phase.scheduleComplex(initPhase), 169 Phase.scheduleComplex(rootClosurePhase), 170 Phase.scheduleComplex(refTypeClosurePhase), 171 Phase.scheduleComplex(forwardPhase), 172 Phase.scheduleComplex(completeClosurePhase), 173 Phase.scheduleComplex(finishPhase)); 174 175 // CHECKSTYLE:ON 176 177 /** 178 * The current collection attempt. 179 */ 180 protected int collectionAttempt; 181 182 /**************************************************************************** 183 * Collection 184 */ 185 186 /** 187 * {@inheritDoc} 188 */ 189 @Override 190 @Inline 191 public void collectionPhase(short phaseId) { 192 if (phaseId == SET_COLLECTION_KIND) { 193 collectionAttempt = Plan.isUserTriggeredCollection() ? 1 : Allocator.determineCollectionAttempts(); 194 emergencyCollection = !Plan.isInternalTriggeredCollection() && 195 lastCollectionWasExhaustive() && collectionAttempt > 1; 196 if (emergencyCollection) { 197 if (Options.verbose.getValue() >= 1) Log.write("[Emergency]"); 198 forceFullHeapCollection(); 199 } 200 return; 201 } 202 203 if (phaseId == INITIATE) { 204 setGCStatus(GC_PREPARE); 205 return; 206 } 207 208 if (phaseId == PREPARE_STACKS) { 209 stacksPrepared = true; 210 return; 211 } 212 213 if (phaseId == PREPARE) { 214 loSpace.prepare(true); 215 nonMovingSpace.prepare(true); 216 if (USE_CODE_SPACE) { 217 smallCodeSpace.prepare(true); 218 largeCodeSpace.prepare(true); 219 } 220 immortalSpace.prepare(); 221 VM.memory.globalPrepareVMSpace(); 222 return; 223 } 224 225 if (phaseId == STACK_ROOTS) { 226 VM.scanning.notifyInitialThreadScanComplete(false); 227 setGCStatus(GC_PROPER); 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 return; 252 } 253 254 if (Options.sanityCheck.getValue() && sanityChecker.collectionPhase(phaseId)) { 255 return; 256 } 257 258 Log.write("Global phase "); Log.write(Phase.getName(phaseId)); 259 Log.writeln(" not handled."); 260 VM.assertions.fail("Global phase not handled!"); 261 } 262 263 /** 264 * Update the nursery zeroing approach based on option settings. 265 * 266 * @param nurserySpace The space to apply the changes to. 267 */ 268 protected void switchNurseryZeroingApproach(Space nurserySpace) { 269 if (Options.nurseryZeroing.getConcurrent()) { 270 if (Options.nurseryZeroing.getAdaptive() && 271 (VM.collection.getActiveThreads() >= VM.collection.getDefaultThreads())) { 272 // Many (non-daemon) threads, so we revert to bulk zeroing. 273 nurserySpace.skipConcurrentZeroing(); 274 } else { 275 nurserySpace.triggerConcurrentZeroing(); 276 } 277 } 278 } 279 280 /** 281 * {@inheritDoc} 282 * Used for example to replace a placeholder. 283 */ 284 @Override 285 public void replacePhase(int oldScheduledPhase, int newScheduledPhase) { 286 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); 287 cp.replacePhase(oldScheduledPhase, newScheduledPhase); 288 } 289 290 /** 291 * Replace a placeholder phase. 292 * 293 * @param placeHolderPhase The placeholder phase 294 * @param newScheduledPhase The new scheduled phase. 295 */ 296 public void replacePlaceholderPhase(short placeHolderPhase, int newScheduledPhase) { 297 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); 298 cp.replacePhase(Phase.schedulePlaceholder(placeHolderPhase), newScheduledPhase); 299 } 300}