< prev index next >
src/hotspot/share/runtime/synchronizer.cpp
Print this page
*** 255,289 ****
return false; // revert to slow-path
}
// -----------------------------------------------------------------------------
! // Fast Monitor Enter/Exit
! // This the fast monitor enter. The interpreter and compiler use
! // some assembly copies of this code. Make sure update those code
! // if the following function is changed. The implementation is
! // extremely sensitive to race condition. Be careful.
! void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,
! bool attempt_rebias, TRAPS) {
if (UseBiasedLocking) {
if (!SafepointSynchronize::is_at_safepoint()) {
! BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
! if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
! return;
! }
} else {
- 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");
}
! slow_enter(obj, lock, THREAD);
}
! void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
markWord mark = object->mark();
// We cannot check for Biased Locking if we are racing an inflation.
assert(mark == markWord::INFLATING() ||
!mark.has_bias_pattern(), "should not see bias pattern here");
--- 255,306 ----
return false; // revert to slow-path
}
// -----------------------------------------------------------------------------
! // Monitor Enter/Exit
! // The interpreter and compiler assembly code tries to lock using the fast path
! // of this algorithm. Make sure to update that code if the following function is
! // changed. The implementation is extremely sensitive to race condition. Be careful.
! void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
if (UseBiasedLocking) {
if (!SafepointSynchronize::is_at_safepoint()) {
! BiasedLocking::revoke(obj, THREAD);
} else {
BiasedLocking::revoke_at_safepoint(obj);
}
}
! markWord mark = obj->mark();
! assert(!mark.has_bias_pattern(), "should not see bias pattern here");
!
! 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(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().value(), "don't relock with same BasicLock");
! lock->set_displaced_header(markWord::from_pointer(NULL));
! return;
! }
!
! // The object header will never be displaced to this lock,
! // 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(markWord::unused_mark());
! inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);
}
! void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
markWord mark = object->mark();
// We cannot check for Biased Locking if we are racing an inflation.
assert(mark == markWord::INFLATING() ||
!mark.has_bias_pattern(), "should not see bias pattern here");
*** 329,379 ****
// We have to take the slow-path of possible inflation and then exit.
inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD);
}
// -----------------------------------------------------------------------------
- // Interpreter/Compiler Slow Case
- // This routine is used to handle interpreter/compiler slow case
- // 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) {
- markWord mark = obj->mark();
- assert(!mark.has_bias_pattern(), "should not see bias pattern here");
-
- 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(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().value(), "don't relock with same BasicLock");
- lock->set_displaced_header(markWord::from_pointer(NULL));
- return;
- }
-
- // The object header will never be displaced to this lock,
- // 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(markWord::unused_mark());
- inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);
- }
-
- // This routine is used to handle interpreter/compiler slow case
- // We don't need to use fast path here, because it must have
- // failed in the interpreter/compiler code. Simply use the heavy
- // weight monitor should be ok, unless someone find otherwise.
- void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {
- fast_exit(object, lock, THREAD);
- }
-
- // -----------------------------------------------------------------------------
// Class Loader support to workaround deadlocks on the class loader lock objects
// Also used by GC
// complete_exit()/reenter() are used to wait on a nested lock
// i.e. to give up an outer lock completely and then re-enter
// Used when holding nested locks - lock acquisition order: lock1 then lock2
--- 346,355 ----
*** 383,393 ****
// 4) reenter lock1 with original recursion count
// 5) lock lock2
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
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");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
--- 359,369 ----
// 4) reenter lock1 with original recursion count
// 5) lock lock2
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
*** 395,405 ****
}
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
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");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
--- 371,381 ----
}
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
*** 409,419 ****
// JNI locks on java objects
// NOTE: must use heavy weight monitor to handle jni monitor enter
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");
}
THREAD->set_current_pending_monitor_is_from_java(false);
inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD);
THREAD->set_current_pending_monitor_is_from_java(true);
--- 385,395 ----
// JNI locks on java objects
// NOTE: must use heavy weight monitor to handle jni monitor enter
void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
// the current locking is from JNI instead of Java code
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
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);
THREAD->set_current_pending_monitor_is_from_java(true);
*** 421,431 ****
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
if (UseBiasedLocking) {
Handle h_obj(THREAD, obj);
! BiasedLocking::revoke_and_rebias(h_obj, false, THREAD);
obj = h_obj();
}
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
--- 397,407 ----
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
if (UseBiasedLocking) {
Handle h_obj(THREAD, obj);
! BiasedLocking::revoke(h_obj, THREAD);
obj = h_obj();
}
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
*** 445,471 ****
_thread = thread;
_thread->check_for_valid_safepoint_state(false);
_obj = obj;
if (_dolock) {
! ObjectSynchronizer::fast_enter(_obj, &_lock, false, _thread);
}
}
ObjectLocker::~ObjectLocker() {
if (_dolock) {
! ObjectSynchronizer::fast_exit(_obj(), &_lock, _thread);
}
}
// -----------------------------------------------------------------------------
// Wait/Notify/NotifyAll
// NOTE: must use heavy weight monitor to handle wait()
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");
}
if (millis < 0) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
--- 421,447 ----
_thread = thread;
_thread->check_for_valid_safepoint_state(false);
_obj = obj;
if (_dolock) {
! ObjectSynchronizer::enter(_obj, &_lock, _thread);
}
}
ObjectLocker::~ObjectLocker() {
if (_dolock) {
! ObjectSynchronizer::exit(_obj(), &_lock, _thread);
}
}
// -----------------------------------------------------------------------------
// Wait/Notify/NotifyAll
// NOTE: must use heavy weight monitor to handle wait()
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
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");
}
*** 481,502 ****
return dtrace_waited_probe(monitor, obj, THREAD);
}
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");
}
if (millis < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD);
}
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");
}
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
--- 457,478 ----
return dtrace_waited_probe(monitor, obj, THREAD);
}
void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
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");
}
inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD);
}
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
*** 506,516 ****
}
// NOTE: see comment of notify()
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");
}
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
--- 482,492 ----
}
// NOTE: see comment of notify()
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(obj, THREAD);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markWord mark = obj->mark();
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
*** 693,703 ****
Handle hobj(Self, obj);
// Relaxing assertion for bug 6320749.
assert(Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(),
"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");
}
}
--- 669,679 ----
Handle hobj(Self, obj);
// Relaxing assertion for bug 6320749.
assert(Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(),
"biases should not be seen by VM thread here");
! BiasedLocking::revoke(hobj, JavaThread::current());
obj = hobj();
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
}
*** 792,802 ****
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(thread == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
--- 768,778 ----
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
Handle h_obj) {
if (UseBiasedLocking) {
! BiasedLocking::revoke(h_obj, thread);
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();
*** 831,841 ****
// Possible mark states: neutral, biased, stack-locked, inflated
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(),
"biases should be revoked by now");
}
assert(self == JavaThread::current(), "Can only be called on current thread");
--- 807,817 ----
// Possible mark states: neutral, biased, stack-locked, inflated
if (UseBiasedLocking && h_obj()->mark().has_bias_pattern()) {
// CASE: biased
! BiasedLocking::revoke(h_obj, self);
assert(!h_obj->mark().has_bias_pattern(),
"biases should be revoked by now");
}
assert(self == JavaThread::current(), "Can only be called on current thread");
*** 867,877 ****
JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) {
if (UseBiasedLocking) {
if (SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke_at_safepoint(h_obj);
} else {
! BiasedLocking::revoke_and_rebias(h_obj, false, JavaThread::current());
}
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
oop obj = h_obj();
--- 843,853 ----
JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_obj) {
if (UseBiasedLocking) {
if (SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke_at_safepoint(h_obj);
} else {
! BiasedLocking::revoke(h_obj, JavaThread::current());
}
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
oop obj = h_obj();
*** 1461,1472 ****
// If we know we're inflating for entry it's better to inflate by swinging a
// pre-locked objectMonitor pointer into the object header. A successful
// CAS inflates the object *and* confers ownership to the inflating thread.
// In the current implementation we use a 2-step mechanism where we CAS()
// to inflate and then CAS() again to try to swing _owner from NULL to Self.
! // An inflateTry() method that we could call from fast_enter() and slow_enter()
! // would be useful.
// 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, mark.value());
ObjectMonitor * m = omAlloc(Self);
--- 1437,1447 ----
// If we know we're inflating for entry it's better to inflate by swinging a
// pre-locked objectMonitor pointer into the object header. A successful
// CAS inflates the object *and* confers ownership to the inflating thread.
// In the current implementation we use a 2-step mechanism where we CAS()
// to inflate and then CAS() again to try to swing _owner from NULL to Self.
! // An inflateTry() method that we could call from enter() would be useful.
// 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, mark.value());
ObjectMonitor * m = omAlloc(Self);
< prev index next >