11/*
2- * Copyright (c) 1999, 2021 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 1999, 2022 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
@@ -278,35 +278,141 @@ void JVMCIEnv::describe_pending_exception(bool clear) {
278278 }
279279}
280280
281- void JVMCIEnv::translate_hotspot_exception_to_jni_exception (JavaThread* THREAD, const Handle& throwable) {
282- assert (!is_hotspot (), " must_be" );
283- // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets
284- // may not have been called.
285- Klass* runtimeKlass = SystemDictionary::resolve_or_fail (vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime (), true , CHECK);
286- JavaCallArguments jargs;
287- jargs.push_oop (throwable);
288- JavaValue result (T_OBJECT);
289- JavaCalls::call_static (&result,
290- runtimeKlass,
291- vmSymbols::encodeThrowable_name (),
292- vmSymbols::encodeThrowable_signature (), &jargs, THREAD);
293- if (HAS_PENDING_EXCEPTION) {
294- JVMCIRuntime::fatal_exception (this , " HotSpotJVMCIRuntime.encodeThrowable should not throw an exception" );
281+ // Shared code for translating an exception from HotSpot to libjvmci or vice versa.
282+ class ExceptionTranslation : public StackObj {
283+ protected:
284+ JVMCIEnv* _from_env; // Source of translation. Can be nullptr.
285+ JVMCIEnv* _to_env; // Destination of translation. Never nullptr.
286+
287+ ExceptionTranslation (JVMCIEnv* from_env, JVMCIEnv* to_env) : _from_env(from_env), _to_env(to_env) {}
288+
289+ // Encodes the exception in `_from_env` into `buffer`.
290+ // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
291+ // and the encoding was written to `buffer` otherwise returns -N.
292+ virtual int encode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) = 0;
293+
294+ // Decodes the exception in `buffer` in `_to_env` and throws it.
295+ virtual void decode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) = 0;
296+
297+ public:
298+ void doit (JavaThread* THREAD) {
299+ // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets
300+ // may not have been called.
301+ Klass* runtimeKlass = SystemDictionary::resolve_or_fail (vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime (), true , CHECK);
302+
303+ int buffer_size = 2048 ;
304+ while (true ) {
305+ ResourceMark rm;
306+ jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD (THREAD, jbyte, buffer_size);
307+ int res = encode (THREAD, runtimeKlass, buffer, buffer_size);
308+ if ((_from_env != nullptr && _from_env->has_pending_exception ()) || HAS_PENDING_EXCEPTION) {
309+ JVMCIRuntime::fatal_exception (_from_env, " HotSpotJVMCIRuntime.encodeThrowable should not throw an exception" );
310+ }
311+ if (res < 0 ) {
312+ int required_buffer_size = -res;
313+ if (required_buffer_size > buffer_size) {
314+ buffer_size = required_buffer_size;
315+ }
316+ } else {
317+ decode (THREAD, runtimeKlass, buffer);
318+ if (!_to_env->has_pending_exception ()) {
319+ JVMCIRuntime::fatal_exception (_to_env, " HotSpotJVMCIRuntime.decodeAndThrowThrowable should throw an exception" );
320+ }
321+ return ;
322+ }
323+ }
295324 }
325+ };
296326
297- oop encoded_throwable_string = result.get_oop ();
327+ // Translates an exception on the HotSpot heap to an exception on the shared library heap.
328+ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
329+ private:
330+ const Handle& _throwable;
298331
299- ResourceMark rm;
300- const char * encoded_throwable_chars = java_lang_String::as_utf8_string (encoded_throwable_string);
332+ int encode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) {
333+ JavaCallArguments jargs;
334+ jargs.push_oop (_throwable);
335+ jargs.push_long (buffer);
336+ jargs.push_int (buffer_size);
337+ JavaValue result (T_INT);
338+ JavaCalls::call_static (&result,
339+ runtimeKlass,
340+ vmSymbols::encodeThrowable_name (),
341+ vmSymbols::encodeThrowable_signature (), &jargs, THREAD);
342+ return result.get_jint ();
343+ }
301344
302- JNIAccessMark jni (this , THREAD);
303- jobject jni_encoded_throwable_string = jni ()->NewStringUTF (encoded_throwable_chars);
304- jthrowable jni_throwable = (jthrowable) jni ()->CallStaticObjectMethod (JNIJVMCI::HotSpotJVMCIRuntime::clazz (),
305- JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method (),
306- jni_encoded_throwable_string);
307- jni ()->Throw (jni_throwable);
345+ void decode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) {
346+ JNIAccessMark jni (_to_env, THREAD);
347+ jni ()->CallStaticVoidMethod (JNIJVMCI::HotSpotJVMCIRuntime::clazz (),
348+ JNIJVMCI::HotSpotJVMCIRuntime::decodeAndThrowThrowable_method (),
349+ buffer);
350+ }
351+ public:
352+ HotSpotToSharedLibraryExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
353+ ExceptionTranslation (hotspot_env, jni_env), _throwable(throwable) {}
354+ };
355+
356+ // Translates an exception on the shared library heap to an exception on the HotSpot heap.
357+ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
358+ private:
359+ jthrowable _throwable;
360+
361+ int encode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) {
362+ JNIAccessMark jni (_from_env, THREAD);
363+ return jni ()->CallStaticIntMethod (JNIJVMCI::HotSpotJVMCIRuntime::clazz (),
364+ JNIJVMCI::HotSpotJVMCIRuntime::encodeThrowable_method (),
365+ _throwable, buffer, buffer_size);
366+ }
367+
368+ void decode (JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) {
369+ JavaCallArguments jargs;
370+ jargs.push_long (buffer);
371+ JavaValue result (T_VOID);
372+ JavaCalls::call_static (&result,
373+ runtimeKlass,
374+ vmSymbols::decodeAndThrowThrowable_name (),
375+ vmSymbols::long_void_signature (), &jargs, THREAD);
376+ }
377+ public:
378+ SharedLibraryToHotSpotExceptionTranslation (JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, jthrowable throwable) :
379+ ExceptionTranslation (jni_env, hotspot_env), _throwable(throwable) {}
380+ };
381+
382+ void JVMCIEnv::translate_to_jni_exception (JavaThread* THREAD, const Handle& throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
383+ HotSpotToSharedLibraryExceptionTranslation (hotspot_env, jni_env, throwable).doit (THREAD);
308384}
309385
386+ void JVMCIEnv::translate_from_jni_exception (JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
387+ SharedLibraryToHotSpotExceptionTranslation (hotspot_env, jni_env, throwable).doit (THREAD);
388+ }
389+
390+ jboolean JVMCIEnv::transfer_pending_exception (JavaThread* THREAD, JVMCIEnv* peer_env) {
391+ if (is_hotspot ()) {
392+ if (HAS_PENDING_EXCEPTION) {
393+ Handle throwable = Handle (THREAD, PENDING_EXCEPTION);
394+ CLEAR_PENDING_EXCEPTION;
395+ translate_to_jni_exception (THREAD, throwable, this , peer_env);
396+ return true ;
397+ }
398+ } else {
399+ jthrowable ex = nullptr ;
400+ {
401+ JNIAccessMark jni (this , THREAD);
402+ ex = jni ()->ExceptionOccurred ();
403+ if (ex != nullptr ) {
404+ jni ()->ExceptionClear ();
405+ }
406+ }
407+ if (ex != nullptr ) {
408+ translate_from_jni_exception (THREAD, ex, peer_env, this );
409+ return true ;
410+ }
411+ }
412+ return false ;
413+ }
414+
415+
310416JVMCIEnv::~JVMCIEnv () {
311417 if (_throw_to_caller) {
312418 if (is_hotspot ()) {
@@ -318,7 +424,7 @@ JVMCIEnv::~JVMCIEnv() {
318424 if (HAS_PENDING_EXCEPTION) {
319425 Handle throwable = Handle (THREAD, PENDING_EXCEPTION);
320426 CLEAR_PENDING_EXCEPTION;
321- translate_hotspot_exception_to_jni_exception (THREAD, throwable);
427+ translate_to_jni_exception (THREAD, throwable, nullptr , this );
322428 }
323429 }
324430 }
@@ -801,6 +907,23 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object,
801907 }
802908}
803909
910+ void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation (JVMCIObject object, JVMCIEnv* JVMCIENV) {
911+ JavaThread* THREAD = JVMCI::compilation_tick (JavaThread::current ()); // For exception macros.
912+ if (is_hotspot ()) {
913+ JavaCallArguments jargs;
914+ jargs.push_oop (Handle (THREAD, HotSpotJVMCI::resolve (object)));
915+ JavaValue result (T_VOID);
916+ JavaCalls::call_static (&result,
917+ HotSpotJVMCI::HotSpotJVMCIRuntime::klass (),
918+ vmSymbols::postTranslation_name (),
919+ vmSymbols::object_void_signature (), &jargs, CHECK);
920+ } else {
921+ JNIAccessMark jni (this , THREAD);
922+ jni ()->CallStaticVoidMethod (JNIJVMCI::HotSpotJVMCIRuntime::clazz (),
923+ JNIJVMCI::HotSpotJVMCIRuntime::postTranslation_method (),
924+ object.as_jobject ());
925+ }
926+ }
804927
805928JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive (JVMCIObject kind, jlong value, JVMCI_TRAPS) {
806929 JavaThread* THREAD = JVMCI::compilation_tick (JavaThread::current ()); // For exception macros.
0 commit comments