< prev index next >
src/hotspot/share/runtime/objectMonitor.cpp
Print this page
rev 57587 : imported patch 8236035.patch.cr0
rev 57588 : dholmes CR - rename simply_set_owner_from() -> set_owner_from() and simply_set_owner_from_BasicLock() -> set_owner_from_BasicLock(); rename release_clear_owner_with_barrier() -> release_clear_owner() and refactor barrier code back into the call sites.
rev 57589 : kbarrett CR - rearrange some loads of _owner field to be more efficient; clarify header comment for try_set_owner_from() declaration; make some loads of _owner field DEBUG_ONLY since they only exist for assert()'s; update related logging calls to use the existing function parameter instead.
rev 57591 : imported patch 8235795.patch.cr0.merged
rev 57593 : coleenp CR part1: add ObjectMonitor::next_om(), set_next_om(), and try_set_next_om(); ObjectMonitor::_next_om field is now private; rename ListGlobals -> ObjectMonitorListGlobals, rename LVars -> om_list_globals, and prefix each ObjectMonitorListGlobals field with '_'; delete static set_next() function; clarify comments; coleenp CR part2: delete stale comments about mux*().
rev 57595 : v2.09a with 8235795, 8235931 and 8236035 extracted; rebased to jdk-14+28; merge with 8236035.patch.cr1; merge with 8235795.patch.cr1; merge with 8236035.patch.cr2; merge with 8235795.patch.cr2; merge with 8235795.patch.cr3.
*** 239,253 ****
// -----------------------------------------------------------------------------
// Enter support
void ObjectMonitor::enter(TRAPS) {
// The following code is ordered to check the most common cases first
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
Thread * const Self = THREAD;
! void * cur = Atomic::cmpxchg(&_owner, (void*)NULL, Self);
if (cur == NULL) {
assert(_recursions == 0, "invariant");
return;
}
--- 239,256 ----
// -----------------------------------------------------------------------------
// Enter support
void ObjectMonitor::enter(TRAPS) {
+ jint l_ref_count = ref_count();
+ ADIM_guarantee(l_ref_count > 0, "must be positive: l_ref_count=%d, ref_count=%d", l_ref_count, ref_count());
+
// The following code is ordered to check the most common cases first
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
Thread * const Self = THREAD;
! void* cur = try_set_owner_from(NULL, Self);
if (cur == NULL) {
assert(_recursions == 0, "invariant");
return;
}
*** 258,270 ****
}
if (Self->is_lock_owned((address)cur)) {
assert(_recursions == 0, "internal state error");
_recursions = 1;
! // Commute owner from a thread-specific on-stack BasicLockObject address to
! // a full-fledged "Thread *".
! _owner = Self;
return;
}
// We've encountered genuine contention.
assert(Self->_Stalled == 0, "invariant");
--- 261,281 ----
}
if (Self->is_lock_owned((address)cur)) {
assert(_recursions == 0, "internal state error");
_recursions = 1;
! set_owner_from_BasicLock(cur, Self); // Convert from BasicLock* to Thread*.
! return;
! }
!
! if (AsyncDeflateIdleMonitors &&
! try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) {
! // The deflation protocol finished the first part (setting owner),
! // but it failed the second part (making ref_count negative) and
! // bailed. Or the ObjectMonitor was async deflated and reused.
! // Acquired the monitor.
! assert(_recursions == 0, "invariant");
return;
}
// We've encountered genuine contention.
assert(Self->_Stalled == 0, "invariant");
*** 291,304 ****
assert(Self->is_Java_thread(), "invariant");
JavaThread * jt = (JavaThread *) Self;
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(jt->thread_state() != _thread_blocked, "invariant");
assert(this->object() != NULL, "invariant");
! assert(_contentions >= 0, "invariant");
! // Prevent deflation at STW-time. See deflate_idle_monitors() and is_busy().
! // Ensure the object-monitor relationship remains stable while there's contention.
Atomic::inc(&_contentions);
JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
EventJavaMonitorEnter event;
if (event.should_commit()) {
--- 302,314 ----
assert(Self->is_Java_thread(), "invariant");
JavaThread * jt = (JavaThread *) Self;
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(jt->thread_state() != _thread_blocked, "invariant");
assert(this->object() != NULL, "invariant");
! assert(_contentions >= 0, "must not be negative: contentions=%d", _contentions);
! // Keep track of contention for JVM/TI and M&M queries.
Atomic::inc(&_contentions);
JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
EventJavaMonitorEnter event;
if (event.should_commit()) {
*** 357,367 ****
// states will still report that the thread is blocked trying to
// acquire it.
}
Atomic::dec(&_contentions);
! assert(_contentions >= 0, "invariant");
Self->_Stalled = 0;
// Must either set _recursions = 0 or ASSERT _recursions == 0.
assert(_recursions == 0, "invariant");
assert(_owner == Self, "invariant");
--- 367,377 ----
// states will still report that the thread is blocked trying to
// acquire it.
}
Atomic::dec(&_contentions);
! assert(_contentions >= 0, "must not be negative: contentions=%d", _contentions);
Self->_Stalled = 0;
// Must either set _recursions = 0 or ASSERT _recursions == 0.
assert(_recursions == 0, "invariant");
assert(_owner == Self, "invariant");
*** 401,433 ****
// Callers must compensate as needed.
int ObjectMonitor::TryLock(Thread * Self) {
void * own = _owner;
if (own != NULL) return 0;
! if (Atomic::replace_if_null(&_owner, Self)) {
assert(_recursions == 0, "invariant");
return 1;
}
// The lock had been free momentarily, but we lost the race to the lock.
// Interference -- the CAS failed.
// We can either return -1 or retry.
// Retry doesn't make as much sense because the lock was just acquired.
return -1;
}
// Convert the fields used by is_busy() to a string that can be
// used for diagnostic output.
const char* ObjectMonitor::is_busy_to_string(stringStream* ss) {
! ss->print("is_busy: contentions=%d, waiters=%d, owner=" INTPTR_FORMAT
! ", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, _contentions,
! _waiters, p2i(_owner), p2i(_cxq), p2i(_EntryList));
return ss->base();
}
#define MAX_RECHECK_INTERVAL 1000
void ObjectMonitor::EnterI(TRAPS) {
Thread * const Self = THREAD;
assert(Self->is_Java_thread(), "invariant");
assert(((JavaThread *) Self)->thread_state() == _thread_blocked, "invariant");
// Try the lock - TATAS
--- 411,528 ----
// Callers must compensate as needed.
int ObjectMonitor::TryLock(Thread * Self) {
void * own = _owner;
if (own != NULL) return 0;
! if (try_set_owner_from(NULL, Self) == NULL) {
assert(_recursions == 0, "invariant");
return 1;
}
// The lock had been free momentarily, but we lost the race to the lock.
// Interference -- the CAS failed.
// We can either return -1 or retry.
// Retry doesn't make as much sense because the lock was just acquired.
return -1;
}
+ // Install the displaced mark word (dmw) of a deflating ObjectMonitor
+ // into the header of the object associated with the monitor. This
+ // idempotent method is called by a thread that is deflating a
+ // monitor and by other threads that have detected a race with the
+ // deflation process.
+ void ObjectMonitor::install_displaced_markword_in_object(const oop obj) {
+ // This function must only be called when (owner == DEFLATER_MARKER
+ // && ref_count <= 0), but we can't guarantee that here because
+ // those values could change when the ObjectMonitor gets moved from
+ // the global free list to a per-thread free list.
+
+ guarantee(obj != NULL, "must be non-NULL");
+ if (object() != obj) {
+ // ObjectMonitor's object ref no longer refers to the target object
+ // so the object's header has already been restored.
+ return;
+ }
+
+ markWord dmw = header();
+ if (dmw.value() == 0) {
+ // ObjectMonitor's header/dmw has been cleared so the ObjectMonitor
+ // has been deflated and taken off the global free list.
+ return;
+ }
+
+ // A non-NULL dmw has to be either neutral (not locked and not marked)
+ // or is already participating in this restoration protocol.
+ assert(dmw.is_neutral() || (dmw.is_marked() && dmw.hash() == 0),
+ "failed precondition: dmw=" INTPTR_FORMAT, dmw.value());
+
+ markWord marked_dmw = markWord::zero();
+ if (!dmw.is_marked() && dmw.hash() == 0) {
+ // This dmw has not yet started the restoration protocol so we
+ // mark a copy of the dmw to begin the protocol.
+ // Note: A dmw with a hashcode does not take this code path.
+ marked_dmw = dmw.set_marked();
+
+ // All of the callers to this function can be racing with each
+ // other trying to update the _header field.
+ dmw = (markWord) Atomic::cmpxchg(&_header, dmw, marked_dmw);
+ if (dmw.value() == 0) {
+ // ObjectMonitor's header/dmw has been cleared so the object's
+ // header has already been restored.
+ return;
+ }
+ // The _header field is now marked. The winner's 'dmw' variable
+ // contains the original, unmarked header/dmw value and any
+ // losers have a marked header/dmw value that will be cleaned
+ // up below.
+ }
+
+ if (dmw.is_marked()) {
+ // Clear the mark from the header/dmw copy in preparation for
+ // possible restoration from this thread.
+ assert(dmw.hash() == 0, "hashcode must be 0: dmw=" INTPTR_FORMAT,
+ dmw.value());
+ dmw = dmw.set_unmarked();
+ }
+ assert(dmw.is_neutral(), "must be neutral: dmw=" INTPTR_FORMAT, dmw.value());
+
+ // Install displaced mark word if the object's header still points
+ // to this ObjectMonitor. All racing callers to this function will
+ // reach this point, but only one can win.
+ obj->cas_set_mark(dmw, markWord::encode(this));
+
+ // Note: It does not matter which thread restored the header/dmw
+ // into the object's header. The thread deflating the monitor just
+ // wanted the object's header restored and it is. The threads that
+ // detected a race with the deflation process also wanted the
+ // object's header restored before they retry their operation and
+ // because it is restored they will only retry once.
+ }
+
// Convert the fields used by is_busy() to a string that can be
// used for diagnostic output.
const char* ObjectMonitor::is_busy_to_string(stringStream* ss) {
! ss->print("is_busy: contentions=%d, waiters=%d, ", _contentions, _waiters);
! if (!AsyncDeflateIdleMonitors) {
! ss->print("owner=" INTPTR_FORMAT, p2i(_owner));
! } else if (_owner != DEFLATER_MARKER) {
! ss->print("owner=" INTPTR_FORMAT, p2i(_owner));
! } else {
! // We report NULL instead of DEFLATER_MARKER here because is_busy()
! // ignores DEFLATER_MARKER values.
! ss->print("owner=" INTPTR_FORMAT, NULL);
! }
! ss->print(", cxq=" INTPTR_FORMAT ", EntryList=" INTPTR_FORMAT, p2i(_cxq),
! p2i(_EntryList));
return ss->base();
}
#define MAX_RECHECK_INTERVAL 1000
void ObjectMonitor::EnterI(TRAPS) {
+ jint l_ref_count = ref_count();
+ ADIM_guarantee(l_ref_count > 0, "must be positive: l_ref_count=%d, ref_count=%d", l_ref_count, ref_count());
+
Thread * const Self = THREAD;
assert(Self->is_Java_thread(), "invariant");
assert(((JavaThread *) Self)->thread_state() == _thread_blocked, "invariant");
// Try the lock - TATAS
*** 436,445 ****
--- 531,551 ----
assert(_owner == Self, "invariant");
assert(_Responsible != Self, "invariant");
return;
}
+ if (AsyncDeflateIdleMonitors &&
+ try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) {
+ // The deflation protocol finished the first part (setting owner),
+ // but it failed the second part (making ref_count negative) and
+ // bailed. Or the ObjectMonitor was async deflated and reused.
+ // Acquired the monitor.
+ assert(_succ != Self, "invariant");
+ assert(_Responsible != Self, "invariant");
+ return;
+ }
+
assert(InitDone, "Unexpectedly not initialized");
// We try one round of spinning *before* enqueueing Self.
//
// If the _owner is ready but OFFPROC we could use a YieldTo()
*** 552,561 ****
--- 658,676 ----
Self->_ParkEvent->park();
}
if (TryLock(Self) > 0) break;
+ if (AsyncDeflateIdleMonitors &&
+ try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) {
+ // The deflation protocol finished the first part (setting owner),
+ // but it failed the second part (making ref_count negative) and
+ // bailed. Or the ObjectMonitor was async deflated and reused.
+ // Acquired the monitor.
+ break;
+ }
+
// The lock is still contested.
// Keep a tally of the # of futile wakeups.
// Note that the counter is not protected by a lock or updated by atomics.
// That is by design - we trade "lossy" counters which are exposed to
// races during updates for a lower probe effect.
*** 656,665 ****
--- 771,783 ----
// monitor reentry in wait().
//
// In the future we should reconcile EnterI() and ReenterI().
void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) {
+ jint l_ref_count = ref_count();
+ ADIM_guarantee(l_ref_count > 0, "must be positive: l_ref_count=%d, ref_count=%d", l_ref_count, ref_count());
+
assert(Self != NULL, "invariant");
assert(SelfNode != NULL, "invariant");
assert(SelfNode->_thread == Self, "invariant");
assert(_waiters > 0, "invariant");
assert(((oop)(object()))->mark() == markWord::encode(this), "invariant");
*** 673,682 ****
--- 791,809 ----
assert(_owner != Self, "invariant");
if (TryLock(Self) > 0) break;
if (TrySpin(Self) > 0) break;
+ if (AsyncDeflateIdleMonitors &&
+ try_set_owner_from(DEFLATER_MARKER, Self) == DEFLATER_MARKER) {
+ // The deflation protocol finished the first part (setting owner),
+ // but it failed the second part (making ref_count negative) and
+ // bailed. Or the ObjectMonitor was async deflated and reused.
+ // Acquired the monitor.
+ break;
+ }
+
// State transition wrappers around park() ...
// ReenterI() wisely defers state transitions until
// it's clear we must park the thread.
{
OSThreadContendState osts(Self->osthread());
*** 816,827 ****
// inopportune) reclamation of "this".
//
// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
// There's one exception to the claim above, however. EnterI() can call
// exit() to drop a lock if the acquirer has been externally suspended.
! // In that case exit() is called with _thread_state as _thread_blocked,
! // but the monitor's _contentions field is > 0, which inhibits reclamation.
//
// 1-0 exit
// ~~~~~~~~
// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
// the fast-path operators have been optimized so the common ::exit()
--- 943,954 ----
// inopportune) reclamation of "this".
//
// We'd like to assert that: (THREAD->thread_state() != _thread_blocked) ;
// There's one exception to the claim above, however. EnterI() can call
// exit() to drop a lock if the acquirer has been externally suspended.
! // In that case exit() is called with _thread_state == _thread_blocked,
! // but the monitor's ref_count is > 0, which inhibits reclamation.
//
// 1-0 exit
// ~~~~~~~~
// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of
// the fast-path operators have been optimized so the common ::exit()
*** 860,878 ****
// then wake a thread unnecessarily. This is benign, and we've
// structured the code so the windows are short and the frequency
// of such futile wakups is low.
void ObjectMonitor::exit(bool not_suspended, TRAPS) {
! Thread * const Self = THREAD;
! if (THREAD != _owner) {
! if (THREAD->is_lock_owned((address) _owner)) {
! // Transmute _owner from a BasicLock pointer to a Thread address.
! // We don't need to hold _mutex for this transition.
! // Non-null to Non-null is safe as long as all readers can
! // tolerate either flavor.
assert(_recursions == 0, "invariant");
! _owner = THREAD;
_recursions = 0;
} else {
// Apparent unbalanced locking ...
// Naively we'd like to throw IllegalMonitorStateException.
// As a practical matter we can neither allocate nor throw an
--- 987,1002 ----
// then wake a thread unnecessarily. This is benign, and we've
// structured the code so the windows are short and the frequency
// of such futile wakups is low.
void ObjectMonitor::exit(bool not_suspended, TRAPS) {
! Thread* const Self = THREAD;
! void* cur = Atomic::load(&_owner);
! if (THREAD != cur) {
! if (THREAD->is_lock_owned((address)cur)) {
assert(_recursions == 0, "invariant");
! set_owner_from_BasicLock(cur, Self); // Convert from BasicLock* to Thread*.
_recursions = 0;
} else {
// Apparent unbalanced locking ...
// Naively we'd like to throw IllegalMonitorStateException.
// As a practical matter we can neither allocate nor throw an
*** 912,925 ****
#endif
for (;;) {
assert(THREAD == _owner, "invariant");
// release semantics: prior loads and stores from within the critical section
// must not float (reorder) past the following store that drops the lock.
! Atomic::release_store(&_owner, (void*)NULL); // drop the lock
! OrderAccess::storeload(); // See if we need to wake a successor
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
return;
}
// Other threads are blocked trying to acquire the lock.
--- 1036,1054 ----
#endif
for (;;) {
assert(THREAD == _owner, "invariant");
+ // Drop the lock.
// release semantics: prior loads and stores from within the critical section
// must not float (reorder) past the following store that drops the lock.
! // Uses a storeload to separate release_store(owner) from the
! // successor check. The try_set_owner() below uses cmpxchg() so
! // we get the fence down there.
! release_clear_owner(Self);
! OrderAccess::storeload();
!
if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {
return;
}
// Other threads are blocked trying to acquire the lock.
*** 957,967 ****
// Only the current lock owner can manipulate the EntryList or
// drain _cxq, so we need to reacquire the lock. If we fail
// to reacquire the lock the responsibility for ensuring succession
// falls to the new owner.
//
! if (!Atomic::replace_if_null(&_owner, THREAD)) {
return;
}
guarantee(_owner == THREAD, "invariant");
--- 1086,1096 ----
// Only the current lock owner can manipulate the EntryList or
// drain _cxq, so we need to reacquire the lock. If we fail
// to reacquire the lock the responsibility for ensuring succession
// falls to the new owner.
//
! if (try_set_owner_from(NULL, Self) != NULL) {
return;
}
guarantee(_owner == THREAD, "invariant");
*** 1089,1101 ****
// Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
// The thread associated with Wakee may have grabbed the lock and "Wakee" may be
// out-of-scope (non-extant).
Wakee = NULL;
! // Drop the lock
! Atomic::release_store(&_owner, (void*)NULL);
! OrderAccess::fence(); // ST _owner vs LD in unpark()
DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
Trigger->unpark();
// Maintain stats and report events to JVMTI
--- 1218,1231 ----
// Hygiene -- once we've set _owner = NULL we can't safely dereference Wakee again.
// The thread associated with Wakee may have grabbed the lock and "Wakee" may be
// out-of-scope (non-extant).
Wakee = NULL;
! // Drop the lock.
! // Uses a fence to separate release_store(owner) from the LD in unpark().
! release_clear_owner(Self);
! OrderAccess::fence();
DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);
Trigger->unpark();
// Maintain stats and report events to JVMTI
*** 1117,1130 ****
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
assert(InitDone, "Unexpectedly not initialized");
! if (THREAD != _owner) {
! if (THREAD->is_lock_owned ((address)_owner)) {
assert(_recursions == 0, "internal state error");
! _owner = THREAD; // Convert from basiclock addr to Thread addr
_recursions = 0;
}
}
guarantee(Self == _owner, "complete_exit not owner");
--- 1247,1261 ----
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
assert(InitDone, "Unexpectedly not initialized");
! void* cur = Atomic::load(&_owner);
! if (THREAD != cur) {
! if (THREAD->is_lock_owned((address)cur)) {
assert(_recursions == 0, "internal state error");
! set_owner_from_BasicLock(cur, Self); // Convert from BasicLock* to Thread*.
_recursions = 0;
}
}
guarantee(Self == _owner, "complete_exit not owner");
*** 1141,1154 ****
Thread * const Self = THREAD;
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
guarantee(_owner != Self, "reenter already owner");
! enter(THREAD); // enter the monitor
guarantee(_recursions == 0, "reenter recursion");
_recursions = recursions;
- return;
}
// Checks that the current THREAD owns this monitor and causes an
// immediate return if it doesn't. We don't use the CHECK macro
// because we want the IMSE to be the only exception that is thrown
--- 1272,1285 ----
Thread * const Self = THREAD;
assert(Self->is_Java_thread(), "Must be Java thread!");
JavaThread *jt = (JavaThread *)THREAD;
guarantee(_owner != Self, "reenter already owner");
! enter(THREAD);
! // Entered the monitor.
guarantee(_recursions == 0, "reenter recursion");
_recursions = recursions;
}
// Checks that the current THREAD owns this monitor and causes an
// immediate return if it doesn't. We don't use the CHECK macro
// because we want the IMSE to be the only exception that is thrown
*** 1165,1179 ****
// Returns true if the specified thread owns the ObjectMonitor.
// Otherwise returns false and throws IllegalMonitorStateException
// (IMSE). If there is a pending exception and the specified thread
// is not the owner, that exception will be replaced by the IMSE.
bool ObjectMonitor::check_owner(Thread* THREAD) {
! if (_owner == THREAD) {
return true;
}
! if (THREAD->is_lock_owned((address)_owner)) {
! _owner = THREAD; // convert from BasicLock addr to Thread addr
_recursions = 0;
return true;
}
THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
"current thread is not owner", false);
--- 1296,1311 ----
// Returns true if the specified thread owns the ObjectMonitor.
// Otherwise returns false and throws IllegalMonitorStateException
// (IMSE). If there is a pending exception and the specified thread
// is not the owner, that exception will be replaced by the IMSE.
bool ObjectMonitor::check_owner(Thread* THREAD) {
! void* cur = Atomic::load(&_owner);
! if (cur == THREAD) {
return true;
}
! if (THREAD->is_lock_owned((address)cur)) {
! set_owner_from_BasicLock(cur, THREAD); // Convert from BasicLock* to Thread*.
_recursions = 0;
return true;
}
THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
"current thread is not owner", false);
*** 1678,1688 ****
// the spin without prejudice or apply a "penalty" to the
// spin count-down variable "ctr", reducing it by 100, say.
Thread * ox = (Thread *) _owner;
if (ox == NULL) {
! ox = (Thread*)Atomic::cmpxchg(&_owner, (void*)NULL, Self);
if (ox == NULL) {
// The CAS succeeded -- this thread acquired ownership
// Take care of some bookkeeping to exit spin state.
if (_succ == Self) {
_succ = NULL;
--- 1810,1820 ----
// the spin without prejudice or apply a "penalty" to the
// spin count-down variable "ctr", reducing it by 100, say.
Thread * ox = (Thread *) _owner;
if (ox == NULL) {
! ox = (Thread*)try_set_owner_from(NULL, Self);
if (ox == NULL) {
// The CAS succeeded -- this thread acquired ownership
// Take care of some bookkeeping to exit spin state.
if (_succ == Self) {
_succ = NULL;
*** 1942,1951 ****
--- 2074,2208 ----
}
DEBUG_ONLY(InitDone = true;)
}
+ ObjectMonitorHandle::~ObjectMonitorHandle() {
+ if (_om_ptr != NULL) {
+ _om_ptr->dec_ref_count();
+ _om_ptr = NULL;
+ }
+ }
+
+ // Save the ObjectMonitor* associated with the specified markWord and
+ // increment the ref_count. This function should only be called if
+ // the caller has verified mark.has_monitor() == true. The object
+ // parameter is needed to verify that ObjectMonitor* has not been
+ // deflated and reused for another object.
+ //
+ // This function returns true if the ObjectMonitor* has been safely
+ // saved. This function returns false if we have lost a race with
+ // async deflation; the caller should retry as appropriate.
+ //
+ bool ObjectMonitorHandle::save_om_ptr(oop object, markWord mark) {
+ // is_marked() is a superset of has_monitor() so make sure we
+ // are called with the proper markWord value.
+ guarantee(mark.has_monitor() && !mark.is_marked(), "sanity check: mark="
+ INTPTR_FORMAT, mark.value());
+
+ ObjectMonitor* om_ptr = mark.monitor();
+ om_ptr->inc_ref_count();
+
+ if (AsyncDeflateIdleMonitors) {
+ // Race here if monitor is not owned! The above ref_count bump
+ // will cause subsequent async deflation to skip it. However,
+ // previous or concurrent async deflation is a race.
+ if (om_ptr->owner_is_DEFLATER_MARKER() && om_ptr->ref_count() <= 0) {
+ // Async deflation is in progress and our ref_count increment
+ // above lost the race to async deflation. Attempt to restore
+ // the header/dmw to the object's header so that we only retry
+ // once if the deflater thread happens to be slow.
+ om_ptr->install_displaced_markword_in_object(object);
+ om_ptr->dec_ref_count();
+ return false;
+ }
+ if (om_ptr->ref_count() <= 0) {
+ // Async deflation is in the process of bailing out, but has not
+ // yet restored the ref_count field so we return false to force
+ // a retry. We want a positive ref_count value for a true return.
+ om_ptr->dec_ref_count();
+ return false;
+ }
+ // The ObjectMonitor could have been deflated and reused for
+ // another object before we bumped the ref_count so make sure
+ // our object still refers to this ObjectMonitor.
+ const markWord tmp = object->mark();
+ if (!tmp.has_monitor() || tmp.monitor() != om_ptr) {
+ // Async deflation and reuse won the race so we have to retry.
+ // Skip object header restoration since that's already done.
+ om_ptr->dec_ref_count();
+ return false;
+ }
+ }
+
+ ADIM_guarantee(_om_ptr == NULL, "sanity check: _om_ptr=" INTPTR_FORMAT,
+ p2i(_om_ptr));
+ _om_ptr = om_ptr;
+ return true;
+ }
+
+ // For internal use by ObjectSynchronizer::inflate().
+ // This function is only used when we don't have to worry about async
+ // deflation of the specified ObjectMonitor*.
+ void ObjectMonitorHandle::set_om_ptr(ObjectMonitor* om_ptr) {
+ if (_om_ptr == NULL) {
+ ADIM_guarantee(om_ptr != NULL, "cannot clear an unset om_ptr");
+ om_ptr->inc_ref_count();
+ _om_ptr = om_ptr;
+ } else {
+ ADIM_guarantee(om_ptr == NULL, "can only clear a set om_ptr");
+ _om_ptr->dec_ref_count();
+ _om_ptr = NULL;
+ }
+ }
+
+ // Save the specified ObjectMonitor* if it is safe, i.e., not being
+ // async deflated.
+ //
+ // This function returns true if the ObjectMonitor* has been safely
+ // saved. This function returns false if the specified ObjectMonitor*
+ // is NULL or if we have lost a race with async deflation; the caller
+ // can retry as appropriate.
+ bool ObjectMonitorHandle::set_om_ptr_if_safe(ObjectMonitor* om_ptr) {
+ if (om_ptr == NULL) {
+ return false; // Nothing to save if input is NULL
+ }
+
+ om_ptr->inc_ref_count();
+
+ if (AsyncDeflateIdleMonitors) {
+ if (om_ptr->owner_is_DEFLATER_MARKER() && om_ptr->ref_count() <= 0) {
+ // Async deflation is in progress and our ref_count increment
+ // above lost the race to async deflation.
+ om_ptr->dec_ref_count();
+ return false;
+ }
+ if (om_ptr->ref_count() <= 0) {
+ // Async deflation is in the process of bailing out, but has not
+ // yet restored the ref_count field so we return false to force
+ // a retry. We want a positive ref_count value for a true return.
+ om_ptr->dec_ref_count();
+ return false;
+ }
+ // Unlike save_om_ptr(), we don't have context to determine if
+ // the ObjectMonitor has been deflated and reused for another
+ // object.
+ }
+
+ ADIM_guarantee(_om_ptr == NULL, "sanity check: _om_ptr=" INTPTR_FORMAT,
+ p2i(_om_ptr));
+ _om_ptr = om_ptr;
+ return true;
+ }
+
+ // Unset the _om_ptr field and decrement the ref_count field.
+ void ObjectMonitorHandle::unset_om_ptr() {
+ ADIM_guarantee(_om_ptr != NULL, "_om_ptr must not be NULL");
+ _om_ptr->dec_ref_count();
+ _om_ptr = NULL;
+ }
+
void ObjectMonitor::print_on(outputStream* st) const {
// The minimal things to print for markWord printing, more can be added for debugging and logging.
st->print("{contentions=0x%08x,waiters=0x%08x"
",recursions=" INTX_FORMAT ",owner=" INTPTR_FORMAT "}",
contentions(), waiters(), recursions(),
*** 1957,1974 ****
// Print the ObjectMonitor like a debugger would:
//
// (ObjectMonitor) 0x00007fdfb6012e40 = {
// _header = 0x0000000000000001
// _object = 0x000000070ff45fd0
! // _next_om = 0x0000000000000000
// _pad_buf0 = {
// [0] = '\0'
// ...
! // [103] = '\0'
// }
// _owner = 0x0000000000000000
// _previous_owner_tid = 0
// _recursions = 0
// _EntryList = 0x0000000000000000
// _cxq = 0x0000000000000000
// _succ = 0x0000000000000000
// _Responsible = 0x0000000000000000
--- 2214,2243 ----
// Print the ObjectMonitor like a debugger would:
//
// (ObjectMonitor) 0x00007fdfb6012e40 = {
// _header = 0x0000000000000001
// _object = 0x000000070ff45fd0
! // _allocation_state = Old
// _pad_buf0 = {
// [0] = '\0'
// ...
! // [43] = '\0'
// }
// _owner = 0x0000000000000000
// _previous_owner_tid = 0
+ // _pad_buf1 = {
+ // [0] = '\0'
+ // ...
+ // [47] = '\0'
+ // }
+ // _ref_count = 1
+ // _pad_buf2 = {
+ // [0] = '\0'
+ // ...
+ // [47] = '\0'
+ // }
+ // _next_om = 0x0000000000000000
// _recursions = 0
// _EntryList = 0x0000000000000000
// _cxq = 0x0000000000000000
// _succ = 0x0000000000000000
// _Responsible = 0x0000000000000000
*** 1982,1999 ****
//
void ObjectMonitor::print_debug_style_on(outputStream* st) const {
st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this));
st->print_cr(" _header = " INTPTR_FORMAT, header().value());
st->print_cr(" _object = " INTPTR_FORMAT, p2i(_object));
! st->print_cr(" _next_om = " INTPTR_FORMAT, p2i(_next_om));
st->print_cr(" _pad_buf0 = {");
st->print_cr(" [0] = '\\0'");
st->print_cr(" ...");
st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf0) - 1);
st->print_cr(" }");
st->print_cr(" _owner = " INTPTR_FORMAT, p2i(_owner));
st->print_cr(" _previous_owner_tid = " JLONG_FORMAT, _previous_owner_tid);
st->print_cr(" _recursions = " INTX_FORMAT, _recursions);
st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList));
st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq));
st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ));
st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible));
--- 2251,2290 ----
//
void ObjectMonitor::print_debug_style_on(outputStream* st) const {
st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this));
st->print_cr(" _header = " INTPTR_FORMAT, header().value());
st->print_cr(" _object = " INTPTR_FORMAT, p2i(_object));
! st->print(" _allocation_state = ");
! if (is_free()) {
! st->print("Free");
! } else if (is_old()) {
! st->print("Old");
! } else if (is_new()) {
! st->print("New");
! } else {
! st->print("unknown=%d", _allocation_state);
! }
! st->cr();
st->print_cr(" _pad_buf0 = {");
st->print_cr(" [0] = '\\0'");
st->print_cr(" ...");
st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf0) - 1);
st->print_cr(" }");
st->print_cr(" _owner = " INTPTR_FORMAT, p2i(_owner));
st->print_cr(" _previous_owner_tid = " JLONG_FORMAT, _previous_owner_tid);
+ st->print_cr(" _pad_buf1 = {");
+ st->print_cr(" [0] = '\\0'");
+ st->print_cr(" ...");
+ st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf1) - 1);
+ st->print_cr(" }");
+ st->print_cr(" _ref_count = %d", ref_count());
+ st->print_cr(" _pad_buf2 = {");
+ st->print_cr(" [0] = '\\0'");
+ st->print_cr(" ...");
+ st->print_cr(" [%d] = '\\0'", (int)sizeof(_pad_buf1) - 1);
+ st->print_cr(" }");
+ st->print_cr(" _next_om = " INTPTR_FORMAT, p2i(next_om()));
st->print_cr(" _recursions = " INTX_FORMAT, _recursions);
st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList));
st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq));
st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ));
st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible));
< prev index next >