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