src/share/vm/memory/referenceProcessor.cpp

Print this page

        

*** 46,55 **** --- 46,57 ---- } } bool empty() const { return head() == ReferenceProcessor::sentinel_ref(); } size_t length() { return _len; } void set_length(size_t len) { _len = len; } + void inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); } + void dec_length(size_t dec) { _len -= dec; } private: // Set value depending on UseCompressedOops. This could be a template class // but then we have to fix all the instantiations and declarations that use this class. oop _oop_head; narrowOop _compressed_head;
*** 434,450 **** // Loads data for the current reference. // The "allow_null_referent" argument tells us to allow for the possibility // of a NULL referent in the discovered Reference object. This typically // happens in the case of concurrent collectors that may have done the ! // discovery concurrently or interleaved with mutator execution. inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); // Move to the next discovered reference. inline void next(); ! // Remove the current reference from the list and move to the next. inline void remove(); // Make the Reference object active again. inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); } --- 436,452 ---- // Loads data for the current reference. // The "allow_null_referent" argument tells us to allow for the possibility // of a NULL referent in the discovered Reference object. This typically // happens in the case of concurrent collectors that may have done the ! // discovery concurrently, or interleaved, with mutator execution. inline void load_ptrs(DEBUG_ONLY(bool allow_null_referent)); // Move to the next discovered reference. inline void next(); ! // Remove the current reference from the list inline void remove(); // Make the Reference object active again. inline void make_active() { java_lang_ref_Reference::set_next(_ref, NULL); }
*** 474,484 **** NOT_PRODUCT( inline size_t processed() const { return _processed; } inline size_t removed() const { return _removed; } ) - private: inline void move_to_next(); private: DiscoveredList& _refs_list; HeapWord* _prev_next; --- 476,485 ----
*** 551,561 **** } else { // Remove Reference object from list. oopDesc::store_heap_oop((oop*)_prev_next, _next); } NOT_PRODUCT(_removed++); ! move_to_next(); } inline void DiscoveredListIterator::move_to_next() { _ref = _next; assert(_ref != _first_seen, "cyclic ref_list found"); --- 552,562 ---- } else { // Remove Reference object from list. oopDesc::store_heap_oop((oop*)_prev_next, _next); } NOT_PRODUCT(_removed++); ! _refs_list.dec_length(1); } inline void DiscoveredListIterator::move_to_next() { _ref = _next; assert(_ref != _first_seen, "cyclic ref_list found");
*** 589,604 **** if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", iter.obj(), iter.obj()->blueprint()->internal_name()); } // Make the Reference object active again iter.make_active(); // keep the referent around iter.make_referent_alive(); ! // Remove Reference object from list ! iter.remove(); } else { iter.next(); } } // Close the reachable set --- 590,606 ---- if (referent_is_dead && !policy->should_clear_reference(iter.obj())) { if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping reference (" INTPTR_FORMAT ": %s" ") by policy", iter.obj(), iter.obj()->blueprint()->internal_name()); } + // Remove Reference object from list + iter.remove(); // Make the Reference object active again iter.make_active(); // keep the referent around iter.make_referent_alive(); ! iter.move_to_next(); } else { iter.next(); } } // Close the reachable set
*** 627,642 **** if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)", iter.obj(), iter.obj()->blueprint()->internal_name()); } // The referent is reachable after all. // Update the referent pointer as necessary: Note that this // should not entail any recursive marking because the // referent must already have been traversed. iter.make_referent_alive(); ! // Remove Reference object from list ! iter.remove(); } else { iter.next(); } } NOT_PRODUCT( --- 629,645 ---- if (TraceReferenceGC) { gclog_or_tty->print_cr("Dropping strongly reachable reference (" INTPTR_FORMAT ": %s)", iter.obj(), iter.obj()->blueprint()->internal_name()); } // The referent is reachable after all. + // Remove Reference object from list. + iter.remove(); // Update the referent pointer as necessary: Note that this // should not entail any recursive marking because the // referent must already have been traversed. iter.make_referent_alive(); ! iter.move_to_next(); } else { iter.next(); } } NOT_PRODUCT(
*** 668,677 **** --- 671,681 ---- if (UseCompressedOops) { keep_alive->do_oop((narrowOop*)next_addr); } else { keep_alive->do_oop((oop*)next_addr); } + iter.move_to_next(); } else { iter.next(); } } // Now close the newly reachable set
*** 830,842 **** move_tail = new_head; new_head = java_lang_ref_Reference::discovered(new_head); } java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); ref_lists[to_idx].set_head(move_head); ! ref_lists[to_idx].set_length(ref_lists[to_idx].length() + refs_to_move); ref_lists[from_idx].set_head(new_head); ! ref_lists[from_idx].set_length(ref_lists[from_idx].length() - refs_to_move); } else { ++to_idx; } } } --- 834,846 ---- move_tail = new_head; new_head = java_lang_ref_Reference::discovered(new_head); } java_lang_ref_Reference::set_discovered(move_tail, ref_lists[to_idx].head()); ref_lists[to_idx].set_head(move_head); ! ref_lists[to_idx].inc_length(refs_to_move); ref_lists[from_idx].set_head(new_head); ! ref_lists[from_idx].dec_length(refs_to_move); } else { ++to_idx; } } }
*** 921,931 **** } void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) { assert(!discovery_is_atomic(), "Else why call this method?"); DiscoveredListIterator iter(refs_list, NULL, NULL); - size_t length = refs_list.length(); 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(), "bad next field"); // If referent has been cleared or Reference is not active, --- 925,934 ----
*** 939,954 **** iter.obj(), next, iter.referent()); } ) // Remove Reference object from list iter.remove(); ! --length; } else { iter.next(); } } - refs_list.set_length(length); NOT_PRODUCT( if (PrintGCDetails && TraceReferenceGC) { gclog_or_tty->print( " Removed %d Refs with NULL referents out of %d discovered Refs", iter.removed(), iter.processed()); --- 942,956 ---- iter.obj(), next, 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());
*** 1022,1032 **** if (retest == NULL) { // This thread just won the right to enqueue the object. // We have separate lists for enqueueing so no synchronization // is necessary. refs_list.set_head(obj); ! refs_list.set_length(refs_list.length() + 1); if (_discovered_list_needs_barrier) { _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); } } else { --- 1024,1034 ---- if (retest == NULL) { // This thread just won the right to enqueue the object. // We have separate lists for enqueueing so no synchronization // is necessary. refs_list.set_head(obj); ! refs_list.inc_length(1); if (_discovered_list_needs_barrier) { _bs->write_ref_field((void*)discovered_addr, current_head); guarantee(false, "Needs to be fixed: YSR"); } } else {
*** 1166,1176 **** oop_store_raw(discovered_addr, current_head); if (_discovered_list_needs_barrier) { _bs->write_ref_field((oop*)discovered_addr, current_head); } list->set_head(obj); ! list->set_length(list->length() + 1); } // In the MT discovery case, it is currently possible to see // the following message multiple times if several threads // discover a reference about the same time. Only one will --- 1168,1178 ---- oop_store_raw(discovered_addr, current_head); if (_discovered_list_needs_barrier) { _bs->write_ref_field((oop*)discovered_addr, current_head); } list->set_head(obj); ! list->inc_length(1); } // In the MT discovery case, it is currently possible to see // the following message multiple times if several threads // discover a reference about the same time. Only one will
*** 1207,1274 **** // Soft references { TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, keep_alive, complete_gc, yield); } } - if (yield->should_return()) { - return; - } // Weak references { TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, keep_alive, complete_gc, yield); } } - if (yield->should_return()) { - return; - } // Final references { TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, keep_alive, complete_gc, yield); } } - if (yield->should_return()) { - return; - } // Phantom references { TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { 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 ! // are not active (have a non-NULL next field). NOTE: For this to work ! // correctly, refs discovery can not be happening concurrently with this ! // step. 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); - size_t length = refs_list.length(); 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() || --- 1209,1281 ---- // Soft references { TraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { + if (yield->should_return()) { + return; + } preclean_discovered_reflist(_discoveredSoftRefs[i], is_alive, keep_alive, complete_gc, yield); } } // Weak references { TraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { + if (yield->should_return()) { + return; + } preclean_discovered_reflist(_discoveredWeakRefs[i], is_alive, keep_alive, complete_gc, yield); } } // Final references { TraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; i++) { + if (yield->should_return()) { + return; + } preclean_discovered_reflist(_discoveredFinalRefs[i], is_alive, keep_alive, complete_gc, yield); } } // Phantom references { TraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC, false, gclog_or_tty); for (int i = 0; i < _num_q; 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 ! // are not active (have a non-NULL next field). NOTE: When we are ! // thus precleaning the ref lists (which happens single-threaded today), ! // we do not disable refs discovery to honour 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() ||
*** 1279,1304 **** gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)", iter.obj(), iter.obj()->blueprint()->internal_name()); } // Remove Reference object from list iter.remove(); - --length; // Keep alive its cohort. iter.make_referent_alive(); if (UseCompressedOops) { narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); keep_alive->do_oop(next_addr); } else { oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); keep_alive->do_oop(next_addr); } } else { iter.next(); } } - refs_list.set_length(length); - // Close the reachable set complete_gc->do_void(); NOT_PRODUCT( if (PrintGCDetails && PrintReferenceGC) { --- 1286,1309 ---- gclog_or_tty->print_cr("Precleaning Reference (" INTPTR_FORMAT ": %s)", iter.obj(), iter.obj()->blueprint()->internal_name()); } // Remove Reference object from list iter.remove(); // Keep alive its cohort. iter.make_referent_alive(); if (UseCompressedOops) { narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj); keep_alive->do_oop(next_addr); } else { oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj); keep_alive->do_oop(next_addr); } + iter.move_to_next(); } else { iter.next(); } } // Close the reachable set complete_gc->do_void(); NOT_PRODUCT( if (PrintGCDetails && PrintReferenceGC) {