Skip to content

Commit 05c095c

Browse files
author
Doug Simon
committed
8308151: [JVMCI] capture JVMCI exceptions in hs-err
Reviewed-by: never
1 parent beb75e6 commit 05c095c

File tree

12 files changed

+395
-65
lines changed

12 files changed

+395
-65
lines changed

src/hotspot/share/jvmci/jvmci.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ class JVMCI : public AllStatic {
152152

153153
static void initialize_globals();
154154

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

157159
// Ensures the boxing cache classes (e.g., java.lang.Integer.IntegerCache) are initialized.

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2408,7 +2408,7 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
24082408
HandleMark hm(THREAD);
24092409
runtime = JVMCI::compiler_runtime(thread);
24102410
if (peerEnv->has_pending_exception()) {
2411-
peerEnv->describe_pending_exception(true);
2411+
peerEnv->describe_pending_exception(tty);
24122412
}
24132413
sl_handle = JVMCI::get_shared_library(sl_path, false);
24142414
if (sl_handle == nullptr) {
@@ -2577,7 +2577,7 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb
25772577
HandleMark hm(thread);
25782578
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerJVMCIEnv);
25792579
if (peerJVMCIEnv->has_pending_exception()) {
2580-
peerJVMCIEnv->describe_pending_exception(true);
2580+
peerJVMCIEnv->describe_pending_exception(tty);
25812581
}
25822582
char* sl_path;
25832583
if (JVMCI::get_shared_library(sl_path, false) == nullptr) {

src/hotspot/share/jvmci/jvmciEnv.cpp

Lines changed: 126 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -311,25 +311,138 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, bool jni_enomem_is_fata
311311
}
312312
}
313313

314-
// Prints a pending exception (if any) and its stack trace.
315-
void JVMCIEnv::describe_pending_exception(bool clear) {
314+
// Prints a pending exception (if any) and its stack trace to st.
315+
// Also partially logs the stack trace to the JVMCI event log.
316+
void JVMCIEnv::describe_pending_exception(outputStream* st) {
317+
ResourceMark rm;
318+
char* stack_trace = nullptr;
319+
if (pending_exception_as_string(nullptr, (const char**) &stack_trace)) {
320+
st->print_raw_cr(stack_trace);
321+
322+
// Use up to half the lines of the JVMCI event log to
323+
// show the stack trace.
324+
char* cursor = stack_trace;
325+
int line = 0;
326+
const int max_lines = LogEventsBufferEntries / 2;
327+
char* last_line = nullptr;
328+
while (*cursor != '\0') {
329+
char* eol = strchr(cursor, '\n');
330+
if (eol == nullptr) {
331+
if (line == max_lines - 1) {
332+
last_line = cursor;
333+
} else if (line < max_lines) {
334+
JVMCI_event_1("%s", cursor);
335+
}
336+
cursor = cursor + strlen(cursor);
337+
} else {
338+
*eol = '\0';
339+
if (line == max_lines - 1) {
340+
last_line = cursor;
341+
} else if (line < max_lines) {
342+
JVMCI_event_1("%s", cursor);
343+
}
344+
cursor = eol + 1;
345+
}
346+
line++;
347+
}
348+
if (last_line != nullptr) {
349+
if (line > max_lines) {
350+
JVMCI_event_1("%s [elided %d more stack trace lines]", last_line, line - max_lines);
351+
} else {
352+
JVMCI_event_1("%s", last_line);
353+
}
354+
}
355+
}
356+
}
357+
358+
bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char** stack_trace) {
316359
JavaThread* THREAD = JavaThread::current(); // For exception macros.
360+
JVMCIObject to_string_obj;
361+
JVMCIObject stack_trace_obj;
362+
bool had_nested_exception = false;
317363
if (!is_hotspot()) {
318364
JNIAccessMark jni(this, THREAD);
319-
if (jni()->ExceptionCheck()) {
320-
jthrowable ex = !clear ? jni()->ExceptionOccurred() : nullptr;
321-
jni()->ExceptionDescribe();
322-
if (ex != nullptr) {
323-
jni()->Throw(ex);
365+
jthrowable ex = jni()->ExceptionOccurred();
366+
if (ex != NULL) {
367+
jni()->ExceptionClear();
368+
jobjectArray pair = (jobjectArray) jni()->CallStaticObjectMethod(
369+
JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
370+
JNIJVMCI::HotSpotJVMCIRuntime::exceptionToString_method(),
371+
ex, to_string != nullptr, stack_trace != nullptr);
372+
if (jni()->ExceptionCheck()) {
373+
// As last resort, dump nested exception
374+
jni()->ExceptionDescribe();
375+
had_nested_exception = true;
376+
} else {
377+
guarantee(pair != nullptr, "pair is null");
378+
int len = jni()->GetArrayLength(pair);
379+
guarantee(len == 2, "bad len is %d", len);
380+
if (to_string != nullptr) {
381+
to_string_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 0), false);
382+
}
383+
if (stack_trace != nullptr) {
384+
stack_trace_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 1), false);
385+
}
324386
}
387+
} else {
388+
return false;
325389
}
326390
} else {
327391
if (HAS_PENDING_EXCEPTION) {
328-
JVMCIRuntime::describe_pending_hotspot_exception(THREAD, clear);
392+
Handle exception(THREAD, PENDING_EXCEPTION);
393+
CLEAR_PENDING_EXCEPTION;
394+
JavaCallArguments jargs;
395+
jargs.push_oop(exception);
396+
jargs.push_int(to_string != nullptr);
397+
jargs.push_int(stack_trace != nullptr);
398+
JavaValue result(T_OBJECT);
399+
JavaCalls::call_static(&result,
400+
HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
401+
vmSymbols::exceptionToString_name(),
402+
vmSymbols::exceptionToString_signature(), &jargs, THREAD);
403+
if (HAS_PENDING_EXCEPTION) {
404+
Handle nested_exception(THREAD, PENDING_EXCEPTION);
405+
CLEAR_PENDING_EXCEPTION;
406+
java_lang_Throwable::print_stack_trace(nested_exception, tty);
407+
// Clear and ignore any exceptions raised during printing
408+
CLEAR_PENDING_EXCEPTION;
409+
had_nested_exception = true;
410+
} else {
411+
oop pair = result.get_oop();
412+
guarantee(pair->is_objArray(), "must be");
413+
objArrayOop pair_arr = objArrayOop(pair);
414+
int len = pair_arr->length();
415+
guarantee(len == 2, "bad len is %d", len);
416+
if (to_string != nullptr) {
417+
to_string_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(0));
418+
}
419+
if (stack_trace != nullptr) {
420+
stack_trace_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(1));
421+
}
422+
}
423+
} else {
424+
return false;
425+
}
426+
}
427+
if (had_nested_exception) {
428+
if (to_string != nullptr) {
429+
*to_string = "nested exception occurred converting exception to string";
430+
}
431+
if (stack_trace != nullptr) {
432+
*stack_trace = "nested exception occurred converting exception stack to string";
433+
}
434+
} else {
435+
if (to_string_obj.is_non_null()) {
436+
*to_string = as_utf8_string(to_string_obj);
437+
}
438+
if (stack_trace_obj.is_non_null()) {
439+
*stack_trace = as_utf8_string(stack_trace_obj);
329440
}
330441
}
442+
return true;
331443
}
332444

