Skip to content

Commit 2e19026

Browse files
Daniel D. Daughertyfisk
andcommitted
8253064: monitor list simplifications and getting rid of TSM
Co-authored-by: Erik Österlund <eosterlund@openjdk.org> Reviewed-by: eosterlund, rehn, coleenp
1 parent 421a7c3 commit 2e19026

25 files changed

+809
-1904
lines changed

src/hotspot/share/oops/markWord.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,42 @@
2525
#include "precompiled.hpp"
2626
#include "oops/markWord.hpp"
2727
#include "runtime/thread.inline.hpp"
28-
#include "runtime/objectMonitor.hpp"
28+
#include "runtime/objectMonitor.inline.hpp"
2929
#include "utilities/ostream.hpp"
3030

31+
markWord markWord::displaced_mark_helper() const {
32+
assert(has_displaced_mark_helper(), "check");
33+
if (has_monitor()) {
34+
// Has an inflated monitor. Must be checked before has_locker().
35+
ObjectMonitor* monitor = this->monitor();
36+
return monitor->header();
37+
}
38+
if (has_locker()) { // has a stack lock
39+
BasicLock* locker = this->locker();
40+
return locker->displaced_header();
41+
}
42+
// This should never happen:
43+
fatal("bad header=" INTPTR_FORMAT, value());
44+
return markWord(value());
45+
}
46+
47+
void markWord::set_displaced_mark_helper(markWord m) const {
48+
assert(has_displaced_mark_helper(), "check");
49+
if (has_monitor()) {
50+
// Has an inflated monitor. Must be checked before has_locker().
51+
ObjectMonitor* monitor = this->monitor();
52+
monitor->set_header(m);
53+
return;
54+
}
55+
if (has_locker()) { // has a stack lock
56+
BasicLock* locker = this->locker();
57+
locker->set_displaced_header(m);
58+
return;
59+
}
60+
// This should never happen:
61+
fatal("bad header=" INTPTR_FORMAT, value());
62+
}
63+
3164
void markWord::print_on(outputStream* st, bool print_monitor_info) const {
3265
if (is_marked()) { // last bits = 11
3366
st->print(" marked(" INTPTR_FORMAT ")", value());

src/hotspot/share/oops/markWord.hpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,16 +286,8 @@ class markWord {
286286
bool has_displaced_mark_helper() const {
287287
return ((value() & unlocked_value) == 0);
288288
}
289-
markWord displaced_mark_helper() const {
290-
assert(has_displaced_mark_helper(), "check");
291-
uintptr_t ptr = (value() & ~monitor_value);
292-
return *(markWord*)ptr;
293-
}
294-
void set_displaced_mark_helper(markWord m) const {
295-
assert(has_displaced_mark_helper(), "check");
296-
uintptr_t ptr = (value() & ~monitor_value);
297-
((markWord*)ptr)->_value = m._value;
298-
}
289+
markWord displaced_mark_helper() const;
290+
void set_displaced_mark_helper(markWord m) const;
299291
markWord copy_set_hash(intptr_t hash) const {
300292
uintptr_t tmp = value() & (~hash_mask_in_place);
301293
tmp |= ((hash & hash_mask) << hash_shift);

src/hotspot/share/runtime/globals.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,20 @@ const intx ObjectAlignmentInBytes = 8;
728728
"MonitorUsedDeflationThreshold is exceeded (0 is off).") \
729729
range(0, max_jint) \
730730
\
731+
/* notice: the max range value here is max_jint, not max_intx */ \
732+
/* because of overflow issue */ \
733+
product(intx, AvgMonitorsPerThreadEstimate, 1024, DIAGNOSTIC, \
734+
"Used to estimate a variable ceiling based on number of threads " \
735+
"for use with MonitorUsedDeflationThreshold (0 is off).") \
736+
range(0, max_jint) \
737+
\
738+
/* notice: the max range value here is max_jint, not max_intx */ \
739+
/* because of overflow issue */ \
740+
product(intx, MonitorDeflationMax, 1000000, DIAGNOSTIC, \
741+
"The maximum number of monitors to deflate, unlink and delete " \
742+
"at one time (minimum is 1024).") \
743+
range(1024, max_jint) \
744+
\
731745
product(intx, MonitorUsedDeflationThreshold, 90, EXPERIMENTAL, \
732746
"Percentage of used monitors before triggering deflation (0 is " \
733747
"off). The check is performed on GuaranteedSafepointInterval " \
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
#include "precompiled.hpp"
26+
#include "classfile/javaClasses.hpp"
27+
#include "runtime/interfaceSupport.inline.hpp"
28+
#include "runtime/java.hpp"
29+
#include "runtime/javaCalls.hpp"
30+
#include "runtime/monitorDeflationThread.hpp"
31+
#include "runtime/mutexLocker.hpp"
32+
33+
MonitorDeflationThread* MonitorDeflationThread::_instance = NULL;
34+
35+
void MonitorDeflationThread::initialize() {
36+
EXCEPTION_MARK;
37+
38+
const char* name = "Monitor Deflation Thread";
39+
Handle string = java_lang_String::create_from_str(name, CHECK);
40+
41+
// Initialize thread_oop to put it into the system threadGroup
42+
Handle thread_group (THREAD, Universe::system_thread_group());
43+
Handle thread_oop = JavaCalls::construct_new_instance(
44+
SystemDictionary::Thread_klass(),
45+
vmSymbols::threadgroup_string_void_signature(),
46+
thread_group,
47+
string,
48+
CHECK);
49+
50+
{
51+
MutexLocker mu(THREAD, Threads_lock);
52+
MonitorDeflationThread* thread = new MonitorDeflationThread(&monitor_deflation_thread_entry);
53+
54+
// At this point it may be possible that no osthread was created for the
55+
// JavaThread due to lack of memory. We would have to throw an exception
56+
// in that case. However, since this must work and we do not allow
57+
// exceptions anyway, check and abort if this fails.
58+
if (thread == NULL || thread->osthread() == NULL) {
59+
vm_exit_during_initialization("java.lang.OutOfMemoryError",
60+
os::native_thread_creation_failed_msg());
61+
}
62+
63+
java_lang_Thread::set_thread(thread_oop(), thread);
64+
java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
65+
java_lang_Thread::set_daemon(thread_oop());
66+
thread->set_threadObj(thread_oop());
67+
_instance = thread;
68+
69+
Threads::add(thread);
70+
Thread::start(thread);
71+
}
72+
}
73+
74+
void MonitorDeflationThread::monitor_deflation_thread_entry(JavaThread* jt, TRAPS) {
75+
while (true) {
76+
{
77+
// Need state transition ThreadBlockInVM so that this thread
78+
// will be handled by safepoint correctly when this thread is
79+
// notified at a safepoint.
80+
81+
// This ThreadBlockInVM object is not also considered to be
82+
// suspend-equivalent because MonitorDeflationThread is not
83+
// visible to external suspension.
84+
85+
ThreadBlockInVM tbivm(jt);
86+
87+
MonitorLocker ml(MonitorDeflation_lock, Mutex::_no_safepoint_check_flag);
88+
while (!ObjectSynchronizer::is_async_deflation_needed()) {
89+
// Wait until notified that there is some work to do.
90+
// We wait for GuaranteedSafepointInterval so that
91+
// is_async_deflation_needed() is checked at the same interval.
92+
ml.wait(GuaranteedSafepointInterval);
93+
}
94+
}
95+
96+
(void)ObjectSynchronizer::deflate_idle_monitors();
97+
}
98+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*
23+
*/
24+
25+
#ifndef SHARE_RUNTIME_MONITORDEFLATIONTHREAD_HPP
26+
#define SHARE_RUNTIME_MONITORDEFLATIONTHREAD_HPP
27+
28+
#include "runtime/thread.hpp"
29+
30+
// A hidden from external view JavaThread for deflating idle monitors.
31+
32+
class MonitorDeflationThread : public JavaThread {
33+
friend class VMStructs;
34+
private:
35+
static MonitorDeflationThread* _instance;
36+
37+
static void monitor_deflation_thread_entry(JavaThread* thread, TRAPS);
38+
MonitorDeflationThread(ThreadFunction entry_point) : JavaThread(entry_point) {};
39+
40+
public:
41+
static void initialize();
42+
43+
// Hide this thread from external view.
44+
bool is_hidden_from_external_view() const { return true; }
45+
bool is_monitor_deflation_thread() const { return true; }
46+
};
47+
48+
#endif // SHARE_RUNTIME_MONITORDEFLATIONTHREAD_HPP

src/hotspot/share/runtime/mutexLocker.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ Mutex* OldSets_lock = NULL;
116116
Monitor* RootRegionScan_lock = NULL;
117117

118118
Mutex* Management_lock = NULL;
119+
Monitor* MonitorDeflation_lock = NULL;
119120
Monitor* Service_lock = NULL;
120121
Monitor* Notification_lock = NULL;
121122
Monitor* PeriodicTask_lock = NULL;
@@ -244,6 +245,7 @@ void mutex_init() {
244245

245246
def(Patching_lock , PaddedMutex , special, true, _safepoint_check_never); // used for safepointing and code patching.
246247
def(CompiledMethod_lock , PaddedMutex , special-1, true, _safepoint_check_never);
248+
def(MonitorDeflation_lock , PaddedMonitor, tty-2, true, _safepoint_check_never); // used for monitor deflation thread operations
247249
def(Service_lock , PaddedMonitor, tty-2, true, _safepoint_check_never); // used for service thread operations
248250

249251
if (UseNotificationThread) {

src/hotspot/share/runtime/mutexLocker.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ extern Mutex* OldSets_lock; // protects the old region sets
111111
extern Monitor* RootRegionScan_lock; // used to notify that the CM threads have finished scanning the IM snapshot regions
112112

113113
extern Mutex* Management_lock; // a lock used to serialize JVM management
114+
extern Monitor* MonitorDeflation_lock; // a lock used for monitor deflation thread operation
114115
extern Monitor* Service_lock; // a lock used for service thread operation
115116
extern Monitor* Notification_lock; // a lock used for notification thread operation
116117
extern Monitor* PeriodicTask_lock; // protects the periodic task structure

0 commit comments

Comments
 (0)