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.policy; 014 015 import org.mmtk.plan.TraceLocal; 016 import org.mmtk.plan.TransitiveClosure; 017 import org.mmtk.utility.alloc.BumpPointer; 018 import org.mmtk.utility.heap.*; 019 import org.mmtk.utility.Constants; 020 import org.mmtk.utility.Log; 021 022 import org.mmtk.vm.Lock; 023 import org.mmtk.vm.VM; 024 025 import org.vmmagic.unboxed.*; 026 import org.vmmagic.pragma.*; 027 028 /** 029 * This class implements functionality for a simple sliding mark-compact 030 * space. 031 */ 032 @Uninterruptible public final class MarkCompactSpace extends Space 033 implements Constants { 034 035 /**************************************************************************** 036 * 037 * Class variables 038 */ 039 040 /** 041 * 042 */ 043 public static final int LOCAL_GC_BITS_REQUIRED = 1; 044 public static final int GLOBAL_GC_BITS_REQUIRED = 0; 045 public static final int GC_HEADER_WORDS_REQUIRED = 1; 046 047 private static final Word GC_MARK_BIT_MASK = Word.one(); 048 private static final Offset FORWARDING_POINTER_OFFSET = VM.objectModel.GC_HEADER_OFFSET(); 049 050 private static final Lock lock = VM.newLock("mcSpace"); 051 052 /** The list of occupied regions */ 053 private Address regionList = Address.zero(); 054 055 // TODO - maintain a separate list of partially allocated regions 056 // for threads to allocate into immediately after a collection. 057 058 /**************************************************************************** 059 * 060 * Instance variables 061 */ 062 063 /**************************************************************************** 064 * 065 * Initialization 066 */ 067 068 /** 069 * The caller specifies the region of virtual memory to be used for 070 * this space. If this region conflicts with an existing space, 071 * then the constructor will fail. 072 * 073 * @param name The name of this space (used when printing error messages etc) 074 * @param vmRequest An object describing the virtual memory requested. 075 */ 076 public MarkCompactSpace(String name, VMRequest vmRequest) { 077 super(name, true, false, true, vmRequest); 078 if (vmRequest.isDiscontiguous()) { 079 pr = new FreeListPageResource(this, 0); 080 } else { 081 pr = new FreeListPageResource(this, start, extent, 0); 082 } 083 } 084 085 /** 086 * Prepare for a collection 087 */ 088 public void prepare() { 089 } 090 091 /** 092 * Release after a collection 093 */ 094 public void release() { 095 // nothing to do 096 } 097 098 099 /** 100 * {@inheritDoc}<p> 101 * 102 * In this case we do nothing ecause we only release pages enmasse. 103 */ 104 @Override 105 @Inline 106 public void release(Address start) { 107 ((FreeListPageResource)pr).releasePages(start); 108 } 109 110 /** 111 * Trace an object under a copying collection policy. 112 * If the object is already copied, the copy is returned. 113 * Otherwise, a copy is created and returned. 114 * In either case, the object will be marked on return. 115 * 116 * @param trace The trace being conducted. 117 * @param object The object to be forwarded. 118 * @return The forwarded object. 119 */ 120 @Override 121 @Inline 122 public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) { 123 if (VM.VERIFY_ASSERTIONS) 124 VM.assertions._assert(false); 125 return null; 126 } 127 128 /** 129 * Trace an object under a copying collection policy. 130 * If the object is already copied, the copy is returned. 131 * Otherwise, a copy is created and returned. 132 * In either case, the object will be marked on return. 133 * 134 * @param trace The trace being conducted. 135 * @param object The object to be forwarded. 136 * @return The forwarded object. 137 */ 138 @Inline 139 public ObjectReference traceMarkObject(TraceLocal trace, ObjectReference object) { 140 if (MarkCompactCollector.VERY_VERBOSE) { 141 Log.write("marking "); Log.write(object); 142 } 143 if (testAndMark(object)) { 144 trace.processNode(object); 145 } else if (!getForwardingPointer(object).isNull()) { 146 if (MarkCompactCollector.VERY_VERBOSE) { 147 Log.write(" -> "); Log.writeln(getForwardingPointer(object)); 148 } 149 return getForwardingPointer(object); 150 } 151 if (MarkCompactCollector.VERY_VERBOSE) { 152 Log.writeln(); 153 } 154 return object; 155 } 156 157 /** 158 * Trace an object under a copying collection policy. 159 * If the object is already copied, the copy is returned. 160 * Otherwise, a copy is created and returned. 161 * In either case, the object will be marked on return. 162 * 163 * @param trace The trace being conducted. 164 * @param object The object to be forwarded. 165 * @return The forwarded object. 166 */ 167 @Inline 168 public ObjectReference traceForwardObject(TraceLocal trace, ObjectReference object) { 169 if (testAndClearMark(object)) { 170 trace.processNode(object); 171 } 172 ObjectReference newObject = getForwardingPointer(object); 173 if (MarkCompactCollector.VERY_VERBOSE) { 174 Log.write("forwarding "); Log.write(object); 175 Log.write(" -> "); Log.writeln(newObject); 176 } 177 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!newObject.isNull()); 178 return getForwardingPointer(object); 179 } 180 181 @Override 182 public boolean isLive(ObjectReference object) { 183 return isMarked(object); 184 } 185 186 @Override 187 public boolean isReachable(ObjectReference object) { 188 return isMarked(object); 189 } 190 191 192 /**************************************************************************** 193 * 194 * Header manipulation 195 */ 196 197 /** 198 * Perform any required post-allocation initialization 199 * 200 * <i>Nothing to be done in this case</i> 201 * 202 * @param object the object ref to the storage to be initialized 203 */ 204 @Inline 205 public void postAlloc(ObjectReference object) { 206 } 207 208 /** 209 * Non-atomic read of forwarding pointer 210 * 211 * @param object The object whose forwarding pointer is to be read 212 * @return The forwarding pointer stored in <code>object</code>'s 213 * header. 214 */ 215 @Inline 216 public static ObjectReference getForwardingPointer(ObjectReference object) { 217 return object.toAddress().loadObjectReference(FORWARDING_POINTER_OFFSET); 218 } 219 220 /** 221 * Initialise the header of the object. 222 * 223 * @param object The object to initialise 224 */ 225 @Inline 226 public void initializeHeader(ObjectReference object) { 227 // nothing to do 228 } 229 230 /** 231 * Used to mark boot image objects during a parallel scan of objects 232 * during GC. 233 * 234 * @param object The object to be marked 235 * @return {@code true} if marking was done. 236 */ 237 @Inline 238 public static boolean testAndMark(ObjectReference object) { 239 Word oldValue; 240 do { 241 oldValue = VM.objectModel.prepareAvailableBits(object); 242 Word markBit = oldValue.and(GC_MARK_BIT_MASK); 243 if (!markBit.isZero()) return false; 244 } while (!VM.objectModel.attemptAvailableBits(object, oldValue, 245 oldValue.or(GC_MARK_BIT_MASK))); 246 return true; 247 } 248 249 /** 250 * Used to mark boot image objects during a parallel scan of objects 251 * during GC Returns true if marking was done. 252 * 253 * @param object The object to be marked 254 */ 255 @Inline 256 public static boolean isMarked(ObjectReference object) { 257 Word oldValue = VM.objectModel.readAvailableBitsWord(object); 258 Word markBit = oldValue.and(GC_MARK_BIT_MASK); 259 return (!markBit.isZero()); 260 } 261 262 /** 263 * Used to mark boot image objects during a parallel scan of objects 264 * during GC Returns true if marking was done. 265 * 266 * @param object The object to be marked 267 */ 268 @Inline 269 private static boolean testAndClearMark(ObjectReference object) { 270 Word oldValue; 271 do { 272 oldValue = VM.objectModel.prepareAvailableBits(object); 273 Word markBit = oldValue.and(GC_MARK_BIT_MASK); 274 if (markBit.isZero()) return false; 275 } while (!VM.objectModel.attemptAvailableBits(object, oldValue, 276 oldValue.and(GC_MARK_BIT_MASK.not()))); 277 return true; 278 } 279 280 281 /** 282 * Used to mark boot image objects during a parallel scan of objects 283 * during GC Returns true if marking was done. 284 * 285 * @param object The object to be marked 286 */ 287 @Inline 288 public static boolean toBeCompacted(ObjectReference object) { 289 Word oldValue = VM.objectModel.readAvailableBitsWord(object); 290 Word markBit = oldValue.and(GC_MARK_BIT_MASK); 291 return !markBit.isZero() && getForwardingPointer(object).isNull(); 292 } 293 294 /** 295 * Used to mark boot image objects during a parallel scan of objects 296 * during GC Returns true if marking was done. 297 * 298 * @param object The object to be marked 299 */ 300 @Inline 301 public static void clearMark(ObjectReference object) { 302 Word oldValue = VM.objectModel.readAvailableBitsWord(object); 303 VM.objectModel.writeAvailableBitsWord(object, oldValue.and(GC_MARK_BIT_MASK.not())); 304 } 305 306 /** 307 * Non-atomic write of forwarding pointer word (assumption, thread 308 * doing the set has done attempt to forward and owns the right to 309 * copy the object) 310 * 311 * @param object The object whose forwarding pointer is to be set 312 * @param ptr The forwarding pointer to be stored in the object's 313 * forwarding word 314 */ 315 @Inline 316 public static void setForwardingPointer(ObjectReference object, 317 ObjectReference ptr) { 318 object.toAddress().store(ptr.toAddress(), FORWARDING_POINTER_OFFSET); 319 } 320 321 /** 322 * Non-atomic clear of forwarding pointer word (assumption, thread 323 * doing the set has done attempt to forward and owns the right to 324 * copy the object) 325 * 326 * @param object The object whose forwarding pointer is to be set 327 */ 328 @Inline 329 public static void clearForwardingPointer(ObjectReference object) { 330 object.toAddress().store(Address.zero(), FORWARDING_POINTER_OFFSET); 331 } 332 333 /** 334 * @return A region of this space that has net yet been compacted during 335 * the current collection 336 */ 337 public Address getNextRegion() { 338 lock.acquire(); 339 if (regionList.isZero()) { 340 lock.release(); 341 return Address.zero(); 342 } 343 Address result = regionList; 344 regionList = BumpPointer.getNextRegion(regionList); 345 BumpPointer.clearNextRegion(result); 346 lock.release(); 347 return result; 348 } 349 350 /** 351 * Append a region or list of regions to the global list 352 * @param region 353 */ 354 public void append(Address region) { 355 lock.acquire(); 356 if (MarkCompactCollector.VERBOSE) { 357 Log.write("Appending region "); Log.write(region); 358 Log.writeln(" to global list"); 359 } 360 if (regionList.isZero()) { 361 regionList = region; 362 } else { 363 appendRegion(regionList,region); 364 } 365 lock.release(); 366 } 367 368 public static void appendRegion(Address listHead, Address region) { 369 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!listHead.isZero()); 370 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!region.isZero()); 371 Address cursor = listHead; 372 while (!BumpPointer.getNextRegion(cursor).isZero()) { 373 cursor = BumpPointer.getNextRegion(cursor); 374 } 375 BumpPointer.setNextRegion(cursor,region); 376 } 377 }