src/share/vm/code/nmethod.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
8029443 Cdiff src/share/vm/code/nmethod.cpp
src/share/vm/code/nmethod.cpp
Print this page
*** 1716,1725 ****
--- 1716,1743 ----
}
ic->set_to_clean();
}
+ /**
+ * Checks if the to-interpreter stub of an optimized compiled IC or a compiled
+ * static call contains a reference to dead Method* metadata.
+ */
+ bool nmethod::stub_contains_dead_metadata(BoolObjectClosure* is_alive, address stub) {
+ RelocIterator iter(this, stub, stub + CompiledStaticCall::to_interp_stub_size());
+ while (iter.next()) {
+ if (iter.type() == relocInfo::metadata_type) {
+ Metadata* md = iter.metadata_reloc()->metadata_value();
+ // Check if class loader of holder Klass is alive
+ if (md != NULL && md->is_method() && !((Method*)md)->method_holder()->is_loader_alive(is_alive)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
// This is called at the end of the strong tracing/marking phase of a
// GC to unload an nmethod if it contains otherwise unreachable
// oops.
void nmethod::do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred) {
*** 1751,1769 ****
// Exception cache
clean_exception_cache(is_alive);
// 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.
! // The remaining live cached oops will be traversed in the relocInfo::oop_type
! // iteration below.
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
--- 1769,1805 ----
// Exception cache
clean_exception_cache(is_alive);
// If class unloading occurred we first iterate over all inline caches and
! // clear ICs where the cached oop or the to-interpreter stub (if in use) is
! // referring to an unloaded klass or method. The to-interpreter stubs of
! // compiled static calls are checked as well. The remaining live cached oops
! // will be traversed in the relocInfo::oop_type iteration below.
if (unloading_occurred) {
RelocIterator iter(this, low_boundary);
while(iter.next()) {
! switch (iter.type()) {
! case relocInfo::virtual_call_type: {
! CompiledIC* ic = CompiledIC_at(&iter);
clean_ic_if_metadata_is_dead(ic, is_alive);
+ break;
+ }
+ case relocInfo::opt_virtual_call_type: {
+ CompiledIC* ic = CompiledIC_at(&iter);
+ if (ic->is_call_to_interpreted() && stub_contains_dead_metadata(is_alive, ic->ic_destination())) {
+ ic->set_to_clean();
+ }
+ break;
+ }
+ case relocInfo::static_call_type: {
+ CompiledStaticCall* csc = compiledStaticCall_at(iter.reloc());
+ if (csc->is_call_to_interpreted() && stub_contains_dead_metadata(is_alive, csc->destination())) {
+ csc->set_to_clean();
+ }
+ break;
+ }
}
}
}
// Compiled code
*** 1878,1891 ****
--- 1914,1941 ----
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
break;
case relocInfo::opt_virtual_call_type:
+ if (unloading_occurred) {
+ // Clear IC if it calls a to-interpreter stub that refers to an unloaded method
+ CompiledIC* ic = CompiledIC_at(&iter);
+ if (ic->is_call_to_interpreted() && stub_contains_dead_metadata(is_alive, ic->ic_destination())) {
+ ic->set_to_clean();
+ }
+ }
postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
break;
case relocInfo::static_call_type:
+ if (unloading_occurred) {
+ // Clear call if it targets a to-interpreter stub that refers to an unloaded method
+ CompiledStaticCall* csc = compiledStaticCall_at(iter.reloc());
+ if (csc->is_call_to_interpreted() && stub_contains_dead_metadata(is_alive, csc->destination())) {
+ csc->set_to_clean();
+ }
+ }
postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
break;
case relocInfo::oop_type:
if (!is_unloaded) {
src/share/vm/code/nmethod.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File