void ICStub::finalize() { if (!is_empty()) { ResourceMark rm; CompiledIC *ic = CompiledIC_at(CodeCache::find_nmethod(ic_site()), ic_site()); assert(CodeCache::find_nmethod(ic->instruction_address()) != NULL, "inline cache in non-nmethod?"); assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer"); ic->set_ic_destination_and_value(destination(), cached_value()); } }
void CompiledIC::set_to_clean() { assert(SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->is_locked() , "MT-unsafe call"); if (TraceInlineCacheClearing || TraceICs) { tty->print_cr("IC@" INTPTR_FORMAT ": set to clean", instruction_address()); print(); } address entry; #ifdef COMPILER1 entry = is_optimized() ? Runtime1::entry_for(Runtime1::resolve_invoke_opt_virtual_id) : Runtime1::entry_for(Runtime1::resolve_invokevirtual_id); #else entry = is_optimized() ? OptoRuntime::resolve_opt_virtual_call_Java() : OptoRuntime::resolve_virtual_call_Java(); #endif // A zombie transition will always be safe, since the oop has already been set to NULL, so // we only need to patch the destination bool safe_transition = is_optimized() || SafepointSynchronize::is_at_safepoint(); if (safe_transition) { if (!is_optimized()) set_cached_oop(NULL); // Kill any leftover stub we might have too if (is_in_transition_state()) { ICStub* old_stub = ICStub_from_destination_address(stub_address()); old_stub->clear(); } set_ic_destination(entry); } else { // Unsafe transition - create stub. InlineCacheBuffer::create_transition_stub(this, NULL, 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_clean(), "sanity check"); }
void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, oop cached_oop, address entry) { assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint"); assert (CompiledIC_lock->is_locked(), ""); assert(cached_oop == NULL || cached_oop->is_perm(), "must belong to perm. space"); if (TraceICBuffer) { tty->print_cr(" create transition stub for " INTPTR_FORMAT, ic->instruction_address()); } // If an transition stub is already associate with the inline cache, then we remove the association. if (ic->is_in_transition_state()) { ICStub* old_stub = ICStub_from_destination_address(ic->stub_address()); old_stub->clear(); } // allocate and initialize new "out-of-line" inline-cache ICStub* ic_stub = get_next_stub(); ic_stub->set_stub(ic, cached_oop, entry); // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache ic->set_ic_destination(ic_stub->code_begin()); set_next_stub(new_ic_stub()); // can cause safepoint synchronization }
void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) { ICStub* stub = ICStub_from_destination_address(ic->stub_address()); return stub->cached_value(); }
address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) { ICStub* stub = ICStub_from_destination_address(ic->stub_address()); return stub->destination(); }
// Clears the IC stub if the compiled IC is in transition state void CompiledIC::clear_ic_stub() { if (is_in_transition_state()) { ICStub* stub = ICStub_from_destination_address(stub_address()); stub->clear(); } }