# HG changeset patch # User ysr # Date 1291915377 28800 # Node ID 8df09fb453524d0277c220d28ec6e11c1ec4d270 # Parent 6cd6d394f280ac264f52e5cfe8b2860afb1832b3 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 diff -r 6cd6d394f280 -r 8df09fb45352 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Dec 07 21:55:53 2010 -0800 +++ b/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, diff -r 6cd6d394f280 -r 8df09fb45352 src/share/vm/memory/referenceProcessor.cpp --- a/src/share/vm/memory/referenceProcessor.cpp Tue Dec 07 21:55:53 2010 -0800 +++ b/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; } diff -r 6cd6d394f280 -r 8df09fb45352 src/share/vm/memory/referenceProcessor.hpp --- a/src/share/vm/memory/referenceProcessor.hpp Tue Dec 07 21:55:53 2010 -0800 +++ b/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).