Skip to content

Commit 998ce78

Browse files
author
Doug Simon
committed
8252543: [JVMCI] Libgraal can deadlock in blocking compilation mode
Reviewed-by: kvn
1 parent b1b0f0b commit 998ce78

File tree

11 files changed

+112
-54
lines changed

11 files changed

+112
-54
lines changed

src/hotspot/share/compiler/compileBroker.cpp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,6 @@ bool compileBroker_init() {
249249
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
250250
CompilerThread* thread = CompilerThread::current();
251251
thread->set_task(task);
252-
#if INCLUDE_JVMCI
253-
if (task->is_blocking() && CompileBroker::compiler(task->comp_level())->is_jvmci()) {
254-
task->set_jvmci_compiler_thread(thread);
255-
}
256-
#endif
257252
CompileLog* log = thread->log();
258253
if (log != NULL && !task->is_unloaded()) task->log_task_start(log);
259254
}
@@ -277,7 +272,7 @@ CompileTaskWrapper::~CompileTaskWrapper() {
277272
// The waiting thread timed out and thus did not free the task.
278273
free_task = true;
279274
}
280-
task->set_jvmci_compiler_thread(NULL);
275+
task->set_blocking_jvmci_compile_state(NULL);
281276
}
282277
#endif
283278
if (!free_task) {
@@ -1604,36 +1599,39 @@ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask*
16041599
assert(UseJVMCICompiler, "sanity");
16051600
MonitorLocker ml(thread, task->lock());
16061601
int progress_wait_attempts = 0;
1607-
int methods_compiled = jvmci->methods_compiled();
1602+
jint thread_jvmci_compilation_ticks = 0;
1603+
jint global_jvmci_compilation_ticks = jvmci->global_compilation_ticks();
16081604
while (!task->is_complete() && !is_compilation_disabled_forever() &&
16091605
ml.wait(JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) {
1610-
CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread();
1606+
JVMCICompileState* jvmci_compile_state = task->blocking_jvmci_compile_state();
16111607

16121608
bool progress;
1613-
if (jvmci_compiler_thread != NULL) {
1614-
// If the JVMCI compiler thread is not blocked or suspended, we deem it to be making progress.
1615-
progress = jvmci_compiler_thread->thread_state() != _thread_blocked &&
1616-
!jvmci_compiler_thread->is_external_suspend();
1609+
if (jvmci_compile_state != NULL) {
1610+
jint ticks = jvmci_compile_state->compilation_ticks();
1611+
progress = (ticks - thread_jvmci_compilation_ticks) != 0;
1612+
JVMCI_event_1("waiting on compilation %d [ticks=%d]", task->compile_id(), ticks);
1613+
thread_jvmci_compilation_ticks = ticks;
16171614
} else {
16181615
// Still waiting on JVMCI compiler queue. This thread may be holding a lock
1619-
// that all JVMCI compiler threads are blocked on. We use the counter for
1620-
// successful JVMCI compilations to determine whether JVMCI compilation
1616+
// that all JVMCI compiler threads are blocked on. We use the global JVMCI
1617+
// compilation ticks to determine whether JVMCI compilation
16211618
// is still making progress through the JVMCI compiler queue.
1622-
progress = jvmci->methods_compiled() != methods_compiled;
1619+
jint ticks = jvmci->global_compilation_ticks();
1620+
progress = (ticks - global_jvmci_compilation_ticks) != 0;
1621+
JVMCI_event_1("waiting on compilation %d to be queued [ticks=%d]", task->compile_id(), ticks);
1622+
global_jvmci_compilation_ticks = ticks;
16231623
}
16241624

16251625
if (!progress) {
16261626
if (++progress_wait_attempts == JVMCI_COMPILATION_PROGRESS_WAIT_ATTEMPTS) {
16271627
if (PrintCompilation) {
16281628
task->print(tty, "wait for blocking compilation timed out");
16291629
}
1630+
JVMCI_event_1("waiting on compilation %d timed out", task->compile_id());
16301631
break;
16311632
}
16321633
} else {
16331634
progress_wait_attempts = 0;
1634-
if (jvmci_compiler_thread == NULL) {
1635-
methods_compiled = jvmci->methods_compiled();
1636-
}
16371635
}
16381636
}
16391637
task->clear_waiter();
@@ -2152,7 +2150,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
21522150

21532151
TraceTime t1("compilation", &time);
21542152
EventCompilation event;
2155-
JVMCICompileState compile_state(task);
2153+
JVMCICompileState compile_state(task, jvmci);
21562154
JVMCIRuntime *runtime = NULL;
21572155

21582156
if (JVMCI::in_shutdown()) {

src/hotspot/share/compiler/compileTask.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void CompileTask::initialize(int compile_id,
100100
_osr_bci = osr_bci;
101101
_is_blocking = is_blocking;
102102
JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();)
103-
JVMCI_ONLY(_jvmci_compiler_thread = NULL;)
103+
JVMCI_ONLY(_blocking_jvmci_compile_state = NULL;)
104104
_comp_level = comp_level;
105105
_num_inlined_bytecodes = 0;
106106

src/hotspot/share/compiler/compileTask.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include "memory/allocation.hpp"
3232
#include "utilities/xmlstream.hpp"
3333

34+
JVMCI_ONLY(class JVMCICompileState;)
35+
3436
// CompileTask
3537
//
3638
// An entry in the compile queue. It represents a pending or current
@@ -81,8 +83,8 @@ class CompileTask : public CHeapObj<mtCompiler> {
8183
bool _is_blocking;
8284
#if INCLUDE_JVMCI
8385
bool _has_waiter;
84-
// Compiler thread for a blocking JVMCI compilation
85-
CompilerThread* _jvmci_compiler_thread;
86+
// Compilation state for a blocking JVMCI compilation
87+
JVMCICompileState* _blocking_jvmci_compile_state;
8688
#endif
8789
int _comp_level;
8890
int _num_inlined_bytecodes;
@@ -144,11 +146,9 @@ class CompileTask : public CHeapObj<mtCompiler> {
144146

145147
bool has_waiter() const { return _has_waiter; }
146148
void clear_waiter() { _has_waiter = false; }
147-
CompilerThread* jvmci_compiler_thread() const { return _jvmci_compiler_thread; }
148-
void set_jvmci_compiler_thread(CompilerThread* t) {
149-
assert(is_blocking(), "must be");
150-
assert((t == NULL) != (_jvmci_compiler_thread == NULL), "must be");
151-
_jvmci_compiler_thread = t;
149+
JVMCICompileState* blocking_jvmci_compile_state() const { return _blocking_jvmci_compile_state; }
150+
void set_blocking_jvmci_compile_state(JVMCICompileState* state) {
151+
_blocking_jvmci_compile_state = state;
152152
}
153153
#endif
154154

src/hotspot/share/jvmci/jvmci.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323

2424
#include "precompiled.hpp"
2525
#include "classfile/systemDictionary.hpp"
26+
#include "compiler/compileTask.hpp"
2627
#include "gc/shared/collectedHeap.hpp"
2728
#include "jvmci/jvmci.hpp"
2829
#include "jvmci/jvmciJavaClasses.hpp"
30+
#include "jvmci/jvmciEnv.hpp"
2931
#include "jvmci/jvmciRuntime.hpp"
3032
#include "jvmci/metadataHandles.hpp"
3133
#include "memory/resourceArea.hpp"
@@ -123,6 +125,18 @@ void JVMCI::initialize_globals() {
123125
}
124126
}
125127

128+
JavaThread* JVMCI::compilation_tick(JavaThread* thread) {
129+
if (thread->is_Compiler_thread()) {
130+
CompileTask *task = thread->as_CompilerThread()->task();
131+
if (task != NULL) {
132+
JVMCICompileState *state = task->blocking_jvmci_compile_state();
133+
if (state != NULL) {
134+
state->inc_compilation_ticks();
135+
}
136+
}
137+
}
138+
return thread;
139+
}
126140

127141
void JVMCI::metadata_do(void f(Metadata*)) {
128142
if (_java_runtime != NULL) {

src/hotspot/share/jvmci/jvmci.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ class JVMCI : public AllStatic {
110110

111111
static void initialize_compiler(TRAPS);
112112

113+
// Increments a value indicating some JVMCI compilation activity
114+
// happened on `thread` if it is a CompilerThread.
115+
// Returns `thread`.
116+
static JavaThread* compilation_tick(JavaThread* thread);
117+
113118
static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; }
114119
// Gets the single runtime for JVMCI on the Java heap. This is the only
115120
// JVMCI runtime available when !UseJVMCINativeLibrary.

src/hotspot/share/jvmci/jvmciCompiler.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ JVMCICompiler::JVMCICompiler() : AbstractCompiler(compiler_jvmci) {
3737
_bootstrapping = false;
3838
_bootstrap_compilation_request_handled = false;
3939
_methods_compiled = 0;
40+
_global_compilation_ticks = 0;
4041
assert(_instance == NULL, "only one instance allowed");
4142
_instance = this;
4243
}
@@ -154,3 +155,12 @@ void JVMCICompiler::print_compilation_timers() {
154155
tty->print_cr(" JVMCI code install time: %6.3f s", code_install_time);
155156
}
156157
}
158+
159+
void JVMCICompiler::inc_methods_compiled() {
160+
Atomic::inc(&_methods_compiled);
161+
Atomic::inc(&_global_compilation_ticks);
162+
}
163+
164+
void JVMCICompiler::inc_global_compilation_ticks() {
165+
Atomic::inc(&_global_compilation_ticks);
166+
}

src/hotspot/share/jvmci/jvmciCompiler.hpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class JVMCICompiler : public AbstractCompiler {
4242
*/
4343
volatile int _methods_compiled;
4444

45+
// Incremented periodically by JVMCI compiler threads
46+
// to indicate JVMCI compilation activity.
47+
volatile int _global_compilation_ticks;
48+
4549
static JVMCICompiler* _instance;
4650

4751
static elapsedTimer _codeInstallTimer;
@@ -99,15 +103,16 @@ class JVMCICompiler : public AbstractCompiler {
99103
// Print compilation timers and statistics
100104
virtual void print_timers();
101105

102-
/**
103-
* Gets the number of methods that have been successfully compiled by
104-
* a call to JVMCICompiler::compile_method().
105-
*/
106+
// Gets the number of methods that have been successfully compiled by
107+
// a call to JVMCICompiler::compile_method().
106108
int methods_compiled() { return _methods_compiled; }
109+
void inc_methods_compiled();
107110

108-
void inc_methods_compiled() {
109-
Atomic::inc(&_methods_compiled);
110-
}
111+
// Gets a value indicating JVMCI compilation activity on any thread.
112+
// If successive calls to this method return a different value, then
113+
// some degree of JVMCI compilation occurred between the calls.
114+
int global_compilation_ticks() const { return _global_compilation_ticks; }
115+
void inc_global_compilation_ticks();
111116

112117
// Print compilation timers and statistics
113118
static void print_compilation_timers();

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
132132
TRACE_CALL(result_type, jvmci_ ## name signature) \
133133
JVMCI_VM_ENTRY_MARK; \
134134
ResourceMark rm; \
135-
JNI_JVMCIENV(thread, env);
135+
JNI_JVMCIENV(JVMCI::compilation_tick(thread), env);
136136

137137
static JavaThread* get_current_thread(bool allow_null=true) {
138138
Thread* thread = Thread::current_or_null_safe();

0 commit comments

Comments
 (0)