From 6402004852ccc993bb6e879c49fb71e2afdcdfbe Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 7 Jun 2023 19:59:13 +0000 Subject: [PATCH] 8256302: releasing oopStorage when deflating allows for faster deleting Reviewed-by: dholmes, rehn, coleenp --- src/hotspot/share/oops/weakHandle.hpp | 1 + src/hotspot/share/runtime/objectMonitor.cpp | 8 +++- src/hotspot/share/runtime/objectMonitor.hpp | 1 + src/hotspot/share/runtime/synchronizer.cpp | 41 ++++++++++++++++----- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/oops/weakHandle.hpp b/src/hotspot/share/oops/weakHandle.hpp index 95328d27aef..b6a76999e6a 100644 --- a/src/hotspot/share/oops/weakHandle.hpp +++ b/src/hotspot/share/oops/weakHandle.hpp @@ -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); diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 9ed77a01bb6..0739de77b8a 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -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. diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index d6c0e31f7a1..92fb58dadb5 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -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 diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 69a712bfb76..09ed8d1a7f8 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1645,6 +1645,15 @@ public: }; }; +static size_t delete_monitors(GrowableArray* 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"); }