Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.

Commit 00f223e

Browse files
Daniel D. Daughertyvarming
andcommitted
8153224: Monitor deflation prolong safepoints
Add support for AsyncDeflateIdleMonitors (default true); the async deflation work is performed by the ServiceThread. Co-authored-by: Carsten Varming <varming@gmail.com> Reviewed-by: dcubed, rehn, rkennke, cvarming, coleenp, acorn, dholmes, eosterlund
1 parent 30aa1b0 commit 00f223e

23 files changed

+1497
-251
lines changed

src/hotspot/share/prims/jvm.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#include "runtime/os.inline.hpp"
7575
#include "runtime/perfData.hpp"
7676
#include "runtime/reflection.hpp"
77+
#include "runtime/synchronizer.hpp"
7778
#include "runtime/thread.inline.hpp"
7879
#include "runtime/threadSMR.hpp"
7980
#include "runtime/vframe.inline.hpp"
@@ -490,6 +491,11 @@ JVM_END
490491
JVM_ENTRY_NO_ENV(void, JVM_GC(void))
491492
JVMWrapper("JVM_GC");
492493
if (!DisableExplicitGC) {
494+
if (AsyncDeflateIdleMonitors) {
495+
// AsyncDeflateIdleMonitors needs to know when System.gc() is
496+
// called so any special deflation can be done at a safepoint.
497+
ObjectSynchronizer::set_is_special_deflation_requested(true);
498+
}
493499
Universe::heap()->collect(GCCause::_java_lang_system_gc);
494500
}
495501
JVM_END

