24
24
import org .jikesrvm .mm .mminterface .Selected ;
25
25
import org .jikesrvm .runtime .Entrypoints ;
26
26
import org .jikesrvm .runtime .Magic ;
27
+ import org .jikesrvm .runtime .Statics ;
27
28
import org .jikesrvm .scheduler .RVMThread ;
28
29
29
30
import java .lang .ref .Reference ;
30
31
import java .lang .ref .SoftReference ;
31
32
import java .lang .ref .WeakReference ;
32
33
import java .lang .ref .PhantomReference ;
33
34
35
+ import static org .jikesrvm .mm .mminterface .Barriers .NEEDS_OBJECT_PUTFIELD_BARRIER ;
36
+ import static org .jikesrvm .mm .mminterface .Barriers .NEEDS_JAVA_LANG_REFERENCE_WRITE_BARRIER ;
34
37
35
38
/**
36
39
* This class manages SoftReferences, WeakReferences, and
@@ -277,6 +280,14 @@ private void addCandidate(Reference<?> ref, ObjectReference referent) {
277
280
public void forward (TraceLocal trace , boolean nursery ) {
278
281
if (VM .VerifyAssertions ) VM ._assert (unforwardedReferences != null );
279
282
if (TRACE ) VM .sysWriteln ("Starting ReferenceGlue.forward(" ,semanticsStr ,")" );
283
+
284
+ if (Selected .Constraints .get ().onTheFlyCollector ()) {
285
+ lock .acquire ();
286
+ /* In on-the-fly collector, unforwardedReference which is captured in scan()
287
+ * may be stale.
288
+ */
289
+ unforwardedReferences = references ;
290
+ }
280
291
if (TRACE_DETAIL ) {
281
292
VM .sysWrite (semanticsStr ," Reference table is " ,
282
293
Magic .objectAsAddress (references ));
@@ -287,12 +298,13 @@ public void forward(TraceLocal trace, boolean nursery) {
287
298
if (TRACE_DETAIL ) VM .sysWrite ("slot " ,i ,": " );
288
299
ObjectReference reference = unforwardedReferences .get (i ).toObjectReference ();
289
300
if (TRACE_DETAIL ) VM .sysWriteln ("forwarding " ,reference );
290
- setReferent (reference , trace .getForwardedReferent (getReferent (reference )));
301
+ setReferentDuringGC (reference , trace .getForwardedReferent (getReferent (reference )));
291
302
ObjectReference newReference = trace .getForwardedReference (reference );
292
303
unforwardedReferences .set (i , newReference .toAddress ());
293
304
}
294
305
if (TRACE ) VM .sysWriteln ("Ending ReferenceGlue.forward(" ,semanticsStr ,")" );
295
306
unforwardedReferences = null ;
307
+ if (Selected .Constraints .get ().onTheFlyCollector ()) lock .release ();
296
308
}
297
309
298
310
@ Override
@@ -311,9 +323,11 @@ public void clear() {
311
323
* TODO parallelise this code
312
324
*
313
325
* @param nursery Scan only the newly created references
326
+ * @param if true, retain referent regardless of its reachability
314
327
*/
315
328
@ Override
316
- public void scan (TraceLocal trace , boolean nursery ) {
329
+ public void scan (TraceLocal trace , boolean nursery , boolean retainUnreachable ) {
330
+ if (Selected .Constraints .get ().onTheFlyCollector ()) lock .acquire ();
317
331
unforwardedReferences = references ;
318
332
319
333
if (TRACE ) VM .sysWriteln ("Starting ReferenceGlue.scan(" ,semanticsStr ,")" );
@@ -324,7 +338,7 @@ public void scan(TraceLocal trace, boolean nursery) {
324
338
ObjectReference reference = getReference (fromIndex );
325
339
326
340
/* Determine liveness (and forward if necessary) the reference */
327
- ObjectReference newReference = processReference (trace ,reference );
341
+ ObjectReference newReference = processReference (trace , reference , retainUnreachable );
328
342
if (!newReference .isNull ()) {
329
343
setReference (toIndex ++,newReference );
330
344
if (TRACE_DETAIL ) {
@@ -340,8 +354,11 @@ public void scan(TraceLocal trace, boolean nursery) {
340
354
VM .sysWrite (semanticsStr );
341
355
VM .sysWriteln (" references: " ,maxIndex ," -> " ,toIndex );
342
356
}
343
- nurseryIndex = maxIndex = toIndex ;
344
-
357
+ maxIndex = toIndex ;
358
+ if (!retainUnreachable )
359
+ nurseryIndex = toIndex ;
360
+ if (Selected .Constraints .get ().onTheFlyCollector ()) lock .release ();
361
+
345
362
/* flush out any remset entries generated during the above activities */
346
363
Selected .Mutator .get ().flushRememberedSets ();
347
364
if (TRACE ) VM .sysWriteln ("Ending ReferenceGlue.scan(" ,semanticsStr ,")" );
@@ -411,14 +428,35 @@ public static void addPhantomCandidate(PhantomReference<?> ref, ObjectReference
411
428
* @param reference the address of the reference. This may or may not
412
429
* be the address of a heap object, depending on the VM.
413
430
* @param trace the thread local trace element.
431
+ * @param retainUnreachable if this is true, retain referent even if it is unreachable
414
432
*/
415
433
@ UninterruptibleNoWarn ("Call out to ReferenceQueue API" )
416
- public ObjectReference processReference (TraceLocal trace , ObjectReference reference ) {
434
+ public ObjectReference processReference (TraceLocal trace , ObjectReference reference , boolean retainUnreachable ) {
417
435
if (VM .VerifyAssertions ) VM ._assert (!reference .isNull ());
418
436
419
437
if (TRACE_DETAIL ) {
420
438
VM .sysWrite ("Processing reference: " ,reference );
421
439
}
440
+
441
+ if (retainUnreachable ) {
442
+ if (!trace .isLive (reference )) {
443
+ /*
444
+ * Some unreachable references may resurrect because they may be reachable from
445
+ * retained referents of other references.
446
+ */
447
+ return reference ;
448
+ }
449
+
450
+ ObjectReference referent = getReferent (reference );
451
+ if (!referent .isNull ())
452
+ trace .retainReferent (referent );
453
+ if (TRACE_DETAIL ) {
454
+ VM .sysWriteln (" ~> " , referent .toAddress (), " (retained)" );
455
+ }
456
+ return reference ;
457
+ }
458
+
459
+ /* clear if referent is unreachable */
422
460
/*
423
461
* If the reference is dead, we're done with it. Let it (and
424
462
* possibly its referent) be garbage-collected.
@@ -453,24 +491,6 @@ public ObjectReference processReference(TraceLocal trace, ObjectReference refere
453
491
454
492
if (TRACE_DETAIL ) VM .sysWrite (" => " ,newReference );
455
493
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
494
if (trace .isLive (oldReferent )) {
475
495
if (VM .VerifyAssertions ) {
476
496
if (!DebugUtil .validRef (oldReferent )) {
@@ -491,6 +511,7 @@ public ObjectReference processReference(TraceLocal trace, ObjectReference refere
491
511
if (!DebugUtil .validRef (newReferent )) {
492
512
VM .sysWriteln ("Error forwarding reference object." );
493
513
DebugUtil .dumpRef (oldReferent );
514
+ VM .sysWriteln ("reference = " , reference );
494
515
VM .sysFail ("Invalid reference" );
495
516
}
496
517
VM ._assert (trace .isLive (newReferent ));
@@ -505,7 +526,7 @@ public ObjectReference processReference(TraceLocal trace, ObjectReference refere
505
526
*/
506
527
507
528
/* Update the referent */
508
- setReferent (newReference , newReferent );
529
+ setReferentDuringGC (newReference , newReferent );
509
530
return newReference ;
510
531
} else {
511
532
/* Referent is unreachable. Clear the referent and enqueue the reference object. */
@@ -527,7 +548,7 @@ public ObjectReference processReference(TraceLocal trace, ObjectReference refere
527
548
* occur.
528
549
*/
529
550
protected void clearReferent (ObjectReference newReference ) {
530
- setReferent (newReference , ObjectReference .nullReference ());
551
+ setReferentDuringGC (newReference , ObjectReference .nullReference ());
531
552
}
532
553
533
554
/***********************************************************************
@@ -553,7 +574,41 @@ protected ObjectReference getReferent(ObjectReference object) {
553
574
* @param referent the referent object reference.
554
575
*/
555
576
protected void setReferent (ObjectReference ref , ObjectReference referent ) {
556
- ref .toAddress ().store (referent , Entrypoints .referenceReferentField .getOffset ());
577
+ if (Options .noReferenceTypes .getValue ()) {
578
+ if (NEEDS_OBJECT_PUTFIELD_BARRIER )
579
+ // treat as a objectReference write
580
+ org .jikesrvm .mm .mminterface .Barriers .objectFieldWrite (ref .toObject (), referent .toObject (),
581
+ Entrypoints .referenceReferentField .getOffset (), 0 );
582
+ else
583
+ // treat as a plain Address write - it is up to the collector to ensure we process the references correctly
584
+ org .jikesrvm .mm .mminterface .Barriers .addressFieldWrite (ref .toObject (), referent .toAddress (),
585
+ Entrypoints .referenceReferentField .getOffset (), 0 );
586
+ } else {
587
+ if (NEEDS_JAVA_LANG_REFERENCE_WRITE_BARRIER )
588
+ // needs special treatment
589
+ org .jikesrvm .mm .mminterface .Barriers .javaLangReferenceWriteBarrier (ref , referent ,
590
+ Entrypoints .referenceReferentField .getOffset (), 0 );
591
+ else
592
+ // treat as a plain Address write - it is up to the collector to ensure we process the references correctly
593
+ org .jikesrvm .mm .mminterface .Barriers .addressFieldWrite (ref .toObject (), referent .toAddress (),
594
+ Entrypoints .referenceReferentField .getOffset (), 0 );
595
+ }
596
+ }
597
+
598
+ protected void setReferentDuringGC (ObjectReference ref , ObjectReference referent ) {
599
+ if (NEEDS_OBJECT_PUTFIELD_BARRIER ) {
600
+ if (Options .noReferenceTypes .getValue ()) {
601
+ // treat as a objectReference write
602
+ org .jikesrvm .mm .mminterface .Barriers .objectFieldWrite (ref .toObject (), referent .toObject (),
603
+ Entrypoints .referenceReferentField .getOffset (), 0 );
604
+ } else {
605
+ // write raw Address avoiding certain Sapphire assertions because ref might be in toSpace
606
+ org .jikesrvm .mm .mminterface .Barriers .addressFieldWriteDuringGC (ref .toObject (), referent .toAddress (),
607
+ Entrypoints .referenceReferentField .getOffset (), 0 );
608
+ }
609
+ } else {
610
+ ref .toAddress ().store (referent , Entrypoints .referenceReferentField .getOffset ());
611
+ }
557
612
}
558
613
559
614
/***********************************************************************
0 commit comments