# HG changeset patch # User rkennke # Date 1494876428 -7200 # Mon May 15 21:27:08 2017 +0200 # Node ID 51a2913ba31364e7abc8b15a00f71666fa1e12ec # Parent 4931b832162d6a5b826def463c7f22eb99e60c0f Deflate idle monitors per thread. diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -1185,6 +1185,10 @@ \ product(bool, MonitorInUseLists, true, "Track Monitors for Deflation") \ \ + experimental(bool, DeflateIdleMonitorsPerThread, false, \ + "Deflate idle monitors in Java thread before entering " \ + "safepoint.") \ + \ experimental(intx, SyncFlags, 0, "(Unsafe, Unstable) " \ "Experimental Sync flags") \ \ diff --git a/src/share/vm/runtime/synchronizer.cpp b/src/share/vm/runtime/synchronizer.cpp --- a/src/share/vm/runtime/synchronizer.cpp +++ b/src/share/vm/runtime/synchronizer.cpp @@ -1662,16 +1662,17 @@ Thread::muxAcquire(&gListLock, "scavenge - return"); if (MonitorInUseLists) { - int inUse = 0; - for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) { - nInCirculation+= cur->omInUseCount; - int deflated_count = deflate_monitor_list(cur->omInUseList_addr(), &freeHeadp, &freeTailp); - cur->omInUseCount-= deflated_count; - if (ObjectMonitor::Knob_VerifyInUse) { - verifyInUse(cur); + if (! DeflateIdleMonitorsPerThread) { + for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) { + nInCirculation+= cur->omInUseCount; + int deflated_count = deflate_monitor_list(cur->omInUseList_addr(), &freeHeadp, &freeTailp); + cur->omInUseCount-= deflated_count; + if (ObjectMonitor::Knob_VerifyInUse) { + verifyInUse(cur); + } + nScavenged += deflated_count; + nInuse += cur->omInUseCount; } - nScavenged += deflated_count; - nInuse += cur->omInUseCount; } // For moribund threads, scan gOmInUseList @@ -1747,6 +1748,34 @@ GVars.stwCycle++; } +void ObjectSynchronizer::deflate_idle_monitors_per_thread(Thread* thread) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); + if (! MonitorInUseLists) return; + if (! DeflateIdleMonitorsPerThread) return; + + ObjectMonitor * freeHeadp = NULL; // Local SLL of scavenged monitors + ObjectMonitor * freeTailp = NULL; + + int deflated_count = deflate_monitor_list(thread->omInUseList_addr(), &freeHeadp, &freeTailp); + thread->omInUseCount-= deflated_count; + if (ObjectMonitor::Knob_VerifyInUse) { + verifyInUse(thread); + } + + // Move the scavenged monitors back to the global free list. + if (freeHeadp != NULL) { + Thread::muxAcquire(&gListLock, "scavenge - return"); + guarantee(freeTailp != NULL && deflated_count > 0, "invariant"); + assert(freeTailp->FreeNext == NULL, "invariant"); + + gMonitorFreeCount += deflated_count; + // constant-time list splice - prepend scavenged segment to gFreeList + freeTailp->FreeNext = gFreeList; + gFreeList = freeHeadp; + Thread::muxRelease(&gListLock); + } +} + // Monitor cleanup on JavaThread::exit // Iterate through monitor cache and attempt to release thread's monitors diff --git a/src/share/vm/runtime/synchronizer.hpp b/src/share/vm/runtime/synchronizer.hpp --- a/src/share/vm/runtime/synchronizer.hpp +++ b/src/share/vm/runtime/synchronizer.hpp @@ -145,6 +145,8 @@ // Basically we deflate all monitors that are not busy. // An adaptive profile-based deflation policy could be used if needed static void deflate_idle_monitors(); + static void deflate_idle_monitors_per_thread(Thread* thread); + // For a given monitor list: global or per-thread, deflate idle monitors static int deflate_monitor_list(ObjectMonitor** listheadp, ObjectMonitor** freeHeadp, diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp +++ b/src/share/vm/runtime/thread.cpp @@ -794,6 +794,9 @@ f->do_oop((oop*)&_pending_exception); handle_area()->oops_do(f); // TODO: Either need better abstractions or have all GCs use this. + if (DeflateIdleMonitorsPerThread) { + ObjectSynchronizer::deflate_idle_monitors_per_thread(this); + } if (UseShenandoahGC && ShenandoahFastSyncRoots && MonitorInUseLists) { ObjectSynchronizer::thread_local_used_oops_do(this, f); }