8315369: [JVMCI] failure to attach to a libgraal isolate during shutdown should not be fatal
Reviewed-by: never
This commit is contained in:
parent
d1cabe4f22
commit
d7e4087faf
@ -2203,7 +2203,14 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
compilable = ciEnv::MethodCompilable_never;
|
||||
} else {
|
||||
JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__);
|
||||
failure_reason = compile_state.failure_reason();
|
||||
if (env.init_error() != JNI_OK) {
|
||||
failure_reason = os::strdup(err_msg("Error attaching to libjvmci (err: %d)", env.init_error()), mtJVMCI);
|
||||
bool reason_on_C_heap = true;
|
||||
// In case of JNI_ENOMEM, there's a good chance a subsequent attempt to create libjvmci or attach to it
|
||||
// might succeed. Other errors most likely indicate a non-recoverable error in the JVMCI runtime.
|
||||
bool retryable = env.init_error() == JNI_ENOMEM;
|
||||
compile_state.set_failure(retryable, failure_reason, reason_on_C_heap);
|
||||
}
|
||||
if (failure_reason == nullptr) {
|
||||
if (WhiteBoxAPI && WhiteBox::compilation_locked) {
|
||||
// Must switch to native to block
|
||||
|
@ -44,6 +44,7 @@ class JNIAccessMark : public StackObj {
|
||||
inline JNIAccessMark(JVMCIEnv* jvmci_env, JavaThread* thread=JavaThread::current()) :
|
||||
_ttnfv(thread), _hm(thread) {
|
||||
_env = jvmci_env->_env;
|
||||
guarantee(jvmci_env->init_error() == JNI_OK, "invalid JVMCIEnv (err: %d)", jvmci_env->init_error());
|
||||
}
|
||||
JNIEnv* env() const { return _env; }
|
||||
JNIEnv* operator () () const { return _env; }
|
||||
|
@ -171,7 +171,7 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
|
||||
#define C2V_BLOCK(result_type, name, signature) \
|
||||
JVMCI_VM_ENTRY_MARK; \
|
||||
ResourceMark rm; \
|
||||
JNI_JVMCIENV(JVMCI::compilation_tick(thread), env);
|
||||
JVMCIENV_FROM_JNI(JVMCI::compilation_tick(thread), env);
|
||||
|
||||
static JavaThread* get_current_thread(bool allow_null=true) {
|
||||
Thread* thread = Thread::current_or_null_safe();
|
||||
@ -2436,16 +2436,13 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
|
||||
JVMCIRuntime* runtime;
|
||||
{
|
||||
// Ensure the JVMCI shared library runtime is initialized.
|
||||
bool jni_enomem_is_fatal = false;
|
||||
JVMCIEnv __peer_jvmci_env__(thread, false, jni_enomem_is_fatal, __FILE__, __LINE__);
|
||||
JVMCIEnv* peerEnv = &__peer_jvmci_env__;
|
||||
if (peerEnv->has_jni_enomem()) {
|
||||
JVMCI_THROW_MSG_0(OutOfMemoryError, "JNI_ENOMEM creating or attaching to libjvmci");
|
||||
}
|
||||
PEER_JVMCIENV_FROM_THREAD(THREAD, false);
|
||||
PEER_JVMCIENV->check_init(JVMCI_CHECK_NULL);
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
runtime = JVMCI::compiler_runtime(thread);
|
||||
if (peerEnv->has_pending_exception()) {
|
||||
peerEnv->describe_pending_exception(tty);
|
||||
if (PEER_JVMCIENV->has_pending_exception()) {
|
||||
PEER_JVMCIENV->describe_pending_exception(tty);
|
||||
}
|
||||
sl_handle = JVMCI::get_shared_library(sl_path, false);
|
||||
if (sl_handle == nullptr) {
|
||||
@ -2604,17 +2601,13 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb
|
||||
|
||||
{
|
||||
// Ensure the JVMCI shared library runtime is initialized.
|
||||
bool jni_enomem_is_fatal = false;
|
||||
JVMCIEnv __peer_jvmci_env__(thread, false, jni_enomem_is_fatal, __FILE__, __LINE__);
|
||||
JVMCIEnv* peerJVMCIEnv = &__peer_jvmci_env__;
|
||||
if (peerJVMCIEnv->has_jni_enomem()) {
|
||||
JVMCI_THROW_MSG_0(OutOfMemoryError, "JNI_ENOMEM creating or attaching to libjvmci");
|
||||
}
|
||||
PEER_JVMCIENV_FROM_THREAD(THREAD, false);
|
||||
PEER_JVMCIENV->check_init(JVMCI_CHECK_0);
|
||||
|
||||
HandleMark hm(thread);
|
||||
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerJVMCIEnv);
|
||||
if (peerJVMCIEnv->has_pending_exception()) {
|
||||
peerJVMCIEnv->describe_pending_exception(tty);
|
||||
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(PEER_JVMCIENV);
|
||||
if (PEER_JVMCIENV->has_pending_exception()) {
|
||||
PEER_JVMCIENV->describe_pending_exception(tty);
|
||||
}
|
||||
char* sl_path;
|
||||
if (JVMCI::get_shared_library(sl_path, false) == nullptr) {
|
||||
@ -2704,33 +2697,29 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
|
||||
if (obj_handle == nullptr) {
|
||||
return 0L;
|
||||
}
|
||||
bool jni_enomem_is_fatal = false;
|
||||
JVMCIEnv __peer_jvmci_env__(thread, !JVMCIENV->is_hotspot(), jni_enomem_is_fatal, __FILE__, __LINE__);
|
||||
JVMCIEnv* peerEnv = &__peer_jvmci_env__;
|
||||
JVMCIEnv* thisEnv = JVMCIENV;
|
||||
if (peerEnv->has_jni_enomem()) {
|
||||
JVMCI_THROW_MSG_0(OutOfMemoryError, "JNI_ENOMEM creating or attaching to libjvmci");
|
||||
}
|
||||
PEER_JVMCIENV_FROM_THREAD(THREAD, !JVMCIENV->is_hotspot());
|
||||
PEER_JVMCIENV->check_init(JVMCI_CHECK_0);
|
||||
|
||||
JVMCIEnv* thisEnv = JVMCIENV;
|
||||
JVMCIObject obj = thisEnv->wrap(obj_handle);
|
||||
JVMCIObject result;
|
||||
if (thisEnv->isa_HotSpotResolvedJavaMethodImpl(obj)) {
|
||||
methodHandle method(THREAD, thisEnv->asMethod(obj));
|
||||
result = peerEnv->get_jvmci_method(method, JVMCI_CHECK_0);
|
||||
result = PEER_JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_0);
|
||||
} else if (thisEnv->isa_HotSpotResolvedObjectTypeImpl(obj)) {
|
||||
Klass* klass = thisEnv->asKlass(obj);
|
||||
JVMCIKlassHandle klass_handle(THREAD);
|
||||
klass_handle = klass;
|
||||
result = peerEnv->get_jvmci_type(klass_handle, JVMCI_CHECK_0);
|
||||
result = PEER_JVMCIENV->get_jvmci_type(klass_handle, JVMCI_CHECK_0);
|
||||
} else if (thisEnv->isa_HotSpotResolvedPrimitiveType(obj)) {
|
||||
BasicType type = JVMCIENV->kindToBasicType(JVMCIENV->get_HotSpotResolvedPrimitiveType_kind(obj), JVMCI_CHECK_0);
|
||||
result = peerEnv->get_jvmci_primitive_type(type);
|
||||
result = PEER_JVMCIENV->get_jvmci_primitive_type(type);
|
||||
} else if (thisEnv->isa_IndirectHotSpotObjectConstantImpl(obj) ||
|
||||
thisEnv->isa_DirectHotSpotObjectConstantImpl(obj)) {
|
||||
Handle constant = thisEnv->asConstant(obj, JVMCI_CHECK_0);
|
||||
result = peerEnv->get_object_constant(constant());
|
||||
result = PEER_JVMCIENV->get_object_constant(constant());
|
||||
} else if (thisEnv->isa_HotSpotNmethod(obj)) {
|
||||
if (peerEnv->is_hotspot()) {
|
||||
if (PEER_JVMCIENV->is_hotspot()) {
|
||||
nmethod* nm = JVMCIENV->get_nmethod(obj);
|
||||
if (nm != nullptr) {
|
||||
JVMCINMethodData* data = nm->jvmci_nmethod_data();
|
||||
@ -2753,7 +2742,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
|
||||
JVMCIObject name_string = thisEnv->get_InstalledCode_name(obj);
|
||||
const char* cstring = name_string.is_null() ? nullptr : thisEnv->as_utf8_string(name_string);
|
||||
// Create a new HotSpotNmethod instance in the peer runtime
|
||||
result = peerEnv->new_HotSpotNmethod(mh, cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0);
|
||||
result = PEER_JVMCIENV->new_HotSpotNmethod(mh, cstring, isDefault, compileIdSnapshot, JVMCI_CHECK_0);
|
||||
nmethod* nm = JVMCIENV->get_nmethod(obj);
|
||||
if (result.is_null()) {
|
||||
// exception occurred (e.g. OOME) creating a new HotSpotNmethod
|
||||
@ -2761,9 +2750,9 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
|
||||
// nmethod must have been unloaded
|
||||
} else {
|
||||
// Link the new HotSpotNmethod to the nmethod
|
||||
peerEnv->initialize_installed_code(result, nm, JVMCI_CHECK_0);
|
||||
PEER_JVMCIENV->initialize_installed_code(result, nm, JVMCI_CHECK_0);
|
||||
// Only HotSpotNmethod instances in the HotSpot heap are tracked directly by the runtime.
|
||||
if (peerEnv->is_hotspot()) {
|
||||
if (PEER_JVMCIENV->is_hotspot()) {
|
||||
JVMCINMethodData* data = nm->jvmci_nmethod_data();
|
||||
if (data == nullptr) {
|
||||
JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot set HotSpotNmethod mirror for default nmethod");
|
||||
@ -2781,13 +2770,13 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
|
||||
err_msg("Cannot translate object of type: %s", thisEnv->klass_name(obj)));
|
||||
}
|
||||
if (callPostTranslation) {
|
||||
peerEnv->call_HotSpotJVMCIRuntime_postTranslation(result, JVMCI_CHECK_0);
|
||||
PEER_JVMCIENV->call_HotSpotJVMCIRuntime_postTranslation(result, JVMCI_CHECK_0);
|
||||
}
|
||||
// Propagate any exception that occurred while creating the translated object
|
||||
if (peerEnv->transfer_pending_exception(thread, thisEnv)) {
|
||||
if (PEER_JVMCIENV->transfer_pending_exception(thread, thisEnv)) {
|
||||
return 0L;
|
||||
}
|
||||
return (jlong) peerEnv->make_global(result).as_jobject();
|
||||
return (jlong) PEER_JVMCIENV->make_global(result).as_jobject();
|
||||
}
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle))
|
||||
|
@ -115,7 +115,7 @@ bool JVMCICompileState::jvmti_state_changed() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, bool jni_enomem_is_fatal) {
|
||||
void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
||||
assert(thread != nullptr, "npe");
|
||||
_env = nullptr;
|
||||
_pop_frame_on_close = false;
|
||||
@ -147,18 +147,14 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, boo
|
||||
_is_hotspot = false;
|
||||
|
||||
_runtime = JVMCI::compiler_runtime(thread);
|
||||
int create_JavaVM_err = JNI_OK;
|
||||
_env = _runtime->init_shared_library_javavm(&create_JavaVM_err);
|
||||
_env = _runtime->init_shared_library_javavm(&_init_error);
|
||||
if (_env != nullptr) {
|
||||
// Creating the JVMCI shared library VM also attaches the current thread
|
||||
_detach_on_close = true;
|
||||
} else if (create_JavaVM_err != JNI_OK) {
|
||||
if (!jni_enomem_is_fatal && create_JavaVM_err == JNI_ENOMEM) {
|
||||
_jni_enomem = true;
|
||||
return;
|
||||
} else {
|
||||
fatal("JNI_CreateJavaVM failed with return value %d", create_JavaVM_err);
|
||||
}
|
||||
} else if (_init_error != JNI_OK) {
|
||||
// Caller creating this JVMCIEnv must handle the error.
|
||||
JVMCI_event_1("[%s:%d] Error creating libjvmci (err: %d)", _file, _line, _init_error);
|
||||
return;
|
||||
} else {
|
||||
_runtime->GetEnv(thread, (void**)&parent_env, JNI_VERSION_1_2);
|
||||
if (parent_env != nullptr) {
|
||||
@ -174,15 +170,14 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, boo
|
||||
attach_args.version = JNI_VERSION_1_2;
|
||||
attach_args.name = const_cast<char*>(thread->name());
|
||||
attach_args.group = nullptr;
|
||||
jint attach_result = _runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args);
|
||||
if (attach_result == JNI_OK) {
|
||||
_init_error = _runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args);
|
||||
if (_init_error == JNI_OK) {
|
||||
_detach_on_close = true;
|
||||
} else if (!jni_enomem_is_fatal && attach_result == JNI_ENOMEM) {
|
||||
_env = nullptr;
|
||||
_jni_enomem = true;
|
||||
return;
|
||||
} else {
|
||||
fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
|
||||
// Caller creating this JVMCIEnv must handle the error.
|
||||
_env = nullptr;
|
||||
JVMCI_event_1("[%s:%d] Error attaching to libjvmci (err: %d)", _file, _line, _init_error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,41 +188,36 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, boo
|
||||
JNIAccessMark jni(this, thread);
|
||||
jint result = _env->PushLocalFrame(32);
|
||||
if (result != JNI_OK) {
|
||||
char message[256];
|
||||
jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
|
||||
JVMCIRuntime::fatal_exception(this, message);
|
||||
JVMCI_event_1("[%s:%d] Error pushing local JNI frame (err: %d)", _file, _line, _init_error);
|
||||
return;
|
||||
}
|
||||
_pop_frame_on_close = true;
|
||||
}
|
||||
|
||||
JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
|
||||
_throw_to_caller(false), _file(file), _line(line), _jni_enomem(false), _compile_state(compile_state) {
|
||||
// In case of JNI_ENOMEM, there's a good chance a subsequent attempt to create libjvmci or attach to it
|
||||
// might succeed. Other errors most likely indicate a non-recoverable error in the JVMCI runtime.
|
||||
bool jni_enomem_is_fatal = false;
|
||||
init_env_mode_runtime(thread, nullptr, jni_enomem_is_fatal);
|
||||
if (_jni_enomem) {
|
||||
compile_state->set_failure(true, "Out of memory while attaching JVMCI compiler to current thread");
|
||||
}
|
||||
_throw_to_caller(false), _file(file), _line(line), _init_error(JNI_OK), _compile_state(compile_state) {
|
||||
init_env_mode_runtime(thread, nullptr);
|
||||
}
|
||||
|
||||
JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
|
||||
_throw_to_caller(false), _file(file), _line(line), _jni_enomem(false), _compile_state(nullptr) {
|
||||
_throw_to_caller(false), _file(file), _line(line), _init_error(JNI_OK), _compile_state(nullptr) {
|
||||
init_env_mode_runtime(thread, nullptr);
|
||||
}
|
||||
|
||||
JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
|
||||
_throw_to_caller(true), _file(file), _line(line), _jni_enomem(false), _compile_state(nullptr) {
|
||||
_throw_to_caller(true), _file(file), _line(line), _init_error(JNI_OK), _compile_state(nullptr) {
|
||||
assert(parent_env != nullptr, "npe");
|
||||
init_env_mode_runtime(thread, parent_env);
|
||||
assert(_env == nullptr || parent_env == _env, "mismatched JNIEnvironment");
|
||||
assert(_init_error == JNI_OK, "err: %d", _init_error);
|
||||
}
|
||||
|
||||
void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fatal, const char* file, int line) {
|
||||
void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
|
||||
_compile_state = nullptr;
|
||||
_throw_to_caller = false;
|
||||
_file = file;
|
||||
_line = line;
|
||||
_jni_enomem = false;
|
||||
_init_error = JNI_OK;
|
||||
if (is_hotspot) {
|
||||
_env = nullptr;
|
||||
_pop_frame_on_close = false;
|
||||
@ -235,10 +225,31 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fata
|
||||
_is_hotspot = true;
|
||||
_runtime = JVMCI::java_runtime();
|
||||
} else {
|
||||
init_env_mode_runtime(thread, nullptr, jni_enomem_is_fatal);
|
||||
init_env_mode_runtime(thread, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void JVMCIEnv::check_init(JVMCI_TRAPS) {
|
||||
guarantee(JVMCIENV != this, "must be");
|
||||
if (_init_error == JNI_OK) {
|
||||
return;
|
||||
}
|
||||
if (_init_error == JNI_ENOMEM) {
|
||||
JVMCI_THROW_MSG(OutOfMemoryError, "JNI_ENOMEM creating or attaching to libjvmci");
|
||||
}
|
||||
JVMCI_THROW_MSG(InternalError, err_msg("Error creating or attaching to libjvmci (err: %d)", _init_error));
|
||||
}
|
||||
|
||||
void JVMCIEnv::check_init(TRAPS) {
|
||||
if (_init_error == JNI_OK) {
|
||||
return;
|
||||
}
|
||||
if (_init_error == JNI_ENOMEM) {
|
||||
THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "JNI_ENOMEM creating or attaching to libjvmci");
|
||||
}
|
||||
THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), err_msg("Error creating or attaching to libjvmci (err: %d)", _init_error));
|
||||
}
|
||||
|
||||
// Prints a pending exception (if any) and its stack trace to st.
|
||||
// Also partially logs the stack trace to the JVMCI event log.
|
||||
void JVMCIEnv::describe_pending_exception(outputStream* st) {
|
||||
@ -561,7 +572,7 @@ jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer
|
||||
}
|
||||
|
||||
JVMCIEnv::~JVMCIEnv() {
|
||||
if (_jni_enomem) {
|
||||
if (_init_error != JNI_OK) {
|
||||
return;
|
||||
}
|
||||
if (_throw_to_caller) {
|
||||
|
@ -157,9 +157,9 @@ class JVMCIEnv : public ResourceObj {
|
||||
friend class JNIAccessMark;
|
||||
|
||||
// Initializes the _env, _mode and _runtime fields.
|
||||
void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, bool jni_enomem_is_fatal = true);
|
||||
void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env);
|
||||
|
||||
void init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fatal, const char* file, int line);
|
||||
void init(JavaThread* thread, bool is_hotspot, const char* file, int line);
|
||||
|
||||
JNIEnv* _env; // JNI env for calling into shared library
|
||||
bool _pop_frame_on_close; // Must pop frame on close?
|
||||
@ -169,9 +169,9 @@ class JVMCIEnv : public ResourceObj {
|
||||
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
|
||||
const char* _file; // The file and ...
|
||||
int _line; // ... line where this JNIEnv was created
|
||||
bool _jni_enomem; // JNI_ENOMEM returned when creating or attaching to a libjvmci isolate.
|
||||
// If true, the JVMCIEnv is invalid and should not be used apart from
|
||||
// calling has_jni_enomem().
|
||||
int _init_error; // JNI code returned when creating or attaching to a libjvmci isolate.
|
||||
// If not JNI_OK, the JVMCIEnv is invalid and should not be used apart from
|
||||
// calling init_error().
|
||||
|
||||
// Translates an exception on the HotSpot heap (i.e., hotspot_env) to an exception on
|
||||
// the shared library heap (i.e., jni_env). The translation includes the stack and cause(s) of `throwable`.
|
||||
@ -185,11 +185,12 @@ class JVMCIEnv : public ResourceObj {
|
||||
|
||||
public:
|
||||
// Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM).
|
||||
// The `parent_env` argument must not be null.
|
||||
// An exception occurring within the scope is left pending when the
|
||||
// scope closes so that it will be propagated back to Java.
|
||||
// The JVMCIEnv destructor translates the exception object for the
|
||||
// Java runtime if necessary.
|
||||
JVMCIEnv(JavaThread* thread, JNIEnv* env, const char* file, int line);
|
||||
JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line);
|
||||
|
||||
// Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
|
||||
// An exception occurring within the scope must not be propagated back to
|
||||
@ -200,34 +201,32 @@ public:
|
||||
// within the scope must not be propagated back to the caller.
|
||||
JVMCIEnv(JavaThread* env, const char* file, int line);
|
||||
|
||||
// Opens a JNIEnv scope for accessing `for_object`. An exception occurring
|
||||
// within the scope must not be propagated back to the caller.
|
||||
JVMCIEnv(JavaThread* thread, JVMCIObject for_object, const char* file, int line) {
|
||||
// A JNI call to access an object in the shared library heap
|
||||
// can block or take a long time so do not allow such access
|
||||
// on the VM thread.
|
||||
assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
|
||||
"cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
|
||||
bool jni_enomem_is_fatal = true;
|
||||
init(thread, for_object.is_hotspot(), jni_enomem_is_fatal, file, line);
|
||||
}
|
||||
|
||||
// Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
|
||||
// otherwise for the shared library runtime. An exception occurring
|
||||
// within the scope must not be propagated back to the caller.
|
||||
JVMCIEnv(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fatal, const char* file, int line) {
|
||||
init(thread, is_hotspot, jni_enomem_is_fatal, file, line);
|
||||
JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) {
|
||||
init(thread, is_hotspot, file, line);
|
||||
}
|
||||
|
||||
~JVMCIEnv();
|
||||
|
||||
// Determines if a JNI_ENOMEM occurred while trying to create a libjvmci
|
||||
// isolate or attach to it within the scope of a JVMCIEnv constructor.
|
||||
bool has_jni_enomem() {
|
||||
return _jni_enomem;
|
||||
// Gets the JNI result code returned when creating or attaching to a libjvmci isolate.
|
||||
// If not JNI_OK, the JVMCIEnv is invalid and the caller must abort the operation
|
||||
// this JVMCIEnv context was created for.
|
||||
int init_error() {
|
||||
return _init_error;
|
||||
}
|
||||
|
||||
// Checks the value of init_error() and throws an exception in `JVMCI_TRAPS`
|
||||
// (which must not be this) if it is not JNI_OK.
|
||||
void check_init(JVMCI_TRAPS);
|
||||
|
||||
// Checks the value of init_error() and throws an exception in `TRAPS`
|
||||
// if it is not JNI_OK.
|
||||
void check_init(TRAPS);
|
||||
|
||||
JVMCIRuntime* runtime() {
|
||||
guarantee(_init_error == 0, "invalid JVMCIEnv: %d", _init_error);
|
||||
return _runtime;
|
||||
}
|
||||
|
||||
|
@ -31,15 +31,21 @@ class JVMCIEnv;
|
||||
|
||||
#define JVMCIENV __jvmci_env__
|
||||
#define JVMCI_TRAPS JVMCIEnv* JVMCIENV
|
||||
#define PEER_JVMCIENV __peer_jvmci_env__
|
||||
|
||||
#define JNI_JVMCIENV(thread, env) \
|
||||
#define JVMCIENV_FROM_JNI(thread, env) \
|
||||
JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__); \
|
||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
|
||||
|
||||
#define THREAD_JVMCIENV(thread) \
|
||||
#define JVMCIENV_FROM_THREAD(thread) \
|
||||
JVMCIEnv __stack_jvmci_env__(thread, __FILE__, __LINE__); \
|
||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
|
||||
|
||||
#define PEER_JVMCIENV_FROM_THREAD(thread, is_hotspot) \
|
||||
JVMCIEnv __peer_stack_jvmci_env__(thread, is_hotspot, __FILE__, __LINE__); \
|
||||
JVMCIEnv* PEER_JVMCIENV = &__peer_stack_jvmci_env__
|
||||
|
||||
|
||||
#define JVMCI_PENDING_EXCEPTION (JVMCIENV->pending_exception())
|
||||
#define JVMCI_HAS_PENDING_EXCEPTION (JVMCIENV->has_pending_exception())
|
||||
#define JVMCI_CLEAR_PENDING_EXCEPTION (JVMCIENV->clear_pending_exception())
|
||||
|
@ -744,9 +744,10 @@ JRT_ENTRY(jint, JVMCIRuntime::test_deoptimize_call_int(JavaThread* current, int
|
||||
JRT_END
|
||||
|
||||
|
||||
// private static JVMCIRuntime JVMCI.initializeRuntime()
|
||||
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
||||
JNI_JVMCIENV(thread, env);
|
||||
// Implementation of JVMCI.initializeRuntime()
|
||||
// When called from libjvmci, `libjvmciOrHotspotEnv` is a libjvmci env so use JVM_ENTRY_NO_ENV.
|
||||
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *libjvmciOrHotspotEnv, jclass c))
|
||||
JVMCIENV_FROM_JNI(thread, libjvmciOrHotspotEnv);
|
||||
if (!EnableJVMCI) {
|
||||
JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
|
||||
}
|
||||
@ -755,9 +756,10 @@ JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
||||
return JVMCIENV->get_jobject(runtime);
|
||||
JVM_END
|
||||
|
||||
// private static long Services.readSystemPropertiesInfo(int[] offsets)
|
||||
// Implementation of Services.readSystemPropertiesInfo(int[] offsets)
|
||||
// When called from libjvmci, `env` is a libjvmci env so use JVM_ENTRY_NO_ENV.
|
||||
JVM_ENTRY_NO_ENV(jlong, JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets_handle))
|
||||
JNI_JVMCIENV(thread, env);
|
||||
JVMCIENV_FROM_JNI(thread, env);
|
||||
if (!EnableJVMCI) {
|
||||
JVMCI_THROW_MSG_0(InternalError, "JVMCI is not enabled");
|
||||
}
|
||||
@ -771,7 +773,8 @@ JVM_END
|
||||
|
||||
|
||||
void JVMCIRuntime::call_getCompiler(TRAPS) {
|
||||
THREAD_JVMCIENV(JavaThread::current());
|
||||
JVMCIENV_FROM_THREAD(THREAD);
|
||||
JVMCIENV->check_init(CHECK);
|
||||
JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);
|
||||
initialize(JVMCI_CHECK);
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_getCompiler(jvmciRuntime, JVMCI_CHECK);
|
||||
@ -1525,9 +1528,10 @@ JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
|
||||
return _HotSpotJVMCIRuntime_instance;
|
||||
}
|
||||
|
||||
// private static void CompilerToVM.registerNatives()
|
||||
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
|
||||
JNI_JVMCIENV(thread, env);
|
||||
// Implementation of CompilerToVM.registerNatives()
|
||||
// When called from libjvmci, `libjvmciOrHotspotEnv` is a libjvmci env so use JVM_ENTRY_NO_ENV.
|
||||
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *libjvmciOrHotspotEnv, jclass c2vmClass))
|
||||
JVMCIENV_FROM_JNI(thread, libjvmciOrHotspotEnv);
|
||||
|
||||
if (!EnableJVMCI) {
|
||||
JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
|
||||
@ -1542,7 +1546,7 @@ JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
|
||||
|
||||
// Ensure _non_oop_bits is initialized
|
||||
Universe::non_oop_word();
|
||||
|
||||
JNIEnv *env = libjvmciOrHotspotEnv;
|
||||
if (JNI_OK != env->RegisterNatives(c2vmClass, CompilerToVM::methods, CompilerToVM::methods_count())) {
|
||||
if (!env->ExceptionCheck()) {
|
||||
for (int i = 0; i < CompilerToVM::methods_count(); i++) {
|
||||
@ -1562,11 +1566,14 @@ JVM_END
|
||||
|
||||
void JVMCIRuntime::shutdown() {
|
||||
if (_HotSpotJVMCIRuntime_instance.is_non_null()) {
|
||||
bool jni_enomem_is_fatal = true;
|
||||
JVMCI_event_1("shutting down HotSpotJVMCIRuntime for JVMCI runtime %d", _id);
|
||||
JVMCIEnv __stack_jvmci_env__(JavaThread::current(), _HotSpotJVMCIRuntime_instance.is_hotspot(), jni_enomem_is_fatal, __FILE__, __LINE__);
|
||||
JVMCIEnv __stack_jvmci_env__(JavaThread::current(), _HotSpotJVMCIRuntime_instance.is_hotspot(),__FILE__, __LINE__);
|
||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__;
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);
|
||||
if (JVMCIENV->init_error() == JNI_OK) {
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);
|
||||
} else {
|
||||
JVMCI_event_1("Error in JVMCIEnv for shutdown (err: %d)", JVMCIENV->init_error());
|
||||
}
|
||||
if (_num_attached_threads == cannot_be_attached) {
|
||||
// Only when no other threads are attached to this runtime
|
||||
// is it safe to reset these fields.
|
||||
@ -1611,7 +1618,8 @@ bool JVMCIRuntime::destroy_shared_library_javavm() {
|
||||
|
||||
void JVMCIRuntime::bootstrap_finished(TRAPS) {
|
||||
if (_HotSpotJVMCIRuntime_instance.is_non_null()) {
|
||||
THREAD_JVMCIENV(JavaThread::current());
|
||||
JVMCIENV_FROM_THREAD(THREAD);
|
||||
JVMCIENV->check_init(CHECK);
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user