Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/hotspot/share/jvmci/jvmci.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ class JVMCI : public AllStatic {

static void initialize_globals();

// Called to force initialization of the JVMCI compiler
// early in VM startup.
static void initialize_compiler(TRAPS);

// Ensures the boxing cache classes (e.g., java.lang.Integer.IntegerCache) are initialized.
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,7 +2408,7 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
HandleMark hm(THREAD);
runtime = JVMCI::compiler_runtime(thread);
if (peerEnv->has_pending_exception()) {
peerEnv->describe_pending_exception(true);
peerEnv->describe_pending_exception(tty);
}
sl_handle = JVMCI::get_shared_library(sl_path, false);
if (sl_handle == nullptr) {
Expand Down Expand Up @@ -2577,7 +2577,7 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb
HandleMark hm(thread);
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerJVMCIEnv);
if (peerJVMCIEnv->has_pending_exception()) {
peerJVMCIEnv->describe_pending_exception(true);
peerJVMCIEnv->describe_pending_exception(tty);
}
char* sl_path;
if (JVMCI::get_shared_library(sl_path, false) == nullptr) {
Expand Down
162 changes: 126 additions & 36 deletions src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,25 +311,138 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fata
}
}

// Prints a pending exception (if any) and its stack trace.
void JVMCIEnv::describe_pending_exception(bool clear) {
// 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) {
ResourceMark rm;
char* stack_trace = nullptr;
if (pending_exception_as_string(nullptr, (const char**) &stack_trace)) {
st->print_raw_cr(stack_trace);

// Use up to half the lines of the JVMCI event log to
// show the stack trace.
char* cursor = stack_trace;
int line = 0;
const int max_lines = LogEventsBufferEntries / 2;
char* last_line = nullptr;
while (*cursor != '\0') {
char* eol = strchr(cursor, '\n');
if (eol == nullptr) {
if (line == max_lines - 1) {
last_line = cursor;
} else if (line < max_lines) {
JVMCI_event_1("%s", cursor);
}
cursor = cursor + strlen(cursor);
} else {
*eol = '\0';
if (line == max_lines - 1) {
last_line = cursor;
} else if (line < max_lines) {
JVMCI_event_1("%s", cursor);
}
cursor = eol + 1;
}
line++;
}
if (last_line != nullptr) {
if (line > max_lines) {
JVMCI_event_1("%s [elided %d more stack trace lines]", last_line, line - max_lines);
} else {
JVMCI_event_1("%s", last_line);
}
}
}
}

bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char** stack_trace) {
JavaThread* THREAD = JavaThread::current(); // For exception macros.
JVMCIObject to_string_obj;
JVMCIObject stack_trace_obj;
bool had_nested_exception = false;
if (!is_hotspot()) {
JNIAccessMark jni(this, THREAD);
if (jni()->ExceptionCheck()) {
jthrowable ex = !clear ? jni()->ExceptionOccurred() : nullptr;
jni()->ExceptionDescribe();
if (ex != nullptr) {
jni()->Throw(ex);
jthrowable ex = jni()->ExceptionOccurred();
if (ex != NULL) {
jni()->ExceptionClear();
jobjectArray pair = (jobjectArray) jni()->CallStaticObjectMethod(
JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
JNIJVMCI::HotSpotJVMCIRuntime::exceptionToString_method(),
ex, to_string != nullptr, stack_trace != nullptr);
if (jni()->ExceptionCheck()) {
// As last resort, dump nested exception
jni()->ExceptionDescribe();
had_nested_exception = true;
} else {
guarantee(pair != nullptr, "pair is null");
int len = jni()->GetArrayLength(pair);
guarantee(len == 2, "bad len is %d", len);
if (to_string != nullptr) {
to_string_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 0), false);
}
if (stack_trace != nullptr) {
stack_trace_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 1), false);
}
}
} else {
return false;
}
} else {
if (HAS_PENDING_EXCEPTION) {
JVMCIRuntime::describe_pending_hotspot_exception(THREAD, clear);
Handle exception(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
JavaCallArguments jargs;
jargs.push_oop(exception);
jargs.push_int(to_string != nullptr);
jargs.push_int(stack_trace != nullptr);
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result,
HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
vmSymbols::exceptionToString_name(),
vmSymbols::exceptionToString_signature(), &jargs, THREAD);
if (HAS_PENDING_EXCEPTION) {
Handle nested_exception(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
java_lang_Throwable::print_stack_trace(nested_exception, tty);
// Clear and ignore any exceptions raised during printing
CLEAR_PENDING_EXCEPTION;
had_nested_exception = true;
} else {
oop pair = result.get_oop();
guarantee(pair->is_objArray(), "must be");
objArrayOop pair_arr = objArrayOop(pair);
int len = pair_arr->length();
guarantee(len == 2, "bad len is %d", len);
if (to_string != nullptr) {
to_string_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(0));
}
if (stack_trace != nullptr) {
stack_trace_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(1));
}
}
} else {
return false;
}
}
if (had_nested_exception) {
if (to_string != nullptr) {
*to_string = "nested exception occurred converting exception to string";
}
if (stack_trace != nullptr) {
*stack_trace = "nested exception occurred converting exception stack to string";
}
} else {
if (to_string_obj.is_non_null()) {
*to_string = as_utf8_string(to_string_obj);
}
if (stack_trace_obj.is_non_null()) {
*stack_trace = as_utf8_string(stack_trace_obj);
}
}
return true;
}


// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
class ExceptionTranslation: public StackObj {
protected:
Expand Down Expand Up @@ -771,10 +884,11 @@ const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
} else {
JNIAccessMark jni(this);
int length = jni()->GetStringLength(str.as_jstring());
int utf8_length = jni()->GetStringUTFLength(str.as_jstring());
jstring jstr = str.as_jstring();
int length = jni()->GetStringLength(jstr);
int utf8_length = jni()->GetStringUTFLength(jstr);
char* result = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
jni()->GetStringUTFRegion(str.as_jstring(), 0, length, result);
jni()->GetStringUTFRegion(jstr, 0, length, result);
return result;
}
}
Expand Down Expand Up @@ -904,7 +1018,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
if (has_pending_exception()) {
// This should never happen as HotSpotJVMCIRuntime.shutdown() should
// handle all exceptions.
describe_pending_exception(true);
describe_pending_exception(tty);
}
}

Expand Down Expand Up @@ -960,30 +1074,6 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime,
}
}


JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
if (is_hotspot()) {
JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result,
HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
vmSymbols::callToString_name(),
vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject()));
return wrap(result.get_oop());
} else {
JNIAccessMark jni(this, THREAD);
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(),
object.as_jobject());
if (jni()->ExceptionCheck()) {
return JVMCIObject();
}
return wrap(result);
}
}

void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) {
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
if (is_hotspot()) {
Expand Down
14 changes: 9 additions & 5 deletions src/hotspot/share/jvmci/jvmciEnv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,16 @@ class JVMCIEnv : public ResourceObj {
// Returns true if a pending exception was transferred, false otherwise.
static jboolean transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env);

// Prints the toString() and stack trace of a pending exception.
// Prints the stack trace of a pending exception to `st` and clears the exception.
// If there is no pending exception, this is a nop.
// If `clear` is false, the pending exception will remain pending upon return.
void describe_pending_exception(bool clear);
void describe_pending_exception(outputStream* st);

// Gets the output of calling toString and/or printStactTrace on the pending exception.
// If to_string is not null, the output of toString is returned in it.
// If stack_trace is not null, the output of printStackTrace is returned in it.
// Returns false if there is no pending exception otherwise clears the pending
// exception and returns true.
bool pending_exception_as_string(const char** to_string, const char** stack_trace);

int get_length(JVMCIArray array);

Expand Down Expand Up @@ -342,8 +348,6 @@ class JVMCIEnv : public ResourceObj {
JVMCIObject call_JVMCI_getRuntime(JVMCI_TRAPS);
JVMCIObject call_HotSpotJVMCIRuntime_getCompiler(JVMCIObject runtime, JVMCI_TRAPS);

JVMCIObject call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCI_TRAPS);

JVMCIObject call_JavaConstant_forPrimitive(jchar type_char, jlong value, JVMCI_TRAPS);

jboolean call_HotSpotJVMCIRuntime_isGCSupported(JVMCIObject runtime, jint gcIdentifier);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciExceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class JVMCIEnv;

#define JVMCI_CATCH \
JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) { \
JVMCIENV->describe_pending_exception(true); \
JVMCIENV->describe_pending_exception(tty); \
ShouldNotReachHere(); \
} (void)(0

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciJavaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, callToString, callToString_signature, (JVMCIObject object, JVMCI_TRAPS)) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature, (JVMCIObject object, bool toString, bool stackTrace, JVMCI_TRAPS)) \
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature, (JVMCIObject object, JVMCI_TRAPS)) \
end_class \
start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \
Expand Down
39 changes: 24 additions & 15 deletions src/hotspot/share/jvmci/jvmciRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "jvmci/jvmciRuntime.hpp"
#include "jvmci/metadataHandles.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.hpp"
#include "oops/constantPool.inline.hpp"
Expand Down Expand Up @@ -1610,19 +1611,14 @@ void JVMCIRuntime::bootstrap_finished(TRAPS) {
}
}

