8229258: Rework markOop and markOopDesc into a simpler mark word value carrier

Reviewed-by: rkennke, coleenp, kbarrett, dcubed
This commit is contained in:
Stefan Karlsson 2019-08-06 10:48:21 +02:00
parent f075a3278b
commit ae5615c614
132 changed files with 1215 additions and 1236 deletions

View file

@ -161,16 +161,16 @@ bool ObjectSynchronizer::quick_notify(oopDesc * obj, Thread * self, bool all) {
assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
NoSafepointVerifier nsv;
if (obj == NULL) return false; // slow-path for invalid obj
const markOop mark = obj->mark();
const markWord mark = obj->mark();
if (mark->has_locker() && self->is_lock_owned((address)mark->locker())) {
if (mark.has_locker() && self->is_lock_owned((address)mark.locker())) {
// Degenerate notify
// stack-locked by caller so by definition the implied waitset is empty.
return true;
}
if (mark->has_monitor()) {
ObjectMonitor * const mon = mark->monitor();
if (mark.has_monitor()) {
ObjectMonitor * const mon = mark.monitor();
assert(oopDesc::equals((oop) mon->object(), obj), "invariant");
if (mon->owner() != self) return false; // slow-path for IMS exception
@ -211,10 +211,10 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread * Self,
assert(((JavaThread *) Self)->thread_state() == _thread_in_Java, "invariant");
NoSafepointVerifier nsv;
if (obj == NULL) return false; // Need to throw NPE
const markOop mark = obj->mark();
const markWord mark = obj->mark();
if (mark->has_monitor()) {
ObjectMonitor * const m = mark->monitor();
if (mark.has_monitor()) {
ObjectMonitor * const m = mark.monitor();
assert(oopDesc::equals((oop) m->object(), obj), "invariant");
Thread * const owner = (Thread *) m->_owner;
@ -238,7 +238,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread * Self,
// stack-locking in the object's header, the third check is for
// recursive stack-locking in the displaced header in the BasicLock,
// and last are the inflated Java Monitor (ObjectMonitor) checks.
lock->set_displaced_header(markOopDesc::unused_mark());
lock->set_displaced_header(markWord::unused_mark());
if (owner == NULL && Atomic::replace_if_null(Self, &(m->_owner))) {
assert(m->_recursions == 0, "invariant");
@ -275,31 +275,31 @@ void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,
assert(!attempt_rebias, "can not rebias toward VM thread");
BiasedLocking::revoke_at_safepoint(obj);
}
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
slow_enter(obj, lock, THREAD);
}
void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
markOop mark = object->mark();
markWord mark = object->mark();
// We cannot check for Biased Locking if we are racing an inflation.
assert(mark == markOopDesc::INFLATING() ||
!mark->has_bias_pattern(), "should not see bias pattern here");
assert(mark == markWord::INFLATING() ||
!mark.has_bias_pattern(), "should not see bias pattern here");
markOop dhw = lock->displaced_header();
if (dhw == NULL) {
markWord dhw = lock->displaced_header();
if (dhw.value() == 0) {
// If the displaced header is NULL, then this exit matches up with
// a recursive enter. No real work to do here except for diagnostics.
#ifndef PRODUCT
if (mark != markOopDesc::INFLATING()) {
if (mark != markWord::INFLATING()) {
// Only do diagnostics if we are not racing an inflation. Simply
// exiting a recursive enter of a Java Monitor that is being
// inflated is safe; see the has_monitor() comment below.
assert(!mark->is_neutral(), "invariant");
assert(!mark->has_locker() ||
THREAD->is_lock_owned((address)mark->locker()), "invariant");
if (mark->has_monitor()) {
assert(!mark.is_neutral(), "invariant");
assert(!mark.has_locker() ||
THREAD->is_lock_owned((address)mark.locker()), "invariant");
if (mark.has_monitor()) {
// The BasicLock's displaced_header is marked as a recursive
// enter and we have an inflated Java Monitor (ObjectMonitor).
// This is a special case where the Java Monitor was inflated
@ -308,7 +308,7 @@ void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
// Monitor owner's stack and update the BasicLocks because a
// Java Monitor can be asynchronously inflated by a thread that
// does not own the Java Monitor.
ObjectMonitor * m = mark->monitor();
ObjectMonitor * m = mark.monitor();
assert(((oop)(m->object()))->mark() == mark, "invariant");
assert(m->is_entered(THREAD), "invariant");
}
@ -317,10 +317,10 @@ void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
return;
}
if (mark == (markOop) lock) {
if (mark == markWord::from_pointer(lock)) {
// If the object is stack-locked by the current thread, try to
// swing the displaced header from the BasicLock back to the mark.
assert(dhw->is_neutral(), "invariant");
assert(dhw.is_neutral(), "invariant");
if (object->cas_set_mark(dhw, mark) == mark) {
return;
}
@ -336,22 +336,22 @@ void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
// We don't need to use fast path here, because it must have been
// failed in the interpreter/compiler code.
void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
markOop mark = obj->mark();
assert(!mark->has_bias_pattern(), "should not see bias pattern here");
markWord mark = obj->mark();
assert(!mark.has_bias_pattern(), "should not see bias pattern here");
if (mark->is_neutral()) {
if (mark.is_neutral()) {
// Anticipate successful CAS -- the ST of the displaced mark must
// be visible <= the ST performed by the CAS.
lock->set_displaced_header(mark);
if (mark == obj()->cas_set_mark((markOop) lock, mark)) {
if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) {
return;
}
// Fall through to inflate() ...
} else if (mark->has_locker() &&
THREAD->is_lock_owned((address)mark->locker())) {
assert(lock != mark->locker(), "must not re-lock the same lock");
assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
lock->set_displaced_header(NULL);
} else if (mark.has_locker() &&
THREAD->is_lock_owned((address)mark.locker())) {
assert(lock != mark.locker(), "must not re-lock the same lock");
assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock");
lock->set_displaced_header(markWord::from_pointer(NULL));
return;
}
@ -359,7 +359,7 @@ void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
// so it does not matter what the value is, except that it
// must be non-zero to avoid looking like a re-entrant lock,
// and must not look locked either.
lock->set_displaced_header(markOopDesc::unused_mark());
lock->set_displaced_header(markWord::unused_mark());
inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);
}
@ -386,7 +386,7 @@ void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
@ -398,7 +398,7 @@ intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
@ -412,7 +412,7 @@ void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
// the current locking is from JNI instead of Java code
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
THREAD->set_current_pending_monitor_is_from_java(false);
inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD);
@ -426,7 +426,7 @@ void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
BiasedLocking::revoke_and_rebias(h_obj, false, THREAD);
obj = h_obj();
}
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
// If this thread has locked the object, exit the monitor. We
@ -464,7 +464,7 @@ ObjectLocker::~ObjectLocker() {
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
@ -484,7 +484,7 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
@ -495,11 +495,11 @@ void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markOop mark = obj->mark();
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
return;
}
inflate(THREAD, obj(), inflate_cause_notify)->notify(THREAD);
@ -509,11 +509,11 @@ void ObjectSynchronizer::notify(Handle obj, TRAPS) {
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markOop mark = obj->mark();
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
return;
}
inflate(THREAD, obj(), inflate_cause_notify)->notifyAll(THREAD);
@ -556,16 +556,16 @@ static SharedGlobals GVars;
static int MonitorScavengeThreshold = 1000000;
static volatile int ForceMonitorScavenge = 0; // Scavenge required and pending
static markOop ReadStableMark(oop obj) {
markOop mark = obj->mark();
if (!mark->is_being_inflated()) {
static markWord ReadStableMark(oop obj) {
markWord mark = obj->mark();
if (!mark.is_being_inflated()) {
return mark; // normal fast-path return
}
int its = 0;
for (;;) {
markOop mark = obj->mark();
if (!mark->is_being_inflated()) {
markWord mark = obj->mark();
if (!mark.is_being_inflated()) {
return mark; // normal fast-path return
}
@ -604,7 +604,7 @@ static markOop ReadStableMark(oop obj) {
assert(ix >= 0 && ix < NINFLATIONLOCKS, "invariant");
assert((NINFLATIONLOCKS & (NINFLATIONLOCKS-1)) == 0, "invariant");
Thread::muxAcquire(gInflationLocks + ix, "gInflationLock");
while (obj->mark() == markOopDesc::INFLATING()) {
while (obj->mark() == markWord::INFLATING()) {
// Beware: NakedYield() is advisory and has almost no effect on some platforms
// so we periodically call Self->_ParkEvent->park(1).
// We use a mixed spin/yield/block mechanism.
@ -673,9 +673,9 @@ static inline intptr_t get_next_hash(Thread * Self, oop obj) {
value = v;
}
value &= markOopDesc::hash_mask;
value &= markWord::hash_mask;
if (value == 0) value = 0xBAD;
assert(value != markOopDesc::no_hash, "invariant");
assert(value != markWord::no_hash, "invariant");
return value;
}
@ -688,7 +688,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
// been checked to make sure they can handle a safepoint. The
// added check of the bias pattern is to avoid useless calls to
// thread-local storage.
if (obj->mark()->has_bias_pattern()) {
if (obj->mark().has_bias_pattern()) {
// Handle for oop obj in case of STW safepoint
Handle hobj(Self, obj);
// Relaxing assertion for bug 6320749.
@ -697,7 +697,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
"biases should not be seen by VM thread here");
BiasedLocking::revoke_and_rebias(hobj, false, JavaThread::current());
obj = hobj();
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
}
@ -711,20 +711,20 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
((JavaThread *)Self)->thread_state() != _thread_blocked, "invariant");
ObjectMonitor* monitor = NULL;
markOop temp, test;
markWord temp, test;
intptr_t hash;
markOop mark = ReadStableMark(obj);
markWord mark = ReadStableMark(obj);
// object should remain ineligible for biased locking
assert(!mark->has_bias_pattern(), "invariant");
assert(!mark.has_bias_pattern(), "invariant");
if (mark->is_neutral()) {
hash = mark->hash(); // this is a normal header
if (mark.is_neutral()) {
hash = mark.hash(); // this is a normal header
if (hash != 0) { // if it has hash, just return it
return hash;
}
hash = get_next_hash(Self, obj); // allocate a new hash code
temp = mark->copy_set_hash(hash); // merge the hash code into header
temp = mark.copy_set_hash(hash); // merge the hash code into header
// use (machine word version) atomic operation to install the hash
test = obj->cas_set_mark(temp, mark);
if (test == mark) {
@ -733,20 +733,20 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
// If atomic operation failed, we must inflate the header
// into heavy weight monitor. We could add more code here
// for fast path, but it does not worth the complexity.
} else if (mark->has_monitor()) {
monitor = mark->monitor();
} else if (mark.has_monitor()) {
monitor = mark.monitor();
temp = monitor->header();
assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
hash = temp->hash();
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
hash = temp.hash();
if (hash != 0) {
return hash;
}
// Skip to the following code to reduce code size
} else if (Self->is_lock_owned((address)mark->locker())) {
temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
hash = temp->hash(); // by current thread, check if the displaced
if (hash != 0) { // header contains hash code
} else if (Self->is_lock_owned((address)mark.locker())) {
temp = mark.displaced_mark_helper(); // this is a lightweight monitor owned
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
hash = temp.hash(); // by current thread, check if the displaced
if (hash != 0) { // header contains hash code
return hash;
}
// WARNING:
@ -763,19 +763,20 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
monitor = inflate(Self, obj, inflate_cause_hash_code);
// Load displaced header and check it has hash code
mark = monitor->header();
assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
hash = mark->hash();
assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
hash = mark.hash();
if (hash == 0) {
hash = get_next_hash(Self, obj);
temp = mark->copy_set_hash(hash); // merge hash code into header
assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
test = Atomic::cmpxchg(temp, monitor->header_addr(), mark);
temp = mark.copy_set_hash(hash); // merge hash code into header
assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
uintptr_t v = Atomic::cmpxchg(temp.value(), (volatile uintptr_t*)monitor->header_addr(), mark.value());
test = markWord(v);
if (test != mark) {
// The only update to the ObjectMonitor's header/dmw field
// is to merge in the hash code. If someone adds a new usage
// of the header/dmw field, please update this code.
hash = test->hash();
assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(test));
hash = test.hash();
assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value());
assert(hash != 0, "Trivial unexpected object/monitor header usage.");
}
}
@ -794,25 +795,25 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
Handle h_obj) {
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(h_obj, false, thread);
assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
assert(thread == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
markOop mark = ReadStableMark(obj);
markWord mark = ReadStableMark(obj);
// Uncontended case, header points to stack
if (mark->has_locker()) {
return thread->is_lock_owned((address)mark->locker());
if (mark.has_locker()) {
return thread->is_lock_owned((address)mark.locker());
}
// Contended case, header points to ObjectMonitor (tagged pointer)
if (mark->has_monitor()) {
ObjectMonitor* monitor = mark->monitor();
if (mark.has_monitor()) {
ObjectMonitor* monitor = mark.monitor();
return monitor->is_entered(thread) != 0;
}
// Unlocked case, header in place
assert(mark->is_neutral(), "sanity check");
assert(mark.is_neutral(), "sanity check");
return false;
}
@ -830,35 +831,35 @@ ObjectSynchronizer::LockOwnership ObjectSynchronizer::query_lock_ownership
// Possible mark states: neutral, biased, stack-locked, inflated
if (UseBiasedLocking && h_obj()->mark()->has_bias_pattern()) {
if (UseBiasedLocking && h_obj()->mark().has_bias_pattern()) {
// CASE: biased
BiasedLocking::revoke_and_rebias(h_obj, false, self);
assert(!h_obj->mark()->has_bias_pattern(),
assert(!h_obj->mark().has_bias_pattern(),
"biases should be revoked by now");
}
assert(self == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
markOop mark = ReadStableMark(obj);
markWord mark = ReadStableMark(obj);
// CASE: stack-locked. Mark points to a BasicLock on the owner's stack.
if (mark->has_locker()) {
return self->is_lock_owned((address)mark->locker()) ?
if (mark.has_locker()) {
return self->is_lock_owned((address)mark.locker()) ?
owner_self : owner_other;
}
// CASE: inflated. Mark (tagged pointer) points to an ObjectMonitor.
// The Object:ObjectMonitor relationship is stable as long as we're
// not at a safepoint.
if (mark->has_monitor()) {
void * owner = mark->monitor()->_owner;
if (mark.has_monitor()) {
void * owner = mark.monitor()->_owner;
if (owner == NULL) return owner_none;
return (owner == self ||
self->is_lock_owned((address)owner)) ? owner_self : owner_other;
}
// CASE: neutral
assert(mark->is_neutral(), "sanity check");
assert(mark.is_neutral(), "sanity check");
return owner_none; // it's unlocked
}
@ -870,22 +871,22 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob
} else {
BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
}
assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
oop obj = h_obj();
address owner = NULL;
markOop mark = ReadStableMark(obj);
markWord mark = ReadStableMark(obj);
// Uncontended case, header points to stack
if (mark->has_locker()) {
owner = (address) mark->locker();
if (mark.has_locker()) {
owner = (address) mark.locker();
}
// Contended case, header points to ObjectMonitor (tagged pointer)
else if (mark->has_monitor()) {
ObjectMonitor* monitor = mark->monitor();
else if (mark.has_monitor()) {
ObjectMonitor* monitor = mark.monitor();
assert(monitor != NULL, "monitor should be non-null");
owner = (address) monitor->owner();
}
@ -898,7 +899,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob
// Unlocked case, header in place
// Cannot have assertion since this object may have been
// locked by another thread when reaching here.
// assert(mark->is_neutral(), "sanity check");
// assert(mark.is_neutral(), "sanity check");
return NULL;
}
@ -1165,7 +1166,7 @@ ObjectMonitor* ObjectSynchronizer::omAlloc(Thread * Self) {
void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
bool fromPerThreadAlloc) {
guarantee(m->header() == NULL, "invariant");
guarantee(m->header().value() == 0, "invariant");
guarantee(m->object() == NULL, "invariant");
stringStream ss;
guarantee((m->is_busy() | m->_recursions) == 0, "freeing in-use monitor: "
@ -1301,10 +1302,10 @@ static void post_monitor_inflate_event(EventJavaMonitorInflate* event,
// Fast path code shared by multiple functions
void ObjectSynchronizer::inflate_helper(oop obj) {
markOop mark = obj->mark();
if (mark->has_monitor()) {
assert(ObjectSynchronizer::verify_objmon_isinpool(mark->monitor()), "monitor is invalid");
assert(mark->monitor()->header()->is_neutral(), "monitor must record a good object header");
markWord mark = obj->mark();
if (mark.has_monitor()) {
assert(ObjectSynchronizer::verify_objmon_isinpool(mark.monitor()), "monitor is invalid");
assert(mark.monitor()->header().is_neutral(), "monitor must record a good object header");
return;
}
inflate(Thread::current(), obj, inflate_cause_vm_internal);
@ -1321,8 +1322,8 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
EventJavaMonitorInflate event;
for (;;) {
const markOop mark = object->mark();
assert(!mark->has_bias_pattern(), "invariant");
const markWord mark = object->mark();
assert(!mark.has_bias_pattern(), "invariant");
// The mark can be in one of the following states:
// * Inflated - just return
@ -1332,10 +1333,10 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
// * BIASED - Illegal. We should never see this
// CASE: inflated
if (mark->has_monitor()) {
ObjectMonitor * inf = mark->monitor();
markOop dmw = inf->header();
assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
if (mark.has_monitor()) {
ObjectMonitor * inf = mark.monitor();
markWord dmw = inf->header();
assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
assert(oopDesc::equals((oop) inf->object(), object), "invariant");
assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
return inf;
@ -1347,7 +1348,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
// The INFLATING value is transient.
// Currently, we spin/yield/park and poll the markword, waiting for inflation to finish.
// We could always eliminate polling by parking the thread on some auxiliary list.
if (mark == markOopDesc::INFLATING()) {
if (mark == markWord::INFLATING()) {
ReadStableMark(object);
continue;
}
@ -1373,7 +1374,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
LogStreamHandle(Trace, monitorinflation) lsh;
if (mark->has_locker()) {
if (mark.has_locker()) {
ObjectMonitor * m = omAlloc(Self);
// Optimistically prepare the objectmonitor - anticipate successful CAS
// We do this before the CAS in order to minimize the length of time
@ -1382,7 +1383,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
m->_Responsible = NULL;
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // Consider: maintain by type/class
markOop cmp = object->cas_set_mark(markOopDesc::INFLATING(), mark);
markWord cmp = object->cas_set_mark(markWord::INFLATING(), mark);
if (cmp != mark) {
omRelease(Self, m, true);
continue; // Interference -- just retry
@ -1410,7 +1411,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
// drop the lock (restoring the header from the basiclock to the object)
// while inflation is in-progress. This protocol avoids races that might
// would otherwise permit hashCode values to change or "flicker" for an object.
// Critically, while object->mark is 0 mark->displaced_mark_helper() is stable.
// Critically, while object->mark is 0 mark.displaced_mark_helper() is stable.
// 0 serves as a "BUSY" inflate-in-progress indicator.
@ -1418,27 +1419,27 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
// The owner can't die or unwind past the lock while our INFLATING
// object is in the mark. Furthermore the owner can't complete
// an unlock on the object, either.
markOop dmw = mark->displaced_mark_helper();
markWord dmw = mark.displaced_mark_helper();
// Catch if the object's header is not neutral (not locked and
// not marked is what we care about here).
assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
// Setup monitor fields to proper values -- prepare the monitor
m->set_header(dmw);
// Optimization: if the mark->locker stack address is associated
// Optimization: if the mark.locker stack address is associated
// with this thread we could simply set m->_owner = Self.
// Note that a thread can inflate an object
// that it has stack-locked -- as might happen in wait() -- directly
// with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
m->set_owner(mark->locker());
m->set_owner(mark.locker());
m->set_object(object);
// TODO-FIXME: assert BasicLock->dhw != 0.
// Must preserve store ordering. The monitor state must
// be stable at the time of publishing the monitor address.
guarantee(object->mark() == markOopDesc::INFLATING(), "invariant");
object->release_set_mark(markOopDesc::encode(m));
guarantee(object->mark() == markWord::INFLATING(), "invariant");
object->release_set_mark(markWord::encode(m));
// Hopefully the performance counters are allocated on distinct cache lines
// to avoid false sharing on MP systems ...
@ -1447,7 +1448,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
ResourceMark rm(Self);
lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", type='%s'", p2i(object),
p2i(object->mark()), object->klass()->external_name());
object->mark().value(), object->klass()->external_name());
}
if (event.should_commit()) {
post_monitor_inflate_event(&event, object, cause);
@ -1467,7 +1468,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
// Catch if the object's header is not neutral (not locked and
// not marked is what we care about here).
assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
ObjectMonitor * m = omAlloc(Self);
// prepare m for installation - set monitor to initial state
m->Recycle();
@ -1476,8 +1477,8 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
m->_Responsible = NULL;
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class
if (object->cas_set_mark(markOopDesc::encode(m), mark) != mark) {
m->set_header(NULL);
if (object->cas_set_mark(markWord::encode(m), mark) != mark) {
m->set_header(markWord::zero());
m->set_object(NULL);
m->Recycle();
omRelease(Self, m, true);
@ -1495,7 +1496,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
ResourceMark rm(Self);
lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", type='%s'", p2i(object),
p2i(object->mark()), object->klass()->external_name());
object->mark().value(), object->klass()->external_name());
}
if (event.should_commit()) {
post_monitor_inflate_event(&event, object, cause);
@ -1533,15 +1534,15 @@ bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
ObjectMonitor** freeTailp) {
bool deflated;
// Normal case ... The monitor is associated with obj.
const markOop mark = obj->mark();
guarantee(mark == markOopDesc::encode(mid), "should match: mark="
INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, p2i(mark),
p2i(markOopDesc::encode(mid)));
// Make sure that mark->monitor() and markOopDesc::encode() agree:
guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid));
const markOop dmw = mid->header();
guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
const markWord mark = obj->mark();
guarantee(mark == markWord::encode(mid), "should match: mark="
INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, mark.value(),
markWord::encode(mid).value());
// Make sure that mark.monitor() and markWord::encode() agree:
guarantee(mark.monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
", mid=" INTPTR_FORMAT, p2i(mark.monitor()), p2i(mid));
const markWord dmw = mid->header();
guarantee(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
if (mid->is_busy()) {
deflated = false;
@ -1554,7 +1555,7 @@ bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
log_trace(monitorinflation)("deflate_monitor: "
"object=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", type='%s'", p2i(obj),
p2i(mark), obj->klass()->external_name());
mark.value(), obj->klass()->external_name());
}
// Restore the header back to obj
@ -1935,16 +1936,16 @@ void ObjectSynchronizer::chk_free_entry(JavaThread * jt, ObjectMonitor * n,
}
*error_cnt_p = *error_cnt_p + 1;
}
if (n->header() != NULL) {
if (n->header().value() != 0) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": free per-thread monitor must have NULL _header "
"field: _header=" INTPTR_FORMAT, p2i(jt), p2i(n),
p2i(n->header()));
n->header().value());
} else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
"must have NULL _header field: _header=" INTPTR_FORMAT,
p2i(n), p2i(n->header()));
p2i(n), n->header().value());
}
*error_cnt_p = *error_cnt_p + 1;
}
@ -2003,7 +2004,7 @@ void ObjectSynchronizer::chk_global_in_use_list_and_count(outputStream * out,
// Check an in-use monitor entry; log any errors.
void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
outputStream * out, int *error_cnt_p) {
if (n->header() == NULL) {
if (n->header().value() == 0) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": in-use per-thread monitor must have non-NULL _header "
@ -2026,34 +2027,34 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
*error_cnt_p = *error_cnt_p + 1;
}
const oop obj = (oop)n->object();
const markOop mark = obj->mark();
if (!mark->has_monitor()) {
const markWord mark = obj->mark();
if (!mark.has_monitor()) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": in-use per-thread monitor's object does not think "
"it has a monitor: obj=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT, p2i(jt), p2i(n), p2i(obj), p2i(mark));
INTPTR_FORMAT, p2i(jt), p2i(n), p2i(obj), mark.value());
} else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
"monitor's object does not think it has a monitor: obj="
INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
p2i(obj), p2i(mark));
p2i(obj), mark.value());
}
*error_cnt_p = *error_cnt_p + 1;
}
ObjectMonitor * const obj_mon = mark->monitor();
ObjectMonitor * const obj_mon = mark.monitor();
if (n != obj_mon) {
if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": in-use per-thread monitor's object does not refer "
"to the same monitor: obj=" INTPTR_FORMAT ", mark="
INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt),
p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
} else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
"monitor's object does not refer to the same monitor: obj="
INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon="
INTPTR_FORMAT, p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
INTPTR_FORMAT, p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
}
*error_cnt_p = *error_cnt_p + 1;
}
@ -2119,10 +2120,10 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
out->print_cr("================== === ================== ==================");
for (ObjectMonitor * n = gOmInUseList; n != NULL; n = n->FreeNext) {
const oop obj = (oop) n->object();
const markOop mark = n->header();
const markWord mark = n->header();
ResourceMark rm;
out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(n),
n->is_busy() != 0, mark->hash() != 0, n->owner() != NULL,
n->is_busy() != 0, mark.hash() != 0, n->owner() != NULL,
p2i(obj), obj->klass()->external_name());
if (n->is_busy() != 0) {
out->print(" (%s)", n->is_busy_to_string(&ss));
@ -2144,11 +2145,11 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
for (ObjectMonitor * n = jt->omInUseList; n != NULL; n = n->FreeNext) {
const oop obj = (oop) n->object();
const markOop mark = n->header();
const markWord mark = n->header();
ResourceMark rm;
out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT
" %s", p2i(jt), p2i(n), n->is_busy() != 0,
mark->hash() != 0, n->owner() != NULL, p2i(obj),
mark.hash() != 0, n->owner() != NULL, p2i(obj),
obj->klass()->external_name());
if (n->is_busy() != 0) {
out->print(" (%s)", n->is_busy_to_string(&ss));