@@ -446,6 +446,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char**
446446// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
447447class ExceptionTranslation : public StackObj {
448448 protected:
449+ enum DecodeFormat {
450+ _encoded_ok = 0 , // exception was successfully encoded into buffer
451+ _buffer_alloc_fail = 1 , // native memory for buffer could not be allocated
452+ _encode_oome_fail = 2 , // OutOfMemoryError thrown during encoding
453+ _encode_fail = 3 // some other problem occured during encoding. If buffer != 0,
454+ // buffer contains a `struct { u4 len; char[len] desc}`
455+ // describing the problem
456+ };
457+
449458 JVMCIEnv* _from_env; // Source of translation. Can be null.
450459 JVMCIEnv* _to_env; // Destination of translation. Never null.
451460
@@ -454,49 +463,34 @@ class ExceptionTranslation: public StackObj {
454463 // Encodes the exception in `_from_env` into `buffer`.
455464 // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
456465 // and the encoding was written to `buffer` otherwise returns -N.
457- virtual int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) = 0;
466+ virtual int encode (JavaThread* THREAD, jlong buffer, int buffer_size) = 0;
458467
459468 // Decodes the exception in `buffer` in `_to_env` and throws it.
460- virtual void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) = 0;
469+ virtual void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) = 0;
461470
462471 public:
463472 void doit (JavaThread* THREAD) {
464- // Resolve VMSupport class explicitly as HotSpotJVMCI::compute_offsets
465- // may not have been called.
466- Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , THREAD);
467- guarantee (!HAS_PENDING_EXCEPTION, " " );
468-
469473 int buffer_size = 2048 ;
470474 while (true ) {
471475 ResourceMark rm;
472476 jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL (THREAD, jbyte, buffer_size);
473477 if (buffer == 0L ) {
474- decode (THREAD, vmSupport, 0L );
478+ JVMCI_event_1 (" error translating exception: translation buffer allocation failed" );
479+ decode (THREAD, _buffer_alloc_fail, 0L );
475480 return ;
476481 }
477- int res = encode (THREAD, vmSupport, buffer, buffer_size);
478- if (_from_env != nullptr && !_from_env->is_hotspot () && _from_env->has_pending_exception ()) {
479- // Cannot get name of exception thrown by `encode` as that involves
480- // calling into libjvmci which in turn can raise another exception.
481- _from_env->clear_pending_exception ();
482- decode (THREAD, vmSupport, -2L );
483- return ;
484- } else if (HAS_PENDING_EXCEPTION) {
485- Symbol *ex_name = PENDING_EXCEPTION->klass ()->name ();
486- CLEAR_PENDING_EXCEPTION;
487- if (ex_name == vmSymbols::java_lang_OutOfMemoryError ()) {
488- decode (THREAD, vmSupport, -1L );
489- } else {
490- decode (THREAD, vmSupport, -2L );
491- }
482+ int res = encode (THREAD, buffer, buffer_size);
483+ if (_to_env->has_pending_exception ()) {
484+ // Propagate pending exception
492485 return ;
493- } else if (res < 0 ) {
486+ }
487+ if (res < 0 ) {
494488 int required_buffer_size = -res;
495489 if (required_buffer_size > buffer_size) {
496490 buffer_size = required_buffer_size;
497491 }
498492 } else {
499- decode (THREAD, vmSupport , buffer);
493+ decode (THREAD, _encoded_ok , buffer);
500494 if (!_to_env->has_pending_exception ()) {
501495 _to_env->throw_InternalError (" decodeAndThrowThrowable should have thrown an exception" );
502496 }
@@ -511,7 +505,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
511505 private:
512506 const Handle& _throwable;
513507
514- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
508+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
509+ Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , THREAD);
510+ if (HAS_PENDING_EXCEPTION) {
511+ Handle throwable = Handle (THREAD, PENDING_EXCEPTION);
512+ Symbol *ex_name = throwable->klass ()->name ();
513+ CLEAR_PENDING_EXCEPTION;
514+ if (ex_name == vmSymbols::java_lang_OutOfMemoryError ()) {
515+ JVMCI_event_1 (" error translating exception: OutOfMemoryError" );
516+ decode (THREAD, _encode_oome_fail, 0L );
517+ } else {
518+ char * char_buffer = (char *) buffer + 4 ;
519+ stringStream st (char_buffer, (size_t ) buffer_size - 4 );
520+ java_lang_Throwable::print_stack_trace (throwable, &st);
521+ u4 len = (u4) st.size ();
522+ *((u4*) buffer) = len;
523+ JVMCI_event_1 (" error translating exception: %s" , char_buffer);
524+ decode (THREAD, _encode_fail, buffer);
525+ }
526+ return 0 ;
527+ }
515528 JavaCallArguments jargs;
516529 jargs.push_oop (_throwable);
517530 jargs.push_long (buffer);
@@ -524,11 +537,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
524537 return result.get_jint ();
525538 }
526539
527- void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) {
540+ void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) {
528541 JNIAccessMark jni (_to_env, THREAD);
529542 jni ()->CallStaticVoidMethod (JNIJVMCI::VMSupport::clazz (),
530543 JNIJVMCI::VMSupport::decodeAndThrowThrowable_method (),
531- buffer, false );
544+ format, buffer, false );
532545 }
533546 public:
534547 HotSpotToSharedLibraryExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
@@ -540,15 +553,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
540553 private:
541554 jthrowable _throwable;
542555
543- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
556+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
544557 JNIAccessMark jni (_from_env, THREAD);
545- return jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
558+ int res = jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
546559 JNIJVMCI::VMSupport::encodeThrowable_method (),
547560 _throwable, buffer, buffer_size);
561+ if (jni ()->ExceptionCheck ()) {
562+ // Cannot get name of exception thrown as that can raise another exception.
563+ jni ()->ExceptionClear ();
564+ JVMCI_event_1 (" error translating exception: unknown error" );
565+ decode (THREAD, _encode_fail, 0L );
566+ return 0 ;
567+ }
568+ return res;
548569 }
549570
550- void decode (JavaThread* THREAD, Klass* vmSupport, jlong buffer) {
571+ void decode (JavaThread* THREAD, DecodeFormat format, jlong buffer) {
572+ Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , CHECK);
551573 JavaCallArguments jargs;
574+ jargs.push_int (format);
552575 jargs.push_long (buffer);
553576 jargs.push_int (true );
554577 JavaValue result (T_VOID);
0 commit comments