--- old/src/hotspot/share/runtime/objectMonitor.cpp 2019-07-11 14:36:29.000000000 -0400 +++ new/src/hotspot/share/runtime/objectMonitor.cpp 2019-07-11 14:36:28.000000000 -0400 @@ -239,7 +239,7 @@ // Enter support void ObjectMonitor::enter(TRAPS) { - ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); + ADIM_guarantee(ref_count() > 0, "must be positive: ref_count=%d", 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. @@ -266,6 +266,16 @@ return; } + if (AsyncDeflateIdleMonitors && + Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == 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"); Self->_Stalled = intptr_t(this); @@ -437,8 +447,8 @@ markOop dmw = header(); if (dmw == NULL) { - // ObjectMonitor's header/dmw has been cleared by the deflating - // thread so the object's header has already been restored. + // ObjectMonitor's header/dmw has been cleared so the object's + // header has already been restored. return; } @@ -458,8 +468,8 @@ // other trying to update the _header field. dmw = (markOop) Atomic::cmpxchg(marked_dmw, &_header, dmw); if (dmw == NULL) { - // ObjectMonitor's header/dmw has been cleared by the deflating - // thread so the object's header has already been restored. + // 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 @@ -499,16 +509,23 @@ // 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)); + 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 { + 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) { - ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); + ADIM_guarantee(ref_count() > 0, "must be positive: ref_count=%d", ref_count()); Thread * const Self = THREAD; assert(Self->is_Java_thread(), "invariant"); @@ -522,15 +539,15 @@ return; } - if (_owner == DEFLATER_MARKER) { - // The deflation protocol finished the first part (setting owner), but - // it failed the second part (making ref_count negative) and bailed. - if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { - // Acquired the monitor. - assert(_succ != Self, "invariant"); - assert(_Responsible != Self, "invariant"); - return; - } + if (AsyncDeflateIdleMonitors && + Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == 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"); @@ -649,13 +666,13 @@ if (TryLock(Self) > 0) break; - if (_owner == DEFLATER_MARKER) { - // The deflation protocol finished the first part (setting owner), but - // it failed the second part (making ref_count negative) and bailed. - if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { - // Acquired the monitor. - break; - } + if (AsyncDeflateIdleMonitors && + Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == 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. @@ -762,7 +779,7 @@ // In the future we should reconcile EnterI() and ReenterI(). void ObjectMonitor::ReenterI(Thread * Self, ObjectWaiter * SelfNode) { - ADIM_guarantee(_ref_count > 0, "must be positive: ref_count=%d", _ref_count); + ADIM_guarantee(ref_count() > 0, "must be positive: ref_count=%d", ref_count()); assert(Self != NULL, "invariant"); assert(SelfNode != NULL, "invariant"); @@ -781,13 +798,13 @@ if (TryLock(Self) > 0) break; if (TrySpin(Self) > 0) break; - if (_owner == DEFLATER_MARKER) { - // The deflation protocol finished the first part (setting owner), but - // it failed the second part (making ref_count negative) and bailed. - if (Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { - // Acquired the monitor. - break; - } + if (AsyncDeflateIdleMonitors && + Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == 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() ... @@ -2083,7 +2100,7 @@ // 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 == DEFLATER_MARKER && om_ptr->ref_count() <= 0) { + 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