diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index c78bdd73a5d44..8ff8258b93c5c 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -2453,7 +2453,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) BacktraceElement bte = iter.next(THREAD); print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name); } - { + if (THREAD->can_call_java()) { // Call getCause() which doesn't necessarily return the _cause field. ExceptionMark em(THREAD); JavaValue cause(T_OBJECT); @@ -2475,6 +2475,9 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st) st->cr(); } } + } else { + st->print_raw_cr("<>"); + return; } } } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 3d1674bca9913..0af5b5fbcf592 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -611,7 +611,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, InstanceKlass* loaded_class = nullptr; SymbolHandle superclassname; // Keep alive while loading in parallel thread. - assert(THREAD->can_call_java(), + guarantee(THREAD->can_call_java(), "can not load classes with compiler thread: class=%s, classloader=%s", name->as_C_string(), class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string()); @@ -2056,7 +2056,7 @@ Method* SystemDictionary::find_method_handle_invoker(Klass* klass, Klass* accessing_klass, Handle* appendix_result, TRAPS) { - assert(THREAD->can_call_java() ,""); + guarantee(THREAD->can_call_java(), ""); Handle method_type = SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_NULL); diff --git a/src/hotspot/share/compiler/compilerThread.cpp b/src/hotspot/share/compiler/compilerThread.cpp index 77a5f4b7027e1..47e3f5a6f499b 100644 --- a/src/hotspot/share/compiler/compilerThread.cpp +++ b/src/hotspot/share/compiler/compilerThread.cpp @@ -39,6 +39,7 @@ CompilerThread::CompilerThread(CompileQueue* queue, _queue = queue; _counters = counters; _buffer_blob = nullptr; + _can_call_java = false; _compiler = nullptr; _arena_stat = CompilationMemoryStatistic::enabled() ? new ArenaStatCounter : nullptr; @@ -56,15 +57,17 @@ CompilerThread::~CompilerThread() { delete _arena_stat; } +void CompilerThread::set_compiler(AbstractCompiler* c) { + // Only jvmci compiler threads can call Java + _can_call_java = c != nullptr && c->is_jvmci(); + _compiler = c; +} + void CompilerThread::thread_entry(JavaThread* thread, TRAPS) { assert(thread->is_Compiler_thread(), "must be compiler thread"); CompileBroker::compiler_thread_loop(); } -bool CompilerThread::can_call_java() const { - return _compiler != nullptr && _compiler->is_jvmci(); -} - // Hide native compiler threads from external view. bool CompilerThread::is_hidden_from_external_view() const { return _compiler == nullptr || _compiler->is_hidden_from_external_view(); diff --git a/src/hotspot/share/compiler/compilerThread.hpp b/src/hotspot/share/compiler/compilerThread.hpp index 65bb4481c020b..3531fb6d72ddf 100644 --- a/src/hotspot/share/compiler/compilerThread.hpp +++ b/src/hotspot/share/compiler/compilerThread.hpp @@ -31,18 +31,17 @@ class AbstractCompiler; class ArenaStatCounter; class BufferBlob; class ciEnv; -class CompileThread; +class CompilerThread; class CompileLog; class CompileTask; class CompileQueue; class CompilerCounters; class IdealGraphPrinter; -class JVMCIEnv; -class JVMCIPrimitiveArray; // A thread used for Compilation. class CompilerThread : public JavaThread { friend class VMStructs; + JVMCI_ONLY(friend class CompilerThreadCanCallJava;) private: CompilerCounters* _counters; @@ -51,6 +50,7 @@ class CompilerThread : public JavaThread { CompileTask* volatile _task; // print_threads_compiling can read this concurrently. CompileQueue* _queue; BufferBlob* _buffer_blob; + bool _can_call_java; AbstractCompiler* _compiler; TimeStamp _idle_time; @@ -73,13 +73,13 @@ class CompilerThread : public JavaThread { bool is_Compiler_thread() const { return true; } - virtual bool can_call_java() const; + virtual bool can_call_java() const { return _can_call_java; } // Returns true if this CompilerThread is hidden from JVMTI and FlightRecorder. C1 and C2 are // always hidden but JVMCI compiler threads might be hidden. virtual bool is_hidden_from_external_view() const; - void set_compiler(AbstractCompiler* c) { _compiler = c; } + void set_compiler(AbstractCompiler* c); AbstractCompiler* compiler() const { return _compiler; } CompileQueue* queue() const { return _queue; } diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index 12b400478caf8..447792b6fcae6 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -23,6 +23,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "compiler/abstractCompiler.hpp" #include "compiler/compileTask.hpp" #include "compiler/compilerThread.hpp" #include "gc/shared/collectedHeap.hpp" @@ -53,6 +54,29 @@ volatile intx JVMCI::_fatal_log_init_thread = -1; volatile int JVMCI::_fatal_log_fd = -1; const char* JVMCI::_fatal_log_filename = nullptr; +CompilerThreadCanCallJava::CompilerThreadCanCallJava(JavaThread* current, bool new_state) { + _current = nullptr; + if (current->is_Compiler_thread()) { + CompilerThread* ct = CompilerThread::cast(current); + if (ct->_can_call_java != new_state && + ct->_compiler != nullptr && + ct->_compiler->is_jvmci()) + { + // Only enter a new context if the ability of the + // current thread to call Java actually changes + _reset_state = ct->_can_call_java; + ct->_can_call_java = new_state; + _current = ct; + } + } +} + +CompilerThreadCanCallJava::~CompilerThreadCanCallJava() { + if (_current != nullptr) { + _current->_can_call_java = _reset_state; + } +} + void jvmci_vmStructs_init() NOT_DEBUG_RETURN; bool JVMCI::can_initialize_JVMCI() { @@ -176,6 +200,10 @@ void JVMCI::ensure_box_caches_initialized(TRAPS) { java_lang_Long_LongCache::symbol() }; + // Class resolution and initialization below + // requires calling into Java + CompilerThreadCanCallJava ccj(THREAD, true); + for (unsigned i = 0; i < sizeof(box_classes) / sizeof(Symbol*); i++) { Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK); InstanceKlass* ik = InstanceKlass::cast(k); diff --git a/src/hotspot/share/jvmci/jvmci.hpp b/src/hotspot/share/jvmci/jvmci.hpp index 200046906f62d..1e9fa08898fc3 100644 --- a/src/hotspot/share/jvmci/jvmci.hpp +++ b/src/hotspot/share/jvmci/jvmci.hpp @@ -29,6 +29,7 @@ #include "utilities/exceptions.hpp" class BoolObjectClosure; +class CompilerThread; class constantPoolHandle; class JavaThread; class JVMCIEnv; @@ -46,6 +47,34 @@ typedef FormatStringEventLog<256> StringEventLog; struct _jmetadata; typedef struct _jmetadata *jmetadata; +// A stack object that manages a scope in which the current thread, if +// it's a CompilerThread, can have its CompilerThread::_can_call_java +// field changed. This allows restricting libjvmci better in terms +// of when it can make Java calls. If a Java call on a CompilerThread +// reaches a clinit, there's a risk of dead-lock when async compilation +// is disabled (e.g. -Xbatch or -Xcomp) as the non-CompilerThread thread +// waiting for the blocking compilation may hold the clinit lock. +// +// This scope is primarily used to disable Java calls when libjvmci enters +// the VM via a C2V (i.e. CompilerToVM) native method. +class CompilerThreadCanCallJava : StackObj { + private: + CompilerThread* _current; // Only non-null if state of thread changed + bool _reset_state; // Value prior to state change, undefined + // if no state change. +public: + // Enters a scope in which the ability of the current CompilerThread + // to call Java is specified by `new_state`. This call only makes a + // change if the current thread is a CompilerThread associated with + // a JVMCI compiler whose CompilerThread::_can_call_java is not + // currently `new_state`. + CompilerThreadCanCallJava(JavaThread* current, bool new_state); + + // Resets CompilerThread::_can_call_java of the current thread if the + // constructor changed it. + ~CompilerThreadCanCallJava(); +}; + class JVMCI : public AllStatic { friend class JVMCIRuntime; friend class JVMCIEnv; diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 00a3984df8acb..f2d58ae3fb317 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -165,14 +165,19 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) { MACOS_AARCH64_ONLY(ThreadWXEnable __wx(WXWrite, thread)); \ ThreadInVMfromNative __tiv(thread); \ HandleMarkCleaner __hm(thread); \ - JavaThread* THREAD = thread; \ + JavaThread* THREAD = thread; \ debug_only(VMNativeEntryWrapper __vew;) // Native method block that transitions current thread to '_thread_in_vm'. -#define C2V_BLOCK(result_type, name, signature) \ - JVMCI_VM_ENTRY_MARK; \ - ResourceMark rm; \ - JVMCIENV_FROM_JNI(JVMCI::compilation_tick(thread), env); +// Note: CompilerThreadCanCallJava must precede JVMCIENV_FROM_JNI so that +// the translation of an uncaught exception in the JVMCIEnv does not make +// a Java call when __is_hotspot == false. +#define C2V_BLOCK(result_type, name, signature) \ + JVMCI_VM_ENTRY_MARK; \ + ResourceMark rm; \ + bool __is_hotspot = env == thread->jni_environment(); \ + CompilerThreadCanCallJava ccj(thread, __is_hotspot); \ + JVMCIENV_FROM_JNI(JVMCI::compilation_tick(thread), env); \ static JavaThread* get_current_thread(bool allow_null=true) { Thread* thread = Thread::current_or_null_safe(); @@ -188,7 +193,7 @@ static JavaThread* get_current_thread(bool allow_null=true) { #define C2V_VMENTRY(result_type, name, signature) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ JavaThread* thread = get_current_thread(); \ - if (thread == nullptr) { \ + if (thread == nullptr) { \ env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return; \ @@ -199,7 +204,7 @@ static JavaThread* get_current_thread(bool allow_null=true) { #define C2V_VMENTRY_(result_type, name, signature, result) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ JavaThread* thread = get_current_thread(); \ - if (thread == nullptr) { \ + if (thread == nullptr) { \ env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return result; \ @@ -221,7 +226,7 @@ static JavaThread* get_current_thread(bool allow_null=true) { #define JNI_THROW(caller, name, msg) do { \ jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ if (__throw_res != JNI_OK) { \ - tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ + JVMCI_event_1("Throwing " #name " in " caller " returned %d", __throw_res); \ } \ return; \ } while (0); @@ -229,7 +234,7 @@ static JavaThread* get_current_thread(bool allow_null=true) { #define JNI_THROW_(caller, name, msg, result) do { \ jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ if (__throw_res != JNI_OK) { \ - tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ + JVMCI_event_1("Throwing " #name " in " caller " returned %d", __throw_res); \ } \ return result; \ } while (0) @@ -579,6 +584,7 @@ C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, ARGUMENT_PAIR( C2V_END C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jint accessing_klass_loader, jboolean resolve)) + CompilerThreadCanCallJava canCallJava(thread, resolve); // Resolution requires Java calls JVMCIObject name = JVMCIENV->wrap(jname); const char* str = JVMCIENV->as_utf8_string(name); TempNewSymbol class_name = SymbolTable::new_symbol(str); @@ -592,7 +598,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU if (val != nullptr) { if (strstr(val, "") != nullptr) { tty->print_cr("CompilerToVM.lookupType: %s", str); - } else if (strstr(val, str) != nullptr) { + } else if (strstr(str, val) != nullptr) { THROW_MSG_0(vmSymbols::java_lang_Exception(), err_msg("lookupTypeException: %s", str)); } @@ -938,6 +944,17 @@ C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, ARGUMENT_PA Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); fieldDescriptor fd; methodHandle mh(THREAD, UNPACK_PAIR(Method, method)); + + Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); + int holder_index = cp->klass_ref_index_at(index, bc); + if (!cp->tag_at(holder_index).is_klass() && !THREAD->can_call_java()) { + // If the holder is not resolved in the constant pool and the current + // thread cannot call Java, return null. This avoids a Java call + // in LinkInfo to load the holder. + Symbol* klass_name = cp->klass_ref_at_noresolve(index, bc); + return nullptr; + } + LinkInfo link_info(cp, index, mh, code, CHECK_NULL); LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL); JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle); @@ -2726,6 +2743,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool return 0L; } PEER_JVMCIENV_FROM_THREAD(THREAD, !JVMCIENV->is_hotspot()); + CompilerThreadCanCallJava canCallJava(thread, PEER_JVMCIENV->is_hotspot()); PEER_JVMCIENV->check_init(JVMCI_CHECK_0); JVMCIEnv* thisEnv = JVMCIENV; @@ -2945,18 +2963,21 @@ static jbyteArray get_encoded_annotation_data(InstanceKlass* holder, AnnotationA C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jobject filter, jint filter_length, jlong filter_klass_pointers)) + CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass)); return get_encoded_annotation_data(holder, holder->class_annotations(), true, filter_length, filter_klass_pointers, THREAD, JVMCIENV); C2V_END C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jobject filter, jint filter_length, jlong filter_klass_pointers)) + CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support methodHandle method(THREAD, UNPACK_PAIR(Method, method)); return get_encoded_annotation_data(method->method_holder(), method->annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV); C2V_END C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index, jobject filter, jint filter_length, jlong filter_klass_pointers)) + CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support InstanceKlass* holder = check_field(InstanceKlass::cast(UNPACK_PAIR(Klass, klass)), index, JVMCIENV); fieldDescriptor fd(holder, index); return get_encoded_annotation_data(holder, fd.annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV); @@ -3013,6 +3034,7 @@ C2V_VMENTRY_0(jboolean, addFailedSpeculation, (JNIEnv* env, jobject, jlong faile C2V_END C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status)) + CompilerThreadCanCallJava canCallJava(thread, true); JavaValue result(T_VOID); JavaCallArguments jargs(1); jargs.push_int(status); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 24af7715a5b1e..f5a3e5b4d4d14 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -448,6 +448,15 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { private: const Handle& _throwable; + char* print_throwable_to_buffer(Handle throwable, jlong buffer, int buffer_size) { + char* char_buffer = (char*) buffer + 4; + stringStream st(char_buffer, (size_t) buffer_size - 4); + java_lang_Throwable::print_stack_trace(throwable, &st); + u4 len = (u4) st.size(); + *((u4*) buffer) = len; + return char_buffer; + } + bool handle_pending_exception(JavaThread* THREAD, jlong buffer, int buffer_size) { if (HAS_PENDING_EXCEPTION) { Handle throwable = Handle(THREAD, PENDING_EXCEPTION); @@ -457,11 +466,7 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { JVMCI_event_1("error translating exception: OutOfMemoryError"); decode(THREAD, _encode_oome_fail, 0L); } else { - char* char_buffer = (char*) buffer + 4; - stringStream st(char_buffer, (size_t) buffer_size - 4); - java_lang_Throwable::print_stack_trace(throwable, &st); - u4 len = (u4) st.size(); - *((u4*) buffer) = len; + char* char_buffer = print_throwable_to_buffer(throwable, buffer, buffer_size); JVMCI_event_1("error translating exception: %s", char_buffer); decode(THREAD, _encode_fail, buffer); } @@ -471,6 +476,13 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { } int encode(JavaThread* THREAD, jlong buffer, int buffer_size) { + if (!THREAD->can_call_java()) { + char* char_buffer = print_throwable_to_buffer(_throwable, buffer, buffer_size); + const char* detail = log_is_enabled(Info, exceptions) ? "" : " (-Xlog:exceptions may give more detail)"; + JVMCI_event_1("cannot call Java to translate exception%s: %s", detail, char_buffer); + decode(THREAD, _encode_fail, buffer); + return 0; + } Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD); if (handle_pending_exception(THREAD, buffer, buffer_size)) { return 0; @@ -1311,6 +1323,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros. jboolean exception = false; if (is_hotspot()) { + CompilerThreadCanCallJava ccj(THREAD, true); JavaValue result(T_OBJECT); JavaCallArguments args; args.push_long(pointer); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index da87341e5bfa1..5e9999f2733c8 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -1819,57 +1819,6 @@ Klass* JVMCIRuntime::get_klass_by_index(const constantPoolHandle& cpool, return result; } -// ------------------------------------------------------------------ -// Implementation of get_field_by_index. -// -// Implementation note: the results of field lookups are cached -// in the accessor klass. -void JVMCIRuntime::get_field_by_index_impl(InstanceKlass* klass, fieldDescriptor& field_desc, - int index, Bytecodes::Code bc) { - JVMCI_EXCEPTION_CONTEXT; - - assert(klass->is_linked(), "must be linked before using its constant-pool"); - - constantPoolHandle cpool(thread, klass->constants()); - - // Get the field's name, signature, and type. - Symbol* name = cpool->name_ref_at(index, bc); - - int nt_index = cpool->name_and_type_ref_index_at(index, bc); - int sig_index = cpool->signature_ref_index_at(nt_index); - Symbol* signature = cpool->symbol_at(sig_index); - - // Get the field's declared holder. - int holder_index = cpool->klass_ref_index_at(index, bc); - bool holder_is_accessible; - Klass* declared_holder = get_klass_by_index(cpool, holder_index, - holder_is_accessible, - klass); - - // The declared holder of this field may not have been loaded. - // Bail out with partial field information. - if (!holder_is_accessible) { - return; - } - - - // Perform the field lookup. - Klass* canonical_holder = - InstanceKlass::cast(declared_holder)->find_field(name, signature, &field_desc); - if (canonical_holder == nullptr) { - return; - } - - assert(canonical_holder == field_desc.field_holder(), "just checking"); -} - -// ------------------------------------------------------------------ -// Get a field by index from a klass's constant pool. -void JVMCIRuntime::get_field_by_index(InstanceKlass* accessor, fieldDescriptor& fd, int index, Bytecodes::Code bc) { - ResourceMark rm; - return get_field_by_index_impl(accessor, fd, index, bc); -} - // ------------------------------------------------------------------ // Perform an appropriate method lookup based on accessor, holder, // name, signature, and bytecode. diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index d3898be4ce0ae..c12c18abd7836 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -231,8 +231,6 @@ class JVMCIRuntime: public CHeapObj { int klass_index, bool& is_accessible, Klass* loading_klass); - static void get_field_by_index_impl(InstanceKlass* loading_klass, fieldDescriptor& fd, - int field_index, Bytecodes::Code bc); static Method* get_method_by_index_impl(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, InstanceKlass* loading_klass); @@ -417,8 +415,6 @@ class JVMCIRuntime: public CHeapObj { int klass_index, bool& is_accessible, Klass* loading_klass); - static void get_field_by_index(InstanceKlass* loading_klass, fieldDescriptor& fd, - int field_index, Bytecodes::Code bc); static Method* get_method_by_index(const constantPoolHandle& cpool, int method_index, Bytecodes::Code bc, InstanceKlass* loading_klass); diff --git a/src/hotspot/share/prims/upcallLinker.cpp b/src/hotspot/share/prims/upcallLinker.cpp index 8358649ac95fa..acaa36216726f 100644 --- a/src/hotspot/share/prims/upcallLinker.cpp +++ b/src/hotspot/share/prims/upcallLinker.cpp @@ -79,7 +79,7 @@ JavaThread* UpcallLinker::on_entry(UpcallStub::FrameData* context, jobject recei guarantee(thread->thread_state() == _thread_in_native, "wrong thread state for upcall"); context->thread = thread; - assert(thread->can_call_java(), "must be able to call Java"); + guarantee(thread->can_call_java(), "must be able to call Java"); // Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java, // since it can potentially block. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index f3bf7f7cf1b21..239529e0320f9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -565,7 +565,8 @@ HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool * The behavior of this method is undefined if {@code rawIndex} is invalid. * * @param info an array in which the details of the field are returned - * @return the type defining the field if resolution is successful, null otherwise + * @return the type defining the field if resolution is successful, null if the type cannot be resolved + * @throws LinkageError if there were other problems resolving the field */ HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int rawIndex, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) { long methodPointer = method != null ? method.getMethodPointer() : 0L; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java index 98eb0093c09df..98615247ce44d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantPool.java @@ -847,10 +847,10 @@ public JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode try { resolvedHolder = compilerToVM().resolveFieldInPool(this, rawIndex, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info); } catch (Throwable t) { - /* - * If there was an exception resolving the field we give up and return an unresolved - * field. - */ + resolvedHolder = null; + } + if (resolvedHolder == null) { + // There was an exception resolving the field or it returned null so return an unresolved field. return new UnresolvedJavaField(fieldHolder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type); } final int flags = info[0];