445+
333446
// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
334447
class ExceptionTranslation: public StackObj {
335448
protected:
@@ -771,10 +884,11 @@ const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
771884
return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
772885
} else {
773886
JNIAccessMark jni(this);
774-
int length = jni()->GetStringLength(str.as_jstring());
775-
int utf8_length = jni()->GetStringUTFLength(str.as_jstring());
887+
jstring jstr = str.as_jstring();
888+
int length = jni()->GetStringLength(jstr);
889+
int utf8_length = jni()->GetStringUTFLength(jstr);
776890
char* result = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
777-
jni()->GetStringUTFRegion(str.as_jstring(), 0, length, result);
891+
jni()->GetStringUTFRegion(jstr, 0, length, result);
778892
return result;
779893
}
780894
}
@@ -904,7 +1018,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
9041018
if (has_pending_exception()) {
9051019
// This should never happen as HotSpotJVMCIRuntime.shutdown() should
9061020
// handle all exceptions.
907-
describe_pending_exception(true);
1021+
describe_pending_exception(tty);
9081022
}
9091023
}
9101024

@@ -960,30 +1074,6 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime,
9601074
}
9611075
}
9621076

963-
964-
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) {
965-
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
966-
if (is_hotspot()) {
967-
JavaCallArguments jargs;
968-
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
969-
JavaValue result(T_OBJECT);
970-
JavaCalls::call_static(&result,
971-
HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
972-
vmSymbols::callToString_name(),
973-
vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject()));
974-
return wrap(result.get_oop());
975-
} else {
976-
JNIAccessMark jni(this, THREAD);
977-
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
978-
JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(),
979-
object.as_jobject());
980-
if (jni()->ExceptionCheck()) {
981-
return JVMCIObject();
982-
}
983-
return wrap(result);
984-
}
985-
}
986-
9871077
void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) {
9881078
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
9891079
if (is_hotspot()) {

src/hotspot/share/jvmci/jvmciEnv.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,10 +258,16 @@ class JVMCIEnv : public ResourceObj {
258258
// Returns true if a pending exception was transferred, false otherwise.
259259
static jboolean transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env);
260260

261-
// Prints the toString() and stack trace of a pending exception.
261+
// Prints the stack trace of a pending exception to `st` and clears the exception.
262262
// If there is no pending exception, this is a nop.
263-
// If `clear` is false, the pending exception will remain pending upon return.
264-
void describe_pending_exception(bool clear);
263+
void describe_pending_exception(outputStream* st);
264+
265+
// Gets the output of calling toString and/or printStactTrace on the pending exception.
266+
// If to_string is not null, the output of toString is returned in it.
267+
// If stack_trace is not null, the output of printStackTrace is returned in it.
268+
// Returns false if there is no pending exception otherwise clears the pending
269+
// exception and returns true.
270+
bool pending_exception_as_string(const char** to_string, const char** stack_trace);
265271

266272
int get_length(JVMCIArray array);
267273

@@ -342,8 +348,6 @@ class JVMCIEnv : public ResourceObj {
342348
JVMCIObject call_JVMCI_getRuntime(JVMCI_TRAPS);
343349
JVMCIObject call_HotSpotJVMCIRuntime_getCompiler(JVMCIObject runtime, JVMCI_TRAPS);
344350

345-
JVMCIObject call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCI_TRAPS);
346-
347351
JVMCIObject call_JavaConstant_forPrimitive(jchar type_char, jlong value, JVMCI_TRAPS);
348352

349353
jboolean call_HotSpotJVMCIRuntime_isGCSupported(JVMCIObject runtime, jint gcIdentifier);

src/hotspot/share/jvmci/jvmciExceptions.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class JVMCIEnv;
7272

7373
#define JVMCI_CATCH \
7474
JVMCIENV); if (JVMCI_HAS_PENDING_EXCEPTION) { \
75-
JVMCIENV->describe_pending_exception(true); \
75+
JVMCIENV->describe_pending_exception(tty); \
7676
ShouldNotReachHere(); \
7777
} (void)(0
7878

src/hotspot/share/jvmci/jvmciJavaClasses.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \
207207
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \
208208
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
209-
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, callToString, callToString_signature, (JVMCIObject object, JVMCI_TRAPS)) \
209+
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature, (JVMCIObject object, bool toString, bool stackTrace, JVMCI_TRAPS)) \
210210
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature, (JVMCIObject object, JVMCI_TRAPS)) \
211211
end_class \
212212
start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \

