RFR: Workaround degen-traversal bugs with evac-assists enabled
Aleksey Shipilev
shade at redhat.com
Tue Aug 21 09:15:48 UTC 2018
I have had a head-scratcher bug during backports testing, which boils down to bad degen-traversal
and evac-assists interaction. Let's turn that off for traversal, until we come up with the proper fix:
diff -r dbd712ba015c src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp
--- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp Mon Aug 20
12:32:27 2018 -0400
+++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahTraversalHeuristics.cpp Tue Aug 21
11:14:05 2018 +0200
@@ -47,10 +47,32 @@
// Adjust class unloading settings only if globally enabled.
if (ClassUnloadingWithConcurrentMark) {
SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahUnloadClassesFrequency, 1);
}
+ // Workaround the bug in degen-traversal that evac assists expose.
+ //
+ // During traversal cycle, WB can evacuate something from region R1 (CS) to R2 (R).
+ // Then degen-traversal happens, drops the cset, and finishes up the fixups.
+ // Then next cycle happens to put both R1 and R2 into CS, and then R2 evacuates to R3.
+ // It creates the double forwarding for that object: R1 (CS) -> R2 (CS) -> R3 (R).
+ //
+ // It is likely at that point that no references to R1 object are left after the degen,
+ // so this double forwarding is not exposed. Unless we have evac assists, that touch
+ // the adjacent objects while evacuating live objects from R1, step on "bad" R1 copy,
+ // and fail the internal asserts when getting oop sizes to walk the heap, or touching
+ // its fwdptrs. The same thing would probably happen if we do size-based iteration
+ // somewhere else.
+ //
+ // AllocHumongousFragment test exposes it nicely, always running into degens.
+ //
+ // TODO: Fix this properly
+ // There are two alternatives: fix it in degen so that it never leaves double forwarding,
+ // or make sure we only use raw accessors in evac assist path when getting oop_size,
+ // including all exotic shapes like instanceMirrorKlass, and touching fwdptrs. The second
+ // option is partly done in jdk12, but not in earlier jdks.
+ FLAG_SET_DEFAULT(ShenandoahEvacAssist, 0);
}
bool ShenandoahTraversalHeuristics::should_start_normal_gc() const {
return false;
}
diff -r dbd712ba015c src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Mon Aug 20 12:32:27 2018 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Tue Aug 21 11:14:05 2018 +0200
@@ -1888,10 +1888,14 @@
// but enters it at different points, depending on which concurrent phase had
// degenerated.
case _degenerated_traversal:
{
+ // Drop the collection set. Note: this leaves some already forwarded objects
+ // behind, which may be problematic, see comments for ShenandoahEvacAssist
+ // workarounds in ShenandoahTraversalHeuristics.
+
ShenandoahHeapLocker locker(lock());
collection_set()->clear_current_index();
for (size_t i = 0; i < collection_set()->count(); i++) {
ShenandoahHeapRegion* r = collection_set()->next();
r->make_regular_bypass();
Testing: tier3_gc_shenandoah
Thanks,
-Aleksey
More information about the shenandoah-dev
mailing list