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.jikesrvm.mm.mmtk; 014 015 import org.mmtk.plan.Plan; 016 import org.mmtk.plan.TraceLocal; 017 import org.mmtk.utility.options.Options; 018 019 import org.vmmagic.pragma.*; 020 import org.vmmagic.unboxed.*; 021 022 import org.jikesrvm.VM; 023 import org.jikesrvm.mm.mminterface.DebugUtil; 024 import org.jikesrvm.mm.mminterface.Selected; 025 import org.jikesrvm.runtime.Entrypoints; 026 import org.jikesrvm.runtime.Magic; 027 import org.jikesrvm.scheduler.RVMThread; 028 029 import java.lang.ref.Reference; 030 import java.lang.ref.SoftReference; 031 import java.lang.ref.WeakReference; 032 import java.lang.ref.PhantomReference; 033 034 035 /** 036 * This class manages SoftReferences, WeakReferences, and 037 * PhantomReferences. When a java/lang/ref/Reference object is created, 038 * its address is added to a table of pending reference objects of the 039 * appropriate type. An address is used so the reference will not stay 040 * alive during GC if it isn't in use elsewhere the mutator. During 041 * GC, the various lists are processed in the proper order to 042 * determine if any Reference objects are ready to be enqueued or 043 * whether referents that have died should be kept alive until the 044 * Reference is explicitly cleared. MMTk drives this processing and 045 * uses this class, via the VM interface, to scan the lists of pending 046 * reference objects. 047 * <p> 048 * As an optimization for generational collectors, each reference type 049 * maintains two queues: a nursery queue and the main queue. 050 */ 051 @Uninterruptible 052 public final class ReferenceProcessor extends org.mmtk.vm.ReferenceProcessor { 053 054 /******************************************************************** 055 * Class fields 056 */ 057 058 private static final Lock lock = new Lock("ReferenceProcessor"); 059 060 private static final ReferenceProcessor softReferenceProcessor = 061 new ReferenceProcessor(Semantics.SOFT); 062 private static final ReferenceProcessor weakReferenceProcessor = 063 new ReferenceProcessor(Semantics.WEAK); 064 private static final ReferenceProcessor phantomReferenceProcessor = 065 new ReferenceProcessor(Semantics.PHANTOM); 066 067 // Debug flags 068 private static final boolean TRACE = false; 069 private static final boolean TRACE_UNREACHABLE = false; 070 private static final boolean TRACE_DETAIL = false; 071 private static final boolean STRESS = false || VM.ForceFrequentGC; 072 073 /** Initial size of the reference object table */ 074 private static final int INITIAL_SIZE = STRESS ? 1 : 256; 075 076 /** 077 * Grow the reference object table by this multiplier 078 * on overflow 079 */ 080 private static final double GROWTH_FACTOR = 2.0; 081 082 083 /************************************************************************* 084 * Instance fields 085 */ 086 087 /** 088 * The table of reference objects for the current semantics 089 */ 090 private volatile AddressArray references = AddressArray.create(INITIAL_SIZE); 091 092 /** 093 * In a MarkCompact (or similar) collector, we need to update the {@code references} 094 * field, and then update its contents. We implement this by saving the pointer in 095 * this untraced field for use during the {@code forward} pass. 096 */ 097 @Untraced 098 private volatile AddressArray unforwardedReferences = null; 099 100 /** 101 * Index into the <code>references</code> table for the start of 102 * the reference nursery. 103 */ 104 private int nurseryIndex = 0; 105 106 /** 107 * Index of the first free slot in the reference table. 108 */ 109 private volatile int maxIndex = 0; 110 111 /** 112 * Flag to prevent a race between threads growing the reference object 113 * table. 114 */ 115 private volatile boolean growingTable = false; 116 117 /** 118 * Semantics 119 */ 120 private final Semantics semantics; 121 122 /** Copy of semantics.toString() for use in uninterruptible code */ 123 private final String semanticsStr; 124 125 126 /** 127 * Create a reference processor for a given semantics 128 * 129 * @param semantics 130 */ 131 private ReferenceProcessor(Semantics semantics) { 132 this.semantics = semantics; 133 this.semanticsStr = semantics.toString(); 134 } 135 136 /** 137 * Factory method. 138 * Creates an instance of the appropriate reference type processor. 139 * @return the reference processor 140 */ 141 @Interruptible 142 public static ReferenceProcessor get(Semantics semantics) { 143 switch(semantics) { 144 case WEAK: return weakReferenceProcessor; 145 case SOFT: return softReferenceProcessor; 146 case PHANTOM: return phantomReferenceProcessor; 147 default: 148 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED,"Unrecognized semantics"); 149 return null; 150 } 151 } 152 153 /** 154 * Add a reference at the end of the table 155 * @param ref The reference to add 156 */ 157 private void addReference(Reference<?> ref, ObjectReference referent) { 158 ObjectReference reference = ObjectReference.fromObject(ref); 159 setReferent(reference, referent); 160 setReference(maxIndex++,reference); 161 } 162 163 /** 164 * Update the reference table 165 * 166 * @param i The table index 167 * @param ref The reference to insert 168 */ 169 private void setReference(int i, ObjectReference ref) { 170 if (TRACE_DETAIL) { 171 VM.sysWrite("slot ",i); 172 VM.sysWriteln(" => ",ref); 173 } 174 references.set(i,ref.toAddress()); 175 } 176 177 /** 178 * Retrieve from the reference table 179 * 180 * @param i Table index 181 * @return The reference object at index i 182 */ 183 private ObjectReference getReference(int i) { 184 return references.get(i).toObjectReference(); 185 } 186 187 /** 188 * Grow the reference table by GROWTH_FACTOR. 189 * 190 * <p>Logically Uninterruptible because it can GC when it allocates, but 191 * the rest of the code can't tolerate GC. 192 * 193 * <p>This method is called without the reference processor lock held, 194 * but with the flag <code>growingTable</code> set. 195 */ 196 @UninterruptibleNoWarn 197 private AddressArray growReferenceTable() { 198 int newLength = STRESS ? references.length() + 1 : (int)(references.length() * GROWTH_FACTOR); 199 if (TRACE) VM.sysWriteln("Expanding reference type table ",semanticsStr," to ",newLength); 200 AddressArray newReferences = AddressArray.create(newLength); 201 for (int i=0; i < references.length(); i++) 202 newReferences.set(i,references.get(i)); 203 return newReferences; 204 } 205 206 /** 207 * Add a reference to the list of references. This method is responsible 208 * for installing the address of the referent into the Reference object 209 * so that the referent is traced at all yield points before the Reference 210 * is correctly installed in the reference table. 211 * 212 * (SJF: This method must NOT be inlined into an inlined allocation 213 * sequence, since it contains a lock!) 214 * 215 * @param referent The referent of the reference 216 * @param ref The reference to add 217 */ 218 @NoInline 219 @Unpreemptible("Non-preemptible but yield when table needs to be grown") 220 private void addCandidate(Reference<?> ref, ObjectReference referent) { 221 if (TRACE) { 222 ObjectReference referenceAsAddress = ObjectReference.fromObject(ref); 223 VM.sysWrite("Adding Reference: ", referenceAsAddress); 224 VM.sysWriteln(" ~> ", referent); 225 } 226 227 /* 228 * Ensure that only one thread at a time can grow the 229 * table of references. The volatile flag <code>growingTable</code> is 230 * used to allow growing the table to trigger GC, but to prevent 231 * any other thread from accessing the table while it is being grown. 232 * 233 * If the table has space, threads will add the reference, incrementing maxIndex 234 * and exit. 235 * 236 * If the table is full, the first thread to notice will grow the table. 237 * Subsequent threads will release the lock and yield at (1) while the 238 * first thread 239 */ 240 lock.acquire(); 241 while (growingTable || maxIndex >= references.length()) { 242 if (growingTable) { 243 // FIXME: We should probably speculatively allocate a new table instead. 244 // note, we can copy without the lock after installing the new table (unint during copy). 245 lock.release(); 246 RVMThread.yieldWithHandshake(); // (1) Allow another thread to grow the table 247 lock.acquire(); 248 } else { 249 growingTable = true; // Prevent other threads from growing table while lock is released 250 lock.release(); // Can't hold the lock while allocating 251 AddressArray newTable = growReferenceTable(); 252 lock.acquire(); 253 references = newTable; 254 growingTable = false; // Allow other threads to grow the table rather than waiting for us 255 } 256 } 257 addReference(ref,referent); 258 lock.release(); 259 } 260 261 /*********************************************************************** 262 * GC time processing 263 */ 264 265 /** 266 * {@inheritDoc} 267 * <p> 268 * Collectors like MarkCompact determine liveness and move objects 269 * using separate traces. 270 * <p> 271 * Currently ignores the nursery hint. 272 * <p> 273 * TODO parallelise this code 274 * 275 */ 276 @Override 277 public void forward(TraceLocal trace, boolean nursery) { 278 if (VM.VerifyAssertions) VM._assert(unforwardedReferences != null); 279 if (TRACE) VM.sysWriteln("Starting ReferenceGlue.forward(",semanticsStr,")"); 280 if (TRACE_DETAIL) { 281 VM.sysWrite(semanticsStr," Reference table is ", 282 Magic.objectAsAddress(references)); 283 VM.sysWriteln("unforwardedReferences is ", 284 Magic.objectAsAddress(unforwardedReferences)); 285 } 286 for (int i=0; i < maxIndex; i++) { 287 if (TRACE_DETAIL) VM.sysWrite("slot ",i,": "); 288 ObjectReference reference = unforwardedReferences.get(i).toObjectReference(); 289 if (TRACE_DETAIL) VM.sysWriteln("forwarding ",reference); 290 setReferent(reference, trace.getForwardedReferent(getReferent(reference))); 291 ObjectReference newReference = trace.getForwardedReference(reference); 292 unforwardedReferences.set(i, newReference.toAddress()); 293 } 294 if (TRACE) VM.sysWriteln("Ending ReferenceGlue.forward(",semanticsStr,")"); 295 unforwardedReferences = null; 296 } 297 298 @Override 299 public void clear() { 300 maxIndex = 0; 301 } 302 303 /** 304 * {@inheritDoc} Calls ReferenceProcessor's 305 * processReference method for each reference and builds a new 306 * list of those references still active. 307 * <p> 308 * Depending on the value of <code>nursery</code>, we will either 309 * scan all references, or just those created since the last scan. 310 * <p> 311 * TODO parallelise this code 312 * 313 * @param nursery Scan only the newly created references 314 */ 315 @Override 316 public void scan(TraceLocal trace, boolean nursery) { 317 unforwardedReferences = references; 318 319 if (TRACE) VM.sysWriteln("Starting ReferenceGlue.scan(",semanticsStr,")"); 320 int toIndex = nursery ? nurseryIndex : 0; 321 322 if (TRACE_DETAIL) VM.sysWriteln(semanticsStr," Reference table is ",Magic.objectAsAddress(references)); 323 for (int fromIndex = toIndex; fromIndex < maxIndex; fromIndex++) { 324 ObjectReference reference = getReference(fromIndex); 325 326 /* Determine liveness (and forward if necessary) the reference */ 327 ObjectReference newReference = processReference(trace,reference); 328 if (!newReference.isNull()) { 329 setReference(toIndex++,newReference); 330 if (TRACE_DETAIL) { 331 int index = toIndex-1; 332 VM.sysWrite("SCANNED ",index); 333 VM.sysWrite(" ",references.get(index)); 334 VM.sysWrite(" -> "); 335 VM.sysWriteln(getReferent(references.get(index).toObjectReference())); 336 } 337 } 338 } 339 if (Options.verbose.getValue() >= 3) { 340 VM.sysWrite(semanticsStr); 341 VM.sysWriteln(" references: ",maxIndex," -> ",toIndex); 342 } 343 nurseryIndex = maxIndex = toIndex; 344 345 /* flush out any remset entries generated during the above activities */ 346 Selected.Mutator.get().flushRememberedSets(); 347 if (TRACE) VM.sysWriteln("Ending ReferenceGlue.scan(",semanticsStr,")"); 348 } 349 350 /** 351 * Put this Reference object on its ReferenceQueue (if it has one) 352 * when its referent is no longer sufficiently reachable. The 353 * definition of "reachable" is defined by the semantics of the 354 * particular subclass of Reference. The implementation of this 355 * routine is determined by the the implementation of 356 * java.lang.ref.ReferenceQueue in GNU classpath. It is in this 357 * class rather than the public Reference class to ensure that Jikes 358 * has a safe way of enqueueing the object, one that cannot be 359 * overridden by the application program. 360 * 361 * ************************ TODO ********************************* 362 * Change this so that we don't call reference.enqueue directly 363 * as this can be overridden by the user. 364 * *************************************************************** 365 * 366 * @see java.lang.ref.ReferenceQueue 367 * @param addr the address of the Reference object 368 * @return <code>true</code> if the reference was enqueued 369 */ 370 @Unpreemptible 371 public boolean enqueueReference(ObjectReference addr) { 372 Reference<?> reference = (Reference<?>)addr.toObject(); 373 return reference.enqueueInternal(); 374 } 375 376 /** 377 * Add a reference to the list of soft references. 378 * @param ref the SoftReference to add 379 */ 380 @Interruptible 381 public static void addSoftCandidate(SoftReference<?> ref, ObjectReference referent) { 382 softReferenceProcessor.addCandidate(ref, referent); 383 } 384 385 /** 386 * Add a reference to the list of weak references. 387 * @param ref the WeakReference to add 388 */ 389 @Interruptible 390 public static void addWeakCandidate(WeakReference<?> ref, ObjectReference referent) { 391 weakReferenceProcessor.addCandidate(ref, referent); 392 } 393 394 /** 395 * Add a reference to the list of phantom references. 396 * @param ref the PhantomReference to add 397 */ 398 @Interruptible 399 public static void addPhantomCandidate(PhantomReference<?> ref, ObjectReference referent) { 400 phantomReferenceProcessor.addCandidate(ref, referent); 401 } 402 403 /**************************************************************************** 404 * 405 * Semantics of reference types 406 * 407 */ 408 409 /** 410 * Process a reference with the current semantics. 411 * @param reference the address of the reference. This may or may not 412 * be the address of a heap object, depending on the VM. 413 * @param trace the thread local trace element. 414 */ 415 @UninterruptibleNoWarn("Call out to ReferenceQueue API") 416 public ObjectReference processReference(TraceLocal trace, ObjectReference reference) { 417 if (VM.VerifyAssertions) VM._assert(!reference.isNull()); 418 419 if (TRACE_DETAIL) { 420 VM.sysWrite("Processing reference: ",reference); 421 } 422 /* 423 * If the reference is dead, we're done with it. Let it (and 424 * possibly its referent) be garbage-collected. 425 */ 426 if (!trace.isLive(reference)) { 427 clearReferent(reference); // Too much paranoia ... 428 if (TRACE_UNREACHABLE) { VM.sysWriteln(" UNREACHABLE reference: ",reference); } 429 if (TRACE_DETAIL) { 430 VM.sysWriteln(" (unreachable)"); 431 } 432 return ObjectReference.nullReference(); 433 } 434 435 /* The reference object is live */ 436 ObjectReference newReference = trace.getForwardedReference(reference); 437 ObjectReference oldReferent = getReferent(reference); 438 439 if (TRACE_DETAIL) { 440 VM.sysWrite(" ~> ",oldReferent); 441 } 442 443 /* 444 * If the application has cleared the referent the Java spec says 445 * this does not cause the Reference object to be enqueued. We 446 * simply allow the Reference object to fall out of our 447 * waiting list. 448 */ 449 if (oldReferent.isNull()) { 450 if (TRACE_DETAIL) VM.sysWriteln(" (null referent)"); 451 return ObjectReference.nullReference(); 452 } 453 454 if (TRACE_DETAIL) VM.sysWrite(" => ",newReference); 455 456 if (semantics == Semantics.SOFT) { 457 /* 458 * Unless we've completely run out of memory, we keep 459 * softly reachable objects alive. 460 */ 461 if (!Plan.isEmergencyCollection()) { 462 if (TRACE_DETAIL) VM.sysWrite(" (soft) "); 463 trace.retainReferent(oldReferent); 464 } 465 } else if (semantics == Semantics.PHANTOM) { 466 /* 467 * The spec says we should forward the reference. Without unsafe uses of 468 * reflection, the application can't tell the difference whether we do or not, 469 * so we don't forward the reference. 470 */ 471 // trace.retainReferent(oldReferent); 472 } 473 474 if (trace.isLive(oldReferent)) { 475 if (VM.VerifyAssertions) { 476 if (!DebugUtil.validRef(oldReferent)) { 477 VM.sysWriteln("Error in old referent."); 478 DebugUtil.dumpRef(oldReferent); 479 VM.sysFail("Invalid reference"); 480 } 481 } 482 /* 483 * Referent is still reachable in a way that is as strong as 484 * or stronger than the current reference level. 485 */ 486 ObjectReference newReferent = trace.getForwardedReferent(oldReferent); 487 488 if (TRACE_DETAIL) VM.sysWriteln(" ~> ",newReferent); 489 490 if (VM.VerifyAssertions) { 491 if (!DebugUtil.validRef(newReferent)) { 492 VM.sysWriteln("Error forwarding reference object."); 493 DebugUtil.dumpRef(oldReferent); 494 VM.sysFail("Invalid reference"); 495 } 496 VM._assert(trace.isLive(newReferent)); 497 } 498 499 /* 500 * The reference object stays on the waiting list, and the 501 * referent is untouched. The only thing we must do is 502 * ensure that the former addresses are updated with the 503 * new forwarding addresses in case the collector is a 504 * copying collector. 505 */ 506 507 /* Update the referent */ 508 setReferent(newReference, newReferent); 509 return newReference; 510 } else { 511 /* Referent is unreachable. Clear the referent and enqueue the reference object. */ 512 513 if (TRACE_DETAIL) VM.sysWriteln(" UNREACHABLE"); 514 else if (TRACE_UNREACHABLE) VM.sysWriteln(" UNREACHABLE referent: ",oldReferent); 515 516 clearReferent(newReference); 517 enqueueReference(newReference); 518 return ObjectReference.nullReference(); 519 } 520 } 521 522 /** 523 * Weak and soft references always clear the referent 524 * before enqueueing. We don't actually call 525 * Reference.clear() as the user could have overridden the 526 * implementation and we don't want any side-effects to 527 * occur. 528 */ 529 protected void clearReferent(ObjectReference newReference) { 530 setReferent(newReference, ObjectReference.nullReference()); 531 } 532 533 /*********************************************************************** 534 * 535 * Reference object field accessors 536 */ 537 538 /** 539 * Get the referent from a reference. For Java the reference 540 * is a Reference object. 541 * @param object the object reference. 542 * @return the referent object reference. 543 */ 544 protected ObjectReference getReferent(ObjectReference object) { 545 if (VM.VerifyAssertions) VM._assert(!object.isNull()); 546 return object.toAddress().loadObjectReference(Entrypoints.referenceReferentField.getOffset()); 547 } 548 549 /** 550 * Set the referent in a reference. For Java the reference is 551 * a Reference object. 552 * @param ref the ObjectReference for the reference (confusing eh?). 553 * @param referent the referent object reference. 554 */ 555 protected void setReferent(ObjectReference ref, ObjectReference referent) { 556 ref.toAddress().store(referent, Entrypoints.referenceReferentField.getOffset()); 557 } 558 559 /*********************************************************************** 560 * 561 * Statistics and debugging 562 */ 563 564 @Override 565 public int countWaitingReferences() { 566 return maxIndex; 567 } 568 }