Path: blob/master/src/hotspot/share/code/icBuffer.cpp
40943 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "code/codeCache.hpp"26#include "code/compiledIC.hpp"27#include "code/icBuffer.hpp"28#include "code/nmethod.hpp"29#include "code/scopeDesc.hpp"30#include "gc/shared/collectedHeap.inline.hpp"31#include "interpreter/interpreter.hpp"32#include "interpreter/linkResolver.hpp"33#include "memory/resourceArea.hpp"34#include "oops/method.hpp"35#include "oops/oop.inline.hpp"36#include "runtime/handles.inline.hpp"37#include "runtime/mutexLocker.hpp"38#include "runtime/stubRoutines.hpp"39#include "runtime/thread.inline.hpp"40#include "runtime/vmOperations.hpp"4142DEF_STUB_INTERFACE(ICStub);4344StubQueue* InlineCacheBuffer::_buffer = NULL;4546CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;47int InlineCacheBuffer::_pending_count = 0;4849#ifdef ASSERT50ICRefillVerifier::ICRefillVerifier()51: _refill_requested(false),52_refill_remembered(false)53{54Thread* thread = Thread::current();55assert(thread->missed_ic_stub_refill_verifier() == NULL, "nesting not supported");56thread->set_missed_ic_stub_refill_verifier(this);57}5859ICRefillVerifier::~ICRefillVerifier() {60assert(!_refill_requested || _refill_remembered,61"Forgot to refill IC stubs after failed IC transition");62Thread::current()->set_missed_ic_stub_refill_verifier(NULL);63}6465ICRefillVerifierMark::ICRefillVerifierMark(ICRefillVerifier* verifier) {66Thread* thread = Thread::current();67assert(thread->missed_ic_stub_refill_verifier() == NULL, "nesting not supported");68thread->set_missed_ic_stub_refill_verifier(verifier);69}7071ICRefillVerifierMark::~ICRefillVerifierMark() {72Thread::current()->set_missed_ic_stub_refill_verifier(NULL);73}7475static ICRefillVerifier* current_ic_refill_verifier() {76Thread* current = Thread::current();77ICRefillVerifier* verifier = current->missed_ic_stub_refill_verifier();78assert(verifier != NULL, "need a verifier for safety");79return verifier;80}81#endif8283void ICStub::finalize() {84if (!is_empty()) {85ResourceMark rm;86CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());87assert(CodeCache::find_compiled(ic->instruction_address()) != NULL, "inline cache in non-compiled?");8889assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");90ic->set_ic_destination_and_value(destination(), cached_value());91}92}939495address ICStub::destination() const {96return InlineCacheBuffer::ic_buffer_entry_point(code_begin());97}9899void* ICStub::cached_value() const {100return InlineCacheBuffer::ic_buffer_cached_value(code_begin());101}102103104void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) {105// We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we106// store the location of the inline cache. Then we have enough information recreate the CompiledIC107// object when we need to remove the stub.108_ic_site = ic->instruction_address();109110// Assemble new stub111InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr);112assert(destination() == dest_addr, "can recover destination");113assert(cached_value() == cached_val, "can recover destination");114}115116117void ICStub::clear() {118if (CompiledIC::is_icholder_entry(destination())) {119InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());120}121_ic_site = NULL;122}123124125#ifndef PRODUCT126// anybody calling to this stub will trap127128void ICStub::verify() {129}130131void ICStub::print() {132tty->print_cr("ICStub: site: " INTPTR_FORMAT, p2i(_ic_site));133}134#endif135136//-----------------------------------------------------------------------------------------------137// Implementation of InlineCacheBuffer138139140void InlineCacheBuffer::initialize() {141if (_buffer != NULL) return; // already initialized142_buffer = new StubQueue(new ICStubInterface, 10*K, InlineCacheBuffer_lock, "InlineCacheBuffer");143assert (_buffer != NULL, "cannot allocate InlineCacheBuffer");144}145146147ICStub* InlineCacheBuffer::new_ic_stub() {148return (ICStub*)buffer()->request_committed(ic_stub_code_size());149}150151152void InlineCacheBuffer::refill_ic_stubs() {153#ifdef ASSERT154ICRefillVerifier* verifier = current_ic_refill_verifier();155verifier->request_remembered();156#endif157// we ran out of inline cache buffer space; must enter safepoint.158// We do this by forcing a safepoint159VM_ICBufferFull ibf;160VMThread::execute(&ibf);161}162163void InlineCacheBuffer::update_inline_caches() {164if (buffer()->number_of_stubs() > 0) {165if (TraceICBuffer) {166tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());167}168buffer()->remove_all();169}170release_pending_icholders();171}172173174bool InlineCacheBuffer::contains(address instruction_address) {175return buffer()->contains(instruction_address);176}177178179bool InlineCacheBuffer::is_empty() {180return buffer()->number_of_stubs() == 0;181}182183184void InlineCacheBuffer_init() {185InlineCacheBuffer::initialize();186}187188bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {189assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");190assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call");191if (TraceICBuffer) {192tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,193p2i(ic->instruction_address()), p2i(entry), p2i(cached_value));194}195196// allocate and initialize new "out-of-line" inline-cache197ICStub* ic_stub = new_ic_stub();198if (ic_stub == NULL) {199#ifdef ASSERT200ICRefillVerifier* verifier = current_ic_refill_verifier();201verifier->request_refill();202#endif203return false;204}205206// If an transition stub is already associate with the inline cache, then we remove the association.207if (ic->is_in_transition_state()) {208ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());209old_stub->clear();210}211212ic_stub->set_stub(ic, cached_value, entry);213214// Update inline cache in nmethod to point to new "out-of-line" allocated inline cache215ic->set_ic_destination(ic_stub);216return true;217}218219220address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {221ICStub* stub = ICStub_from_destination_address(ic->stub_address());222return stub->destination();223}224225226void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {227ICStub* stub = ICStub_from_destination_address(ic->stub_address());228return stub->cached_value();229}230231232// Free CompiledICHolder*s that are no longer in use233void InlineCacheBuffer::release_pending_icholders() {234assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");235CompiledICHolder* holder = _pending_released;236_pending_released = NULL;237while (holder != NULL) {238CompiledICHolder* next = holder->next();239delete holder;240holder = next;241_pending_count--;242}243assert(_pending_count == 0, "wrong count");244}245246// Enqueue this icholder for release during the next safepoint. It's247// not safe to free them until them since they might be visible to248// another thread.249void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {250MutexLocker mex(InlineCacheBuffer_lock, Mutex::_no_safepoint_check_flag);251icholder->set_next(_pending_released);252_pending_released = icholder;253_pending_count++;254if (TraceICBuffer) {255tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", p2i(icholder));256}257}258259260