--- a/src/hotspot/share/runtime/objectMonitor.cpp Thu Oct 17 20:27:44 2019 +0100
+++ b/src/hotspot/share/runtime/objectMonitor.cpp Thu Oct 17 20:53:35 2019 +0100
@@ -28,7 +28,7 @@
#include "jfr/support/jfrThreadId.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
-#include "oops/markOop.hpp"
+#include "oops/markWord.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.inline.hpp"
@@ -245,9 +245,7 @@
void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL);
if (cur == NULL) {
- // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
assert(_recursions == 0, "invariant");
- assert(_owner == Self, "invariant");
return;
}
@@ -279,10 +277,10 @@
assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner));
assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT,
_recursions);
- assert(((oop)object())->mark() == markOopDesc::encode(this),
+ assert(((oop)object())->mark() == markWord::encode(this),
"object mark must match encoded this: mark=" INTPTR_FORMAT
- ", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()),
- p2i(markOopDesc::encode(this)));
+ ", encoded this=" INTPTR_FORMAT, ((oop)object())->mark().value(),
+ markWord::encode(this).value());
Self->_Stalled = 0;
return;
}
@@ -367,7 +365,7 @@
assert(_recursions == 0, "invariant");
assert(_owner == Self, "invariant");
assert(_succ != Self, "invariant");
- assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
+ assert(((oop)(object()))->mark() == markWord::encode(this), "invariant");
// The thread -- now the owner -- is back in vm mode.
// Report the glorious news via TI,DTrace and jvmstat.
@@ -405,9 +403,7 @@
void * own = _owner;
if (own != NULL) return 0;
if (Atomic::replace_if_null(Self, &_owner)) {
- // Either guarantee _recursions == 0 or set _recursions = 0.
assert(_recursions == 0, "invariant");
- assert(_owner == Self, "invariant");
return 1;
}
// The lock had been free momentarily, but we lost the race to the lock.
@@ -417,6 +413,15 @@
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) {
@@ -588,7 +593,7 @@
assert(_owner == Self, "invariant");
assert(object() != NULL, "invariant");
// I'd like to write:
- // guarantee (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
+ // guarantee (((oop)(object()))->mark() == markWord::encode(this), "invariant") ;
// but as we're at a safepoint that's not safe.
UnlinkAfterAcquire(Self, &node);
@@ -656,7 +661,7 @@
assert(SelfNode != NULL, "invariant");
assert(SelfNode->_thread == Self, "invariant");
assert(_waiters > 0, "invariant");
- assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
+ assert(((oop)(object()))->mark() == markWord::encode(this), "invariant");
assert(((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant");
JavaThread * jt = (JavaThread *) Self;
@@ -724,7 +729,7 @@
// In addition, Self.TState is stable.
assert(_owner == Self, "invariant");
- assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
+ assert(((oop)(object()))->mark() == markWord::encode(this), "invariant");
UnlinkAfterAcquire(Self, SelfNode);
if (_succ == Self) _succ = NULL;
assert(_succ != Self, "invariant");
@@ -1138,31 +1143,34 @@
return;
}
-
-// -----------------------------------------------------------------------------
-// A macro is used below because there may already be a pending
-// exception which should not abort the execution of the routines
-// which use this (which is why we don't put this into check_slow and
-// call it with a CHECK argument).
-
-#define CHECK_OWNER() \
- do { \
- if (THREAD != _owner) { \
- if (THREAD->is_lock_owned((address) _owner)) { \
- _owner = THREAD; /* Convert from basiclock addr to Thread addr */ \
- _recursions = 0; \
- } else { \
- THROW(vmSymbols::java_lang_IllegalMonitorStateException()); \
- } \
- } \
+// 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
+// from the call site when false is returned. Any other pending
+// exception is ignored.
+#define CHECK_OWNER() \
+ do { \
+ if (!check_owner(THREAD)) { \
+ assert(HAS_PENDING_EXCEPTION, "expected a pending IMSE here."); \
+ return; \
+ } \
} while (false)
-// check_slow() is a misnomer. It's called to simply to throw an IMSX exception.
-// TODO-FIXME: remove check_slow() -- it's likely dead.
-
-void ObjectMonitor::check_slow(TRAPS) {
- assert(THREAD != _owner && !THREAD->is_lock_owned((address) _owner), "must not be owner");
- THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), "current thread not owner");
+// 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);
}
static void post_monitor_wait_event(EventJavaMonitorWait* event,
@@ -1192,13 +1200,12 @@
assert(InitDone, "Unexpectedly not initialized");
- // Throw IMSX or IEX.
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
EventJavaMonitorWait event;
// check for a pending interrupt
- if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+ if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
// post monitor waited event. Note that this is past-tense, we are done waiting.
if (JvmtiExport::should_post_monitor_waited()) {
// Note: 'false' parameter is passed here because the
@@ -1268,7 +1275,7 @@
// Thread is in thread_blocked state and oop access is unsafe.
jt->set_suspend_equivalent();
- if (interruptible && (Thread::is_interrupted(THREAD, false) || HAS_PENDING_EXCEPTION)) {
+ if (interruptible && (jt->is_interrupted(false) || HAS_PENDING_EXCEPTION)) {
// Intentionally empty
} else if (node._notified == 0) {
if (millis <= 0) {
@@ -1388,13 +1395,13 @@
// Verify a few postconditions
assert(_owner == Self, "invariant");
assert(_succ != Self, "invariant");
- assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
+ assert(((oop)(object()))->mark() == markWord::encode(this), "invariant");
// check if the notification happened
if (!WasNotified) {
// no, it could be timeout or Thread.interrupt() or both
// check for interrupt event, otherwise it is timeout
- if (interruptible && Thread::is_interrupted(Self, true) && !HAS_PENDING_EXCEPTION) {
+ if (interruptible && jt->is_interrupted(true) && !HAS_PENDING_EXCEPTION) {
THROW(vmSymbols::java_lang_InterruptedException());
}
}
@@ -1472,7 +1479,7 @@
// that suggests a lost wakeup bug.
void ObjectMonitor::notify(TRAPS) {
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
if (_WaitSet == NULL) {
return;
}
@@ -1490,7 +1497,7 @@
// mode the waitset will be empty and the EntryList will be "DCBAXYZ".
void ObjectMonitor::notifyAll(TRAPS) {
- CHECK_OWNER();
+ CHECK_OWNER(); // Throws IMSE if not owner.
if (_WaitSet == NULL) {
return;
}
@@ -1928,7 +1935,7 @@
}
void ObjectMonitor::print_on(outputStream* st) const {
- // The minimal things to print for markOop printing, more can be added for debugging and logging.
+ // 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=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
contentions(), waiters(), recursions(),