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.alloc.Allocator; 019 import org.mmtk.utility.options.*; 020 import org.mmtk.utility.statistics.Timer; 021 import org.mmtk.vm.VM; 022 023 import org.vmmagic.pragma.*; 024 025 /** 026 * This abstract class implements the core functionality for 027 * simple collectors.<p> 028 * 029 * This class defines the collection phases, and provides base 030 * level implementations of them. Subclasses should provide 031 * implementations for the spaces that they introduce, and 032 * delegate up the class hierarchy.<p> 033 * 034 * For details of the split between global and thread-local operations 035 * @see org.mmtk.plan.Plan 036 */ 037 @Uninterruptible 038 public abstract class Simple extends Plan implements Constants { 039 /**************************************************************************** 040 * Constants 041 */ 042 043 /* Shared Timers */ 044 private static final Timer refTypeTime = new Timer("refType", false, true); 045 private static final Timer scanTime = new Timer("scan", false, true); 046 private static final Timer finalizeTime = new Timer("finalize", false, true); 047 048 /* Phases */ 049 public static final short SET_COLLECTION_KIND = Phase.createSimple("set-collection-kind", null); 050 public static final short INITIATE = Phase.createSimple("initiate", null); 051 public static final short PREPARE = Phase.createSimple("prepare"); 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.scheduleMutator (PREPARE_STACKS), 086 Phase.scheduleGlobal (PREPARE_STACKS)); 087 088 /** Trace and set up a sanity table */ 089 protected static final short sanityBuildPhase = Phase.createComplex("sanity-build", null, 090 Phase.scheduleGlobal (SANITY_PREPARE), 091 Phase.scheduleCollector (SANITY_PREPARE), 092 Phase.scheduleComplex (prepareStacks), 093 Phase.scheduleCollector (SANITY_ROOTS), 094 Phase.scheduleGlobal (SANITY_ROOTS), 095 Phase.scheduleCollector (SANITY_COPY_ROOTS), 096 Phase.scheduleGlobal (SANITY_BUILD_TABLE)); 097 098 /** Validate a sanity table */ 099 protected static final short sanityCheckPhase = Phase.createComplex("sanity-check", null, 100 Phase.scheduleGlobal (SANITY_CHECK_TABLE), 101 Phase.scheduleCollector (SANITY_RELEASE), 102 Phase.scheduleGlobal (SANITY_RELEASE)); 103 104 /** Start the collection, including preparation for any collected spaces. */ 105 protected static final short initPhase = Phase.createComplex("init", 106 Phase.scheduleGlobal (SET_COLLECTION_KIND), 107 Phase.scheduleGlobal (INITIATE), 108 Phase.schedulePlaceholder(PRE_SANITY_PLACEHOLDER)); 109 110 /** 111 * Perform the initial determination of liveness from the roots. 112 */ 113 protected static final short rootClosurePhase = Phase.createComplex("initial-closure", null, 114 Phase.scheduleMutator (PREPARE), 115 Phase.scheduleGlobal (PREPARE), 116 Phase.scheduleCollector (PREPARE), 117 Phase.scheduleComplex (prepareStacks), 118 Phase.scheduleCollector (STACK_ROOTS), 119 Phase.scheduleGlobal (STACK_ROOTS), 120 Phase.scheduleCollector (ROOTS), 121 Phase.scheduleGlobal (ROOTS), 122 Phase.scheduleGlobal (CLOSURE), 123 Phase.scheduleCollector (CLOSURE)); 124 125 /** 126 * Complete closure including reference types and finalizable objects. 127 */ 128 protected static final short refTypeClosurePhase = Phase.createComplex("refType-closure", null, 129 Phase.scheduleCollector (SOFT_REFS), 130 Phase.scheduleGlobal (CLOSURE), 131 Phase.scheduleCollector (CLOSURE), 132 Phase.scheduleCollector (WEAK_REFS), 133 Phase.scheduleCollector (FINALIZABLE), 134 Phase.scheduleGlobal (CLOSURE), 135 Phase.scheduleCollector (CLOSURE), 136 Phase.schedulePlaceholder(WEAK_TRACK_REFS), 137 Phase.scheduleCollector (PHANTOM_REFS)); 138 139 /** 140 * Ensure that all references in the system are correct. 141 */ 142 protected static final short forwardPhase = Phase.createComplex("forward-all", null, 143 /* Finish up */ 144 Phase.schedulePlaceholder(FORWARD), 145 Phase.scheduleCollector (FORWARD_REFS), 146 Phase.scheduleCollector (FORWARD_FINALIZABLE)); 147 148 /** 149 * Complete closure including reference types and finalizable objects. 150 */ 151 protected static final short completeClosurePhase = Phase.createComplex("release", null, 152 Phase.scheduleMutator (RELEASE), 153 Phase.scheduleCollector (RELEASE), 154 Phase.scheduleGlobal (RELEASE)); 155 156 157 /** 158 * The collection scheme - this is a small tree of complex phases. 159 */ 160 protected static final short finishPhase = Phase.createComplex("finish", 161 Phase.schedulePlaceholder(POST_SANITY_PLACEHOLDER), 162 Phase.scheduleCollector (COMPLETE), 163 Phase.scheduleGlobal (COMPLETE)); 164 165 /** 166 * This is the phase that is executed to perform a collection. 167 */ 168 public short collection = Phase.createComplex("collection", null, 169 Phase.scheduleComplex(initPhase), 170 Phase.scheduleComplex(rootClosurePhase), 171 Phase.scheduleComplex(refTypeClosurePhase), 172 Phase.scheduleComplex(forwardPhase), 173 Phase.scheduleComplex(completeClosurePhase), 174 Phase.scheduleComplex(finishPhase)); 175 176 // CHECKSTYLE:ON 177 178 /** 179 * The current collection attempt. 180 */ 181 protected int collectionAttempt; 182 183 /**************************************************************************** 184 * Collection 185 */ 186 187 /** 188 * {@inheritDoc} 189 */ 190 @Override 191 @Inline 192 public void collectionPhase(short phaseId) { 193 if (phaseId == SET_COLLECTION_KIND) { 194 collectionAttempt = Plan.isUserTriggeredCollection() ? 1 : Allocator.determineCollectionAttempts(); 195 emergencyCollection = !Plan.isInternalTriggeredCollection() && 196 lastCollectionWasExhaustive() && collectionAttempt > 1; 197 if (emergencyCollection) { 198 if (Options.verbose.getValue() >= 1) Log.write("[Emergency]"); 199 forceFullHeapCollection(); 200 } 201 return; 202 } 203 204 if (phaseId == INITIATE) { 205 setGCStatus(GC_PREPARE); 206 return; 207 } 208 209 if (phaseId == PREPARE_STACKS) { 210 stacksPrepared = true; 211 return; 212 } 213 214 if (phaseId == PREPARE) { 215 loSpace.prepare(true); 216 nonMovingSpace.prepare(true); 217 if (USE_CODE_SPACE) { 218 smallCodeSpace.prepare(true); 219 largeCodeSpace.prepare(true); 220 } 221 immortalSpace.prepare(); 222 VM.memory.globalPrepareVMSpace(); 223 return; 224 } 225 226 if (phaseId == STACK_ROOTS) { 227 VM.scanning.notifyInitialThreadScanComplete(); 228 setGCStatus(GC_PROPER); 229 return; 230 } 231 232 if (phaseId == ROOTS) { 233 VM.scanning.resetThreadCounter(); 234 setGCStatus(GC_PROPER); 235 return; 236 } 237 238 if (phaseId == RELEASE) { 239 loSpace.release(true); 240 nonMovingSpace.release(); 241 if (USE_CODE_SPACE) { 242 smallCodeSpace.release(); 243 largeCodeSpace.release(true); 244 } 245 immortalSpace.release(); 246 VM.memory.globalReleaseVMSpace(); 247 return; 248 } 249 250 if (phaseId == COMPLETE) { 251 setGCStatus(NOT_IN_GC); 252 return; 253 } 254 255 if (Options.sanityCheck.getValue() && sanityChecker.collectionPhase(phaseId)) { 256 return; 257 } 258 259 Log.write("Global phase "); Log.write(Phase.getName(phaseId)); 260 Log.writeln(" not handled."); 261 VM.assertions.fail("Global phase not handled!"); 262 } 263 264 /** 265 * Update the nursery zeroing approach based on option settings. 266 * 267 * @param nurserySpace The space to apply the changes to. 268 */ 269 protected void switchNurseryZeroingApproach(Space nurserySpace) { 270 if (Options.nurseryZeroing.getConcurrent()) { 271 if (Options.nurseryZeroing.getAdaptive() && 272 (VM.collection.getActiveThreads() >= VM.collection.getDefaultThreads())) { 273 // Many (non-daemon) threads, so we revert to bulk zeroing. 274 nurserySpace.skipConcurrentZeroing(); 275 } else { 276 nurserySpace.triggerConcurrentZeroing(); 277 } 278 } 279 } 280 281 /** 282 * {@inheritDoc} 283 * Used for example to replace a placeholder. 284 */ 285 @Override 286 public void replacePhase(int oldScheduledPhase, int newScheduledPhase) { 287 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); 288 cp.replacePhase(oldScheduledPhase, newScheduledPhase); 289 } 290 291 /** 292 * Replace a placeholder phase. 293 * 294 * @param placeHolderPhase The placeholder phase 295 * @param newScheduledPhase The new scheduled phase. 296 */ 297 public void replacePlaceholderPhase(short placeHolderPhase, int newScheduledPhase) { 298 ComplexPhase cp = (ComplexPhase)Phase.getPhase(collection); 299 cp.replacePhase(Phase.schedulePlaceholder(placeHolderPhase), newScheduledPhase); 300 } 301 }