8256302: releasing oopStorage when deflating allows for faster deleting

Reviewed-by: dholmes, rehn, coleenp
This commit is contained in:
Daniel D. Daugherty 2023-06-07 19:59:13 +00:00
parent 02bce0b145
commit 6402004852
4 changed files with 41 additions and 10 deletions

@ -54,6 +54,7 @@ class WeakHandle {
inline oop peek() const;
void release(OopStorage* storage) const;
bool is_null() const { return _obj == nullptr; }
void set_null() { _obj = nullptr; }
void replace(oop with_obj);

@ -276,7 +276,10 @@ ObjectMonitor::ObjectMonitor(oop object) :
{ }
ObjectMonitor::~ObjectMonitor() {
_object.release(_oop_storage);
if (!_object.is_null()) {
// Release object's oop storage if it hasn't already been done.
release_object();
}
}
oop ObjectMonitor::object() const {
@ -595,6 +598,9 @@ bool ObjectMonitor::deflate_monitor() {
install_displaced_markword_in_object(obj);
}
// Release object's oop storage since the ObjectMonitor has been deflated:
release_object();
// We leave owner == DEFLATER_MARKER and contentions < 0
// to force any racing threads to retry.
return true; // Success, ObjectMonitor has been deflated.

@ -363,6 +363,7 @@ private:
// Deflation support
bool deflate_monitor();
void install_displaced_markword_in_object(const oop obj);
void release_object() { _object.release(_oop_storage); _object.set_null(); }
};
#endif // SHARE_RUNTIME_OBJECTMONITOR_HPP

@ -1645,6 +1645,15 @@ public:
};
};
static size_t delete_monitors(GrowableArray<ObjectMonitor*>* delete_list) {
size_t count = 0;
for (ObjectMonitor* monitor: *delete_list) {
delete monitor;
count++;
}
return count;
}
// This function is called by the MonitorDeflationThread to deflate
// ObjectMonitors. It is also called via do_final_audit_and_print_stats()
// and VM_ThreadDump::doit() by the VMThread.
@ -1719,16 +1728,30 @@ size_t ObjectSynchronizer::deflate_idle_monitors(ObjectMonitorsHashtable* table)
}
// After the handshake, safely free the ObjectMonitors that were
// deflated in this cycle.
for (ObjectMonitor* monitor: delete_list) {
delete monitor;
deleted_count++;
if (current->is_Java_thread()) {
// A JavaThread must check for a safepoint/handshake and honor it.
chk_for_block_req(JavaThread::cast(current), "deletion", "deleted_count",
deleted_count, ls, &timer);
// deflated and unlinked in this cycle.
if (current->is_Java_thread()) {
if (ls != NULL) {
timer.stop();
ls->print_cr("before setting blocked: unlinked_count=" SIZE_FORMAT
", in_use_list stats: ceiling=" SIZE_FORMAT ", count="
SIZE_FORMAT ", max=" SIZE_FORMAT,
unlinked_count, in_use_list_ceiling(),
_in_use_list.count(), _in_use_list.max());
}
// Mark the calling JavaThread blocked (safepoint safe) while we free
// the ObjectMonitors so we don't delay safepoints whilst doing that.
ThreadBlockInVM tbivm(JavaThread::cast(current));
if (ls != NULL) {
ls->print_cr("after setting blocked: in_use_list stats: ceiling="
SIZE_FORMAT ", count=" SIZE_FORMAT ", max=" SIZE_FORMAT,
in_use_list_ceiling(), _in_use_list.count(), _in_use_list.max());
timer.start();
}
deleted_count = delete_monitors(&delete_list);
// ThreadBlockInVM is destroyed here
} else {
// A non-JavaThread can just free the ObjectMonitors:
deleted_count = delete_monitors(&delete_list);
}
assert(unlinked_count == deleted_count, "must be");
}