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.semispace.gcspy;
014
015 import org.mmtk.plan.Phase;
016 import org.mmtk.plan.semispace.SS;
017 import org.mmtk.plan.semispace.SSCollector;
018 import org.mmtk.policy.CopySpace;
019 import org.mmtk.utility.Log;
020 import org.mmtk.utility.gcspy.GCspy;
021 import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver;
022 import org.mmtk.vm.VM;
023
024 import org.vmmagic.unboxed.*;
025 import org.vmmagic.pragma.*;
026
027 /**
028 * This class implements <i>per-collector thread</i> behavior and state for the
029 * <i>SSGCspy</i> plan.<p>
030 *
031 * See {@link SSGCspy} for an overview of the GC-spy mechanisms.<p>
032 *
033 * @see SSCollector
034 * @see SSGCspy
035 * @see SSGCspyMutator
036 * @see org.mmtk.plan.StopTheWorldCollector
037 * @see org.mmtk.plan.CollectorContext
038 * @see org.mmtk.plan.SimplePhase
039 */
040 @Uninterruptible public class SSGCspyCollector extends SSCollector {
041
042 /****************************************************************************
043 *
044 * Initialization
045 */
046
047 /*****************************************************************************
048 * Instance fields
049 */
050
051 /**
052 *
053 */
054 private static final boolean DEBUG = false;
055
056 /**
057 * Constructor
058 */
059 public SSGCspyCollector() {
060 super(new SSGCspyTraceLocal(global().ssTrace));
061 }
062
063
064 /****************************************************************************
065 *
066 * Data gathering
067 */
068
069 /**
070 * Perform a (local) collection phase.
071 * Before a collection, we need to discover
072 * <ul>
073 * <li>the tospace objects copied by the collector in the last GC cycle
074 * <li>the semispace objects allocated since by the mutator.
075 * <li>all immortal objects allocated by the mutator
076 * <li>all large objects allocated by the mutator
077 * </ul>
078 * After the semispace has been copied, we need to discover
079 * <ul>
080 * <li>the tospace objects copied by the collector
081 * <li>all immortal objects allocated by the mutator
082 * <li>all large objects allocated by the mutator
083 * </ul>
084 */
085 @Override
086 @Inline
087 public final void collectionPhase(short phaseId, boolean primary) {
088 if (DEBUG) { Log.write("--Phase Collector."); Log.writeln(Phase.getName(phaseId)); }
089
090 //TODO do we need to worry any longer about primary??
091 if (phaseId == SS.PREPARE) {
092 //if (primary)
093 gcspyGatherData(SSGCspy.BEFORE_COLLECTION);
094 super.collectionPhase(phaseId, primary);
095 return;
096 }
097
098 if (phaseId == SS.FORWARD_FINALIZABLE) {
099 super.collectionPhase(phaseId, primary);
100 //if (primary)
101 gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
102 return;
103 }
104
105 if (phaseId == SS.RELEASE) {
106 //if (primary)
107 //gcspyGatherData(SSGCspy.SEMISPACE_COPIED);
108 super.collectionPhase(phaseId, primary);
109 //if (primary)
110 gcspyGatherData(SSGCspy.AFTER_COLLECTION);
111 return;
112 }
113
114 super.collectionPhase(phaseId, primary);
115 }
116
117 /**
118 * Gather data for GCspy for the semispaces only.
119 * <p>
120 * This method sweeps the semispace under consideration to gather data.
121 * Alternatively and more efficiently, 'used space' can obviously be
122 * discovered in constant time simply by comparing the start and the end
123 * addresses of the semispace. However, per-object information can only be
124 * gathered by sweeping through the space and we do this here for tutorial
125 * purposes.
126 *
127 * @param event
128 * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or
129 * AFTER_COLLECTION
130 */
131 private void gcspyGatherData(int event) {
132 if(DEBUG) {
133 Log.writeln("SSGCspyCollector.gcspyGatherData, event=", event);
134 Log.writeln("SSGCspyCollector.gcspyGatherData, port=", GCspy.getGCspyPort());
135 }
136
137 // If port = 0 there can be no GCspy client connected
138 if (GCspy.getGCspyPort() == 0)
139 return;
140
141 // If the server is connected to a client that is interested in this
142 // event, then we gather data. But first we start a timer to
143 // compensate for the time spent gathering data here.
144 if (GCspy.server.isConnected(event)) {
145
146 if (DEBUG) {
147 if (SSGCspy.hi)
148 Log.write("\nCollector Examining Lowspace (event ", event);
149 else
150 Log.write("\nCollector Examining Highspace (event ", event);
151 Log.write(")");
152 SSGCspy.reportSpaces(); Log.writeln();
153 }
154
155 if (event == SSGCspy.BEFORE_COLLECTION) {
156 if (DEBUG) debugSpaces(SSGCspy.fromSpace());
157
158 // Just send the old values again
159 if (DEBUG) {
160 Log.write("SSGCspyCollector.gcspyGatherData transmit driver, ");
161 Log.writeln(SSGCspy.fromSpace().getName());
162 }
163
164 fromSpaceDriver().transmit(event);
165 // Mutator.gcspyGatherData follows so leave safepoint to there.
166 } else if (event == SSGCspy.SEMISPACE_COPIED) {
167 if (DEBUG) debugSpaces(SSGCspy.toSpace());
168
169 // We need to reset, scan and send values for tospace
170 // We'll leave resetting fromspace to AFTER_COLLECTION
171 if (DEBUG) {
172 Log.write("SSGCspyCollector.gcspyGatherData reset, gather and transmit driver ");
173 Log.writeln(SSGCspy.toSpace().getName());
174 }
175
176 GCspy.server.startCompensationTimer();
177 toSpaceDriver().resetData();
178 ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace());
179 GCspy.server.stopCompensationTimer();
180 toSpaceDriver().transmit(event);
181
182 // We'll leave the safepoint to RELEASE
183 } else if (event == SSGCspy.AFTER_COLLECTION) {
184 if (DEBUG) {
185 Log.write("SSGCspyCollector.gcspyGatherData transmit toSpaceDriver, ");
186 Log.writeln(SSGCspy.toSpace().getName());
187 Log.write("SSGCspyCollector.gcspyGatherData reset fromSpaceDriver, ");
188 Log.writeln(SSGCspy.fromSpace().getName());
189 }
190
191 toSpaceDriver().transmit(event);
192
193 // Here we reset fromspace data
194 fromSpaceDriver().resetData();
195 Address start = SSGCspy.fromSpace().getStart();
196 fromSpaceDriver().setRange(start, start);
197 fromSpaceDriver().transmit(event);
198 }
199
200 }
201 // else Log.write("not transmitting...");
202 }
203
204 /**
205 * Print some debugging info
206 * @param scannedSpace
207 */
208 private void debugSpaces(CopySpace scannedSpace) {
209 Log.write("SSGCspyCollector.gcspyGatherData: gather data for active semispace ");
210 Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush();
211 Log.write(". The space is: "); Log.writeln(ss.getSpace().getName());
212 Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName());
213 Log.write("The range is "); Log.write(ss.getSpace().getStart());
214 Log.write(" to "); Log.writeln(ss.getCursor());
215 SSGCspy.reportSpaces();
216 }
217
218 /**
219 * Reset all root streams.<p>
220 */
221 void resetRootStreams() {
222 SSGCspy.ss0Driver.resetRootsStream();
223 SSGCspy.ss1Driver.resetRootsStream();
224 SSGCspy.immortalDriver.resetRootsStream();
225 SSGCspy.losNurseryDriver.resetRootsStream();
226 SSGCspy.losDriver.resetRootsStream();
227 SSGCspy.plosNurseryDriver.resetRootsStream();
228 SSGCspy.plosDriver.resetRootsStream();
229 ss.getCursor();
230 }
231
232 /**
233 * Pass a root to all drivers.<p>
234 * @param addr The Address of the object to be checked
235 */
236 protected void checkAllDriversForRootAddress(Address addr) {
237 if(addr.isZero())
238 return;
239
240 SSGCspy.ss0Driver.handleRoot(addr);
241 SSGCspy.ss1Driver.handleRoot(addr);
242 SSGCspy.immortalDriver.handleRoot(addr);
243 SSGCspy.losNurseryDriver.handleRoot(addr);
244 SSGCspy.losDriver.handleRoot(addr);
245 SSGCspy.plosNurseryDriver.handleRoot(addr);
246 SSGCspy.plosDriver.handleRoot(addr);
247 }
248
249 /****************************************************************************
250 *
251 * Miscellaneous
252 */
253
254 /** @return The active global plan as an <code>SSGCspy</code> instance. */
255 @Inline
256 private static SSGCspy global() {
257 return (SSGCspy) VM.activePlan.global();
258 }
259
260 /** @return the driver for toSpace */
261 private LinearSpaceDriver toSpaceDriver() {
262 return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver;
263 }
264
265 /** @return the driver for fromSpace */
266 private LinearSpaceDriver fromSpaceDriver() {
267 return SSGCspy.hi ? SSGCspy.ss0Driver : SSGCspy.ss1Driver;
268 }
269 }