8252543: [JVMCI] Libgraal can deadlock in blocking compilation mode

Reviewed-by: kvn
This commit is contained in:
Doug Simon 2020-09-12 05:26:16 +00:00
parent b1b0f0b2cc
commit 998ce78e53
11 changed files with 112 additions and 54 deletions

View file

@ -249,11 +249,6 @@ bool compileBroker_init() {
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
CompilerThread* thread = CompilerThread::current(); CompilerThread* thread = CompilerThread::current();
thread->set_task(task); thread->set_task(task);
#if INCLUDE_JVMCI
if (task->is_blocking() && CompileBroker::compiler(task->comp_level())->is_jvmci()) {
task->set_jvmci_compiler_thread(thread);
}
#endif
CompileLog* log = thread->log(); CompileLog* log = thread->log();
if (log != NULL && !task->is_unloaded()) task->log_task_start(log); if (log != NULL && !task->is_unloaded()) task->log_task_start(log);
} }
@ -277,7 +272,7 @@ CompileTaskWrapper::~CompileTaskWrapper() {
// The waiting thread timed out and thus did not free the task. // The waiting thread timed out and thus did not free the task.
free_task = true; free_task = true;
} }
task->set_jvmci_compiler_thread(NULL); task->set_blocking_jvmci_compile_state(NULL);
} }
#endif #endif
if (!free_task) { if (!free_task) {
@ -1604,22 +1599,27 @@ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask*
assert(UseJVMCICompiler, "sanity"); assert(UseJVMCICompiler, "sanity");
MonitorLocker ml(thread, task->lock()); MonitorLocker ml(thread, task->lock());
int progress_wait_attempts = 0; int progress_wait_attempts = 0;
int methods_compiled = jvmci->methods_compiled(); jint thread_jvmci_compilation_ticks = 0;
jint global_jvmci_compilation_ticks = jvmci->global_compilation_ticks();
while (!task->is_complete() && !is_compilation_disabled_forever() && while (!task->is_complete() && !is_compilation_disabled_forever() &&
ml.wait(JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) { ml.wait(JVMCI_COMPILATION_PROGRESS_WAIT_TIMESLICE)) {
CompilerThread* jvmci_compiler_thread = task->jvmci_compiler_thread(); JVMCICompileState* jvmci_compile_state = task->blocking_jvmci_compile_state();
bool progress; bool progress;
if (jvmci_compiler_thread != NULL) { if (jvmci_compile_state != NULL) {
// If the JVMCI compiler thread is not blocked or suspended, we deem it to be making progress. jint ticks = jvmci_compile_state->compilation_ticks();
progress = jvmci_compiler_thread->thread_state() != _thread_blocked && progress = (ticks - thread_jvmci_compilation_ticks) != 0;
!jvmci_compiler_thread->is_external_suspend(); JVMCI_event_1("waiting on compilation %d [ticks=%d]", task->compile_id(), ticks);
thread_jvmci_compilation_ticks = ticks;
} else { } else {
// Still waiting on JVMCI compiler queue. This thread may be holding a lock // Still waiting on JVMCI compiler queue. This thread may be holding a lock
// that all JVMCI compiler threads are blocked on. We use the counter for // that all JVMCI compiler threads are blocked on. We use the global JVMCI
// successful JVMCI compilations to determine whether JVMCI compilation // compilation ticks to determine whether JVMCI compilation
// is still making progress through the JVMCI compiler queue. // is still making progress through the JVMCI compiler queue.
progress = jvmci->methods_compiled() != methods_compiled; jint ticks = jvmci->global_compilation_ticks();
progress = (ticks - global_jvmci_compilation_ticks) != 0;
JVMCI_event_1("waiting on compilation %d to be queued [ticks=%d]", task->compile_id(), ticks);
global_jvmci_compilation_ticks = ticks;
} }
if (!progress) { if (!progress) {
@ -1627,13 +1627,11 @@ bool CompileBroker::wait_for_jvmci_completion(JVMCICompiler* jvmci, CompileTask*
if (PrintCompilation) { if (PrintCompilation) {
task->print(tty, "wait for blocking compilation timed out"); task->print(tty, "wait for blocking compilation timed out");
} }
JVMCI_event_1("waiting on compilation %d timed out", task->compile_id());
break; break;
} }
} else { } else {
progress_wait_attempts = 0; progress_wait_attempts = 0;
if (jvmci_compiler_thread == NULL) {
methods_compiled = jvmci->methods_compiled();
}
} }
} }
task->clear_waiter(); task->clear_waiter();
@ -2152,7 +2150,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
TraceTime t1("compilation", &time); TraceTime t1("compilation", &time);
EventCompilation event; EventCompilation event;
JVMCICompileState compile_state(task); JVMCICompileState compile_state(task, jvmci);
JVMCIRuntime *runtime = NULL; JVMCIRuntime *runtime = NULL;
if (JVMCI::in_shutdown()) { if (JVMCI::in_shutdown()) {

View file

@ -100,7 +100,7 @@ void CompileTask::initialize(int compile_id,
_osr_bci = osr_bci; _osr_bci = osr_bci;
_is_blocking = is_blocking; _is_blocking = is_blocking;
JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();) JVMCI_ONLY(_has_waiter = CompileBroker::compiler(comp_level)->is_jvmci();)
JVMCI_ONLY(_jvmci_compiler_thread = NULL;) JVMCI_ONLY(_blocking_jvmci_compile_state = NULL;)
_comp_level = comp_level; _comp_level = comp_level;
_num_inlined_bytecodes = 0; _num_inlined_bytecodes = 0;

View file

@ -31,6 +31,8 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "utilities/xmlstream.hpp" #include "utilities/xmlstream.hpp"
JVMCI_ONLY(class JVMCICompileState;)
// CompileTask // CompileTask
// //
// An entry in the compile queue. It represents a pending or current // An entry in the compile queue. It represents a pending or current
@ -81,8 +83,8 @@ class CompileTask : public CHeapObj<mtCompiler> {
bool _is_blocking; bool _is_blocking;
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
bool _has_waiter; bool _has_waiter;
// Compiler thread for a blocking JVMCI compilation // Compilation state for a blocking JVMCI compilation
CompilerThread* _jvmci_compiler_thread; JVMCICompileState* _blocking_jvmci_compile_state;
#endif #endif
int _comp_level; int _comp_level;
int _num_inlined_bytecodes; int _num_inlined_bytecodes;
@ -144,11 +146,9 @@ class CompileTask : public CHeapObj<mtCompiler> {
bool has_waiter() const { return _has_waiter; } bool has_waiter() const { return _has_waiter; }
void clear_waiter() { _has_waiter = false; } void clear_waiter() { _has_waiter = false; }
CompilerThread* jvmci_compiler_thread() const { return _jvmci_compiler_thread; } JVMCICompileState* blocking_jvmci_compile_state() const { return _blocking_jvmci_compile_state; }
void set_jvmci_compiler_thread(CompilerThread* t) { void set_blocking_jvmci_compile_state(JVMCICompileState* state) {
assert(is_blocking(), "must be"); _blocking_jvmci_compile_state = state;
assert((t == NULL) != (_jvmci_compiler_thread == NULL), "must be");
_jvmci_compiler_thread = t;
} }
#endif #endif

View file

@ -23,9 +23,11 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "compiler/compileTask.hpp"
#include "gc/shared/collectedHeap.hpp" #include "gc/shared/collectedHeap.hpp"
#include "jvmci/jvmci.hpp" #include "jvmci/jvmci.hpp"
#include "jvmci/jvmciJavaClasses.hpp" #include "jvmci/jvmciJavaClasses.hpp"
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciRuntime.hpp"
#include "jvmci/metadataHandles.hpp" #include "jvmci/metadataHandles.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
@ -123,6 +125,18 @@ void JVMCI::initialize_globals() {
} }
} }
JavaThread* JVMCI::compilation_tick(JavaThread* thread) {
if (thread->is_Compiler_thread()) {
CompileTask *task = thread->as_CompilerThread()->task();
if (task != NULL) {
JVMCICompileState *state = task->blocking_jvmci_compile_state();
if (state != NULL) {
state->inc_compilation_ticks();
}
}
}
return thread;
}
void JVMCI::metadata_do(void f(Metadata*)) { void JVMCI::metadata_do(void f(Metadata*)) {
if (_java_runtime != NULL) { if (_java_runtime != NULL) {

View file

@ -110,6 +110,11 @@ class JVMCI : public AllStatic {
static void initialize_compiler(TRAPS); static void initialize_compiler(TRAPS);
// Increments a value indicating some JVMCI compilation activity
// happened on `thread` if it is a CompilerThread.
// Returns `thread`.
static JavaThread* compilation_tick(JavaThread* thread);
static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; } static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; }
// Gets the single runtime for JVMCI on the Java heap. This is the only // Gets the single runtime for JVMCI on the Java heap. This is the only
// JVMCI runtime available when !UseJVMCINativeLibrary. // JVMCI runtime available when !UseJVMCINativeLibrary.

View file

@ -37,6 +37,7 @@ JVMCICompiler::JVMCICompiler() : AbstractCompiler(compiler_jvmci) {
_bootstrapping = false; _bootstrapping = false;
_bootstrap_compilation_request_handled = false; _bootstrap_compilation_request_handled = false;
_methods_compiled = 0; _methods_compiled = 0;
_global_compilation_ticks = 0;
assert(_instance == NULL, "only one instance allowed"); assert(_instance == NULL, "only one instance allowed");
_instance = this; _instance = this;
} }
@ -154,3 +155,12 @@ void JVMCICompiler::print_compilation_timers() {
tty->print_cr(" JVMCI code install time: %6.3f s", code_install_time); tty->print_cr(" JVMCI code install time: %6.3f s", code_install_time);
} }
} }
void JVMCICompiler::inc_methods_compiled() {
Atomic::inc(&_methods_compiled);
Atomic::inc(&_global_compilation_ticks);
}
void JVMCICompiler::inc_global_compilation_ticks() {
Atomic::inc(&_global_compilation_ticks);
}

View file

@ -42,6 +42,10 @@ private:
*/ */
volatile int _methods_compiled; volatile int _methods_compiled;
// Incremented periodically by JVMCI compiler threads
// to indicate JVMCI compilation activity.
volatile int _global_compilation_ticks;
static JVMCICompiler* _instance; static JVMCICompiler* _instance;
static elapsedTimer _codeInstallTimer; static elapsedTimer _codeInstallTimer;
@ -99,15 +103,16 @@ public:
// Print compilation timers and statistics // Print compilation timers and statistics
virtual void print_timers(); virtual void print_timers();
/** // Gets the number of methods that have been successfully compiled by
* Gets the number of methods that have been successfully compiled by // a call to JVMCICompiler::compile_method().
* a call to JVMCICompiler::compile_method().
*/
int methods_compiled() { return _methods_compiled; } int methods_compiled() { return _methods_compiled; }
void inc_methods_compiled();
void inc_methods_compiled() { // Gets a value indicating JVMCI compilation activity on any thread.
Atomic::inc(&_methods_compiled); // If successive calls to this method return a different value, then
} // some degree of JVMCI compilation occurred between the calls.
int global_compilation_ticks() const { return _global_compilation_ticks; }
void inc_global_compilation_ticks();
// Print compilation timers and statistics // Print compilation timers and statistics
static void print_compilation_timers(); static void print_compilation_timers();

View file

@ -132,7 +132,7 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
TRACE_CALL(result_type, jvmci_ ## name signature) \ TRACE_CALL(result_type, jvmci_ ## name signature) \
JVMCI_VM_ENTRY_MARK; \ JVMCI_VM_ENTRY_MARK; \
ResourceMark rm; \ ResourceMark rm; \
JNI_JVMCIENV(thread, env); JNI_JVMCIENV(JVMCI::compilation_tick(thread), env);
static JavaThread* get_current_thread(bool allow_null=true) { static JavaThread* get_current_thread(bool allow_null=true) {
Thread* thread = Thread::current_or_null_safe(); Thread* thread = Thread::current_or_null_safe();

View file

@ -36,10 +36,12 @@
#include "runtime/jniHandles.inline.hpp" #include "runtime/jniHandles.inline.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jniAccessMark.inline.hpp"
#include "jvmci/jvmciCompiler.hpp"
#include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciRuntime.hpp"
JVMCICompileState::JVMCICompileState(CompileTask* task): JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):
_task(task), _task(task),
_compiler(compiler),
_retryable(true), _retryable(true),
_failure_reason(NULL), _failure_reason(NULL),
_failure_reason_on_C_heap(false) { _failure_reason_on_C_heap(false) {
@ -51,6 +53,20 @@ JVMCICompileState::JVMCICompileState(CompileTask* task):
_jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0; _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0;
_jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0; _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0;
_target_method_is_old = _task != NULL && _task->method()->is_old(); _target_method_is_old = _task != NULL && _task->method()->is_old();
if (task->is_blocking()) {
task->set_blocking_jvmci_compile_state(this);
}
}
// Update global JVMCI compilation ticks after 512 thread-local JVMCI compilation ticks.
// This mitigates the overhead of the atomic operation used for the global update.
#define THREAD_TICKS_PER_GLOBAL_TICKS (2 << 9)
#define THREAD_TICKS_PER_GLOBAL_TICKS_MASK (THREAD_TICKS_PER_GLOBAL_TICKS - 1)
void JVMCICompileState::inc_compilation_ticks() {
if ((++_compilation_ticks & THREAD_TICKS_PER_GLOBAL_TICKS_MASK) == 0) {
_compiler->inc_global_compilation_ticks();
}
} }
bool JVMCICompileState::jvmti_state_changed() const { bool JVMCICompileState::jvmti_state_changed() const {
@ -620,8 +636,8 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...)
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci, JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
jlong compile_state, int id) { jlong compile_state, int id) {
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
Thread* THREAD = Thread::current();
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method)));
@ -635,7 +651,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtim
vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject())); vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject()));
return wrap((oop) result.get_jobject()); return wrap((oop) result.get_jobject());
} else { } else {
JNIAccessMark jni(this); JNIAccessMark jni(this, THREAD);
jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(), jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(),
JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(), JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(),
@ -648,14 +664,14 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtim
} }
void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
Thread* THREAD = Thread::current();
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
JavaValue result(T_VOID); JavaValue result(T_VOID);
JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK); JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
} else { } else {
JNIAccessMark jni(this); JNIAccessMark jni(this, THREAD);
jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method()); jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());
} }
@ -681,7 +697,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
} }
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) { JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
@ -698,7 +714,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
} }
JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) { JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
@ -715,7 +731,7 @@ JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
} }
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) { JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
@ -734,7 +750,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime,
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) { JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object))); jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
@ -758,7 +774,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object,
JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) { JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_int(kind); jargs.push_int(kind);
@ -782,7 +798,7 @@ JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value
} }
JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) { JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_float(value); jargs.push_float(value);
@ -805,7 +821,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
} }
JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) { JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaCallArguments jargs; JavaCallArguments jargs;
jargs.push_double(value); jargs.push_double(value);
@ -886,7 +902,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci,
} }
JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) { JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject())); JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject()));
@ -989,7 +1005,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
return method_object; return method_object;
} }
Thread* THREAD = Thread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
jmetadata handle = _runtime->allocate_handle(method); jmetadata handle = _runtime->allocate_handle(method);
jboolean exception = false; jboolean exception = false;
if (is_hotspot()) { if (is_hotspot()) {
@ -1005,7 +1021,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
method_object = wrap((oop)result.get_jobject()); method_object = wrap((oop)result.get_jobject());
} }
} else { } else {
JNIAccessMark jni(this); JNIAccessMark jni(this, THREAD);
method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(), method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(), JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
(jlong) handle)); (jlong) handle));
@ -1032,7 +1048,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
} }
jlong pointer = (jlong) klass(); jlong pointer = (jlong) klass();
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject())); JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject()));
jboolean exception = false; jboolean exception = false;
if (is_hotspot()) { if (is_hotspot()) {
@ -1071,7 +1087,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC
JVMCIObject cp_object; JVMCIObject cp_object;
jmetadata handle = _runtime->allocate_handle(cp); jmetadata handle = _runtime->allocate_handle(cp);
jboolean exception = false; jboolean exception = false;
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());
if (is_hotspot()) { if (is_hotspot()) {
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
JavaCallArguments args; JavaCallArguments args;

View file

@ -94,6 +94,7 @@ class JVMCICompileState : public ResourceObj {
friend class JVMCIVMStructs; friend class JVMCIVMStructs;
private: private:
CompileTask* _task; CompileTask* _task;
JVMCICompiler* _compiler;
// Cache JVMTI state. Defined as bytes so that reading them from Java // Cache JVMTI state. Defined as bytes so that reading them from Java
// via Unsafe is well defined (the C++ type for bool is implementation // via Unsafe is well defined (the C++ type for bool is implementation
@ -113,8 +114,13 @@ class JVMCICompileState : public ResourceObj {
// with the mtJVMCI NMT flag. // with the mtJVMCI NMT flag.
bool _failure_reason_on_C_heap; bool _failure_reason_on_C_heap;
// A value indicating compilation activity during the compilation.
// If successive calls to this method return a different value, then
// some degree of JVMCI compilation occurred between the calls.
jint _compilation_ticks;
public: public:
JVMCICompileState(CompileTask* task); JVMCICompileState(CompileTask* task, JVMCICompiler* compiler);
CompileTask* task() { return _task; } CompileTask* task() { return _task; }
@ -135,6 +141,9 @@ class JVMCICompileState : public ResourceObj {
_failure_reason_on_C_heap = reason_on_C_heap; _failure_reason_on_C_heap = reason_on_C_heap;
_retryable = retryable; _retryable = retryable;
} }
jint compilation_ticks() const { return _compilation_ticks; }
void inc_compilation_ticks();
}; };
@ -284,7 +293,7 @@ public:
JVMCIPrimitiveArray wrap(typeArrayOop obj) { assert(is_hotspot(), "must be"); return (JVMCIPrimitiveArray) wrap(JNIHandles::make_local(obj)); } JVMCIPrimitiveArray wrap(typeArrayOop obj) { assert(is_hotspot(), "must be"); return (JVMCIPrimitiveArray) wrap(JNIHandles::make_local(obj)); }
public: public:
// Compiles a method with the JVMIC compiler. // Compiles a method with the JVMCI compiler.
// Caller must handle pending exception. // Caller must handle pending exception.
JVMCIObject call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime, JVMCIObject method, int entry_bci, JVMCIObject call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime, JVMCIObject method, int entry_bci,
jlong compile_state, int id); jlong compile_state, int id);

View file

@ -163,6 +163,7 @@
nonstatic_field(JVMCICompileState, _jvmti_can_access_local_variables, jbyte) \ nonstatic_field(JVMCICompileState, _jvmti_can_access_local_variables, jbyte) \
nonstatic_field(JVMCICompileState, _jvmti_can_post_on_exceptions, jbyte) \ nonstatic_field(JVMCICompileState, _jvmti_can_post_on_exceptions, jbyte) \
nonstatic_field(JVMCICompileState, _jvmti_can_pop_frame, jbyte) \ nonstatic_field(JVMCICompileState, _jvmti_can_pop_frame, jbyte) \
nonstatic_field(JVMCICompileState, _compilation_ticks, jint) \
\ \
nonstatic_field(JavaThread, _threadObj, OopHandle) \ nonstatic_field(JavaThread, _threadObj, OopHandle) \
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \