8231197: Shenandoah: JVMTI heap walking cleanup crashes with NULL forwardee
authorshade
Thu, 19 Sep 2019 20:26:51 +0200
changeset 58231 13e041be4e5c
parent 58230 0ff1aeedc338
child 58232 de9d23469c68
8231197: Shenandoah: JVMTI heap walking cleanup crashes with NULL forwardee Reviewed-by: zgu, rkennke
src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp
src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
--- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Thu Sep 19 16:53:17 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp	Thu Sep 19 20:26:51 2019 +0200
@@ -316,7 +316,11 @@
     oop *loc = _oops[c];
     assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
     oop o = RawAccess<>::oop_load(loc);
-    shenandoah_assert_correct_except(loc, o, o == NULL || heap->is_full_gc_move_in_progress());
+    shenandoah_assert_correct_except(loc, o,
+             o == NULL ||
+             heap->is_full_gc_move_in_progress() ||
+             (VMThread::vm_operation() != NULL) && (VMThread::vm_operation()->type() == VM_Operation::VMOp_HeapWalkOperation)
+    );
   }
 }
 
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Thu Sep 19 16:53:17 2019 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp	Thu Sep 19 20:26:51 2019 +0200
@@ -1225,7 +1225,22 @@
     T o = RawAccess<>::oop_load(p);
     if (!CompressedOops::is_null(o)) {
       oop obj = CompressedOops::decode_not_null(o);
-      obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+      oop fwd = (oop) ShenandoahForwarding::get_forwardee_raw_unchecked(obj);
+      if (fwd == NULL) {
+        // There is an odd interaction with VM_HeapWalkOperation, see jvmtiTagMap.cpp.
+        //
+        // That operation walks the reachable objects on its own, storing the marking
+        // wavefront in the object marks. When it is done, it calls the CollectedHeap
+        // to iterate over all objects to clean up the mess. When it reaches here,
+        // the Shenandoah fwdptr resolution code encounters the marked objects with
+        // NULL forwardee. Trying to act on that would crash the VM. Or fail the
+        // asserts, should we go for resolve_forwarded_pointer(obj).
+        //
+        // Therefore, we have to dodge it by doing the raw access to forwardee, and
+        // assuming the object had no forwardee, if that thing is NULL.
+      } else {
+        obj = fwd;
+      }
       assert(oopDesc::is_oop(obj), "must be a valid oop");
       if (!_bitmap->is_marked((HeapWord*) obj)) {
         _bitmap->mark((HeapWord*) obj);