| /* |
| * This file is part of the Jikes RVM project (http://jikesrvm.org). |
| * |
| * This file is licensed to You under the Eclipse Public License (EPL); |
| * You may not use this file except in compliance with the License. You |
| * may obtain a copy of the License at |
| * |
| * http://www.opensource.org/licenses/eclipse-1.0.php |
| * |
| * See the COPYRIGHT.txt file distributed with this work for information |
| * regarding copyright ownership. |
| */ |
| package org.mmtk.plan.refcount; |
| |
| import org.mmtk.plan.Phase; |
| import org.mmtk.plan.StopTheWorldCollector; |
| import org.mmtk.plan.TraceLocal; |
| import org.mmtk.plan.TransitiveClosure; |
| import org.mmtk.plan.refcount.backuptrace.BTTraceLocal; |
| import org.mmtk.policy.Space; |
| import org.mmtk.utility.deque.ObjectReferenceDeque; |
| import org.mmtk.vm.VM; |
| import org.vmmagic.pragma.Inline; |
| import org.vmmagic.pragma.Uninterruptible; |
| import org.vmmagic.unboxed.ObjectReference; |
| |
| /** |
| * This class implements the collector context for a simple reference counting |
| * collector. |
| */ |
| @Uninterruptible |
| public abstract class RCBaseCollector extends StopTheWorldCollector { |
| |
| /************************************************************************ |
| * Initialization |
| */ |
| protected final ObjectReferenceDeque newRootBuffer; |
| private final BTTraceLocal backupTrace; |
| private final ObjectReferenceDeque modBuffer; |
| private final ObjectReferenceDeque oldRootBuffer; |
| private final RCDecBuffer decBuffer; |
| private final RCZero zero; |
| |
| /** |
| * Constructor. |
| */ |
| public RCBaseCollector() { |
| newRootBuffer = new ObjectReferenceDeque("new-root", global().newRootPool); |
| oldRootBuffer = new ObjectReferenceDeque("old-root", global().oldRootPool); |
| modBuffer = new ObjectReferenceDeque("mod buf", global().modPool); |
| decBuffer = new RCDecBuffer(global().decPool); |
| backupTrace = new BTTraceLocal(global().backupTrace); |
| zero = new RCZero(); |
| } |
| |
| /** |
| * Get the modified processor to use. |
| */ |
| protected abstract TransitiveClosure getModifiedProcessor(); |
| |
| /** |
| * Get the root trace to use. |
| */ |
| protected abstract TraceLocal getRootTrace(); |
| |
| /**************************************************************************** |
| * |
| * Collection |
| */ |
| |
| /** Perform garbage collection */ |
| public void collect() { |
| Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection)); |
| } |
| |
| /** |
| * Perform a per-collector collection phase. |
| * |
| * @param phaseId The collection phase to perform |
| * @param primary perform any single-threaded local activities. |
| */ |
| public void collectionPhase(short phaseId, boolean primary) { |
| if (phaseId == RCBase.PREPARE) { |
| getRootTrace().prepare(); |
| if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) backupTrace.prepare(); |
| return; |
| } |
| |
| if (phaseId == RCBase.CLOSURE) { |
| getRootTrace().completeTrace(); |
| newRootBuffer.flushLocal(); |
| return; |
| } |
| |
| if (phaseId == RCBase.BT_CLOSURE) { |
| if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { |
| backupTrace.completeTrace(); |
| } |
| return; |
| } |
| |
| if (phaseId == RCBase.PROCESS_OLDROOTBUFFER) { |
| ObjectReference current; |
| while(!(current = oldRootBuffer.pop()).isNull()) { |
| decBuffer.push(current); |
| } |
| return; |
| } |
| |
| if (phaseId == RCBase.PROCESS_NEWROOTBUFFER) { |
| ObjectReference current; |
| while(!(current = newRootBuffer.pop()).isNull()) { |
| RCHeader.incRC(current); |
| oldRootBuffer.push(current); |
| if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { |
| if (RCHeader.testAndMark(current)) { |
| backupTrace.processNode(current); |
| } |
| } |
| } |
| oldRootBuffer.flushLocal(); |
| return; |
| } |
| |
| if (phaseId == RCBase.PROCESS_MODBUFFER) { |
| ObjectReference current; |
| while(!(current = modBuffer.pop()).isNull()) { |
| RCHeader.makeUnlogged(current); |
| VM.scanning.scanObject(getModifiedProcessor(), current); |
| } |
| return; |
| } |
| |
| if (phaseId == RCBase.PROCESS_DECBUFFER) { |
| ObjectReference current; |
| while(!(current = decBuffer.pop()).isNull()) { |
| if (RCHeader.decRC(current) == RCHeader.DEC_KILL) { |
| decBuffer.processChildren(current); |
| if (Space.isInSpace(RCBase.REF_COUNT, current)) { |
| RCBase.rcSpace.free(current); |
| } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) { |
| RCBase.rcloSpace.free(current); |
| } else if (Space.isInSpace(RCBase.IMMORTAL, current)) { |
| VM.scanning.scanObject(zero, current); |
| } |
| } |
| } |
| return; |
| } |
| |
| if (phaseId == RCBase.RELEASE) { |
| if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) { |
| backupTrace.release(); |
| } |
| getRootTrace().release(); |
| if (VM.VERIFY_ASSERTIONS) { |
| VM.assertions._assert(newRootBuffer.isEmpty()); |
| VM.assertions._assert(modBuffer.isEmpty()); |
| VM.assertions._assert(decBuffer.isEmpty()); |
| } |
| return; |
| } |
| |
| super.collectionPhase(phaseId, primary); |
| } |
| |
| /**************************************************************************** |
| * |
| * Miscellaneous |
| */ |
| |
| /** @return The active global plan as an <code>RC</code> instance. */ |
| @Inline |
| protected static RCBase global() { |
| return (RCBase) VM.activePlan.global(); |
| } |
| |
| /** @return The current trace instance. */ |
| public final TraceLocal getCurrentTrace() { |
| return getRootTrace(); |
| } |
| } |