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