< prev index next >

src/hotspot/share/gc/shared/referenceProcessor.cpp

Print this page
rev 49944 : imported patch 8201492-properly-implement-non-contiguous-reference-processing
rev 49945 : imported patch 8201492-stefanj-review
rev 49949 : imported patch 8202021-cleanup-referenceprocessor
rev 49950 : imported patch 8202021-stefanj-review
rev 49951 : imported patch 8202017-reference-processor-remove-enqueue
rev 49952 : imported patch 8202017-kim-review
rev 49953 : imported patch 8201491-precleaning

*** 592,614 **** } private: bool _clear_referent; }; #ifndef PRODUCT ! void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint active_length, size_t total_refs) { if (!log_is_enabled(Trace, gc, ref)) { return; } ! stringStream st; ! for (uint i = 0; i < active_length; ++i) { ! st.print(SIZE_FORMAT " ", ref_lists[i].length()); ! } ! log_develop_trace(gc, ref)("%s= " SIZE_FORMAT, st.as_string(), total_refs); #ifdef ASSERT ! for (uint i = active_length; i < _max_num_queues; i++) { assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u", ref_lists[i].length(), i); } #endif } --- 592,628 ---- } private: bool _clear_referent; }; + void ReferenceProcessor::log_reflist(const char* prefix, DiscoveredList list[], uint num_active_queues) { + LogTarget(Trace, gc, ref) lt; + + if (!lt.is_enabled()) { + return; + } + + size_t total = 0; + + LogStream ls(lt); + ls.print("%s", prefix); + for (uint i = 0; i < num_active_queues; i++) { + ls.print(SIZE_FORMAT " ", list[i].length()); + total += list[i].length(); + } + ls.print_cr("(" SIZE_FORMAT ")", total); + } + #ifndef PRODUCT ! void ReferenceProcessor::log_reflist_counts(DiscoveredList ref_lists[], uint num_active_queues) { if (!log_is_enabled(Trace, gc, ref)) { return; } ! log_reflist("", ref_lists, num_active_queues); #ifdef ASSERT ! for (uint i = num_active_queues; i < _max_num_queues; i++) { assert(ref_lists[i].length() == 0, SIZE_FORMAT " unexpected References in %u", ref_lists[i].length(), i); } #endif }
*** 627,640 **** { // calculate total length size_t total_refs = 0; log_develop_trace(gc, ref)("Balance ref_lists "); for (uint i = 0; i < _max_num_queues; ++i) { total_refs += ref_lists[i].length(); } - log_reflist_counts(ref_lists, _max_num_queues, total_refs); size_t avg_refs = total_refs / _num_queues + 1; uint to_idx = 0; for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) { bool move_all = false; if (from_idx >= _num_queues) { --- 641,655 ---- { // calculate total length size_t total_refs = 0; log_develop_trace(gc, ref)("Balance ref_lists "); + log_reflist_counts(ref_lists, _max_num_queues); + for (uint i = 0; i < _max_num_queues; ++i) { total_refs += ref_lists[i].length(); } size_t avg_refs = total_refs / _num_queues + 1; uint to_idx = 0; for (uint from_idx = 0; from_idx < _max_num_queues; from_idx++) { bool move_all = false; if (from_idx >= _num_queues) {
*** 691,705 **** to_idx = (to_idx + 1) % _num_queues; } } } #ifdef ASSERT size_t balanced_total_refs = 0; for (uint i = 0; i < _num_queues; ++i) { balanced_total_refs += ref_lists[i].length(); } - log_reflist_counts(ref_lists, _num_queues, balanced_total_refs); assert(total_refs == balanced_total_refs, "Balancing was incomplete"); #endif } void ReferenceProcessor::process_discovered_reflist( --- 706,720 ---- to_idx = (to_idx + 1) % _num_queues; } } } #ifdef ASSERT + log_reflist_counts(ref_lists, _num_queues); size_t balanced_total_refs = 0; for (uint i = 0; i < _num_queues; ++i) { balanced_total_refs += ref_lists[i].length(); } assert(total_refs == balanced_total_refs, "Balancing was incomplete"); #endif } void ReferenceProcessor::process_discovered_reflist(
*** 1009,1075 **** } } return false; } ! // Preclean the discovered references by removing those ! // whose referents are alive, and by marking from those that ! // are not active. These lists can be handled here ! // in any order and, indeed, concurrently. ! void ReferenceProcessor::preclean_discovered_references( ! BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield, GCTimer* gc_timer) { // Soft references { GCTraceTime(Debug, gc, ref) tm("Preclean SoftReferences", gc_timer); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, ! keep_alive, complete_gc, yield); } } // Weak references { GCTraceTime(Debug, gc, ref) tm("Preclean WeakReferences", gc_timer); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, ! keep_alive, complete_gc, yield); } } // Final references { GCTraceTime(Debug, gc, ref) tm("Preclean FinalReferences", gc_timer); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, ! keep_alive, complete_gc, yield); } } // Phantom references { GCTraceTime(Debug, gc, ref) tm("Preclean PhantomReferences", gc_timer); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, ! keep_alive, complete_gc, yield); } } } // Walk the given discovered ref list, and remove all reference objects // whose referents are still alive, whose referents are NULL or which --- 1024,1106 ---- } } return false; } ! void ReferenceProcessor::preclean_discovered_references(BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield, GCTimer* gc_timer) { + // These lists can be handled here in any order and, indeed, concurrently. // Soft references { GCTraceTime(Debug, gc, ref) tm("Preclean SoftReferences", gc_timer); + log_reflist("SoftRef before: ", _discoveredSoftRefs, _max_num_queues); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! if (preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, ! keep_alive, complete_gc, yield)) { ! log_reflist("SoftRef abort: ", _discoveredSoftRefs, _max_num_queues); ! return; ! } } + log_reflist("SoftRef after: ", _discoveredSoftRefs, _max_num_queues); } // Weak references { GCTraceTime(Debug, gc, ref) tm("Preclean WeakReferences", gc_timer); + log_reflist("WeakRef before: ", _discoveredWeakRefs, _max_num_queues); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! if (preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, ! keep_alive, complete_gc, yield)) { ! log_reflist("WeakRef abort: ", _discoveredWeakRefs, _max_num_queues); ! return; ! } } + log_reflist("WeakRef after: ", _discoveredWeakRefs, _max_num_queues); } // Final references { GCTraceTime(Debug, gc, ref) tm("Preclean FinalReferences", gc_timer); + log_reflist("FinalRef before: ", _discoveredFinalRefs, _max_num_queues); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! if (preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, ! keep_alive, complete_gc, yield)) { ! log_reflist("FinalRef abort: ", _discoveredFinalRefs, _max_num_queues); ! return; ! } } + log_reflist("FinalRef after: ", _discoveredFinalRefs, _max_num_queues); } // Phantom references { GCTraceTime(Debug, gc, ref) tm("Preclean PhantomReferences", gc_timer); + log_reflist("PhantomRef before: ", _discoveredPhantomRefs, _max_num_queues); for (uint i = 0; i < _max_num_queues; i++) { if (yield->should_return()) { return; } ! if (preclean_discovered_reflist(_discoveredPhantomRefs[i], is_alive, ! keep_alive, complete_gc, yield)) { ! log_reflist("PhantomRef abort: ", _discoveredPhantomRefs, _max_num_queues); ! return; ! } } + log_reflist("PhantomRef after: ", _discoveredPhantomRefs, _max_num_queues); } } // Walk the given discovered ref list, and remove all reference objects // whose referents are still alive, whose referents are NULL or which
*** 1077,1099 **** // thus precleaning the ref lists (which happens single-threaded today), // we do not disable refs discovery to honor the correct semantics of // java.lang.Reference. As a result, we need to be careful below // that ref removal steps interleave safely with ref discovery steps // (in this thread). ! void ! ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); oop obj = iter.obj(); oop next = java_lang_ref_Reference::next(obj); ! if (iter.referent() == NULL || iter.is_referent_alive() || ! next != NULL) { // The referent has been cleared, or is alive, or the Reference is not // active; we need to trace and mark its cohort. log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)", p2i(iter.obj()), iter.obj()->klass()->internal_name()); // Remove Reference object from list --- 1108,1131 ---- // thus precleaning the ref lists (which happens single-threaded today), // we do not disable refs discovery to honor the correct semantics of // java.lang.Reference. As a result, we need to be careful below // that ref removal steps interleave safely with ref discovery steps // (in this thread). ! bool ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, BoolObjectClosure* is_alive, OopClosure* keep_alive, VoidClosure* complete_gc, YieldClosure* yield) { DiscoveredListIterator iter(refs_list, keep_alive, is_alive); while (iter.has_next()) { + if (yield->should_return_fine_grain()) { + return true; + } iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); oop obj = iter.obj(); oop next = java_lang_ref_Reference::next(obj); ! if (iter.referent() == NULL || iter.is_referent_alive() || next != NULL) { // The referent has been cleared, or is alive, or the Reference is not // active; we need to trace and mark its cohort. log_develop_trace(gc, ref)("Precleaning Reference (" INTPTR_FORMAT ": %s)", p2i(iter.obj()), iter.obj()->klass()->internal_name()); // Remove Reference object from list
*** 1119,1128 **** --- 1151,1161 ---- if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, iter.removed(), iter.processed(), p2i(&refs_list)); } ) + return false; } const char* ReferenceProcessor::list_name(uint i) { assert(i <= _max_num_queues * number_of_subclasses_of_ref(), "Out of bounds index");
< prev index next >