@@ -374,6 +374,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char**
374374// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
375375class ExceptionTranslation : public StackObj {
376376 protected:
377+ enum DecodeFormat {
378+ _encoded_ok = 0 , // exception was successfully encoded into buffer
379+ _buffer_alloc_fail = 1 , // native memory for buffer could not be allocated
380+ _encode_oome_fail = 2 , // OutOfMemoryError thrown during encoding
381+ _encode_fail = 3 // some other problem occured during encoding. If buffer != 0,
382+ // buffer contains a `struct { u4 len; char[len] desc}`
383+ // describing the problem
384+ };
385+
377386 JVMCIEnv* _from_env; // Source of translation. Can be null.
378387 JVMCIEnv* _to_env; // Destination of translation. Never null.
379388
@@ -382,49 +391,34 @@ class ExceptionTranslation: public StackObj {
382391 // Encodes the exception in `_from_env` into `buffer`.
383392 // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
384393 // and the encoding was written to `buffer` otherwise returns -N.
385- virtual int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) = 0;
394+ virtual int encode (JavaThread* THREAD, jlong buffer, int buffer_size) = 0;
386395
387396 // Decodes the exception in `buffer` in `_to_env` and throws it.
388- virtual void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) = 0;
397+ virtual void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) = 0;
389398
390399 public:
391400 void doit (JavaThread* THREAD) {
392- // Resolve VMSupport class explicitly as HotSpotJVMCI::compute_offsets
393- // may not have been called.
394- Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , THREAD);
395- guarantee (!HAS_PENDING_EXCEPTION, " " );
396-
397401 int buffer_size = 2048 ;
398402 while (true ) {
399403 ResourceMark rm;
400404 jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL (THREAD, jbyte, buffer_size);
401405 if (buffer == 0L ) {
402- decode (THREAD, vmSupport, 0L );
406+ JVMCI_event_1 (" error translating exception: translation buffer allocation failed" );
407+ decode (THREAD, _buffer_alloc_fail, 0L );
403408 return ;
404409 }
405- int res = encode (THREAD, vmSupport, buffer, buffer_size);
406- if (_from_env != nullptr && !_from_env->is_hotspot () && _from_env->has_pending_exception ()) {
407- // Cannot get name of exception thrown by `encode` as that involves
408- // calling into libjvmci which in turn can raise another exception.
409- _from_env->clear_pending_exception ();
410- decode (THREAD, vmSupport, -2L );
411- return ;
412- } else if (HAS_PENDING_EXCEPTION) {
413- Symbol *ex_name = PENDING_EXCEPTION->klass ()->name ();
414- CLEAR_PENDING_EXCEPTION;
415- if (ex_name == vmSymbols::java_lang_OutOfMemoryError ()) {
416- decode (THREAD, vmSupport, -1L );
417- } else {
418- decode (THREAD, vmSupport, -2L );
419- }
410+ int res = encode (THREAD, buffer, buffer_size);
411+ if (_to_env->has_pending_exception ()) {
412+ // Propagate pending exception
420413 return ;
421- } else if (res < 0 ) {
414+ }
415+ if (res < 0 ) {
422416 int required_buffer_size = -res;
423417 if (required_buffer_size > buffer_size) {
424418 buffer_size = required_buffer_size;
425419 }
426420 } else {
427- decode (THREAD, vmSupport , buffer);
421+ decode (THREAD, _encoded_ok , buffer);
428422 if (!_to_env->has_pending_exception ()) {
429423 _to_env->throw_InternalError (" decodeAndThrowThrowable should have thrown an exception" );
430424 }
@@ -439,7 +433,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
439433 private:
440434 const Handle& _throwable;
441435
442- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
436+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
437+ Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , THREAD);
438+ if (HAS_PENDING_EXCEPTION) {
439+ Handle throwable = Handle (THREAD, PENDING_EXCEPTION);
440+ Symbol *ex_name = throwable->klass ()->name ();
441+ CLEAR_PENDING_EXCEPTION;
442+ if (ex_name == vmSymbols::java_lang_OutOfMemoryError ()) {
443+ JVMCI_event_1 (" error translating exception: OutOfMemoryError" );
444+ decode (THREAD, _encode_oome_fail, 0L );
445+ } else {
446+ char * char_buffer = (char *) buffer + 4 ;
447+ stringStream st (char_buffer, (size_t ) buffer_size - 4 );
448+ java_lang_Throwable::print_stack_trace (throwable, &st);
449+ u4 len = (u4) st.size ();
450+ *((u4*) buffer) = len;
451+ JVMCI_event_1 (" error translating exception: %s" , char_buffer);
452+ decode (THREAD, _encode_fail, buffer);
453+ }
454+ return 0 ;
455+ }
443456 JavaCallArguments jargs;
444457 jargs.push_oop (_throwable);
445458 jargs.push_long (buffer);
@@ -452,11 +465,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
452465 return result.get_jint ();
453466 }
454467
455- void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) {
468+ void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) {
456469 JNIAccessMark jni (_to_env, THREAD);
457470 jni ()->CallStaticVoidMethod (JNIJVMCI::VMSupport::clazz (),
458471 JNIJVMCI::VMSupport::decodeAndThrowThrowable_method (),
459- buffer, false );
472+ format, buffer, false );
460473 }
461474 public:
462475 HotSpotToSharedLibraryExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
@@ -468,15 +481,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
468481 private:
469482 jthrowable _throwable;
470483
471- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
484+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
472485 JNIAccessMark jni (_from_env, THREAD);
473- return jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
486+ int res = jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
474487 JNIJVMCI::VMSupport::encodeThrowable_method (),
475488 _throwable, buffer, buffer_size);
489+ if (jni ()->ExceptionCheck ()) {
490+ // Cannot get name of exception thrown as that can raise another exception.
491+ jni ()->ExceptionClear ();
492+ JVMCI_event_1 (" error translating exception: unknown error" );
493+ decode (THREAD, _encode_fail, 0L );
494+ return 0 ;
495+ }
496+ return res;
476497 }
477498
478- void decode (JavaThread* THREAD, Klass* vmSupport, jlong buffer) {
499+ void decode (JavaThread* THREAD, DecodeFormat format, jlong buffer) {
500+ Klass* vmSupport = SystemDictionary::resolve_or_fail (vmSymbols::jdk_internal_vm_VMSupport (), true , CHECK);
479501 JavaCallArguments jargs;
502+ jargs.push_int (format);
480503 jargs.push_long (buffer);
481504 jargs.push_int (true );
482505 JavaValue result (T_VOID);
0 commit comments