8256425: Obsolete Biased Locking in JDK 18

Reviewed-by: kvn, dholmes, dcubed, rrich
This commit is contained in:
Patricio Chilano Mateo 2021-06-24 18:54:41 +00:00
parent 595446bff4
commit 2fd7943ec1
165 changed files with 293 additions and 5261 deletions

View file

@ -34,7 +34,6 @@
#include "oops/markWord.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/handshake.hpp"
#include "runtime/interfaceSupport.inline.hpp"
@ -300,7 +299,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al
return true;
}
// biased locking and any other IMS exception states take the slow-path
// other IMS exception states take the slow-path
return false;
}
@ -349,8 +348,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current,
// being locked. We do this unconditionally so that this thread's
// BasicLock cannot be mis-interpreted by any stack walkers. For
// performance reasons, stack walkers generally first check for
// Biased Locking in the object's header, the second check is for
// stack-locking in the object's header, the third check is for
// stack-locking in the object's header, the second 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(markWord::unused_mark());
@ -364,7 +362,6 @@ bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current,
// Note that we could inflate in quick_enter.
// This is likely a useful optimization
// Critically, in quick_enter() we must not:
// -- perform bias revocation, or
// -- block indefinitely, or
// -- reach a safepoint
@ -431,13 +428,7 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current)
handle_sync_on_value_based_class(obj, current);
}
if (UseBiasedLocking) {
BiasedLocking::revoke(current, 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.
@ -472,9 +463,6 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current)
void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) {
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");
markWord dhw = lock->displaced_header();
if (dhw.value() == 0) {
@ -535,11 +523,6 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current)
// 5) lock lock2
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
intx ObjectSynchronizer::complete_exit(Handle obj, JavaThread* current) {
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
// The ObjectMonitor* can't be async deflated until ownership is
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_vm_internal);
@ -549,11 +532,6 @@ intx ObjectSynchronizer::complete_exit(Handle obj, JavaThread* current) {
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
void ObjectSynchronizer::reenter(Handle obj, intx recursions, JavaThread* current) {
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
// An async deflation can race after the inflate() call and before
// reenter() -> enter() can make the ObjectMonitor busy. reenter() ->
// enter() returns false if we have lost the race to async deflation
@ -575,10 +553,6 @@ void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) {
}
// the current locking is from JNI instead of Java code
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
current->set_current_pending_monitor_is_from_java(false);
// An async deflation can race after the inflate() call and before
// enter() can make the ObjectMonitor busy. enter() returns false if
@ -595,12 +569,6 @@ void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) {
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, TRAPS) {
JavaThread* current = THREAD;
if (UseBiasedLocking) {
Handle h_obj(current, obj);
BiasedLocking::revoke(current, h_obj);
obj = h_obj();
}
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
// The ObjectMonitor* can't be async deflated until ownership is
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
@ -638,10 +606,6 @@ ObjectLocker::~ObjectLocker() {
// NOTE: must use heavy weight monitor to handle wait()
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
JavaThread* current = THREAD;
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
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");
}
@ -664,10 +628,6 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
// No exception are possible in this case as we only use this internally when locking is
// correct and we have to wait until notified - so no interrupts or timeouts.
void ObjectSynchronizer::wait_uninterruptibly(Handle obj, JavaThread* current) {
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
// The ObjectMonitor* can't be async deflated because the _waiters
// field is incremented before ownership is dropped and decremented
// after ownership is regained.
@ -677,10 +637,6 @@ void ObjectSynchronizer::wait_uninterruptibly(Handle obj, JavaThread* current) {
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
JavaThread* current = THREAD;
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markWord mark = obj->mark();
if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
@ -696,10 +652,6 @@ void ObjectSynchronizer::notify(Handle obj, TRAPS) {
// NOTE: see comment of notify()
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
JavaThread* current = THREAD;
if (UseBiasedLocking) {
BiasedLocking::revoke(current, obj);
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
markWord mark = obj->mark();
if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
@ -846,25 +798,6 @@ static inline intptr_t get_next_hash(Thread* current, oop obj) {
}
intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
if (UseBiasedLocking) {
// NOTE: many places throughout the JVM do not expect a safepoint
// to be taken here. However, we only ever bias Java instances and all
// of the call sites of identity_hash that might revoke biases have
// 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()) {
// Handle for oop obj in case of STW safepoint
Handle hobj(current, obj);
if (SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::revoke_at_safepoint(hobj);
} else {
BiasedLocking::revoke(JavaThread::cast(current), hobj);
}
obj = hobj();
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
}
while (true) {
ObjectMonitor* monitor = NULL;
@ -872,9 +805,6 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
intptr_t hash;
markWord mark = read_stable_mark(obj);
// object should remain ineligible for biased locking
assert(!mark.has_bias_pattern(), "invariant");
if (mark.is_neutral()) { // if this is a normal header
hash = mark.hash();
if (hash != 0) { // if it has a hash, just return it
@ -985,11 +915,6 @@ intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
Handle h_obj) {
if (UseBiasedLocking) {
BiasedLocking::revoke(current, h_obj);
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
assert(current == JavaThread::current(), "Can only be called on current thread");
oop obj = h_obj();
@ -1013,15 +938,6 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
// FIXME: jvmti should call this
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(JavaThread::current(), h_obj);
}
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
}
oop obj = h_obj();
address owner = NULL;
@ -1202,14 +1118,12 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop object,
for (;;) {
const markWord mark = object->mark();
assert(!mark.has_bias_pattern(), "invariant");
// The mark can be in one of the following states:
// * Inflated - just return
// * Stack-locked - coerce it to inflated
// * INFLATING - busy wait for conversion to complete
// * Neutral - aggressively inflate the object.
// * BIASED - Illegal. We should never see this
// CASE: inflated
if (mark.has_monitor()) {