8308151: [JVMCI] capture JVMCI exceptions in hs-err

Reviewed-by: never
This commit is contained in:
Doug Simon 2023-05-24 07:15:12 +00:00
parent beb75e651f
commit 05c095cf39
12 changed files with 400 additions and 70 deletions

View file

@ -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) {
JavaThread* THREAD = JavaThread::current(); // For exception macros.
if (!is_hotspot()) {
JNIAccessMark jni(this, THREAD);
if (jni()->ExceptionCheck()) {
jthrowable ex = !clear ? jni()->ExceptionOccurred() : nullptr;
jni()->ExceptionDescribe();
if (ex != nullptr) {
jni()->Throw(ex);
// 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++;
}
} else {
if (HAS_PENDING_EXCEPTION) {
JVMCIRuntime::describe_pending_hotspot_exception(THREAD, clear);
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);
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) {
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:
@ -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;
}
}
@ -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);
}
}
@ -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()) {