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;
014    
015    import org.mmtk.utility.Log;
016    import org.mmtk.utility.options.Options;
017    import org.mmtk.utility.sanitychecker.SanityCheckerLocal;
018    
019    import org.mmtk.vm.VM;
020    
021    import org.vmmagic.pragma.*;
022    
023    /**
024     * This class (and its sub-classes) implement <i>per-collector thread</i>
025     * behavior and state.<p>
026     *
027     * MMTk assumes that the VM instantiates instances of CollectorContext
028     * in thread local storage (TLS) for each thread participating in
029     * collection.  Accesses to this state are therefore assumed to be
030     * low-cost during mutator time.<p>
031     *
032     * @see CollectorContext
033     */
034    @Uninterruptible
035    public abstract class SimpleCollector extends ParallelCollector {
036    
037      /****************************************************************************
038       * Instance fields
039       */
040    
041      /** Used for sanity checking. */
042      protected final SanityCheckerLocal sanityLocal = new SanityCheckerLocal();
043    
044      /****************************************************************************
045       *
046       * Collection
047       */
048    
049      /**
050       * {@inheritDoc}
051       */
052      @Override
053      @Inline
054      public void collectionPhase(short phaseId, boolean primary) {
055        if (phaseId == Simple.PREPARE) {
056          // Nothing to do
057          return;
058        }
059    
060        if (phaseId == Simple.STACK_ROOTS) {
061          VM.scanning.computeThreadRoots(getCurrentTrace());
062          return;
063        }
064    
065        if (phaseId == Simple.ROOTS) {
066          VM.scanning.computeGlobalRoots(getCurrentTrace());
067          VM.scanning.computeStaticRoots(getCurrentTrace());
068          if (Plan.SCAN_BOOT_IMAGE) {
069            VM.scanning.computeBootImageRoots(getCurrentTrace());
070          }
071          return;
072        }
073    
074        if (phaseId == Simple.SOFT_REFS) {
075          if (primary) {
076            if (Options.noReferenceTypes.getValue())
077              VM.softReferences.clear();
078            else
079              VM.softReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
080          }
081          return;
082        }
083    
084        if (phaseId == Simple.WEAK_REFS) {
085          if (primary) {
086            if (Options.noReferenceTypes.getValue())
087              VM.weakReferences.clear();
088            else
089              VM.weakReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
090          }
091          return;
092        }
093    
094        if (phaseId == Simple.FINALIZABLE) {
095          if (primary) {
096            if (Options.noFinalizer.getValue())
097              VM.finalizableProcessor.clear();
098            else
099              VM.finalizableProcessor.scan(getCurrentTrace(),global().isCurrentGCNursery());
100          }
101          return;
102        }
103    
104        if (phaseId == Simple.PHANTOM_REFS) {
105          if (primary) {
106            if (Options.noReferenceTypes.getValue())
107              VM.phantomReferences.clear();
108            else
109              VM.phantomReferences.scan(getCurrentTrace(),global().isCurrentGCNursery());
110          }
111          return;
112        }
113    
114        if (phaseId == Simple.FORWARD_REFS) {
115          if (primary && !Options.noReferenceTypes.getValue() &&
116              VM.activePlan.constraints().needsForwardAfterLiveness()) {
117            VM.softReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
118            VM.weakReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
119            VM.phantomReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
120          }
121          return;
122        }
123    
124        if (phaseId == Simple.FORWARD_FINALIZABLE) {
125          if (primary && !Options.noFinalizer.getValue() &&
126              VM.activePlan.constraints().needsForwardAfterLiveness()) {
127            VM.finalizableProcessor.forward(getCurrentTrace(),global().isCurrentGCNursery());
128          }
129          return;
130        }
131    
132        if (phaseId == Simple.COMPLETE) {
133          // Nothing to do
134          return;
135        }
136    
137        if (phaseId == Simple.RELEASE) {
138          // Nothing to do
139          return;
140        }
141    
142        if (Options.sanityCheck.getValue() && sanityLocal.collectionPhase(phaseId, primary)) {
143          return;
144        }
145    
146        Log.write("Per-collector phase "); Log.write(Phase.getName(phaseId));
147        Log.writeln(" not handled.");
148        VM.assertions.fail("Per-collector phase not handled!");
149      }
150    
151      /****************************************************************************
152       *
153       * Miscellaneous.
154       */
155    
156      /** @return The active global plan as a <code>Simple</code> instance. */
157      @Inline
158      private static Simple global() {
159        return (Simple) VM.activePlan.global();
160      }
161    }