@@ -446,6 +446,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char**
446
446
// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
447
447
class ExceptionTranslation : public StackObj {
448
448
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
+
449
458
JVMCIEnv* _from_env; // Source of translation. Can be null.
450
459
JVMCIEnv* _to_env; // Destination of translation. Never null.
451
460
@@ -454,49 +463,34 @@ class ExceptionTranslation: public StackObj {
454
463
// Encodes the exception in `_from_env` into `buffer`.
455
464
// Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
456
465
// 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;
458
467
459
468
// 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;
461
470
462
471
public:
463
472
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
-
469
473
int buffer_size = 2048 ;
470
474
while (true ) {
471
475
ResourceMark rm;
472
476
jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL (THREAD, jbyte, buffer_size);
473
477
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 );
475
480
return ;
476
481
}
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
492
485
return ;
493
- } else if (res < 0 ) {
486
+ }
487
+ if (res < 0 ) {
494
488
int required_buffer_size = -res;
495
489
if (required_buffer_size > buffer_size) {
496
490
buffer_size = required_buffer_size;
497
491
}
498
492
} else {
499
- decode (THREAD, vmSupport , buffer);
493
+ decode (THREAD, _encoded_ok , buffer);
500
494
if (!_to_env->has_pending_exception ()) {
501
495
_to_env->throw_InternalError (" decodeAndThrowThrowable should have thrown an exception" );
502
496
}
@@ -511,7 +505,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
511
505
private:
512
506
const Handle & _throwable;
513
507
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
+ }
515
528
JavaCallArguments jargs;
516
529
jargs.push_oop (_throwable);
517
530
jargs.push_long (buffer);
@@ -524,11 +537,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
524
537
return result.get_jint ();
525
538
}
526
539
527
- void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) {
540
+ void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) {
528
541
JNIAccessMark jni (_to_env, THREAD);
529
542
jni ()->CallStaticVoidMethod (JNIJVMCI::VMSupport::clazz (),
530
543
JNIJVMCI::VMSupport::decodeAndThrowThrowable_method (),
531
- buffer, false );
544
+ format, buffer, false );
532
545
}
533
546
public:
534
547
HotSpotToSharedLibraryExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle & throwable) :
@@ -540,15 +553,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
540
553
private:
541
554
jthrowable _throwable;
542
555
543
- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
556
+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
544
557
JNIAccessMark jni (_from_env, THREAD);
545
- return jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
558
+ int res = jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
546
559
JNIJVMCI::VMSupport::encodeThrowable_method (),
547
560
_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;
548
569
}
549
570
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);
551
573
JavaCallArguments jargs;
574
+ jargs.push_int (format);
552
575
jargs.push_long (buffer);
553
576
jargs.push_int (true );
554
577
JavaValue result (T_VOID);
0 commit comments