8066827: Remove ReferenceProcessor::clean_up_discovered_references()

Abandon rather than clean up discovered references.

Reviewed-by: jmasa, ysr
This commit is contained in:
Kim Barrett 2014-12-17 22:32:44 -05:00
parent c40b1dd803
commit 093d2698fc
9 changed files with 22 additions and 81 deletions

@ -1608,14 +1608,15 @@ void CMSCollector::acquire_control_and_collect(bool full,
// If the collection is being acquired from the background
// collector, there may be references on the discovered
// references lists that have NULL referents (being those
// that were concurrently cleared by a mutator) or
// that are no longer active (having been enqueued concurrently
// by the mutator).
// Scrub the list of those references because Mark-Sweep-Compact
// code assumes referents are not NULL and that all discovered
// Reference objects are active.
ref_processor()->clean_up_discovered_references();
// references lists. Abandon those references, since some
// of them may have become unreachable after concurrent
// discovery; the STW compacting collector will redo discovery
// more precisely, without being subject to floating garbage.
// Leaving otherwise unreachable references in the discovered
// lists would require special handling.
ref_processor()->disable_discovery();
ref_processor()->abandon_partial_discovery();
ref_processor()->verify_no_references_recorded();
if (first_state > Idling) {
save_heap_summary();
@ -1681,7 +1682,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false);
ref_processor()->set_enqueuing_is_done(false);
ref_processor()->enable_discovery(false /*verify_disabled*/, false /*check_no_refs*/);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_soft_refs);
// If an asynchronous collection finishes, the _modUnionTable is
// all clear. If we are assuming the collection from an asynchronous
@ -2998,7 +2999,7 @@ void CMSCollector::checkpointRootsInitial() {
Mutex::_no_safepoint_check_flag);
checkpointRootsInitialWork();
// enable ("weak") refs discovery
rp->enable_discovery(true /*verify_disabled*/, true /*check_no_refs*/);
rp->enable_discovery();
_collectorState = Marking;
}
SpecializationStats::print();

@ -971,7 +971,7 @@ void ConcurrentMark::checkpointRootsInitialPost() {
// Start Concurrent Marking weak-reference discovery.
ReferenceProcessor* rp = g1h->ref_processor_cm();
// enable ("weak") refs discovery
rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
rp->enable_discovery();
rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();

@ -1301,7 +1301,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc,
// Temporarily clear the STW ref processor's _is_alive_non_header field.
ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL);
ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
ref_processor_stw()->enable_discovery();
ref_processor_stw()->setup_policy(do_clear_all_soft_refs);
// Do collection work
@ -3750,8 +3750,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
// reference processing currently works in G1.
// Enable discovery in the STW reference processor
ref_processor_stw()->enable_discovery(true /*verify_disabled*/,
true /*verify_no_refs*/);
ref_processor_stw()->enable_discovery();
{
// We want to temporarily turn off discovery by the

@ -195,7 +195,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(clear_all_softrefs);
mark_sweep_phase1(clear_all_softrefs);

@ -2069,7 +2069,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
ref_processor()->enable_discovery();
ref_processor()->setup_policy(maximum_heap_compaction);
bool marked_for_unloading = false;

@ -362,7 +362,7 @@ bool PSScavenge::invoke_no_policy() {
COMPILER2_PRESENT(DerivedPointerTable::clear());
reference_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
reference_processor()->enable_discovery();
reference_processor()->setup_policy(false);
// We track how much was promoted to the next generation for

@ -465,7 +465,7 @@ void GenCollectedHeap::do_collection(bool full,
// atomic wrt other collectors in this configuration, we
// are guaranteed to have empty discovered ref lists.
if (rp->discovery_is_atomic()) {
rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);
rp->enable_discovery();
rp->setup_policy(do_clear_all_soft_refs);
} else {
// collect() below will enable discovery as appropriate

@ -68,10 +68,10 @@ void ReferenceProcessor::init_statics() {
_pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field();
}
void ReferenceProcessor::enable_discovery(bool verify_disabled, bool check_no_refs) {
void ReferenceProcessor::enable_discovery(bool check_no_refs) {
#ifdef ASSERT
// Verify that we're not currently discovering refs
assert(!verify_disabled || !_discovering_refs, "nested call?");
assert(!_discovering_refs, "nested call?");
if (check_no_refs) {
// Verify that the discovered lists are empty
@ -963,52 +963,6 @@ ReferenceProcessor::process_discovered_reflist(
return total_list_count;
}
void ReferenceProcessor::clean_up_discovered_references() {
// loop over the lists
for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) {
if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) {
gclog_or_tty->print_cr(
"\nScrubbing %s discovered list of Null referents",
list_name(i));
}
clean_up_discovered_reflist(_discovered_refs[i]);
}
}
void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) {
assert(!discovery_is_atomic(), "Else why call this method?");
DiscoveredListIterator iter(refs_list, NULL, NULL);
while (iter.has_next()) {
iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */));
oop next = java_lang_ref_Reference::next(iter.obj());
assert(next->is_oop_or_null(), err_msg("Expected an oop or NULL for next field at " PTR_FORMAT, p2i(next)));
// If referent has been cleared or Reference is not active,
// drop it.
if (iter.referent() == NULL || next != NULL) {
debug_only(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: "
INTPTR_FORMAT " with next field: " INTPTR_FORMAT
" and referent: " INTPTR_FORMAT,
(void *)iter.obj(), (void *)next, (void *)iter.referent());
}
)
// Remove Reference object from list
iter.remove();
iter.move_to_next();
} else {
iter.next();
}
}
NOT_PRODUCT(
if (PrintGCDetails && TraceReferenceGC) {
gclog_or_tty->print(
" Removed %d Refs with NULL referents out of %d discovered Refs",
iter.removed(), iter.processed());
}
)
}
inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) {
uint id = 0;
// Determine the queue index to use for this object.

@ -353,19 +353,6 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
GCTimer* gc_timer,
GCId gc_id);
// Delete entries in the discovered lists that have
// either a null referent or are not active. Such
// Reference objects can result from the clearing
// or enqueueing of Reference objects concurrent
// with their discovery by a (concurrent) collector.
// For a definition of "active" see java.lang.ref.Reference;
// Refs are born active, become inactive when enqueued,
// and never become active again. The state of being
// active is encoded as follows: A Ref is active
// if and only if its "next" field is NULL.
void clean_up_discovered_references();
void clean_up_discovered_reflist(DiscoveredList& refs_list);
// Returns the name of the discovered reference list
// occupying the i / _num_q slot.
const char* list_name(uint i);
@ -439,7 +426,7 @@ class ReferenceProcessor : public CHeapObj<mtGC> {
void set_span(MemRegion span) { _span = span; }
// start and stop weak ref discovery
void enable_discovery(bool verify_disabled, bool check_no_refs);
void enable_discovery(bool check_no_refs = true);
void disable_discovery() { _discovering_refs = false; }
bool discovery_enabled() { return _discovering_refs; }
@ -517,7 +504,7 @@ class NoRefDiscovery: StackObj {
~NoRefDiscovery() {
if (_was_discovering_refs) {
_rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/);
_rp->enable_discovery(false /*check_no_refs*/);
}
}
};