void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool clear) {
void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD) {
if (HAS_PENDING_EXCEPTION) {
Handle exception(THREAD, PENDING_EXCEPTION);
const char* exception_file = THREAD->exception_file();
int exception_line = THREAD->exception_line();
CLEAR_PENDING_EXCEPTION;
java_lang_Throwable::print_stack_trace(exception, tty);

// Clear and ignore any exceptions raised during printing
CLEAR_PENDING_EXCEPTION;
if (!clear) {
THREAD->set_pending_exception(exception(), exception_file, exception_line);
}
}
}

Expand All @@ -1635,15 +1631,15 @@ void JVMCIRuntime::fatal_exception(JVMCIEnv* JVMCIENV, const char* message) {
// Only report an error once
tty->print_raw_cr(message);
if (JVMCIENV != nullptr) {
JVMCIENV->describe_pending_exception(true);
JVMCIENV->describe_pending_exception(tty);
} else {
describe_pending_hotspot_exception(THREAD, true);
describe_pending_hotspot_exception(THREAD);
}
} else {
// Allow error reporting thread to print the stack trace.
// Allow error reporting thread time to print the stack trace.
THREAD->sleep(200);
}
fatal("Fatal exception in JVMCI: %s", message);
fatal("Fatal JVMCI exception (see JVMCI Events for stack trace): %s", message);
}

// ------------------------------------------------------------------
Expand Down Expand Up @@ -1992,19 +1988,25 @@ JVMCI::CodeInstallResult JVMCIRuntime::validate_compile_task_dependencies(Depend
// Otherwise, it returns false.
static bool after_compiler_upcall(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& method, const char* function) {
if (JVMCIENV->has_pending_exception()) {
ResourceMark rm;
bool reason_on_C_heap = true;
const char* failure_reason = os::strdup(err_msg("uncaught exception in %s", function), mtJVMCI);
const char* pending_string = nullptr;
const char* pending_stack_trace = nullptr;
JVMCIENV->pending_exception_as_string(&pending_string, &pending_stack_trace);
if (pending_string == nullptr) pending_string = "null";
const char* failure_reason = os::strdup(err_msg("uncaught exception in %s [%s]", function, pending_string), mtJVMCI);
if (failure_reason == nullptr) {
failure_reason = "uncaught exception";
reason_on_C_heap = false;
}
JVMCI_event_1("%s", failure_reason);
Log(jit, compilation) log;
if (log.is_info()) {
ResourceMark rm;
log.info("%s while compiling %s", failure_reason, method->name_and_sig_as_C_string());
JVMCIENV->describe_pending_exception(true);
} else {
JVMCIENV->clear_pending_exception();
if (pending_stack_trace != nullptr) {
LogStream ls(log.info());
ls.print_raw_cr(pending_stack_trace);
}
}
JVMCICompileState* compile_state = JVMCIENV->compile_state();
compile_state->set_failure(true, failure_reason, reason_on_C_heap);
Expand Down Expand Up @@ -2049,6 +2051,13 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c

JVMCIObject result_object = JVMCIENV->call_HotSpotJVMCIRuntime_compileMethod(receiver, jvmci_method, entry_bci,
(jlong) compile_state, compile_state->task()->compile_id());
if (JVMCIENV->has_pending_exception()) {
const char* val = Arguments::PropertyList_get_value(Arguments::system_properties(), "test.jvmci.compileMethodExceptionIsFatal");
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this view on system properties is restricted to properties set at VM startup (e.g. on the command line) and will not see the result of calls to System.setProperty() made by an application.

if (val != nullptr && strcmp(val, "true") == 0) {
fatal_exception(JVMCIENV, "testing JVMCI fatal exception handling");
}
}

if (after_compiler_upcall(JVMCIENV, compiler, method, "call_HotSpotJVMCIRuntime_compileMethod")) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
// Reports an unexpected exception and exits the VM with a fatal error.
static void fatal_exception(JVMCIEnv* JVMCIENV, const char* message);

static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);
static void describe_pending_hotspot_exception(JavaThread* THREAD);

#define CHECK_EXIT THREAD); \
if (HAS_PENDING_EXCEPTION) { \
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/jvmci/vmSymbols_jvmci.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@
template(runtime_signature, "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;") \
template(getCompiler_name, "getCompiler") \
template(getCompiler_signature, "()Ljdk/vm/ci/runtime/JVMCICompiler;") \
template(callToString_name, "callToString") \
template(callToString_signature, "(Ljava/lang/Object;)Ljava/lang/String;") \
template(exceptionToString_name, "exceptionToString") \
template(exceptionToString_signature, "(Ljava/lang/Throwable;ZZ)[Ljava/lang/String;") \
template(postTranslation_name, "postTranslation") \
template(getName_name, "getName") \
template(bootstrapFinished_name, "bootstrapFinished") \
Expand Down
Loading