src/hotspot/share/jvmci/jvmciRuntime.cpp

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "jvmci/jvmciRuntime.hpp"
3636
#include "jvmci/metadataHandles.hpp"
3737
#include "logging/log.hpp"
38+
#include "logging/logStream.hpp"
3839
#include "memory/oopFactory.hpp"
3940
#include "memory/universe.hpp"
4041
#include "oops/constantPool.inline.hpp"
@@ -1610,19 +1611,14 @@ void JVMCIRuntime::bootstrap_finished(TRAPS) {
16101611
}
16111612
}
16121613

1613-
void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD, bool clear) {
1614+
void JVMCIRuntime::describe_pending_hotspot_exception(JavaThread* THREAD) {
16141615
if (HAS_PENDING_EXCEPTION) {
16151616
Handle exception(THREAD, PENDING_EXCEPTION);
1616-
const char* exception_file = THREAD->exception_file();
1617-
int exception_line = THREAD->exception_line();
16181617
CLEAR_PENDING_EXCEPTION;
16191618
java_lang_Throwable::print_stack_trace(exception, tty);
16201619

16211620
// Clear and ignore any exceptions raised during printing
16221621
CLEAR_PENDING_EXCEPTION;
1623-
if (!clear) {
1624-
THREAD->set_pending_exception(exception(), exception_file, exception_line);
1625-
}
16261622
}
16271623
}
16281624

@@ -1635,15 +1631,15 @@ void JVMCIRuntime::fatal_exception(JVMCIEnv* JVMCIENV, const char* message) {
16351631
// Only report an error once
16361632
tty->print_raw_cr(message);
16371633
if (JVMCIENV != nullptr) {
1638-
JVMCIENV->describe_pending_exception(true);
1634+
JVMCIENV->describe_pending_exception(tty);
16391635
} else {
1640-
describe_pending_hotspot_exception(THREAD, true);
1636+
describe_pending_hotspot_exception(THREAD);
16411637
}
16421638
} else {
1643-
// Allow error reporting thread to print the stack trace.
1639+
// Allow error reporting thread time to print the stack trace.
16441640
THREAD->sleep(200);
16451641
}
1646-
fatal("Fatal exception in JVMCI: %s", message);
1642+
fatal("Fatal JVMCI exception (see JVMCI Events for stack trace): %s", message);
16471643
}
16481644

