8318694: [JVMCI] disable can_call_java in most contexts for libjvmci compiler threads
Reviewed-by: dholmes, never
This commit is contained in:
parent
c86592d38d
commit
d354141aa1
@ -2453,7 +2453,7 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st)
|
|||||||
BacktraceElement bte = iter.next(THREAD);
|
BacktraceElement bte = iter.next(THREAD);
|
||||||
print_stack_element_to_stream(st, bte._mirror, bte._method_id, bte._version, bte._bci, bte._name);
|
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.
|
// Call getCause() which doesn't necessarily return the _cause field.
|
||||||
ExceptionMark em(THREAD);
|
ExceptionMark em(THREAD);
|
||||||
JavaValue cause(T_OBJECT);
|
JavaValue cause(T_OBJECT);
|
||||||
@ -2475,6 +2475,9 @@ void java_lang_Throwable::print_stack_trace(Handle throwable, outputStream* st)
|
|||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
st->print_raw_cr("<<cannot call Java to get cause>>");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,7 +611,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
|||||||
InstanceKlass* loaded_class = nullptr;
|
InstanceKlass* loaded_class = nullptr;
|
||||||
SymbolHandle superclassname; // Keep alive while loading in parallel thread.
|
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",
|
"can not load classes with compiler thread: class=%s, classloader=%s",
|
||||||
name->as_C_string(),
|
name->as_C_string(),
|
||||||
class_loader.is_null() ? "null" : class_loader->klass()->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,
|
Klass* accessing_klass,
|
||||||
Handle* appendix_result,
|
Handle* appendix_result,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
assert(THREAD->can_call_java() ,"");
|
guarantee(THREAD->can_call_java(), "");
|
||||||
Handle method_type =
|
Handle method_type =
|
||||||
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_NULL);
|
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_NULL);
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ CompilerThread::CompilerThread(CompileQueue* queue,
|
|||||||
_queue = queue;
|
_queue = queue;
|
||||||
_counters = counters;
|
_counters = counters;
|
||||||
_buffer_blob = nullptr;
|
_buffer_blob = nullptr;
|
||||||
|
_can_call_java = false;
|
||||||
_compiler = nullptr;
|
_compiler = nullptr;
|
||||||
_arena_stat = CompilationMemoryStatistic::enabled() ? new ArenaStatCounter : nullptr;
|
_arena_stat = CompilationMemoryStatistic::enabled() ? new ArenaStatCounter : nullptr;
|
||||||
|
|
||||||
@ -56,15 +57,17 @@ CompilerThread::~CompilerThread() {
|
|||||||
delete _arena_stat;
|
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) {
|
void CompilerThread::thread_entry(JavaThread* thread, TRAPS) {
|
||||||
assert(thread->is_Compiler_thread(), "must be compiler thread");
|
assert(thread->is_Compiler_thread(), "must be compiler thread");
|
||||||
CompileBroker::compiler_thread_loop();
|
CompileBroker::compiler_thread_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CompilerThread::can_call_java() const {
|
|
||||||
return _compiler != nullptr && _compiler->is_jvmci();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide native compiler threads from external view.
|
// Hide native compiler threads from external view.
|
||||||
bool CompilerThread::is_hidden_from_external_view() const {
|
bool CompilerThread::is_hidden_from_external_view() const {
|
||||||
return _compiler == nullptr || _compiler->is_hidden_from_external_view();
|
return _compiler == nullptr || _compiler->is_hidden_from_external_view();
|
||||||
|
@ -31,18 +31,17 @@ class AbstractCompiler;
|
|||||||
class ArenaStatCounter;
|
class ArenaStatCounter;
|
||||||
class BufferBlob;
|
class BufferBlob;
|
||||||
class ciEnv;
|
class ciEnv;
|
||||||
class CompileThread;
|
class CompilerThread;
|
||||||
class CompileLog;
|
class CompileLog;
|
||||||
class CompileTask;
|
class CompileTask;
|
||||||
class CompileQueue;
|
class CompileQueue;
|
||||||
class CompilerCounters;
|
class CompilerCounters;
|
||||||
class IdealGraphPrinter;
|
class IdealGraphPrinter;
|
||||||
class JVMCIEnv;
|
|
||||||
class JVMCIPrimitiveArray;
|
|
||||||
|
|
||||||
// A thread used for Compilation.
|
// A thread used for Compilation.
|
||||||
class CompilerThread : public JavaThread {
|
class CompilerThread : public JavaThread {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
JVMCI_ONLY(friend class CompilerThreadCanCallJava;)
|
||||||
private:
|
private:
|
||||||
CompilerCounters* _counters;
|
CompilerCounters* _counters;
|
||||||
|
|
||||||
@ -51,6 +50,7 @@ class CompilerThread : public JavaThread {
|
|||||||
CompileTask* volatile _task; // print_threads_compiling can read this concurrently.
|
CompileTask* volatile _task; // print_threads_compiling can read this concurrently.
|
||||||
CompileQueue* _queue;
|
CompileQueue* _queue;
|
||||||
BufferBlob* _buffer_blob;
|
BufferBlob* _buffer_blob;
|
||||||
|
bool _can_call_java;
|
||||||
|
|
||||||
AbstractCompiler* _compiler;
|
AbstractCompiler* _compiler;
|
||||||
TimeStamp _idle_time;
|
TimeStamp _idle_time;
|
||||||
@ -73,13 +73,13 @@ class CompilerThread : public JavaThread {
|
|||||||
|
|
||||||
bool is_Compiler_thread() const { return true; }
|
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
|
// Returns true if this CompilerThread is hidden from JVMTI and FlightRecorder. C1 and C2 are
|
||||||
// always hidden but JVMCI compiler threads might be hidden.
|
// always hidden but JVMCI compiler threads might be hidden.
|
||||||
virtual bool is_hidden_from_external_view() const;
|
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; }
|
AbstractCompiler* compiler() const { return _compiler; }
|
||||||
|
|
||||||
CompileQueue* queue() const { return _queue; }
|
CompileQueue* queue() const { return _queue; }
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#include "compiler/abstractCompiler.hpp"
|
||||||
#include "compiler/compileTask.hpp"
|
#include "compiler/compileTask.hpp"
|
||||||
#include "compiler/compilerThread.hpp"
|
#include "compiler/compilerThread.hpp"
|
||||||
#include "gc/shared/collectedHeap.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;
|
volatile int JVMCI::_fatal_log_fd = -1;
|
||||||
const char* JVMCI::_fatal_log_filename = nullptr;
|
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;
|
void jvmci_vmStructs_init() NOT_DEBUG_RETURN;
|
||||||
|
|
||||||
bool JVMCI::can_initialize_JVMCI() {
|
bool JVMCI::can_initialize_JVMCI() {
|
||||||
@ -176,6 +200,10 @@ void JVMCI::ensure_box_caches_initialized(TRAPS) {
|
|||||||
java_lang_Long_LongCache::symbol()
|
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++) {
|
for (unsigned i = 0; i < sizeof(box_classes) / sizeof(Symbol*); i++) {
|
||||||
Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK);
|
Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK);
|
||||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "utilities/exceptions.hpp"
|
#include "utilities/exceptions.hpp"
|
||||||
|
|
||||||
class BoolObjectClosure;
|
class BoolObjectClosure;
|
||||||
|
class CompilerThread;
|
||||||
class constantPoolHandle;
|
class constantPoolHandle;
|
||||||
class JavaThread;
|
class JavaThread;
|
||||||
class JVMCIEnv;
|
class JVMCIEnv;
|
||||||
@ -46,6 +47,34 @@ typedef FormatStringEventLog<256> StringEventLog;
|
|||||||
struct _jmetadata;
|
struct _jmetadata;
|
||||||
typedef struct _jmetadata *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 {
|
class JVMCI : public AllStatic {
|
||||||
friend class JVMCIRuntime;
|
friend class JVMCIRuntime;
|
||||||
friend class JVMCIEnv;
|
friend class JVMCIEnv;
|
||||||
|
@ -169,10 +169,15 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
|
|||||||
debug_only(VMNativeEntryWrapper __vew;)
|
debug_only(VMNativeEntryWrapper __vew;)
|
||||||
|
|
||||||
// Native method block that transitions current thread to '_thread_in_vm'.
|
// Native method block that transitions current thread to '_thread_in_vm'.
|
||||||
|
// 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) \
|
#define C2V_BLOCK(result_type, name, signature) \
|
||||||
JVMCI_VM_ENTRY_MARK; \
|
JVMCI_VM_ENTRY_MARK; \
|
||||||
ResourceMark rm; \
|
ResourceMark rm; \
|
||||||
JVMCIENV_FROM_JNI(JVMCI::compilation_tick(thread), env);
|
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) {
|
static JavaThread* get_current_thread(bool allow_null=true) {
|
||||||
Thread* thread = Thread::current_or_null_safe();
|
Thread* thread = Thread::current_or_null_safe();
|
||||||
@ -221,7 +226,7 @@ static JavaThread* get_current_thread(bool allow_null=true) {
|
|||||||
#define JNI_THROW(caller, name, msg) do { \
|
#define JNI_THROW(caller, name, msg) do { \
|
||||||
jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \
|
jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \
|
||||||
if (__throw_res != JNI_OK) { \
|
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; \
|
return; \
|
||||||
} while (0);
|
} while (0);
|
||||||
@ -229,7 +234,7 @@ static JavaThread* get_current_thread(bool allow_null=true) {
|
|||||||
#define JNI_THROW_(caller, name, msg, result) do { \
|
#define JNI_THROW_(caller, name, msg, result) do { \
|
||||||
jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \
|
jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \
|
||||||
if (__throw_res != JNI_OK) { \
|
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; \
|
return result; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@ -579,6 +584,7 @@ C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, ARGUMENT_PAIR(
|
|||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jint accessing_klass_loader, jboolean resolve))
|
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);
|
JVMCIObject name = JVMCIENV->wrap(jname);
|
||||||
const char* str = JVMCIENV->as_utf8_string(name);
|
const char* str = JVMCIENV->as_utf8_string(name);
|
||||||
TempNewSymbol class_name = SymbolTable::new_symbol(str);
|
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 (val != nullptr) {
|
||||||
if (strstr(val, "<trace>") != nullptr) {
|
if (strstr(val, "<trace>") != nullptr) {
|
||||||
tty->print_cr("CompilerToVM.lookupType: %s", str);
|
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(),
|
THROW_MSG_0(vmSymbols::java_lang_Exception(),
|
||||||
err_msg("lookupTypeException: %s", str));
|
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);
|
Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
methodHandle mh(THREAD, UNPACK_PAIR(Method, method));
|
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);
|
LinkInfo link_info(cp, index, mh, code, CHECK_NULL);
|
||||||
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL);
|
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_NULL);
|
||||||
JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
|
JVMCIPrimitiveArray info = JVMCIENV->wrap(info_handle);
|
||||||
@ -2726,6 +2743,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
|
|||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
PEER_JVMCIENV_FROM_THREAD(THREAD, !JVMCIENV->is_hotspot());
|
PEER_JVMCIENV_FROM_THREAD(THREAD, !JVMCIENV->is_hotspot());
|
||||||
|
CompilerThreadCanCallJava canCallJava(thread, PEER_JVMCIENV->is_hotspot());
|
||||||
PEER_JVMCIENV->check_init(JVMCI_CHECK_0);
|
PEER_JVMCIENV->check_init(JVMCI_CHECK_0);
|
||||||
|
|
||||||
JVMCIEnv* thisEnv = JVMCIENV;
|
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),
|
C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass),
|
||||||
jobject filter, jint filter_length, jlong filter_klass_pointers))
|
jobject filter, jint filter_length, jlong filter_klass_pointers))
|
||||||
|
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
|
||||||
InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass));
|
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);
|
return get_encoded_annotation_data(holder, holder->class_annotations(), true, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
|
||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(method),
|
C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(method),
|
||||||
jobject filter, jint filter_length, jlong filter_klass_pointers))
|
jobject filter, jint filter_length, jlong filter_klass_pointers))
|
||||||
|
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
|
||||||
methodHandle method(THREAD, UNPACK_PAIR(Method, method));
|
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);
|
return get_encoded_annotation_data(method->method_holder(), method->annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
|
||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index,
|
C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index,
|
||||||
jobject filter, jint filter_length, jlong filter_klass_pointers))
|
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);
|
InstanceKlass* holder = check_field(InstanceKlass::cast(UNPACK_PAIR(Klass, klass)), index, JVMCIENV);
|
||||||
fieldDescriptor fd(holder, index);
|
fieldDescriptor fd(holder, index);
|
||||||
return get_encoded_annotation_data(holder, fd.annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
|
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_END
|
||||||
|
|
||||||
C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status))
|
C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status))
|
||||||
|
CompilerThreadCanCallJava canCallJava(thread, true);
|
||||||
JavaValue result(T_VOID);
|
JavaValue result(T_VOID);
|
||||||
JavaCallArguments jargs(1);
|
JavaCallArguments jargs(1);
|
||||||
jargs.push_int(status);
|
jargs.push_int(status);
|
||||||
|
@ -448,6 +448,15 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
|
|||||||
private:
|
private:
|
||||||
const Handle& _throwable;
|
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) {
|
bool handle_pending_exception(JavaThread* THREAD, jlong buffer, int buffer_size) {
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
|
Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
|
||||||
@ -457,11 +466,7 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
|
|||||||
JVMCI_event_1("error translating exception: OutOfMemoryError");
|
JVMCI_event_1("error translating exception: OutOfMemoryError");
|
||||||
decode(THREAD, _encode_oome_fail, 0L);
|
decode(THREAD, _encode_oome_fail, 0L);
|
||||||
} else {
|
} else {
|
||||||
char* char_buffer = (char*) buffer + 4;
|
char* char_buffer = print_throwable_to_buffer(throwable, buffer, buffer_size);
|
||||||
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;
|
|
||||||
JVMCI_event_1("error translating exception: %s", char_buffer);
|
JVMCI_event_1("error translating exception: %s", char_buffer);
|
||||||
decode(THREAD, _encode_fail, buffer);
|
decode(THREAD, _encode_fail, buffer);
|
||||||
}
|
}
|
||||||
@ -471,6 +476,13 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
|
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);
|
Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD);
|
||||||
if (handle_pending_exception(THREAD, buffer, buffer_size)) {
|
if (handle_pending_exception(THREAD, buffer, buffer_size)) {
|
||||||
return 0;
|
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.
|
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
|
||||||
jboolean exception = false;
|
jboolean exception = false;
|
||||||
if (is_hotspot()) {
|
if (is_hotspot()) {
|
||||||
|
CompilerThreadCanCallJava ccj(THREAD, true);
|
||||||
JavaValue result(T_OBJECT);
|
JavaValue result(T_OBJECT);
|
||||||
JavaCallArguments args;
|
JavaCallArguments args;
|
||||||
args.push_long(pointer);
|
args.push_long(pointer);
|
||||||
|
@ -1819,57 +1819,6 @@ Klass* JVMCIRuntime::get_klass_by_index(const constantPoolHandle& cpool,
|
|||||||
return result;
|
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,
|
// Perform an appropriate method lookup based on accessor, holder,
|
||||||
// name, signature, and bytecode.
|
// name, signature, and bytecode.
|
||||||
|
@ -231,8 +231,6 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||||||
int klass_index,
|
int klass_index,
|
||||||
bool& is_accessible,
|
bool& is_accessible,
|
||||||
Klass* loading_klass);
|
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,
|
static Method* get_method_by_index_impl(const constantPoolHandle& cpool,
|
||||||
int method_index, Bytecodes::Code bc,
|
int method_index, Bytecodes::Code bc,
|
||||||
InstanceKlass* loading_klass);
|
InstanceKlass* loading_klass);
|
||||||
@ -417,8 +415,6 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||||||
int klass_index,
|
int klass_index,
|
||||||
bool& is_accessible,
|
bool& is_accessible,
|
||||||
Klass* loading_klass);
|
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,
|
static Method* get_method_by_index(const constantPoolHandle& cpool,
|
||||||
int method_index, Bytecodes::Code bc,
|
int method_index, Bytecodes::Code bc,
|
||||||
InstanceKlass* loading_klass);
|
InstanceKlass* loading_klass);
|
||||||
|
@ -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");
|
guarantee(thread->thread_state() == _thread_in_native, "wrong thread state for upcall");
|
||||||
context->thread = thread;
|
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,
|
// Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java,
|
||||||
// since it can potentially block.
|
// since it can potentially block.
|
||||||
|
@ -565,7 +565,8 @@ final class CompilerToVM {
|
|||||||
* The behavior of this method is undefined if {@code rawIndex} is invalid.
|
* 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
|
* @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) {
|
HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int rawIndex, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info) {
|
||||||
long methodPointer = method != null ? method.getMethodPointer() : 0L;
|
long methodPointer = method != null ? method.getMethodPointer() : 0L;
|
||||||
|
@ -847,10 +847,10 @@ public final class HotSpotConstantPool implements ConstantPool, MetaspaceHandleO
|
|||||||
try {
|
try {
|
||||||
resolvedHolder = compilerToVM().resolveFieldInPool(this, rawIndex, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
resolvedHolder = compilerToVM().resolveFieldInPool(this, rawIndex, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
/*
|
resolvedHolder = null;
|
||||||
* If there was an exception resolving the field we give up and return an unresolved
|
}
|
||||||
* field.
|
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);
|
return new UnresolvedJavaField(fieldHolder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
|
||||||
}
|
}
|
||||||
final int flags = info[0];
|
final int flags = info[0];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user