--- old/src/hotspot/share/runtime/objectMonitor.cpp 2019-10-17 17:31:38.000000000 -0400 +++ new/src/hotspot/share/runtime/objectMonitor.cpp 2019-10-17 17:31:38.000000000 -0400 @@ -245,7 +245,7 @@ // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors. Thread * const Self = THREAD; - void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL); + void* cur = try_set_owner_from(Self, NULL); if (cur == NULL) { assert(_recursions == 0, "invariant"); return; @@ -260,14 +260,12 @@ 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; + set_owner_from_BasicLock(Self, cur); // Convert from BasicLock* to Thread*. return; } if (AsyncDeflateIdleMonitors && - Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { + try_set_owner_from(Self, 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. @@ -415,7 +413,7 @@ int ObjectMonitor::TryLock(Thread * Self) { void * own = _owner; if (own != NULL) return 0; - if (Atomic::replace_if_null(Self, &_owner)) { + if (try_set_owner_from(Self, NULL) == NULL) { assert(_recursions == 0, "invariant"); return 1; } @@ -446,8 +444,8 @@ markWord dmw = header(); if (dmw.value() == 0) { - // ObjectMonitor's header/dmw has been cleared so the object's - // header has already been restored. + // ObjectMonitor's header/dmw has been cleared so the ObjectMonitor + // has been deflated and taken off the global free list. return; } @@ -497,12 +495,6 @@ // 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. - - if (marked_dmw.value() != 0) { - // Clear _header to NULL if it is still marked_dmw so a racing - // install_displaced_markword_in_object() can bail out sooner. - Atomic::cmpxchg(markWord::zero(), &_header, marked_dmw); - } } // Convert the fields used by is_busy() to a string that can be @@ -539,7 +531,7 @@ } if (AsyncDeflateIdleMonitors && - Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { + try_set_owner_from(Self, 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. @@ -666,7 +658,7 @@ if (TryLock(Self) > 0) break; if (AsyncDeflateIdleMonitors && - Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { + try_set_owner_from(Self, 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. @@ -798,7 +790,7 @@ if (TrySpin(Self) > 0) break; if (AsyncDeflateIdleMonitors && - Atomic::cmpxchg(Self, &_owner, DEFLATER_MARKER) == DEFLATER_MARKER) { + try_set_owner_from(Self, 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. @@ -995,13 +987,10 @@ 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. + void* cur = _owner; + if (THREAD->is_lock_owned((address)cur)) { assert(_recursions == 0, "invariant"); - _owner = THREAD; + set_owner_from_BasicLock(Self, cur); // Convert from BasicLock* to Thread*. _recursions = 0; } else { // Apparent unbalanced locking ... @@ -1013,8 +1002,14 @@ // way we should encounter this situation is in the presence of // unbalanced JNI locking. TODO: CheckJNICalls. // See also: CR4414101 - assert(false, "Non-balanced monitor enter/exit! Likely JNI locking: " - "owner=" INTPTR_FORMAT, p2i(_owner)); + tty->print_cr("ERROR: ObjectMonitor::exit(): thread=" INTPTR_FORMAT + " is exiting an ObjectMonitor it does not own.", + p2i(THREAD)); + tty->print_cr("The imbalance is possibly caused by JNI locking."); + print_debug_style_on(tty); + // Changing this from an assert() to ADIM_guarantee() may run + // afoul of any test that is inducing non-balanced JNI locking. + ADIM_guarantee(false, "Non-balanced monitor enter/exit!"); return; } } @@ -1043,8 +1038,12 @@ // must not float (reorder) past the following store that drops the lock. // On SPARC that requires MEMBAR #loadstore|#storestore. // But of course in TSO #loadstore|#storestore is not required. - OrderAccess::release_store(&_owner, (void*)NULL); // drop the lock - OrderAccess::storeload(); // See if we need to wake a successor + if (AsyncDeflateIdleMonitors) { + set_owner_from(NULL, Self); + } else { + OrderAccess::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; } @@ -1086,7 +1085,7 @@ // to reacquire the lock the responsibility for ensuring succession // falls to the new owner. // - if (!Atomic::replace_if_null(THREAD, &_owner)) { + if (try_set_owner_from(Self, NULL) != NULL) { return; } @@ -1219,8 +1218,12 @@ Wakee = NULL; // Drop the lock - OrderAccess::release_store(&_owner, (void*)NULL); - OrderAccess::fence(); // ST _owner vs LD in unpark() + if (AsyncDeflateIdleMonitors) { + set_owner_from(NULL, Self); + } else { + OrderAccess::release_store(&_owner, (void*)NULL); + OrderAccess::fence(); // ST _owner vs LD in unpark() + } DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self); Trigger->unpark(); @@ -1247,9 +1250,10 @@ assert(InitDone, "Unexpectedly not initialized"); if (THREAD != _owner) { - if (THREAD->is_lock_owned ((address)_owner)) { + void* cur = _owner; + if (THREAD->is_lock_owned((address)cur)) { assert(_recursions == 0, "internal state error"); - _owner = THREAD; // Convert from basiclock addr to Thread addr + set_owner_from_BasicLock(Self, cur); // Convert from BasicLock* to Thread*. _recursions = 0; } } @@ -1297,8 +1301,9 @@ if (_owner == THREAD) { return true; } - if (THREAD->is_lock_owned((address)_owner)) { - _owner = THREAD; // convert from BasicLock addr to Thread addr + void* cur = _owner; + if (THREAD->is_lock_owned((address)cur)) { + set_owner_from_BasicLock(THREAD, cur); // Convert from BasicLock* to Thread*. _recursions = 0; return true; } @@ -1803,7 +1808,7 @@ Thread * ox = (Thread *) _owner; if (ox == NULL) { - ox = (Thread*)Atomic::cmpxchg(Self, &_owner, (void*)NULL); + ox = (Thread*)try_set_owner_from(Self, NULL); if (ox == NULL) { // The CAS succeeded -- this thread acquired ownership // Take care of some bookkeeping to exit spin state. @@ -2156,3 +2161,89 @@ p2i(owner())); } void ObjectMonitor::print() const { print_on(tty); } + +// Print the ObjectMonitor like a debugger would: +// +// (ObjectMonitor) 0x00007fdfb6012e40 = { +// _header = (_value = 1) +// _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' +// ... +// [59] = '\0' +// } +// _next_om = 0x0000000000000000 +// _recursions = 0 +// _EntryList = 0x0000000000000000 +// _cxq = 0x0000000000000000 +// _succ = 0x0000000000000000 +// _Responsible = 0x0000000000000000 +// _Spinner = 0 +// _SpinDuration = 5000 +// _contentions = 0 +// _WaitSet = 0x0000700009756248 +// _waiters = 1 +// _WaitSetLock = 0 +// } +// +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)); + st->print_cr(" _Spinner = %d", _Spinner); + st->print_cr(" _SpinDuration = %d", _SpinDuration); + st->print_cr(" _contentions = %d", _contentions); + st->print_cr(" _WaitSet = " INTPTR_FORMAT, p2i(_WaitSet)); + st->print_cr(" _waiters = %d", _waiters); + st->print_cr(" _WaitSetLock = %d", _WaitSetLock); + st->print_cr("}"); +}