< prev index next >

src/hotspot/share/code/icBuffer.cpp

 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/stubRoutines.hpp"
+#include "runtime/thread.hpp"
 
 DEF_STUB_INTERFACE(ICStub);
 
 StubQueue* InlineCacheBuffer::_buffer    = NULL;
 
 CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;
 int InlineCacheBuffer::_pending_count = 0;
-DEBUG_ONLY(volatile int InlineCacheBuffer::_needs_refill = 0;)
+
+#ifdef ASSERT
+ICRefillVerifier::ICRefillVerifier()
+  : _refill_requested(false),
+    _refill_remembered(false)
+{
+  Thread* thread = Thread::current();
+  assert(thread->missed_ic_stub_refill_mark() == NULL, "nesting not supported");
+  thread->set_missed_ic_stub_refill_mark(this);
+}
+
+ICRefillVerifier::~ICRefillVerifier() {
+  assert(!_refill_requested || _refill_remembered,
+         "Forgot to refill IC stubs after failed IC transition");
+  Thread::current()->set_missed_ic_stub_refill_mark(NULL);
+}
+
+ICRefillVerifierMark::ICRefillVerifierMark(ICRefillVerifier* verifier) {
+  Thread* thread = Thread::current();
+  assert(thread->missed_ic_stub_refill_mark() == NULL, "nesting not supported");
+  thread->set_missed_ic_stub_refill_mark(this);
+}
+
+ICRefillVerifierMark::~ICRefillVerifierMark() {
+  Thread::current()->set_missed_ic_stub_refill_mark(NULL);
+}
+
+static ICRefillVerifier* current_ic_refill_verifier() {
+  Thread* current = Thread::current();
+  ICRefillVerifier* verifier = reinterpret_cast<ICRefillVerifier*>(current->missed_ic_stub_refill_mark());
+  assert(verifier != NULL, "need a verifier for safety");
+  return verifier;
+}
+#endif
 
 void ICStub::finalize() {
   if (!is_empty()) {
     ResourceMark rm;
     CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());

@@ -115,11 +149,14 return (ICStub*)buffer()->request_committed(ic_stub_code_size()); } void InlineCacheBuffer::refill_ic_stubs() { - DEBUG_ONLY(Atomic::store(0, &_needs_refill)); +#ifdef ASSERT + ICRefillVerifier* verifier = current_ic_refill_verifier(); + verifier->request_remembered(); +#endif // we ran out of inline cache buffer space; must enter safepoint. // We do this by forcing a safepoint EXCEPTION_MARK; VM_ICBufferFull ibf;
@@ -133,12 +170,10 } } void InlineCacheBuffer::update_inline_caches() { - 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();
@@ -159,11 +194,10 void InlineCacheBuffer_init() { InlineCacheBuffer::initialize(); } - 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) { tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
@@ -171,11 +205,14 } // 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)); +#ifdef ASSERT + ICRefillVerifier* verifier = current_ic_refill_verifier(); + verifier->request_refill(); +#endif return false; } // If an transition stub is already associate with the inline cache, then we remove the association. if (ic->is_in_transition_state()) {
< prev index next >