src/hotspot/share/prims/jvmtiEnvBase.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ JvmtiEnvBase::get_current_contended_monitor(JavaThread *java_thread, jobject *mo
653653
current_jt == java_thread->active_handshaker(),
654654
"call by myself or at direct handshake");
655655
oop obj = NULL;
656+
// The ObjectMonitor* can't be async deflated since we are either
657+
// at a safepoint or the calling thread is operating on itself so
658+
// it cannot leave the underlying wait()/enter() call.
656659
ObjectMonitor *mon = java_thread->current_waiting_monitor();
657660
if (mon == NULL) {
658661
// thread is not doing an Object.wait() call
@@ -730,15 +733,21 @@ JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread
730733
HandleMark hm;
731734
oop wait_obj = NULL;
732735
{
733-
// save object of current wait() call (if any) for later comparison
736+
// The ObjectMonitor* can't be async deflated since we are either
737+
// at a safepoint or the calling thread is operating on itself so
738+
// it cannot leave the underlying wait() call.
739+
// Save object of current wait() call (if any) for later comparison.
734740
ObjectMonitor *mon = java_thread->current_waiting_monitor();
735741
if (mon != NULL) {
736742
wait_obj = (oop)mon->object();
737743
}
738744
}
739745
oop pending_obj = NULL;
740746
{
741-
// save object of current enter() call (if any) for later comparison
747+
// The ObjectMonitor* can't be async deflated since we are either
748+
// at a safepoint or the calling thread is operating on itself so
749+
// it cannot leave the underlying enter() call.
750+
// Save object of current enter() call (if any) for later comparison.
742751
ObjectMonitor *mon = java_thread->current_pending_monitor();
743752
if (mon != NULL) {
744753
pending_obj = (oop)mon->object();

src/hotspot/share/prims/whitebox.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include "runtime/jniHandles.inline.hpp"
7474
#include "runtime/os.hpp"
7575
#include "runtime/sweeper.hpp"
76+
#include "runtime/synchronizer.hpp"
7677
#include "runtime/thread.hpp"
7778
#include "runtime/threadSMR.hpp"
7879
#include "runtime/vm_version.hpp"
@@ -477,6 +478,12 @@ WB_END
477478

478479
WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
479480
if (UseG1GC) {
481+
if (AsyncDeflateIdleMonitors) {
482+
// AsyncDeflateIdleMonitors needs to know when System.gc() or
483+
// the equivalent is called so any special clean up can be done
484+
// at a safepoint, e.g., TestHumongousClassLoader.java.
485+
ObjectSynchronizer::set_is_special_deflation_requested(true);
486+
}
480487
G1CollectedHeap* g1h = G1CollectedHeap::heap();
481488
if (!g1h->concurrent_mark()->cm_thread()->during_cycle()) {
482489
g1h->collect(GCCause::_wb_conc_mark);
@@ -1448,6 +1455,12 @@ WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString
14481455
WB_END
14491456

14501457
WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
1458+
if (AsyncDeflateIdleMonitors) {
1459+
// AsyncDeflateIdleMonitors needs to know when System.gc() or
1460+
// the equivalent is called so any special clean up can be done
1461+
// at a safepoint, e.g., TestHumongousClassLoader.java.
1462+
ObjectSynchronizer::set_is_special_deflation_requested(true);
1463+
}
14511464
Universe::heap()->soft_ref_policy()->set_should_clear_all_soft_refs(true);
14521465
Universe::heap()->collect(GCCause::_wb_full_gc);
14531466
#if INCLUDE_G1GC
@@ -1797,6 +1810,13 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
17971810
WB_END
17981811

17991812
WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
1813+
if (AsyncDeflateIdleMonitors) {
1814+
// AsyncDeflateIdleMonitors needs to know when System.gc() or
1815+
// the equivalent is called so any special clean up can be done
1816+
// at a safepoint, e.g., TestRTMTotalCountIncrRate.java or
1817+
// TestUseRTMForStackLocks.java.
1818+
ObjectSynchronizer::set_is_special_deflation_requested(true);
1819+
}
18001820
VM_ForceSafepoint force_safepoint_op;
18011821
VMThread::execute(&force_safepoint_op);
18021822
WB_END

src/hotspot/share/runtime/basicLock.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,24 +36,24 @@ void BasicLock::print_on(outputStream* st) const {
3636
void BasicLock::move_to(oop obj, BasicLock* dest) {
3737
// Check to see if we need to inflate the lock. This is only needed
3838
// if an object is locked using "this" lightweight monitor. In that
39-
// case, the displaced_header() is unlocked, because the
39+
// case, the displaced_header() is unlocked/is_neutral, because the
4040
// displaced_header() contains the header for the originally unlocked
41-
// object. However the object could have already been inflated. But it
42-
// does not matter, the inflation will just a no-op. For other cases,
41+
// object. However the lock could have already been inflated. But it
42+
// does not matter, this inflation will just a no-op. For other cases,
4343
// the displaced header will be either 0x0 or 0x3, which are location
4444
// independent, therefore the BasicLock is free to move.
4545
//
4646
// During OSR we may need to relocate a BasicLock (which contains a
4747
// displaced word) from a location in an interpreter frame to a
4848
// new location in a compiled frame. "this" refers to the source
49-
// basiclock in the interpreter frame. "dest" refers to the destination
50-
// basiclock in the new compiled frame. We *always* inflate in move_to().
51-
// The always-Inflate policy works properly, but in 1.5.0 it can sometimes
52-
// cause performance problems in code that makes heavy use of a small # of
53-
// uncontended locks. (We'd inflate during OSR, and then sync performance
54-
// would subsequently plummet because the thread would be forced thru the slow-path).
55-
// This problem has been made largely moot on IA32 by inlining the inflated fast-path
56-
// operations in Fast_Lock and Fast_Unlock in i486.ad.
49+
// BasicLock in the interpreter frame. "dest" refers to the destination
50+
// BasicLock in the new compiled frame. We *always* inflate in move_to()
51+
// when the object is locked using "this" lightweight monitor.
52+
//
53+
// The always-Inflate policy works properly, but it depends on the
54+
// inflated fast-path operations in fast_lock and fast_unlock to avoid
55+
// performance problems. See x86/macroAssembler_x86.cpp: fast_lock()
56+
// and fast_unlock() for examples.
5757
//
5858
// Note that there is a way to safely swing the object's markword from
5959
// one stack location to another. This avoids inflation. Obviously,
@@ -63,8 +63,10 @@ void BasicLock::move_to(oop obj, BasicLock* dest) {
6363
// we'll leave that optimization for another time.
6464

6565
if (displaced_header().is_neutral()) {
66+
// The object is locked and the resulting ObjectMonitor* will also be
67+
// locked so it can't be async deflated until ownership is dropped.
6668
ObjectSynchronizer::inflate_helper(obj);
67-
// WARNING: We can not put check here, because the inflation
69+
// WARNING: We cannot put a check here, because the inflation
6870
// will not update the displaced header. Once BasicLock is inflated,
6971
// no one should ever look at its content.
7072
} else {

src/hotspot/share/runtime/globals.hpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -683,11 +683,21 @@ const size_t minimumSymbolTableSize = 1024;
683683
"Disable the use of stack guard pages if the JVM is loaded " \
684684
"on the primordial process thread") \
685685
\
686+
diagnostic(bool, AsyncDeflateIdleMonitors, true, \
687+
"Deflate idle monitors using the ServiceThread.") \
688+
\
689+
/* notice: the max range value here is max_jint, not max_intx */ \
690+
/* because of overflow issue */ \
691+
diagnostic(intx, AsyncDeflationInterval, 250, \
692+
"Async deflate idle monitors every so many milliseconds when " \
693+
"MonitorUsedDeflationThreshold is exceeded (0 is off).") \
694+
range(0, max_jint) \
695+
\
686696
experimental(intx, MonitorUsedDeflationThreshold, 90, \
687-
"Percentage of used monitors before triggering cleanup " \
688-
"safepoint which deflates monitors (0 is off). " \
689-
"The check is performed on GuaranteedSafepointInterval.") \
690-
range(0, 100) \
697+
"Percentage of used monitors before triggering deflation (0 is " \
698+
"off). The check is performed on GuaranteedSafepointInterval " \
699+
"or AsyncDeflationInterval.") \
700+
range(0, 100) \
691701
\
692702
experimental(intx, hashCode, 5, \
693703
"(Unstable) select hashCode generation algorithm") \

src/hotspot/share/runtime/init.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,12 @@ void exit_globals() {
172172
if (log_is_enabled(Info, monitorinflation)) {
173173
// The ObjectMonitor subsystem uses perf counters so
174174
// do this before perfMemory_exit().
175-
// ObjectSynchronizer::finish_deflate_idle_monitors()'s call
176-
// to audit_and_print_stats() is done at the Debug level.
175+
// These other two audit_and_print_stats() calls are done at the
176+
// Debug level at a safepoint:
177+
// - for safepoint based deflation auditing:
178+
// ObjectSynchronizer::finish_deflate_idle_monitors()
179+
// - for async deflation auditing:
180+
// ObjectSynchronizer::do_safepoint_work()
177181
ObjectSynchronizer::audit_and_print_stats(true /* on_exit */);
178182
}
179183
perfMemory_exit();

0 commit comments

Comments
 (0)