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.utility.deque.ObjectReferenceDeque;
022 import org.mmtk.vm.VM;
023 import org.vmmagic.pragma.Inline;
024 import org.vmmagic.pragma.Uninterruptible;
025 import org.vmmagic.unboxed.ObjectReference;
026
027 /**
028 * This class implements the collector context for a simple reference counting
029 * collector.
030 */
031 @Uninterruptible
032 public abstract class RCBaseCollector extends StopTheWorldCollector {
033
034 /************************************************************************
035 * Initialization
036 */
037 protected final ObjectReferenceDeque newRootBuffer;
038 private final BTTraceLocal backupTrace;
039 private final ObjectReferenceDeque modBuffer;
040 private final ObjectReferenceDeque oldRootBuffer;
041 private final RCDecBuffer decBuffer;
042 private final RCZero zero;
043
044 /**
045 * Constructor.
046 */
047 public RCBaseCollector() {
048 newRootBuffer = new ObjectReferenceDeque("new-root", global().newRootPool);
049 oldRootBuffer = new ObjectReferenceDeque("old-root", global().oldRootPool);
050 modBuffer = new ObjectReferenceDeque("mod buf", global().modPool);
051 decBuffer = new RCDecBuffer(global().decPool);
052 backupTrace = new BTTraceLocal(global().backupTrace);
053 zero = new RCZero();
054 }
055
056 /**
057 * Get the modified processor to use.
058 */
059 protected abstract TransitiveClosure getModifiedProcessor();
060
061 /**
062 * Get the root trace to use.
063 */
064 protected abstract TraceLocal getRootTrace();
065
066 /****************************************************************************
067 *
068 * Collection
069 */
070
071 /** Perform garbage collection */
072 public void collect() {
073 Phase.beginNewPhaseStack(Phase.scheduleComplex(global().collection));
074 }
075
076 /**
077 * Perform a per-collector collection phase.
078 *
079 * @param phaseId The collection phase to perform
080 * @param primary perform any single-threaded local activities.
081 */
082 public void collectionPhase(short phaseId, boolean primary) {
083 if (phaseId == RCBase.PREPARE) {
084 getRootTrace().prepare();
085 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) backupTrace.prepare();
086 return;
087 }
088
089 if (phaseId == RCBase.CLOSURE) {
090 getRootTrace().completeTrace();
091 newRootBuffer.flushLocal();
092 return;
093 }
094
095 if (phaseId == RCBase.BT_CLOSURE) {
096 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
097 backupTrace.completeTrace();
098 }
099 return;
100 }
101
102 if (phaseId == RCBase.PROCESS_OLDROOTBUFFER) {
103 ObjectReference current;
104 while(!(current = oldRootBuffer.pop()).isNull()) {
105 decBuffer.push(current);
106 }
107 return;
108 }
109
110 if (phaseId == RCBase.PROCESS_NEWROOTBUFFER) {
111 ObjectReference current;
112 while(!(current = newRootBuffer.pop()).isNull()) {
113 RCHeader.incRC(current);
114 oldRootBuffer.push(current);
115 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
116 if (RCHeader.testAndMark(current)) {
117 backupTrace.processNode(current);
118 }
119 }
120 }
121 oldRootBuffer.flushLocal();
122 return;
123 }
124
125 if (phaseId == RCBase.PROCESS_MODBUFFER) {
126 ObjectReference current;
127 while(!(current = modBuffer.pop()).isNull()) {
128 RCHeader.makeUnlogged(current);
129 VM.scanning.scanObject(getModifiedProcessor(), current);
130 }
131 return;
132 }
133
134 if (phaseId == RCBase.PROCESS_DECBUFFER) {
135 ObjectReference current;
136 while(!(current = decBuffer.pop()).isNull()) {
137 if (RCHeader.decRC(current) == RCHeader.DEC_KILL) {
138 decBuffer.processChildren(current);
139 if (Space.isInSpace(RCBase.REF_COUNT, current)) {
140 RCBase.rcSpace.free(current);
141 } else if (Space.isInSpace(RCBase.REF_COUNT_LOS, current)) {
142 RCBase.rcloSpace.free(current);
143 } else if (Space.isInSpace(RCBase.IMMORTAL, current)) {
144 VM.scanning.scanObject(zero, current);
145 }
146 }
147 }
148 return;
149 }
150
151 if (phaseId == RCBase.RELEASE) {
152 if (RCBase.CC_BACKUP_TRACE && RCBase.performCycleCollection) {
153 backupTrace.release();
154 }
155 getRootTrace().release();
156 if (VM.VERIFY_ASSERTIONS) {
157 VM.assertions._assert(newRootBuffer.isEmpty());
158 VM.assertions._assert(modBuffer.isEmpty());
159 VM.assertions._assert(decBuffer.isEmpty());
160 }
161 return;
162 }
163
164 super.collectionPhase(phaseId, primary);
165 }
166
167 /****************************************************************************
168 *
169 * Miscellaneous
170 */
171
172 /** @return The active global plan as an <code>RC</code> instance. */
173 @Inline
174 protected static RCBase global() {
175 return (RCBase) VM.activePlan.global();
176 }
177
178 /** @return The current trace instance. */
179 public final TraceLocal getCurrentTrace() {
180 return getRootTrace();
181 }
182 }