@@ -374,6 +374,15 @@ bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char**
374
374
// Shared code for translating an exception from HotSpot to libjvmci or vice versa.
375
375
class ExceptionTranslation : public StackObj {
376
376
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
+
377
386
JVMCIEnv* _from_env; // Source of translation. Can be null.
378
387
JVMCIEnv* _to_env; // Destination of translation. Never null.
379
388
@@ -382,49 +391,34 @@ class ExceptionTranslation: public StackObj {
382
391
// Encodes the exception in `_from_env` into `buffer`.
383
392
// Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
384
393
// 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;
386
395
387
396
// 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;
389
398
390
399
public:
391
400
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
-
397
401
int buffer_size = 2048 ;
398
402
while (true ) {
399
403
ResourceMark rm;
400
404
jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL (THREAD, jbyte, buffer_size);
401
405
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 );
403
408
return ;
404
409
}
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
420
413
return ;
421
- } else if (res < 0 ) {
414
+ }
415
+ if (res < 0 ) {
422
416
int required_buffer_size = -res;
423
417
if (required_buffer_size > buffer_size) {
424
418
buffer_size = required_buffer_size;
425
419
}
426
420
} else {
427
- decode (THREAD, vmSupport , buffer);
421
+ decode (THREAD, _encoded_ok , buffer);
428
422
if (!_to_env->has_pending_exception ()) {
429
423
_to_env->throw_InternalError (" decodeAndThrowThrowable should have thrown an exception" );
430
424
}
@@ -439,7 +433,26 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
439
433
private:
440
434
const Handle & _throwable;
441
435
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
+ }
443
456
JavaCallArguments jargs;
444
457
jargs.push_oop (_throwable);
445
458
jargs.push_long (buffer);
@@ -452,11 +465,11 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
452
465
return result.get_jint ();
453
466
}
454
467
455
- void decode (JavaThread* THREAD, Klass* vmSupport , jlong buffer) {
468
+ void decode (JavaThread* THREAD, DecodeFormat format , jlong buffer) {
456
469
JNIAccessMark jni (_to_env, THREAD);
457
470
jni ()->CallStaticVoidMethod (JNIJVMCI::VMSupport::clazz (),
458
471
JNIJVMCI::VMSupport::decodeAndThrowThrowable_method (),
459
- buffer, false );
472
+ format, buffer, false );
460
473
}
461
474
public:
462
475
HotSpotToSharedLibraryExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle & throwable) :
@@ -468,15 +481,25 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
468
481
private:
469
482
jthrowable _throwable;
470
483
471
- int encode (JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) {
484
+ int encode (JavaThread* THREAD, jlong buffer, int buffer_size) {
472
485
JNIAccessMark jni (_from_env, THREAD);
473
- return jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
486
+ int res = jni ()->CallStaticIntMethod (JNIJVMCI::VMSupport::clazz (),
474
487
JNIJVMCI::VMSupport::encodeThrowable_method (),
475
488
_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;
476
497
}
477
498
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);
479
501
JavaCallArguments jargs;
502
+ jargs.push_int (format);
480
503
jargs.push_long (buffer);
481
504
jargs.push_int (true );
482
505
JavaValue result (T_VOID);
0 commit comments