< prev index next >
src/share/vm/code/nmethod.cpp
Print this page
rev 6875 : 8056240: Investigate increased GC remark time after class unloading changes in CRM Fuse
Reviewed-by: mgerdin, coleenp, bdelsart
*** 1718,1739 ****
// attempt to report the event in the unlikely scenario where the
// event is enabled at the time the nmethod is made a zombie.
set_unload_reported();
}
! void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) {
if (ic->is_icholder_call()) {
// The only exception is compiledICHolder oops which may
// yet be marked below. (We check this further below).
CompiledICHolder* cichk_oop = ic->cached_icholder();
if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
return;
}
} else {
Metadata* ic_oop = ic->cached_metadata();
if (ic_oop != NULL) {
if (ic_oop->is_klass()) {
if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
return;
}
} else if (ic_oop->is_method()) {
--- 1718,1749 ----
// attempt to report the event in the unlikely scenario where the
// event is enabled at the time the nmethod is made a zombie.
set_unload_reported();
}
! void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive, bool mark_on_stack) {
if (ic->is_icholder_call()) {
// The only exception is compiledICHolder oops which may
// yet be marked below. (We check this further below).
CompiledICHolder* cichk_oop = ic->cached_icholder();
+
+ if (mark_on_stack) {
+ Metadata::mark_on_stack(cichk_oop->holder_method());
+ Metadata::mark_on_stack(cichk_oop->holder_klass());
+ }
+
if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
return;
}
} else {
Metadata* ic_oop = ic->cached_metadata();
if (ic_oop != NULL) {
+ if (mark_on_stack) {
+ Metadata::mark_on_stack(ic_oop);
+ }
+
if (ic_oop->is_klass()) {
if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
return;
}
} else if (ic_oop->is_method()) {
*** 1790,1800 ****
if (unloading_occurred) {
RelocIterator iter(this, low_boundary);
while(iter.next()) {
if (iter.type() == relocInfo::virtual_call_type) {
CompiledIC *ic = CompiledIC_at(&iter);
! clean_ic_if_metadata_is_dead(ic, is_alive);
}
}
}
// Compiled code
--- 1800,1810 ----
if (unloading_occurred) {
RelocIterator iter(this, low_boundary);
while(iter.next()) {
if (iter.type() == relocInfo::virtual_call_type) {
CompiledIC *ic = CompiledIC_at(&iter);
! clean_ic_if_metadata_is_dead(ic, is_alive, false);
}
}
}
// Compiled code
*** 1858,1867 ****
--- 1868,1924 ----
static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, BoolObjectClosure *is_alive, nmethod* from) {
return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from);
}
+ bool nmethod::unload_if_dead_at(RelocIterator* iter_at_oop, BoolObjectClosure *is_alive, bool unloading_occurred) {
+ assert(iter_at_oop->type() == relocInfo::oop_type, "Wrong relocation type");
+
+ oop_Relocation* r = iter_at_oop->oop_reloc();
+ // Traverse those oops directly embedded in the code.
+ // Other oops (oop_index>0) are seen as part of scopes_oops.
+ assert(1 == (r->oop_is_immediate()) +
+ (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()),
+ "oop must be found in exactly one place");
+ if (r->oop_is_immediate() && r->oop_value() != NULL) {
+ // Unload this nmethod if the oop is dead.
+ if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) {
+ return true;;
+ }
+ }
+
+ return false;
+ }
+
+ void nmethod::mark_metadata_on_stack_at(RelocIterator* iter_at_metadata) {
+ assert(iter_at_metadata->type() == relocInfo::metadata_type, "Wrong relocation type");
+
+ metadata_Relocation* r = iter_at_metadata->metadata_reloc();
+ // In this metadata, we must only follow those metadatas directly embedded in
+ // the code. Other metadatas (oop_index>0) are seen as part of
+ // the metadata section below.
+ assert(1 == (r->metadata_is_immediate()) +
+ (r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()),
+ "metadata must be found in exactly one place");
+ if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
+ Metadata* md = r->metadata_value();
+ if (md != _method) Metadata::mark_on_stack(md);
+ }
+ }
+
+ void nmethod::mark_metadata_on_stack_non_relocs() {
+ // Visit the metadata section
+ for (Metadata** p = metadata_begin(); p < metadata_end(); p++) {
+ if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops
+ Metadata* md = *p;
+ Metadata::mark_on_stack(md);
+ }
+
+ // Visit metadata not embedded in the other places.
+ if (_method != NULL) Metadata::mark_on_stack(_method);
+ }
+
bool nmethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) {
ResourceMark rm;
// Make sure the oop's ready to receive visitors
assert(!is_zombie() && !is_unloaded(),
*** 1887,1896 ****
--- 1944,1958 ----
// call to post_compiled_method_unload() so that the unloading
// of this nmethod is reported.
unloading_occurred = true;
}
+ // When class redefinition is used all metadata in the CodeCache has to be recorded,
+ // so that unused "previous versions" can be purged. Since walking the CodeCache can
+ // be expensive, the "mark on stack" is piggy-backed on this parallel unloading code.
+ bool mark_metadata_on_stack = a_class_was_redefined;
+
// Exception cache
clean_exception_cache(is_alive);
bool is_unloaded = false;
bool postponed = false;
*** 1902,1912 ****
case relocInfo::virtual_call_type:
if (unloading_occurred) {
// If class unloading occurred we first iterate over all inline caches and
// clear ICs where the cached oop is referring to an unloaded klass or method.
! clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive);
}
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
break;
--- 1964,1974 ----
case relocInfo::virtual_call_type:
if (unloading_occurred) {
// If class unloading occurred we first iterate over all inline caches and
// clear ICs where the cached oop is referring to an unloaded klass or method.
! clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive, mark_metadata_on_stack);
}
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
break;
*** 1918,1944 ****
postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
break;
case relocInfo::oop_type:
if (!is_unloaded) {
! // Unload check
! oop_Relocation* r = iter.oop_reloc();
! // Traverse those oops directly embedded in the code.
! // Other oops (oop_index>0) are seen as part of scopes_oops.
! assert(1 == (r->oop_is_immediate()) +
! (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()),
! "oop must be found in exactly one place");
! if (r->oop_is_immediate() && r->oop_value() != NULL) {
! if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) {
! is_unloaded = true;
! }
! }
}
break;
}
}
if (is_unloaded) {
return postponed;
}
--- 1980,2003 ----
postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
break;
case relocInfo::oop_type:
if (!is_unloaded) {
! is_unloaded = unload_if_dead_at(&iter, is_alive, unloading_occurred);
}
break;
+ case relocInfo::metadata_type:
+ if (mark_metadata_on_stack) {
+ mark_metadata_on_stack_at(&iter);
}
}
+ }
+
+ if (mark_metadata_on_stack) {
+ mark_metadata_on_stack_non_relocs();
+ }
if (is_unloaded) {
return postponed;
}
*** 2083,2093 ****
// Visit all immediate references that are embedded in the instruction stream.
RelocIterator iter(this, low_boundary);
while (iter.next()) {
if (iter.type() == relocInfo::metadata_type ) {
metadata_Relocation* r = iter.metadata_reloc();
! // In this lmetadata, we must only follow those metadatas directly embedded in
// the code. Other metadatas (oop_index>0) are seen as part of
// the metadata section below.
assert(1 == (r->metadata_is_immediate()) +
(r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()),
"metadata must be found in exactly one place");
--- 2142,2152 ----
// Visit all immediate references that are embedded in the instruction stream.
RelocIterator iter(this, low_boundary);
while (iter.next()) {
if (iter.type() == relocInfo::metadata_type ) {
metadata_Relocation* r = iter.metadata_reloc();
! // In this metadata, we must only follow those metadatas directly embedded in
// the code. Other metadatas (oop_index>0) are seen as part of
// the metadata section below.
assert(1 == (r->metadata_is_immediate()) +
(r->metadata_addr() >= metadata_begin() && r->metadata_addr() < metadata_end()),
"metadata must be found in exactly one place");
*** 2117,2127 ****
if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops
Metadata* md = *p;
f(md);
}
! // Call function Method*, not embedded in these other places.
if (_method != NULL) f(_method);
}
void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
// make sure the oops ready to receive visitors
--- 2176,2186 ----
if (*p == Universe::non_oop_word() || *p == NULL) continue; // skip non-oops
Metadata* md = *p;
f(md);
}
! // Visit metadata not embedded in the other places.
if (_method != NULL) f(_method);
}
void nmethod::oops_do(OopClosure* f, bool allow_zombie) {
// make sure the oops ready to receive visitors
< prev index next >