blob: ab99da182dc92744a3b5dd52bf2c267750bf7e27 [file] [log] [blame]
/*
* 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();
}
}