16491645
// ------------------------------------------------------------------
@@ -1992,19 +1988,25 @@ JVMCI::CodeInstallResult JVMCIRuntime::validate_compile_task_dependencies(Depend
19921988
// Otherwise, it returns false.
19931989
static bool after_compiler_upcall(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& method, const char* function) {
19941990
if (JVMCIENV->has_pending_exception()) {
1991+
ResourceMark rm;
19951992
bool reason_on_C_heap = true;
1996-
const char* failure_reason = os::strdup(err_msg("uncaught exception in %s", function), mtJVMCI);
1993+
const char* pending_string = nullptr;
1994+
const char* pending_stack_trace = nullptr;
1995+
JVMCIENV->pending_exception_as_string(&pending_string, &pending_stack_trace);
1996+
if (pending_string == nullptr) pending_string = "null";
1997+
const char* failure_reason = os::strdup(err_msg("uncaught exception in %s [%s]", function, pending_string), mtJVMCI);
19971998
if (failure_reason == nullptr) {
19981999
failure_reason = "uncaught exception";
19992000
reason_on_C_heap = false;
20002001
}
2002+
JVMCI_event_1("%s", failure_reason);
20012003
Log(jit, compilation) log;
20022004
if (log.is_info()) {
2003-
ResourceMark rm;
20042005
log.info("%s while compiling %s", failure_reason, method->name_and_sig_as_C_string());
2005-
JVMCIENV->describe_pending_exception(true);
2006-
} else {
2007-
JVMCIENV->clear_pending_exception();
2006+
if (pending_stack_trace != nullptr) {
2007+
LogStream ls(log.info());
2008+
ls.print_raw_cr(pending_stack_trace);
2009+
}
20082010
}
20092011
JVMCICompileState* compile_state = JVMCIENV->compile_state();
20102012
compile_state->set_failure(true, failure_reason, reason_on_C_heap);
@@ -2049,6 +2051,13 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c
20492051

20502052
JVMCIObject result_object = JVMCIENV->call_HotSpotJVMCIRuntime_compileMethod(receiver, jvmci_method, entry_bci,
20512053
(jlong) compile_state, compile_state->task()->compile_id());
2054+
if (JVMCIENV->has_pending_exception()) {
2055+
const char* val = Arguments::PropertyList_get_value(Arguments::system_properties(), "test.jvmci.compileMethodExceptionIsFatal");
2056+
if (val != nullptr && strcmp(val, "true") == 0) {
2057+
fatal_exception(JVMCIENV, "testing JVMCI fatal exception handling");
2058+
}
2059+
}
2060+
20522061
if (after_compiler_upcall(JVMCIENV, compiler, method, "call_HotSpotJVMCIRuntime_compileMethod")) {
20532062
return;
20542063
}

src/hotspot/share/jvmci/jvmciRuntime.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
469469
// Reports an unexpected exception and exits the VM with a fatal error.
470470
static void fatal_exception(JVMCIEnv* JVMCIENV, const char* message);
471471

472-
static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);
472+
static void describe_pending_hotspot_exception(JavaThread* THREAD);
473473

474474
#define CHECK_EXIT THREAD); \
475475
if (HAS_PENDING_EXCEPTION) { \

src/hotspot/share/jvmci/vmSymbols_jvmci.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@
9494
template(runtime_signature, "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;") \
9595
template(getCompiler_name, "getCompiler") \
9696
template(getCompiler_signature, "()Ljdk/vm/ci/runtime/JVMCICompiler;") \
97-
template(callToString_name, "callToString") \
98-
template(callToString_signature, "(Ljava/lang/Object;)Ljava/lang/String;") \
97+
template(exceptionToString_name, "exceptionToString") \
98+
template(exceptionToString_signature, "(Ljava/lang/Throwable;ZZ)[Ljava/lang/String;") \
9999
template(postTranslation_name, "postTranslation") \
100100
template(getName_name, "getName") \
101101
template(bootstrapFinished_name, "bootstrapFinished") \

0 commit comments

Comments
 (0)