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.refcount; 014 015 import org.mmtk.plan.Phase; 016 import org.mmtk.plan.StopTheWorldCollector; 017 import org.mmtk.plan.TraceLocal; 018 import org.mmtk.plan.TransitiveClosure; 019 import org.mmtk.plan.refcount.backuptrace.BTTraceLocal; 020 import org.mmtk.policy.Space; 021 import org.mmtk.policy.ExplicitFreeListSpace; 022 import org.mmtk.utility.deque.ObjectReferenceDeque; 023 import org.mmtk.vm.VM; 024 import org.vmmagic.pragma.Inline; 025 import org.vmmagic.pragma.Uninterruptible; 026 import org.vmmagic.unboxed.ObjectReference; 027 028 /** 029 * This class implements the collector context for a reference counting collector. 030 * See Shahriyar et al for details of and rationale for the optimizations used 031 * here (http://dx.doi.org/10.1145/2258996.2259008). See Chapter 4 of 032 * Daniel Frampton's PhD thesis for details of and rationale for the cycle 033 * collection strategy used by this collector. 034 */ 035 @Uninterruptible 036 public abstract class RCBaseCollector extends StopTheWorldCollector { 037 038 /************************************************************************ 039 * Initialization 040 */ 041 042 /** 043 * 044 */ 045 protected final ObjectReferenceDeque newRootBuffer; 046 private final BTTraceLocal backupTrace; 047 private final ObjectReferenceDeque modBuffer; 048 private final ObjectReferenceDeque oldRootBuffer; 049 private final RCDecBuffer decBuffer; 050 private final RCZero zero; 051 052 /** 053 * Constructor. 054 */ 055 public RCBaseCollector() { 056 newRootBuffer = new ObjectReferenceDeque("new-root", global().newRootPool); 057 oldRootBuffer = new ObjectReferenceDeque("old-root", global().oldRootPool); 058 modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); 059 decBuffer = new RCDecBuffer(global().decPool); 060 backupTrace = new BTTraceLocal(global().backupTrace); 061 zero = new RCZero(); 062 } 063 064 /** 065 * Get the modified processor to use. 066 */ 067 protected abstract TransitiveClosure getModifiedProcessor(); 068 069 /** 070 * Get the root trace to use. 071 */ 072 protected abstract TraceLocal getRootTrace(); 073 074 /**************************************************************************** 075 * 076 * Collection 077 */ 078 079 /** 080 * {@inheritDoc} 081 */ 082 @Override 083 public void collect() { 084 if (RCBase.BUILD_FOR_GENRC) Phase.beginNewPhaseStack(Phase.scheduleComplex(global().genRCCollection)); 085 else Phase.beginNewPhaseStack(Phase.scheduleComplex(global().refCountCollection)); 086 } 087 088 @Override 089 public void collectionPhase(short phaseId, boolean primary) { 090 if (phaseId == RCBase.PREPARE) { 091 getRootTrace().prepare(); 092 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) backupTrace.prepare(); 093 return; 094 } 095 096 if (phaseId == RCBase.CLOSURE) { 097 getRootTrace().completeTrace(); 098 newRootBuffer.flushLocal(); 099 return; 100 } 101 102 if (phaseId == RCBase.BT_CLOSURE) { 103 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { 104 backupTrace.completeTrace(); 105 } 106 return; 107 } 108 109 if (phaseId == RCBase.PROCESS_OLDROOTBUFFER) { 110 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) return; 111 ObjectReference current; 112 while(!(current = oldRootBuffer.pop()).isNull()) { 113 decBuffer.push(current); 114 } 115 return; 116 } 117 118 if (phaseId == RCBase.PROCESS_NEWROOTBUFFER) { 119 ObjectReference current; 120 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { 121 while(!(current = newRootBuffer.pop()).isNull()) { 122 if (RCHeader.testAndMark(current)) { 123 if (RCBase.BUILD_FOR_GENRC) { 124 RCHeader.initRC(current); 125 } else { 126 if (RCHeader.initRC(current) == RCHeader.INC_NEW) { 127 modBuffer.push(current); 128 } 129 } 130 backupTrace.processNode(current); 131 } else { 132 if (RCBase.BUILD_FOR_GENRC) { 133 RCHeader.incRC(current); 134 } else { 135 if (RCHeader.incRC(current) == RCHeader.INC_NEW) { 136 modBuffer.push(current); 137 } 138 } 139 } 140 } 141 if (!RCBase.BUILD_FOR_GENRC) modBuffer.flushLocal(); 142 return; 143 } 144 while(!(current = newRootBuffer.pop()).isNull()) { 145 if (RCBase.BUILD_FOR_GENRC) { 146 RCHeader.incRC(current); 147 } else { 148 if (RCHeader.incRC(current) == RCHeader.INC_NEW) { 149 modBuffer.push(current); 150 } 151 } 152 oldRootBuffer.push(current); 153 } 154 oldRootBuffer.flushLocal(); 155 if (!RCBase.BUILD_FOR_GENRC) modBuffer.flushLocal(); 156 return; 157 } 158 159 if (phaseId == RCBase.PROCESS_MODBUFFER) { 160 ObjectReference current; 161 while(!(current = modBuffer.pop()).isNull()) { 162 RCHeader.makeUnlogged(current); 163 if (!RCBase.BUILD_FOR_GENRC) { 164 if (Space.isInSpace(RCBase.REF_COUNT, current)) { 165 ExplicitFreeListSpace.testAndSetLiveBit(current); 166 } 167 } 168 VM.scanning.scanObject(getModifiedProcessor(), current); 169 } 170 return; 171 } 172 173 if (phaseId == RCBase.PROCESS_DECBUFFER) { 174 ObjectReference current; 175 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { 176 if (!RCBase.BUILD_FOR_GENRC) { 177 while(!(current = decBuffer.pop()).isNull()) { 178 if (RCHeader.isNew(current)) { 179 if (Space.isInSpace(RCBase.REF_COUNT, current)) { 180 RCBase.rcSpace.free(current); 181 } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { 182 RCBase.rcloSpace.free(current); 183 } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { 184 VM.scanning.scanObject(zero, current); 185 } 186 } 187 } 188 } 189 return; 190 } 191 while(!(current = decBuffer.pop()).isNull()) { 192 if (RCBase.BUILD_FOR_GENRC) { 193 if (RCHeader.decRC(current) == RCHeader.DEC_KILL) { 194 decBuffer.processChildren(current); 195 if (Space.isInSpace(RCBase.REF_COUNT, current)) { 196 RCBase.rcSpace.free(current); 197 } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { 198 RCBase.rcloSpace.free(current); 199 } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { 200 VM.scanning.scanObject(zero, current); 201 } 202 } 203 } else { 204 if (RCHeader.isNew(current)) { 205 if (Space.isInSpace(RCBase.REF_COUNT, current)) { 206 RCBase.rcSpace.free(current); 207 } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { 208 RCBase.rcloSpace.free(current); 209 } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { 210 VM.scanning.scanObject(zero, current); 211 } 212 } else { 213 if (RCHeader.decRC(current) == RCHeader.DEC_KILL) { 214 decBuffer.processChildren(current); 215 if (Space.isInSpace(RCBase.REF_COUNT, current)) { 216 RCBase.rcSpace.free(current); 217 } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { 218 RCBase.rcloSpace.free(current); 219 } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { 220 VM.scanning.scanObject(zero, current); 221 } 222 } 223 } 224 } 225 } 226 return; 227 } 228 229 if (phaseId == RCBase.RELEASE) { 230 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { 231 backupTrace.release(); 232 global().oldRootPool.clearDeque(1); 233 if (RCBase.BUILD_FOR_GENRC) global().decPool.clearDeque(1); 234 } 235 getRootTrace().release(); 236 if (VM.VERIFY_ASSERTIONS) { 237 VM.assertions._assert(newRootBuffer.isEmpty()); 238 VM.assertions._assert(modBuffer.isEmpty()); 239 VM.assertions._assert(decBuffer.isEmpty()); 240 } 241 return; 242 } 243 244 super.collectionPhase(phaseId, primary); 245 } 246 247 /**************************************************************************** 248 * 249 * Miscellaneous 250 */ 251 252 /** @return The active global plan as an <code>RC</code> instance. */ 253 @Inline 254 protected static RCBase global() { 255 return (RCBase) VM.activePlan.global(); 256 } 257 258 @Override 259 public final TraceLocal getCurrentTrace() { 260 return getRootTrace(); 261 } 262 263 /** @return The current modBuffer instance. */ 264 @Inline 265 public final ObjectReferenceDeque getModBuffer() { 266 return modBuffer; 267 } 268 }