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.utility.gcspy.drivers; 014 015 import org.mmtk.policy.LargeObjectSpace; 016 import org.mmtk.utility.gcspy.Color; 017 import org.mmtk.utility.gcspy.StreamConstants; 018 import org.mmtk.utility.gcspy.Subspace; 019 import org.mmtk.vm.gcspy.IntStream; 020 import org.mmtk.vm.gcspy.ShortStream; 021 import org.mmtk.vm.gcspy.ServerInterpreter; 022 import org.mmtk.utility.Conversions; 023 import org.mmtk.utility.Log; 024 import org.mmtk.vm.VM; 025 026 import org.vmmagic.unboxed.*; 027 import org.vmmagic.pragma.*; 028 029 030 /** 031 * This class implements a simple driver for the MMTk LargeObjectSpace. 032 */ 033 @Uninterruptible public class TreadmillDriver extends AbstractDriver { 034 035 private static final boolean DEBUG = false; 036 037 // The streams 038 protected IntStream usedSpaceStream; 039 protected ShortStream objectsStream; 040 protected ShortStream rootsStream; 041 protected ShortStream refFromImmortalStream; 042 043 protected Subspace subspace; // A single subspace for this space 044 protected int allTileNum; // total number of tiles 045 046 // Overall statistics 047 protected int totalObjects = 0; // total number of objects allocated 048 protected int totalUsedSpace = 0; // total space used 049 protected int totalRoots = 0; // total of roots 050 protected int totalRefFromImmortal = 0; // total direct references from the immortal space 051 protected Address maxAddr; // the largest address seen 052 protected int threshold; 053 054 055 /** 056 * Create a new driver for this collector 057 * 058 * @param server The name of the GCspy server that owns this space 059 * @param spaceName The name of this driver 060 * @param lospace the large object space for this allocator 061 * @param blockSize The tile size 062 * @param threshold the size threshold of the LOS 063 * @param mainSpace Is this the main space? 064 */ 065 public TreadmillDriver( 066 ServerInterpreter server, 067 String spaceName, 068 LargeObjectSpace lospace, 069 int blockSize, 070 int threshold, 071 boolean mainSpace) { 072 //TODO blocksize should be a multiple of treadmill granularity 073 super(server, spaceName, lospace, blockSize, mainSpace); 074 075 if (DEBUG) { 076 Log.write("TreadmillDriver for "); Log.write(spaceName); 077 Log.write(", blocksize="); Log.write(blockSize); 078 Log.write(", start="); Log.write(lospace.getStart()); 079 Log.write(", extent="); Log.write(lospace.getExtent()); 080 Log.write(", maxTileNum="); Log.writeln(maxTileNum); 081 } 082 083 this.threshold = threshold; 084 085 // Initialise a subspace and 2 Streams 086 subspace = createSubspace(lospace); 087 allTileNum = 0; 088 maxAddr = lospace.getStart(); 089 usedSpaceStream = createUsedSpaceStream(); 090 objectsStream = createObjectsStream(); 091 rootsStream = createRootsStream(); 092 refFromImmortalStream = createRefFromImmortalStream(); 093 serverSpace.resize(0); // the collector must call resize() before gathering data 094 095 // Initialise the statistics 096 resetData(); 097 } 098 099 /** 100 * @return The name, "MMTk TreadmillDriver" for this driver. 101 */ 102 @Override 103 protected String getDriverName() { 104 return "MMTk TreadmillDriver"; 105 } 106 107 // private creator methods for the streams 108 @Interruptible 109 private IntStream createUsedSpaceStream() { 110 return VM.newGCspyIntStream( 111 this, 112 "Used Space stream", // stream name 113 0, // min. data value 114 blockSize, // max. data value 115 0, // zero value 116 0, // default value 117 "Space used: ", // value prefix 118 " bytes", // value suffix 119 StreamConstants.PRESENTATION_PERCENT, // presentation style 120 StreamConstants.PAINT_STYLE_ZERO, // paint style 121 0, // index of the max stream (only needed if presentation is *_VAR) 122 Color.Red, // tile colour 123 true); // summary enabled 124 } 125 126 @Interruptible 127 private ShortStream createObjectsStream() { 128 return VM.newGCspyShortStream( 129 this, 130 "Objects stream", 131 (short)0, 132 (short)(blockSize/threshold), 133 (short)0, 134 (short)0, 135 "No. of objects = ", 136 " objects", 137 StreamConstants.PRESENTATION_PLUS, 138 StreamConstants.PAINT_STYLE_ZERO, 139 0, 140 Color.Green, 141 true); 142 } 143 144 @Interruptible 145 private ShortStream createRootsStream() { 146 return VM.newGCspyShortStream( 147 this, 148 "Roots stream", 149 (short)0, 150 // Say, typical size = 4 * typical scalar size? 151 (short)(maxObjectsPerBlock(blockSize)/8), 152 (short)0, 153 (short)0, 154 "Roots: ", 155 " objects", 156 StreamConstants.PRESENTATION_PLUS, 157 StreamConstants.PAINT_STYLE_ZERO, 158 0, 159 Color.Blue, 160 true); 161 } 162 163 @Interruptible 164 private ShortStream createRefFromImmortalStream() { 165 return VM.newGCspyShortStream( 166 this, 167 "References from Immortal stream", 168 (short)0, 169 // Say, typical size = 4 * typical scalar size? 170 (short)(maxObjectsPerBlock(blockSize)/8), 171 (short)0, 172 (short)0, 173 "References from immortal space: ", 174 " references", 175 StreamConstants.PRESENTATION_PLUS, 176 StreamConstants.PAINT_STYLE_ZERO, 177 0, 178 Color.Blue, 179 true); 180 } 181 182 /** 183 * Reset the tile stats for all streams, including values used for summaries 184 */ 185 @Override 186 public void resetData() { 187 super.resetData(); 188 189 // Reset all the streams 190 usedSpaceStream.resetData(); 191 objectsStream.resetData(); 192 refFromImmortalStream.resetData(); 193 194 // Reset the summary counts 195 totalUsedSpace = 0; 196 totalObjects = 0; 197 totalRefFromImmortal = 0; 198 } 199 200 201 /** 202 * Update the tile statistics 203 * In this case, we are accounting for super-page objects, rather than 204 * simply for the objects they contain. 205 * 206 * @param addr The address of the superpage 207 */ 208 @Override 209 public void scan(Address addr) { 210 211 int index = subspace.getIndex(addr); 212 int length = ((LargeObjectSpace)mmtkSpace).getSize(addr).toInt(); 213 214 if (DEBUG) { 215 Log.write("TreadmillDriver: super=", addr); 216 Log.write(", index=", index); 217 Log.write(", pages=", length); 218 Log.write(", bytes=", Conversions.pagesToBytes(length).toInt()); 219 Log.writeln(", max=", usedSpaceStream.getMaxValue()); 220 } 221 222 totalObjects++; 223 totalUsedSpace += length; 224 objectsStream.increment(index, (short)1); 225 int remainder = subspace.spaceRemaining(addr); 226 usedSpaceStream.distribute(index, remainder, blockSize, length); 227 228 Address tmp = addr.plus(length); 229 if (tmp.GT(maxAddr)) maxAddr = tmp; 230 } 231 232 /** 233 * Transmit the data if this event is of interest to the client 234 * @param event The event, either BEFORE_COLLECTION, SEMISPACE_COPIED 235 * or AFTER_COLLECTION 236 */ 237 @Override 238 public void transmit(int event) { 239 if (!isConnected(event)) 240 return; 241 242 // At this point, we've filled the tiles with data, 243 // however, we don't know the size of the space 244 // Calculate the highest indexed tile used so far, and update the subspace 245 Address start = subspace.getStart(); 246 int required = countTileNum(start, maxAddr, blockSize); 247 int current = subspace.getBlockNum(); 248 if (required > current || maxAddr != subspace.getEnd()) { 249 subspace.reset(start, maxAddr, 0, required); 250 allTileNum = required; 251 serverSpace.resize(allTileNum); 252 setTilenames(subspace, allTileNum); 253 } 254 255 // Set the summaries 256 setupSummaries(); 257 258 // set the control info: all of space is USED 259 controlValues(CONTROL_USED, 260 subspace.getFirstIndex(), subspace.getBlockNum()); 261 262 // send the space info 263 Offset size = subspace.getEnd().diff(subspace.getStart()); 264 setSpaceInfo(size); 265 266 // Send the streams 267 send(event, allTileNum); 268 } 269 270 /** 271 * Setup summaries part of the <code>transmit</code> method.<p> 272 * Override this method to setup summaries of additional streams in subclasses. 273 */ 274 protected void setupSummaries() { 275 usedSpaceStream.setSummary(totalUsedSpace, 276 subspace.getEnd().diff(subspace.getStart()).toInt()); 277 objectsStream.setSummary(totalObjects); 278 rootsStream.setSummary(totalRoots); 279 refFromImmortalStream.setSummary(totalRefFromImmortal); 280 } 281 282 283 /** 284 * Handle a root address 285 * 286 * @param addr Root Address 287 * @return {@code true} if the given Address is in this subspace. 288 */ 289 public boolean handleRoot(Address addr) { 290 if(subspace.addressInRange(addr)) { 291 // increment tile 292 int index = subspace.getIndex(addr); 293 rootsStream.increment(index, (short)1); 294 // increment summary 295 this.totalRoots++; 296 return true; 297 } else { 298 return false; 299 } 300 } 301 302 /** 303 * Reset the roots Stream. <br> 304 * The roots Stream has to be reset separately because we do not 305 * gather data in the usual way using <code>scan()</code>. 306 */ 307 public void resetRootsStream() { 308 rootsStream.resetData(); 309 totalRoots = 0; 310 } 311 312 /** 313 * Handle a direct reference from the immortal space. 314 * 315 * @param addr The Address 316 * @return {@code true} if the given Address is in this subspace. 317 */ 318 @Override 319 public boolean handleReferenceFromImmortalSpace(Address addr) { 320 if(subspace.addressInRange(addr)) { 321 // increment tile 322 int index = subspace.getIndex(addr); 323 refFromImmortalStream.increment(index, (short)1); 324 // increment summary 325 this.totalRefFromImmortal++; 326 return true; 327 } else { 328 return false; 329 } 330 } 331 }