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