CompiledICHolder* claim_cached_icholder() { assert(_is_icholder, ""); assert(_cached_value != NULL, "must be non-NULL"); _release_icholder = false; CompiledICHolder* icholder = (CompiledICHolder*)_cached_value; icholder->claim(); return icholder; }
~CompiledICInfo() { // In rare cases the info is computed but not used, so release any // CompiledICHolder* that was created if (_release_icholder) { assert(_is_icholder, "must be"); CompiledICHolder* icholder = (CompiledICHolder*)_cached_value; icholder->claim(); delete icholder; } }
// Free CompiledICHolder*s that are no longer in use void InlineCacheBuffer::release_pending_icholders() { assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint"); CompiledICHolder* holder = _pending_released; _pending_released = NULL; while (holder != NULL) { CompiledICHolder* next = holder->next(); delete holder; holder = next; _pending_count--; } assert(_pending_count == 0, "wrong count"); }
bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) { assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), ""); assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic"); assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?"); address entry; if (call_info->call_kind() == CallInfo::itable_call) { assert(bytecode == Bytecodes::_invokeinterface, ""); int itable_index = call_info->itable_index(); entry = VtableStubs::find_itable_stub(itable_index); if (entry == false) { return false; } #ifdef ASSERT int index = call_info->resolved_method()->itable_index(); assert(index == itable_index, "CallInfo pre-computes this"); InstanceKlass* k = call_info->resolved_method()->method_holder(); assert(k->verify_itable_index(itable_index), "sanity check"); #endif //ASSERT CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), call_info->resolved_klass()(), false); holder->claim(); InlineCacheBuffer::create_transition_stub(this, holder, entry); } else { assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); // Can be different than selected_method->vtable_index(), due to package-private etc. int vtable_index = call_info->vtable_index(); assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check"); entry = VtableStubs::find_vtable_stub(vtable_index); if (entry == NULL) { return false; } InlineCacheBuffer::create_transition_stub(this, NULL, entry); } if (TraceICs) { ResourceMark rm; tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, p2i(instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry)); } // We can't check this anymore. With lazy deopt we could have already // cleaned this IC entry before we even return. This is possible if // we ran out of space in the inline cache buffer trying to do the // set_next and we safepointed to free up space. This is a benign // race because the IC entry was complete when we safepointed so // cleaning it immediately is harmless. // assert(is_megamorphic(), "sanity check"); return true; }
// Iterate over metadata calling this function. Used by RedefineClasses // Copied from nmethod::metadata_do void AOTCompiledMethod::metadata_do(void f(Metadata*)) { address low_boundary = verified_entry_point(); { // 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"); if (r->metadata_is_immediate() && r->metadata_value() != NULL) { Metadata* md = r->metadata_value(); if (md != _method) f(md); } } else if (iter.type() == relocInfo::virtual_call_type) { // Check compiledIC holders associated with this nmethod CompiledIC *ic = CompiledIC_at(&iter); if (ic->is_icholder_call()) { CompiledICHolder* cichk = ic->cached_icholder(); f(cichk->holder_method()); f(cichk->holder_klass()); } else { // Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub. Metadata* ic_oop = ic->cached_metadata(); if (ic_oop != NULL) { f(ic_oop); } } } else if (iter.type() == relocInfo::static_call_type || iter.type() == relocInfo::opt_virtual_call_type){ // Check Method* in AOT c2i stub for other calls. Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data(); if (meta != NULL) { f(meta); } } } } // Visit the metadata section for (Metadata** p = metadata_begin(); p < metadata_end(); p++) { Metadata* m = *p; intptr_t meta = (intptr_t)m; if ((meta & 1) == 1) { // already resolved m = (Metadata*)(meta & ~1); } else { continue; } assert(Metaspace::contains(m), ""); f(m); } // Visit metadata not embedded in the other places. if (_method != NULL) f(_method); }