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    }