< prev index next >

src/hotspot/share/code/nmethodBarrier.cpp

Concurrent class unloading
 #include "gc/shared/barrierSet.hpp"
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/orderAccess.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/spinYield.hpp"
 
 bool nmethodBarrierState::is_safe() const {
-  CounterUnion twin_value;
-  twin_value._value = Atomic::load(&_state);
-  return twin_value._counters._lock > 0;
+  return Thread::current()->in_nmethod_entry_barrier();
 }
 
 bool nmethodBarrierState::enter() {
   while (true) {
     CounterUnion old;

@@ -49,22 +47,26 CounterUnion next; next._value = old._value; int disarmed_value = nmethodBarrier::disarmed_value(); + assert(disarmed_value != 0, "sanity"); + if (old._counters._epoch != disarmed_value) { next._counters._epoch = disarmed_value; next._counters._lock = 1; } else if (old._counters._lock == 0) { return false; } else { ++next._counters._lock; } assert(next._counters._lock > 0, "check"); + assert(next._counters._epoch == nmethodBarrier::disarmed_value(), "sanity"); if (Atomic::cmpxchg(next._value, &_state, old._value) == old._value) { + Thread::current()->set_is_in_nmethod_entry_barrier(true); return true; } } }
@@ -76,11 +78,16 CounterUnion next; next._value = old._value; --next._counters._lock; + assert(old._counters._epoch == nmethodBarrier::disarmed_value(), "sanity"); + assert(old._counters._lock > 0, "check"); + assert(next._counters._lock >= 0, "check"); + if (Atomic::cmpxchg(next._value, &_state, old._value) == old._value) { + Thread::current()->set_is_in_nmethod_entry_barrier(false); return; } } }
@@ -117,17 +124,10 nmethod* nm = cb->as_nmethod(); nmethodBarrier nmbarrier(nm, return_address_ptr); return bs->on_nmethod_entry_barrier(nm, &nmbarrier) ? 0 : 1; } -void nmethodBarrier::initialize(nmethod* nm) { - BarrierSet* bs = BarrierSet::barrier_set(); - if (bs->needs_nmethod_entry_barrier()) { - nm->disarm_barrier(); - } -} - void nmethodBarrier::disarm() { _nm->disarm_barrier(); // multiple threads can enter the barrier at the same time while armed // one can finish and decide that the barrier can be disarmed, in the meantime the other // have made the same decision continued on and deoptimized on something else.
@@ -135,10 +135,16 assert(!_is_deoptimized, "can only disarm methods that didn't deoptimize!"); } int nmethodBarrier::disarmed_value() { BarrierSet* bs = BarrierSet::barrier_set(); + int value = bs->nmethod_entry_barrier_state(); +#ifdef ASSERT Thread* thread = Thread::current(); - int* state_addr = reinterpret_cast<int*>(reinterpret_cast<char*>(thread) + - in_bytes(bs->nmethod_entry_barrier_state_thread_offset())); - return *state_addr; + if (thread->is_Java_thread()) { + int* state_addr = reinterpret_cast<int*>(reinterpret_cast<char*>(thread) + + in_bytes(bs->nmethod_entry_barrier_state_thread_offset())); + assert(*state_addr == value, "global and local values out of sync"); + } +#endif + return value; }
< prev index next >