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
--- 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).