diff --git a/src/hotspot/share/code/icBuffer.cpp b/src/hotspot/share/code/icBuffer.cpp index a26ec16..8e0fee4 100644 --- a/src/hotspot/share/code/icBuffer.cpp +++ b/src/hotspot/share/code/icBuffer.cpp @@ -42,10 +42,10 @@ DEF_STUB_INTERFACE(ICStub); StubQueue* InlineCacheBuffer::_buffer = NULL; -ICStub* InlineCacheBuffer::_next_stub = NULL; CompiledICHolder* InlineCacheBuffer::_pending_released = NULL; int InlineCacheBuffer::_pending_count = 0; +DEBUG_ONLY(volatile int InlineCacheBuffer::_needs_refill = 0;) void ICStub::finalize() { if (!is_empty()) { @@ -103,52 +103,45 @@ void ICStub::print() { //----------------------------------------------------------------------------------------------- // Implementation of InlineCacheBuffer -void InlineCacheBuffer::init_next_stub() { - ICStub* ic_stub = (ICStub*)buffer()->request_committed (ic_stub_code_size()); - assert (ic_stub != NULL, "no room for a single stub"); - set_next_stub(ic_stub); -} void InlineCacheBuffer::initialize() { if (_buffer != NULL) return; // already initialized _buffer = new StubQueue(new ICStubInterface, 10*K, InlineCacheBuffer_lock, "InlineCacheBuffer"); assert (_buffer != NULL, "cannot allocate InlineCacheBuffer"); - init_next_stub(); } ICStub* InlineCacheBuffer::new_ic_stub() { - while (true) { - ICStub* ic_stub = (ICStub*)buffer()->request_committed(ic_stub_code_size()); - if (ic_stub != NULL) { - return ic_stub; - } - // we ran out of inline cache buffer space; must enter safepoint. - // We do this by forcing a safepoint - EXCEPTION_MARK; - - VM_ICBufferFull ibf; - VMThread::execute(&ibf); - // We could potential get an async. exception at this point. - // In that case we will rethrow it to ourselvs. - if (HAS_PENDING_EXCEPTION) { - oop exception = PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; - Thread::send_async_exception(JavaThread::current()->threadObj(), exception); - } + return (ICStub*)buffer()->request_committed(ic_stub_code_size()); +} + + +void InlineCacheBuffer::refill_ic_stubs() { + DEBUG_ONLY(Atomic::store(0, &_needs_refill)); + // we ran out of inline cache buffer space; must enter safepoint. + // We do this by forcing a safepoint + EXCEPTION_MARK; + + VM_ICBufferFull ibf; + VMThread::execute(&ibf); + // We could potential get an async. exception at this point. + // In that case we will rethrow it to ourselvs. + if (HAS_PENDING_EXCEPTION) { + oop exception = PENDING_EXCEPTION; + CLEAR_PENDING_EXCEPTION; + Thread::send_async_exception(JavaThread::current()->threadObj(), exception); } - ShouldNotReachHere(); - return NULL; } void InlineCacheBuffer::update_inline_caches() { - if (buffer()->number_of_stubs() > 1) { + assert(_needs_refill == 0, + "Forgot to handle a failed IC transition requiring IC stubs"); + if (buffer()->number_of_stubs() > 0) { if (TraceICBuffer) { tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs()); } buffer()->remove_all(); - init_next_stub(); } release_pending_icholders(); } @@ -160,7 +153,7 @@ bool InlineCacheBuffer::contains(address instruction_address) { bool InlineCacheBuffer::is_empty() { - return buffer()->number_of_stubs() == 1; // always has sentinel + return buffer()->number_of_stubs() == 0; } @@ -169,8 +162,7 @@ void InlineCacheBuffer_init() { } -void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) { - MutexLockerEx ml(CompiledIC_lock->owned_by_self() ? NULL : CompiledIC_lock); +bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) { assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint"); assert(CompiledICLocker::is_safe(ic->instruction_address()), "mt unsafe call"); if (TraceICBuffer) { @@ -178,20 +170,24 @@ void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_valu p2i(ic->instruction_address()), p2i(entry), p2i(cached_value)); } + // allocate and initialize new "out-of-line" inline-cache + ICStub* ic_stub = new_ic_stub(); + if (ic_stub == NULL) { + DEBUG_ONLY(Atomic::inc(&_needs_refill)); + return false; + } + // 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_value, entry); // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache ic->set_ic_destination(ic_stub); - - set_next_stub(new_ic_stub()); // can cause safepoint synchronization + return true; } @@ -225,9 +221,7 @@ void InlineCacheBuffer::release_pending_icholders() { // not safe to free them until them since they might be visible to // another thread. void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) { - MutexLockerEx mex1((CompiledIC_lock->owned_by_self() || - SafepointSynchronize::is_at_safepoint()) ? NULL : CompiledIC_lock); - MutexLockerEx mex2(InlineCacheBuffer_lock); + MutexLockerEx mex(InlineCacheBuffer_lock, Mutex::_no_safepoint_check_flag); icholder->set_next(_pending_released); _pending_released = icholder; _pending_count++;