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 }