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.semispace.gcspy; 014 015import org.mmtk.plan.Phase; 016import org.mmtk.plan.semispace.SS; 017import org.mmtk.plan.semispace.SSCollector; 018import org.mmtk.policy.CopySpace; 019import org.mmtk.utility.Log; 020import org.mmtk.utility.gcspy.GCspy; 021import org.mmtk.utility.gcspy.drivers.LinearSpaceDriver; 022import org.mmtk.vm.VM; 023 024import org.vmmagic.unboxed.*; 025import 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. 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) { 089 Log.write("--Phase Collector."); 090 Log.writeln(Phase.getName(phaseId)); 091 } 092 093 //TODO do we need to worry any longer about primary?? 094 if (phaseId == SS.PREPARE) { 095 //if (primary) 096 gcspyGatherData(SSGCspy.BEFORE_COLLECTION); 097 super.collectionPhase(phaseId, primary); 098 return; 099 } 100 101 if (phaseId == SS.FORWARD_FINALIZABLE) { 102 super.collectionPhase(phaseId, primary); 103 //if (primary) 104 gcspyGatherData(SSGCspy.SEMISPACE_COPIED); 105 return; 106 } 107 108 if (phaseId == SS.RELEASE) { 109 //if (primary) 110 //gcspyGatherData(SSGCspy.SEMISPACE_COPIED); 111 super.collectionPhase(phaseId, primary); 112 //if (primary) 113 gcspyGatherData(SSGCspy.AFTER_COLLECTION); 114 return; 115 } 116 117 super.collectionPhase(phaseId, primary); 118 } 119 120 /** 121 * Gather data for GCspy for the semispaces only. 122 * <p> 123 * This method sweeps the semispace under consideration to gather data. 124 * Alternatively and more efficiently, 'used space' can obviously be 125 * discovered in constant time simply by comparing the start and the end 126 * addresses of the semispace. However, per-object information can only be 127 * gathered by sweeping through the space and we do this here for tutorial 128 * purposes. 129 * 130 * @param event 131 * The event, either BEFORE_COLLECTION, SEMISPACE_COPIED or 132 * AFTER_COLLECTION 133 */ 134 private void gcspyGatherData(int event) { 135 if (DEBUG) { 136 Log.writeln("SSGCspyCollector.gcspyGatherData, event=", event); 137 Log.writeln("SSGCspyCollector.gcspyGatherData, port=", GCspy.getGCspyPort()); 138 } 139 140 // If port = 0 there can be no GCspy client connected 141 if (GCspy.getGCspyPort() == 0) 142 return; 143 144 // If the server is connected to a client that is interested in this 145 // event, then we gather data. But first we start a timer to 146 // compensate for the time spent gathering data here. 147 if (GCspy.server.isConnected(event)) { 148 149 if (DEBUG) { 150 if (SSGCspy.hi) 151 Log.write("\nCollector Examining Lowspace (event ", event); 152 else 153 Log.write("\nCollector Examining Highspace (event ", event); 154 Log.write(")"); 155 SSGCspy.reportSpaces(); Log.writeln(); 156 } 157 158 if (event == SSGCspy.BEFORE_COLLECTION) { 159 if (DEBUG) debugSpaces(SSGCspy.fromSpace()); 160 161 // Just send the old values again 162 if (DEBUG) { 163 Log.write("SSGCspyCollector.gcspyGatherData transmit driver, "); 164 Log.writeln(SSGCspy.fromSpace().getName()); 165 } 166 167 fromSpaceDriver().transmit(event); 168 // Mutator.gcspyGatherData follows so leave safepoint to there. 169 } else if (event == SSGCspy.SEMISPACE_COPIED) { 170 if (DEBUG) debugSpaces(SSGCspy.toSpace()); 171 172 // We need to reset, scan and send values for tospace 173 // We'll leave resetting fromspace to AFTER_COLLECTION 174 if (DEBUG) { 175 Log.write("SSGCspyCollector.gcspyGatherData reset, gather and transmit driver "); 176 Log.writeln(SSGCspy.toSpace().getName()); 177 } 178 179 GCspy.server.startCompensationTimer(); 180 toSpaceDriver().resetData(); 181 ss.gcspyGatherData(toSpaceDriver(), SSGCspy.toSpace()); 182 GCspy.server.stopCompensationTimer(); 183 toSpaceDriver().transmit(event); 184 185 // We'll leave the safepoint to RELEASE 186 } else if (event == SSGCspy.AFTER_COLLECTION) { 187 if (DEBUG) { 188 Log.write("SSGCspyCollector.gcspyGatherData transmit toSpaceDriver, "); 189 Log.writeln(SSGCspy.toSpace().getName()); 190 Log.write("SSGCspyCollector.gcspyGatherData reset fromSpaceDriver, "); 191 Log.writeln(SSGCspy.fromSpace().getName()); 192 } 193 194 toSpaceDriver().transmit(event); 195 196 // Here we reset fromspace data 197 fromSpaceDriver().resetData(); 198 Address start = SSGCspy.fromSpace().getStart(); 199 fromSpaceDriver().setRange(start, start); 200 fromSpaceDriver().transmit(event); 201 } 202 203 } 204 // else Log.write("not transmitting..."); 205 } 206 207 /** 208 * Prints some debugging info. 209 * @param scannedSpace the space that was scanned 210 */ 211 private void debugSpaces(CopySpace scannedSpace) { 212 Log.write("SSGCspyCollector.gcspyGatherData: gather data for active semispace "); 213 Log.write(scannedSpace.getStart()); Log.write("-",ss.getCursor()); Log.flush(); 214 Log.write(". The space is: "); Log.writeln(ss.getSpace().getName()); 215 Log.write("scannedSpace is "); Log.writeln(scannedSpace.getName()); 216 Log.write("The range is "); Log.write(ss.getSpace().getStart()); 217 Log.write(" to "); Log.writeln(ss.getCursor()); 218 SSGCspy.reportSpaces(); 219 } 220 221 /** 222 * Reset all root streams. 223 */ 224 void resetRootStreams() { 225 SSGCspy.ss0Driver.resetRootsStream(); 226 SSGCspy.ss1Driver.resetRootsStream(); 227 SSGCspy.immortalDriver.resetRootsStream(); 228 SSGCspy.losNurseryDriver.resetRootsStream(); 229 SSGCspy.losDriver.resetRootsStream(); 230 SSGCspy.plosNurseryDriver.resetRootsStream(); 231 SSGCspy.plosDriver.resetRootsStream(); 232 ss.getCursor(); 233 } 234 235 /** 236 * Pass a root to all drivers.<p> 237 * @param addr The Address of the object to be checked 238 */ 239 protected void checkAllDriversForRootAddress(Address addr) { 240 if (addr.isZero()) 241 return; 242 243 SSGCspy.ss0Driver.handleRoot(addr); 244 SSGCspy.ss1Driver.handleRoot(addr); 245 SSGCspy.immortalDriver.handleRoot(addr); 246 SSGCspy.losNurseryDriver.handleRoot(addr); 247 SSGCspy.losDriver.handleRoot(addr); 248 SSGCspy.plosNurseryDriver.handleRoot(addr); 249 SSGCspy.plosDriver.handleRoot(addr); 250 } 251 252 /**************************************************************************** 253 * 254 * Miscellaneous 255 */ 256 257 /** @return The active global plan as an <code>SSGCspy</code> instance. */ 258 @Inline 259 private static SSGCspy global() { 260 return (SSGCspy) VM.activePlan.global(); 261 } 262 263 /** @return the driver for toSpace */ 264 private LinearSpaceDriver toSpaceDriver() { 265 return SSGCspy.hi ? SSGCspy.ss1Driver : SSGCspy.ss0Driver; 266 } 267 268 /** @return the driver for fromSpace */ 269 private LinearSpaceDriver fromSpaceDriver() { 270 return SSGCspy.hi ? SSGCspy.ss0Driver : SSGCspy.ss1Driver; 271 } 272}