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