7005259: CMS: BubbleUpRef asserts referent(obj)->is_oop() failed: Enqueued a bad referent
authorysr
Thu, 09 Dec 2010 09:22:57 -0800
changeset 7420 24071b15dde6
parent 7419 263dd4e89b9d
child 7421 4abc09aaa48d
7005259: CMS: BubbleUpRef asserts referent(obj)->is_oop() failed: Enqueued a bad referent Summary: Relaxed the assert by allowing NULL referents when discovery may be concurrent. Reviewed-by: johnc, jcoomes
hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
hotspot/src/share/vm/memory/referenceProcessor.cpp
hotspot/src/share/vm/memory/referenceProcessor.hpp
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Dec 07 21:55:53 2010 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Thu Dec 09 09:22:57 2010 -0800
@@ -2060,7 +2060,6 @@
   _ref_processor = ReferenceProcessor::create_ref_processor(
                                          mr,    // span
                                          false, // Reference discovery is not atomic
-                                                // (though it shouldn't matter here.)
                                          true,  // mt_discovery
                                          NULL,  // is alive closure: need to fill this in for efficiency
                                          ParallelGCThreads,
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp	Tue Dec 07 21:55:53 2010 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp	Thu Dec 09 09:22:57 2010 -0800
@@ -1146,6 +1146,20 @@
   }
 }
 
+#ifndef PRODUCT
+// Non-atomic (i.e. concurrent) discovery might allow us
+// to observe j.l.References with NULL referents, being those
+// cleared concurrently by mutators during (or after) discovery.
+void ReferenceProcessor::verify_referent(oop obj) {
+  bool da = discovery_is_atomic();
+  oop referent = java_lang_ref_Reference::referent(obj);
+  assert(da ? referent->is_oop() : referent->is_oop_or_null(),
+         err_msg("Bad referent " INTPTR_FORMAT " found in Reference "
+                 INTPTR_FORMAT " during %satomic discovery ",
+                 (intptr_t)referent, (intptr_t)obj, da ? "" : "non-"));
+}
+#endif
+
 // We mention two of several possible choices here:
 // #0: if the reference object is not in the "originating generation"
 //     (or part of the heap being collected, indicated by our "span"
@@ -1196,14 +1210,8 @@
   // We only enqueue references whose referents are not (yet) strongly
   // reachable.
   if (is_alive_non_header() != NULL) {
-    oop referent = java_lang_ref_Reference::referent(obj);
-    // In the case of non-concurrent discovery, the last
-    // disjunct below should hold. It may not hold in the
-    // case of concurrent discovery because mutators may
-    // concurrently clear() a Reference.
-    assert(UseConcMarkSweepGC || UseG1GC || referent != NULL,
-           "Refs with null referents already filtered");
-    if (is_alive_non_header()->do_object_b(referent)) {
+    verify_referent(obj);
+    if (is_alive_non_header()->do_object_b(java_lang_ref_Reference::referent(obj))) {
       return false;  // referent is reachable
     }
   }
@@ -1247,13 +1255,13 @@
   }
 
   if (RefDiscoveryPolicy == ReferentBasedDiscovery) {
-    oop referent = java_lang_ref_Reference::referent(obj);
-    assert(referent->is_oop(), "bad referent");
+    verify_referent(obj);
     // enqueue if and only if either:
     // reference is in our span or
     // we are an atomic collector and referent is in our span
     if (_span.contains(obj_addr) ||
-        (discovery_is_atomic() && _span.contains(referent))) {
+        (discovery_is_atomic() &&
+         _span.contains(java_lang_ref_Reference::referent(obj)))) {
       // should_enqueue = true;
     } else {
       return false;
@@ -1301,7 +1309,7 @@
     }
   }
   assert(obj->is_oop(), "Enqueued a bad reference");
-  assert(java_lang_ref_Reference::referent(obj)->is_oop(), "Enqueued a bad referent");
+  verify_referent(obj);
   return true;
 }
 
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp	Tue Dec 07 21:55:53 2010 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp	Thu Dec 09 09:22:57 2010 -0800
@@ -345,6 +345,7 @@
 
   // debugging
   void verify_no_references_recorded() PRODUCT_RETURN;
+  void verify_referent(oop obj)        PRODUCT_RETURN;
   static void verify();
 
   // clear the discovered lists (unlinking each entry).