8379371: Proposed cleanups for JDK-8373595 A new ObjectMonitorTable implementation

Reviewed-by: stefank, fbredberg
This commit is contained in:
Daniel D. Daugherty 2026-03-06 15:39:27 +00:00
parent b349f661ea
commit 0aa52d633a
10 changed files with 58 additions and 57 deletions

View File

@ -1529,7 +1529,7 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec
GrowableArray<JavaThread*>* wantList = nullptr;
ObjectMonitor* mon = mark.has_monitor()
? ObjectSynchronizer::read_monitor(current_thread, hobj(), mark)
? ObjectSynchronizer::read_monitor(hobj(), mark)
: nullptr;
if (mon != nullptr) {

View File

@ -1686,7 +1686,7 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray<MonitorInf
assert(mon_info->owner()->is_locked(), "object must be locked now");
assert(obj->mark().has_monitor(), "must be");
assert(!deoptee_thread->lock_stack().contains(obj()), "must be");
assert(ObjectSynchronizer::read_monitor(thread, obj(), obj->mark())->has_owner(deoptee_thread), "must be");
assert(ObjectSynchronizer::read_monitor(obj(), obj->mark())->has_owner(deoptee_thread), "must be");
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Copyright (c) 2022, Red Hat, Inc. All rights reserved.
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -254,7 +254,7 @@ inline void OMCache::set_monitor(ObjectMonitor *monitor) {
oop obj = monitor->object_peek();
assert(obj != nullptr, "must be alive");
assert(monitor == ObjectSynchronizer::get_monitor_from_table(JavaThread::current(), obj), "must exist in table");
assert(monitor == ObjectSynchronizer::get_monitor_from_table(obj), "must exist in table");
OMCacheEntry to_insert = {obj, monitor};

View File

@ -854,7 +854,7 @@ bool ObjectMonitor::deflate_monitor(Thread* current) {
}
if (UseObjectMonitorTable) {
ObjectSynchronizer::deflate_monitor(current, obj, this);
ObjectSynchronizer::deflate_monitor(obj, this);
} else if (obj != nullptr) {
// Install the old mark word if nobody else has already done it.
install_displaced_markword_in_object(obj);

View File

@ -46,7 +46,7 @@
//
// When you want to find a monitor associated with an object, you extract the
// hash value of the object. Then calculate an index by taking the hash value
// and bit-wise AND it with the capacity mask (e.g. size-1) of the OMT. Now
// and bit-wise AND it with the capacity mask (i.e., size-1) of the OMT. Now
// use that index into the OMT's array of pointers. If the pointer is non
// null, check if it's a monitor pointer that is associated with the object.
// If so you're done. If the pointer is non null, but associated with another
@ -55,7 +55,7 @@
// means that the monitor is simply not in the OMT.
//
// If the size of the pointer array is significantly larger than the number of
// pointers in it, the chance of finding the monitor in the hash index
// pointers in it, the chance of finding the monitor at the hash index
// (without any further linear searching) is quite high. It is also straight
// forward to generate C2 code for this, which for the fast path doesn't
// contain any branching at all. See: C2_MacroAssembler::fast_lock().
@ -69,10 +69,10 @@
// old monitor pointers from the old table to the new.
//
// But since the OMT is a concurrent hash table and things needs to work for
// other clients of the OMT while we grow it, it's gets a bit more
// other clients of the OMT while we grow it, it gets a bit more
// complicated.
//
// Both the new and (potentially several) old table(s) may exist at the same
// The new and (potentially several) old table(s) may exist at the same
// time. The newest is always called the "current", and the older ones are
// singly linked using a "prev" pointer.
//
@ -82,7 +82,8 @@
//
// After that we start to go through all the indexes in the old table. If the
// index is empty (the pointer is null) we put a "tombstone" into that index,
// which will prevent any future concurrent insert ending up in that index.
// which will prevent any future concurrent insert from ending up in that
// index.
//
// If the index contains a monitor pointer, we insert that monitor pointer
// into the OMT which can be considered as one generation newer. If the index
@ -92,11 +93,11 @@
// that is not null, not a tombstone and not removed, is considered to be a
// pointer to a monitor.
//
// When all the monitor pointers from an old OMT has been transferred to the
// When all the monitor pointers from an old OMT have been transferred to the
// new OMT, the old table is unlinked.
//
// This copying from an old OMT to one generation newer OMT, will continue
// until all the monitor pointers from old OMTs has been transferred to the
// until all the monitor pointers from old OMTs have been transferred to the
// newest "current" OMT.
//
// The memory for old, unlinked OMTs will be freed after a thread-local
@ -255,7 +256,7 @@ public:
}
ObjectMonitor* prepare_insert(oop obj, intptr_t hash) {
// Acquire any tomb stones and relocations if prev transitioned to null.
// Acquire any tombstones and relocations if prev transitioned to null.
Table* prev = AtomicAccess::load_acquire(&_prev);
if (prev != nullptr) {
ObjectMonitor* result = prev->prepare_insert(obj, hash);
@ -273,7 +274,7 @@ public:
if (entry == empty()) {
// Found an empty slot to install the new monitor in.
// To avoid concurrent inserts succeeding, place a tomb stone here.
// To avoid concurrent inserts succeeding, place a tombstone here.
Entry result = AtomicAccess::cmpxchg(bucket, entry, tombstone(), memory_order_relaxed);
if (result == entry) {
// Success! Nobody will try to insert here again, except reinsert from rehashing.
@ -515,7 +516,7 @@ void ObjectMonitorTable::create() {
_curr = new Table(128, nullptr);
}
ObjectMonitor* ObjectMonitorTable::monitor_get(Thread* current, oop obj) {
ObjectMonitor* ObjectMonitorTable::monitor_get(oop obj) {
const intptr_t hash = obj->mark().hash();
Table* curr = AtomicAccess::load_acquire(&_curr);
ObjectMonitor* monitor = curr->get(obj, hash);
@ -562,7 +563,7 @@ ObjectMonitorTable::Table* ObjectMonitorTable::grow_table(Table* curr) {
return result;
}
ObjectMonitor* ObjectMonitorTable::monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj) {
ObjectMonitor* ObjectMonitorTable::monitor_put_get(ObjectMonitor* monitor, oop obj) {
const intptr_t hash = obj->mark().hash();
Table* curr = AtomicAccess::load_acquire(&_curr);
@ -577,7 +578,7 @@ ObjectMonitor* ObjectMonitorTable::monitor_put_get(Thread* current, ObjectMonito
}
}
void ObjectMonitorTable::remove_monitor_entry(Thread* current, ObjectMonitor* monitor) {
void ObjectMonitorTable::remove_monitor_entry(ObjectMonitor* monitor) {
oop obj = monitor->object_peek();
if (obj == nullptr) {
// Defer removal until subsequent rebuilding.
@ -586,7 +587,7 @@ void ObjectMonitorTable::remove_monitor_entry(Thread* current, ObjectMonitor* mo
const intptr_t hash = obj->mark().hash();
Table* curr = AtomicAccess::load_acquire(&_curr);
curr->remove(obj, curr->as_entry(monitor), hash);
assert(monitor_get(current, obj) != monitor, "should have been removed");
assert(monitor_get(obj) != monitor, "should have been removed");
}
// Before handshake; rehash and unlink tables.

View File

@ -61,11 +61,11 @@ public:
} SpecialPointerValues;
static void create();
static ObjectMonitor* monitor_get(Thread* current, oop obj);
static ObjectMonitor* monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj);
static ObjectMonitor* monitor_get(oop obj);
static ObjectMonitor* monitor_put_get(ObjectMonitor* monitor, oop obj);
static void rebuild(GrowableArray<Table*>* delete_list);
static void destroy(GrowableArray<Table*>* delete_list);
static void remove_monitor_entry(Thread* current, ObjectMonitor* monitor);
static void remove_monitor_entry(ObjectMonitor* monitor);
// Compiler support
static address current_table_address();

View File

@ -350,7 +350,7 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool al
}
if (mark.has_monitor()) {
ObjectMonitor* const mon = read_monitor(current, obj, mark);
ObjectMonitor* const mon = read_monitor(obj, mark);
if (mon == nullptr) {
// Racing with inflation/deflation go slow path
return false;
@ -485,7 +485,7 @@ ObjectLocker::ObjectLocker(Handle obj, TRAPS) : _thread(THREAD), _obj(obj),
// otherwise just force other vthreads to preempt in case they try
// to acquire this monitor.
_skip_exit = !_thread->preemption_cancelled();
ObjectSynchronizer::read_monitor(_thread, _obj())->set_object_strong();
ObjectSynchronizer::read_monitor(_obj())->set_object_strong();
_thread->set_pending_preempted_exception();
}
@ -502,7 +502,7 @@ void ObjectLocker::wait_uninterruptibly(TRAPS) {
ObjectSynchronizer::waitUninterruptibly(_obj, 0, _thread);
if (_thread->preempting()) {
_skip_exit = true;
ObjectSynchronizer::read_monitor(_thread, _obj())->set_object_strong();
ObjectSynchronizer::read_monitor(_obj())->set_object_strong();
_thread->set_pending_preempted_exception();
}
}
@ -749,7 +749,7 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
}
while (mark.has_monitor()) {
ObjectMonitor* monitor = read_monitor(current, obj, mark);
ObjectMonitor* monitor = read_monitor(obj, mark);
if (monitor != nullptr) {
return monitor->is_entered(current) != 0;
}
@ -778,7 +778,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob
}
while (mark.has_monitor()) {
ObjectMonitor* monitor = read_monitor(Thread::current(), obj, mark);
ObjectMonitor* monitor = read_monitor(obj, mark);
if (monitor != nullptr) {
return Threads::owning_thread_from_monitor(t_list, monitor);
}
@ -1425,7 +1425,7 @@ void ObjectSynchronizer::chk_in_use_entry(ObjectMonitor* n, outputStream* out,
return;
}
ObjectMonitor* const obj_mon = read_monitor(Thread::current(), obj, mark);
ObjectMonitor* const obj_mon = read_monitor(obj, mark);
if (n != obj_mon) {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use monitor's "
"object does not refer to the same monitor: obj="
@ -1471,8 +1471,8 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream* out, bool log_
out->flush();
}
ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted) {
ObjectMonitor* monitor = get_monitor_from_table(current, object);
ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, bool* inserted) {
ObjectMonitor* monitor = get_monitor_from_table(object);
if (monitor != nullptr) {
*inserted = false;
return monitor;
@ -1482,7 +1482,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object,
alloced_monitor->set_anonymous_owner();
// Try insert monitor
monitor = add_monitor(current, alloced_monitor, object);
monitor = add_monitor(alloced_monitor, object);
*inserted = alloced_monitor == monitor;
if (!*inserted) {
@ -1522,7 +1522,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor(oop object, JavaThread*
EventJavaMonitorInflate event;
bool inserted;
ObjectMonitor* monitor = get_or_insert_monitor_from_table(object, current, &inserted);
ObjectMonitor* monitor = get_or_insert_monitor_from_table(object, &inserted);
if (inserted) {
log_inflate(current, object, cause);
@ -1538,7 +1538,7 @@ ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor(oop object, JavaThread*
}
// Add the hashcode to the monitor to match the object and put it in the hashtable.
ObjectMonitor* ObjectSynchronizer::add_monitor(JavaThread* current, ObjectMonitor* monitor, oop obj) {
ObjectMonitor* ObjectSynchronizer::add_monitor(ObjectMonitor* monitor, oop obj) {
assert(UseObjectMonitorTable, "must be");
assert(obj == monitor->object(), "must be");
@ -1546,14 +1546,14 @@ ObjectMonitor* ObjectSynchronizer::add_monitor(JavaThread* current, ObjectMonito
assert(hash != 0, "must be set when claiming the object monitor");
monitor->set_hash(hash);
return ObjectMonitorTable::monitor_put_get(current, monitor, obj);
return ObjectMonitorTable::monitor_put_get(monitor, obj);
}
void ObjectSynchronizer::remove_monitor(Thread* current, ObjectMonitor* monitor, oop obj) {
void ObjectSynchronizer::remove_monitor(ObjectMonitor* monitor, oop obj) {
assert(UseObjectMonitorTable, "must be");
assert(monitor->object_peek() == obj, "must be, cleared objects are removed by is_dead");
ObjectMonitorTable::remove_monitor_entry(current, monitor);
ObjectMonitorTable::remove_monitor_entry(monitor);
}
void ObjectSynchronizer::deflate_mark_word(oop obj) {
@ -1721,7 +1721,7 @@ bool ObjectSynchronizer::fast_lock_spin_enter(oop obj, LockStack& lock_stack, Ja
return true;
} else if (observed_deflation) {
// Spin while monitor is being deflated.
ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(current, obj, mark);
ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark);
return monitor == nullptr || monitor->is_being_async_deflated();
}
// Else stop spinning.
@ -1881,7 +1881,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current)
if (UseObjectMonitorTable) {
monitor = read_caches(current, lock, object);
if (monitor == nullptr) {
monitor = get_monitor_from_table(current, object);
monitor = get_monitor_from_table(object);
}
} else {
monitor = ObjectSynchronizer::read_monitor(mark);
@ -1925,7 +1925,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_locked_or_imse(oop obj, ObjectSynchro
}
assert(mark.has_monitor(), "must be");
ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(current, obj, mark);
ObjectMonitor* monitor = ObjectSynchronizer::read_monitor(obj, mark);
if (monitor != nullptr) {
if (monitor->has_anonymous_owner()) {
LockStack& lock_stack = current->lock_stack();
@ -2087,7 +2087,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_fast_locked_object(oop object, Object
// contains a deflating monitor it must be anonymously owned.
if (monitor->has_anonymous_owner()) {
// The monitor must be anonymously owned if it was added
assert(monitor == get_monitor_from_table(current, object), "The monitor must be found");
assert(monitor == get_monitor_from_table(object), "The monitor must be found");
// New fresh monitor
break;
}
@ -2279,31 +2279,31 @@ ObjectMonitor* ObjectSynchronizer::inflate_and_enter(oop object, BasicLock* lock
return monitor;
}
void ObjectSynchronizer::deflate_monitor(Thread* current, oop obj, ObjectMonitor* monitor) {
void ObjectSynchronizer::deflate_monitor(oop obj, ObjectMonitor* monitor) {
if (obj != nullptr) {
deflate_mark_word(obj);
remove_monitor(current, monitor, obj);
remove_monitor(monitor, obj);
}
}
ObjectMonitor* ObjectSynchronizer::get_monitor_from_table(Thread* current, oop obj) {
ObjectMonitor* ObjectSynchronizer::get_monitor_from_table(oop obj) {
assert(UseObjectMonitorTable, "must be");
return ObjectMonitorTable::monitor_get(current, obj);
return ObjectMonitorTable::monitor_get(obj);
}
ObjectMonitor* ObjectSynchronizer::read_monitor(markWord mark) {
return mark.monitor();
}
ObjectMonitor* ObjectSynchronizer::read_monitor(Thread* current, oop obj) {
return ObjectSynchronizer::read_monitor(current, obj, obj->mark());
ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj) {
return ObjectSynchronizer::read_monitor(obj, obj->mark());
}
ObjectMonitor* ObjectSynchronizer::read_monitor(Thread* current, oop obj, markWord mark) {
ObjectMonitor* ObjectSynchronizer::read_monitor(oop obj, markWord mark) {
if (!UseObjectMonitorTable) {
return read_monitor(mark);
} else {
return ObjectSynchronizer::get_monitor_from_table(current, obj);
return ObjectSynchronizer::get_monitor_from_table(obj);
}
}

View File

@ -126,8 +126,8 @@ public:
static const char* inflate_cause_name(const InflateCause cause);
static ObjectMonitor* read_monitor(markWord mark);
static ObjectMonitor* read_monitor(Thread* current, oop obj);
static ObjectMonitor* read_monitor(Thread* current, oop obj, markWord mark);
static ObjectMonitor* read_monitor(oop obj);
static ObjectMonitor* read_monitor(oop obj, markWord mark);
// Returns the identity hash value for an oop
// NOTE: It may cause monitor inflation
@ -209,11 +209,11 @@ public:
static void handle_sync_on_value_based_class(Handle obj, JavaThread* locking_thread);
static ObjectMonitor* get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted);
static ObjectMonitor* get_or_insert_monitor_from_table(oop object, bool* inserted);
static ObjectMonitor* get_or_insert_monitor(oop object, JavaThread* current, ObjectSynchronizer::InflateCause cause);
static ObjectMonitor* add_monitor(JavaThread* current, ObjectMonitor* monitor, oop obj);
static void remove_monitor(Thread* current, ObjectMonitor* monitor, oop obj);
static ObjectMonitor* add_monitor(ObjectMonitor* monitor, oop obj);
static void remove_monitor(ObjectMonitor* monitor, oop obj);
static void deflate_mark_word(oop object);
@ -239,9 +239,9 @@ public:
static ObjectMonitor* inflate_fast_locked_object(oop object, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current);
static ObjectMonitor* inflate_and_enter(oop object, BasicLock* lock, ObjectSynchronizer::InflateCause cause, JavaThread* locking_thread, JavaThread* current);
static void deflate_monitor(Thread* current, oop obj, ObjectMonitor* monitor);
static void deflate_monitor(oop obj, ObjectMonitor* monitor);
static ObjectMonitor* get_monitor_from_table(Thread* current, oop obj);
static ObjectMonitor* get_monitor_from_table(oop obj);
static bool contains_monitor(Thread* current, ObjectMonitor* monitor);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -248,7 +248,7 @@ void javaVFrame::print_lock_info_on(outputStream* st, bool is_virtual, int frame
// The first stage of async deflation does not affect any field
// used by this comparison so the ObjectMonitor* is usable here.
if (mark.has_monitor()) {
ObjectMonitor* mon = ObjectSynchronizer::read_monitor(current, monitor->owner(), mark);
ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark);
if (// if the monitor is null we must be in the process of locking
mon == nullptr ||
// we have marked ourself as pending on this monitor

View File

@ -1252,7 +1252,7 @@ private:
// The first stage of async deflation does not affect any field
// used by this comparison so the ObjectMonitor* is usable here.
if (mark.has_monitor()) {
ObjectMonitor* mon = ObjectSynchronizer::read_monitor(current, monitor->owner(), mark);
ObjectMonitor* mon = ObjectSynchronizer::read_monitor(monitor->owner(), mark);
if (// if the monitor is null we must be in the process of locking
mon == nullptr ||
// we have marked ourself as pending on this monitor