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 */
013package org.mmtk.plan;
014
015import org.mmtk.utility.Log;
016import org.mmtk.utility.options.Options;
017import org.mmtk.utility.sanitychecker.SanityCheckerLocal;
018
019import org.mmtk.vm.VM;
020
021import 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.
031 *
032 * @see CollectorContext
033 */
034@Uninterruptible
035public 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          if (!Plan.isEmergencyCollection()) {
078            VM.softReferences.scan(getCurrentTrace(),global().isCurrentGCNursery(),true);
079          }
080        }
081      }
082      return;
083    }
084
085    if (phaseId == Simple.WEAK_REFS) {
086      if (primary) {
087        if (Options.noReferenceTypes.getValue()) {
088          VM.softReferences.clear();
089          VM.weakReferences.clear();
090        } else {
091            VM.softReferences.scan(getCurrentTrace(),global().isCurrentGCNursery(), false);
092            VM.weakReferences.scan(getCurrentTrace(),global().isCurrentGCNursery(), false);
093        }
094      }
095      return;
096    }
097
098    if (phaseId == Simple.FINALIZABLE) {
099      if (primary) {
100        if (Options.noFinalizer.getValue())
101          VM.finalizableProcessor.clear();
102        else
103          VM.finalizableProcessor.scan(getCurrentTrace(),global().isCurrentGCNursery());
104      }
105      return;
106    }
107
108    if (phaseId == Simple.PHANTOM_REFS) {
109      if (primary) {
110        if (Options.noReferenceTypes.getValue())
111          VM.phantomReferences.clear();
112        else
113          VM.phantomReferences.scan(getCurrentTrace(),global().isCurrentGCNursery(),false);
114      }
115      return;
116    }
117
118    if (phaseId == Simple.FORWARD_REFS) {
119      if (primary && !Options.noReferenceTypes.getValue() &&
120          VM.activePlan.constraints().needsForwardAfterLiveness()) {
121        VM.softReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
122        VM.weakReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
123        VM.phantomReferences.forward(getCurrentTrace(),global().isCurrentGCNursery());
124      }
125      return;
126    }
127
128    if (phaseId == Simple.FORWARD_FINALIZABLE) {
129      if (primary && !Options.noFinalizer.getValue() &&
130          VM.activePlan.constraints().needsForwardAfterLiveness()) {
131        VM.finalizableProcessor.forward(getCurrentTrace(),global().isCurrentGCNursery());
132      }
133      return;
134    }
135
136    if (phaseId == Simple.COMPLETE) {
137      // Nothing to do
138      return;
139    }
140
141    if (phaseId == Simple.RELEASE) {
142      // Nothing to do
143      return;
144    }
145
146    if (Options.sanityCheck.getValue() && sanityLocal.collectionPhase(phaseId, primary)) {
147      return;
148    }
149
150    Log.write("Per-collector phase "); Log.write(Phase.getName(phaseId));
151    Log.writeln(" not handled.");
152    VM.assertions.fail("Per-collector phase not handled!");
153  }
154
155  /****************************************************************************
156   *
157   * Miscellaneous.
158   */
159
160  /** @return The active global plan as a <code>Simple</code> instance. */
161  @Inline
162  private static Simple global() {
163    return (Simple) VM.activePlan.global();
164  }
165}