mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8248359: Update JVMCI
Reviewed-by: kvn, never
This commit is contained in:
parent
eb78035d05
commit
03d47d58d6
16 changed files with 799 additions and 505 deletions
|
@ -1201,7 +1201,7 @@ void CompileBroker::compile_method_base(const methodHandle& method,
|
|||
// Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown
|
||||
// to avoid deadlock between compiler thread(s) and threads run at shutdown
|
||||
// such as the DestroyJavaVM thread.
|
||||
if (JVMCI::shutdown_called()) {
|
||||
if (JVMCI::in_shutdown()) {
|
||||
blocking = false;
|
||||
}
|
||||
}
|
||||
|
@ -2150,16 +2150,22 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
|||
TraceTime t1("compilation", &time);
|
||||
EventCompilation event;
|
||||
JVMCICompileState compile_state(task);
|
||||
JVMCIRuntime *runtime = NULL;
|
||||
|
||||
if (JVMCI::in_shutdown()) {
|
||||
failure_reason = "in JVMCI shutdown";
|
||||
retry_message = "not retryable";
|
||||
compilable = ciEnv::MethodCompilable_never;
|
||||
} else if (compile_state.target_method_is_old()) {
|
||||
// Skip redefined methods
|
||||
if (compile_state.target_method_is_old()) {
|
||||
failure_reason = "redefined method";
|
||||
retry_message = "not retryable";
|
||||
compilable = ciEnv::MethodCompilable_never;
|
||||
} else {
|
||||
JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__);
|
||||
methodHandle method(thread, target_handle);
|
||||
env.runtime()->compile_method(&env, jvmci, method, osr_bci);
|
||||
runtime = env.runtime();
|
||||
runtime->compile_method(&env, jvmci, method, osr_bci);
|
||||
|
||||
failure_reason = compile_state.failure_reason();
|
||||
failure_reason_on_C_heap = compile_state.failure_reason_on_C_heap();
|
||||
|
|
|
@ -35,12 +35,12 @@
|
|||
// to a GC in the shared library).
|
||||
class JNIAccessMark : public StackObj {
|
||||
private:
|
||||
ThreadToNativeFromVM ttnfv;
|
||||
HandleMark hm;
|
||||
ThreadToNativeFromVM _ttnfv;
|
||||
HandleMark _hm;
|
||||
JNIEnv* _env;
|
||||
public:
|
||||
inline JNIAccessMark(JVMCIEnv* jvmci_env) :
|
||||
ttnfv(JavaThread::current()), hm(JavaThread::current()) {
|
||||
inline JNIAccessMark(JVMCIEnv* jvmci_env, JavaThread* thread=JavaThread::current()) :
|
||||
_ttnfv(thread), _hm(thread) {
|
||||
_env = jvmci_env->_env;
|
||||
}
|
||||
JNIEnv* env() const { return _env; }
|
||||
|
|
|
@ -24,17 +24,19 @@
|
|||
#include "precompiled.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/oopStorage.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
#include "jvmci/jvmci.hpp"
|
||||
#include "jvmci/jvmciJavaClasses.hpp"
|
||||
#include "jvmci/jvmciRuntime.hpp"
|
||||
#include "jvmci/metadataHandleBlock.hpp"
|
||||
#include "jvmci/metadataHandles.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
|
||||
MetadataHandleBlock* JVMCI::_metadata_handles = NULL;
|
||||
JVMCIRuntime* JVMCI::_compiler_runtime = NULL;
|
||||
JVMCIRuntime* JVMCI::_java_runtime = NULL;
|
||||
volatile bool JVMCI::_is_initialized = false;
|
||||
void* JVMCI::_shared_library_handle = NULL;
|
||||
char* JVMCI::_shared_library_path = NULL;
|
||||
volatile bool JVMCI::_in_shutdown = false;
|
||||
|
||||
void jvmci_vmStructs_init() NOT_DEBUG_RETURN;
|
||||
|
||||
|
@ -50,6 +52,40 @@ bool JVMCI::can_initialize_JVMCI() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void* JVMCI::get_shared_library(char*& path, bool load) {
|
||||
void* sl_handle = _shared_library_handle;
|
||||
if (sl_handle != NULL || !load) {
|
||||
path = _shared_library_path;
|
||||
return sl_handle;
|
||||
}
|
||||
assert(JVMCI_lock->owner() == Thread::current(), "must be");
|
||||
path = NULL;
|
||||
if (_shared_library_handle == NULL) {
|
||||
char path[JVM_MAXPATHLEN];
|
||||
char ebuf[1024];
|
||||
if (JVMCILibPath != NULL) {
|
||||
if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) {
|
||||
vm_exit_during_initialization("Unable to locate JVMCI shared library in path specified by -XX:JVMCILibPath value", JVMCILibPath);
|
||||
}
|
||||
} else {
|
||||
if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
|
||||
vm_exit_during_initialization("Unable to create path to JVMCI shared library");
|
||||
}
|
||||
}
|
||||
|
||||
void* handle = os::dll_load(path, ebuf, sizeof ebuf);
|
||||
if (handle == NULL) {
|
||||
vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf);
|
||||
}
|
||||
_shared_library_handle = handle;
|
||||
_shared_library_path = strdup(path);
|
||||
|
||||
TRACE_jvmci_1("loaded JVMCI shared library from %s", path);
|
||||
}
|
||||
path = _shared_library_path;
|
||||
return _shared_library_handle;
|
||||
}
|
||||
|
||||
void JVMCI::initialize_compiler(TRAPS) {
|
||||
if (JVMCILibDumpJNIConfig) {
|
||||
JNIJVMCI::initialize_ids(NULL);
|
||||
|
@ -61,93 +97,57 @@ void JVMCI::initialize_compiler(TRAPS) {
|
|||
|
||||
void JVMCI::initialize_globals() {
|
||||
jvmci_vmStructs_init();
|
||||
_metadata_handles = MetadataHandleBlock::allocate_block();
|
||||
if (UseJVMCINativeLibrary) {
|
||||
// There are two runtimes.
|
||||
_compiler_runtime = new JVMCIRuntime();
|
||||
_java_runtime = new JVMCIRuntime();
|
||||
_compiler_runtime = new JVMCIRuntime(0);
|
||||
_java_runtime = new JVMCIRuntime(-1);
|
||||
} else {
|
||||
// There is only a single runtime
|
||||
_java_runtime = _compiler_runtime = new JVMCIRuntime();
|
||||
_java_runtime = _compiler_runtime = new JVMCIRuntime(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Handles to objects in the Hotspot heap.
|
||||
static OopStorage* object_handles() {
|
||||
return OopStorageSet::vm_global();
|
||||
}
|
||||
|
||||
jobject JVMCI::make_global(const Handle& obj) {
|
||||
assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
|
||||
assert(oopDesc::is_oop(obj()), "not an oop");
|
||||
oop* ptr = object_handles()->allocate();
|
||||
jobject res = NULL;
|
||||
if (ptr != NULL) {
|
||||
assert(*ptr == NULL, "invariant");
|
||||
NativeAccess<>::oop_store(ptr, obj());
|
||||
res = reinterpret_cast<jobject>(ptr);
|
||||
} else {
|
||||
vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
|
||||
"Cannot create JVMCI oop handle");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void JVMCI::destroy_global(jobject handle) {
|
||||
// Assert before nulling out, for better debugging.
|
||||
assert(is_global_handle(handle), "precondition");
|
||||
oop* oop_ptr = reinterpret_cast<oop*>(handle);
|
||||
NativeAccess<>::oop_store(oop_ptr, (oop)NULL);
|
||||
object_handles()->release(oop_ptr);
|
||||
}
|
||||
|
||||
bool JVMCI::is_global_handle(jobject handle) {
|
||||
const oop* ptr = reinterpret_cast<oop*>(handle);
|
||||
return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
|
||||
}
|
||||
|
||||
jmetadata JVMCI::allocate_handle(const methodHandle& handle) {
|
||||
assert(_metadata_handles != NULL, "uninitialized");
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
return _metadata_handles->allocate_handle(handle);
|
||||
}
|
||||
|
||||
jmetadata JVMCI::allocate_handle(const constantPoolHandle& handle) {
|
||||
assert(_metadata_handles != NULL, "uninitialized");
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
return _metadata_handles->allocate_handle(handle);
|
||||
}
|
||||
|
||||
void JVMCI::release_handle(jmetadata handle) {
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
_metadata_handles->chain_free_list(handle);
|
||||
}
|
||||
|
||||
void JVMCI::metadata_do(void f(Metadata*)) {
|
||||
if (_metadata_handles != NULL) {
|
||||
_metadata_handles->metadata_do(f);
|
||||
if (_java_runtime != NULL) {
|
||||
_java_runtime->_metadata_handles->metadata_do(f);
|
||||
}
|
||||
if (_compiler_runtime != NULL && _compiler_runtime != _java_runtime) {
|
||||
_compiler_runtime->_metadata_handles->metadata_do(f);
|
||||
}
|
||||
}
|
||||
|
||||
void JVMCI::do_unloading(bool unloading_occurred) {
|
||||
if (_metadata_handles != NULL && unloading_occurred) {
|
||||
_metadata_handles->do_unloading();
|
||||
if (unloading_occurred) {
|
||||
if (_java_runtime != NULL) {
|
||||
_java_runtime->_metadata_handles->do_unloading();
|
||||
}
|
||||
if (_compiler_runtime != NULL && _compiler_runtime != _java_runtime) {
|
||||
_compiler_runtime->_metadata_handles->do_unloading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JVMCI::is_compiler_initialized() {
|
||||
return compiler_runtime()->is_HotSpotJVMCIRuntime_initialized();
|
||||
return _is_initialized;
|
||||
}
|
||||
|
||||
void JVMCI::shutdown() {
|
||||
ResourceMark rm;
|
||||
{
|
||||
MutexLocker locker(JVMCI_lock);
|
||||
_in_shutdown = true;
|
||||
TRACE_jvmci_1("shutting down JVMCI");
|
||||
}
|
||||
JVMCIRuntime* java_runtime = _java_runtime;
|
||||
if (java_runtime != compiler_runtime()) {
|
||||
java_runtime->shutdown();
|
||||
}
|
||||
if (compiler_runtime() != NULL) {
|
||||
compiler_runtime()->shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
bool JVMCI::shutdown_called() {
|
||||
if (compiler_runtime() != NULL) {
|
||||
return compiler_runtime()->shutdown_called();
|
||||
}
|
||||
return false;
|
||||
bool JVMCI::in_shutdown() {
|
||||
return _in_shutdown;
|
||||
}
|
||||
|
|
|
@ -45,15 +45,24 @@ class JVMCI : public AllStatic {
|
|||
friend class JVMCIEnv;
|
||||
|
||||
private:
|
||||
// Handles to Metadata objects.
|
||||
static MetadataHandleBlock* _metadata_handles;
|
||||
|
||||
// Access to the HotSpotJVMCIRuntime used by the CompileBroker.
|
||||
static JVMCIRuntime* _compiler_runtime;
|
||||
|
||||
// Access to the HotSpotJVMCIRuntime used by Java code running on the
|
||||
// HotSpot heap. It will be the same as _compiler_runtime if
|
||||
// UseJVMCINativeLibrary is false
|
||||
// True when at least one JVMCIRuntime::initialize_HotSpotJVMCIRuntime()
|
||||
// execution has completed successfully.
|
||||
static volatile bool _is_initialized;
|
||||
|
||||
// Handle created when loading the JVMCI shared library with os::dll_load.
|
||||
// Must hold JVMCI_lock when initializing.
|
||||
static void* _shared_library_handle;
|
||||
|
||||
// Argument to os::dll_load when loading JVMCI shared library
|
||||
static char* _shared_library_path;
|
||||
|
||||
// Records whether JVMCI::shutdown has been called.
|
||||
static volatile bool _in_shutdown;
|
||||
|
||||
// Access to the HotSpot heap based JVMCIRuntime
|
||||
static JVMCIRuntime* _java_runtime;
|
||||
|
||||
public:
|
||||
|
@ -64,13 +73,20 @@ class JVMCI : public AllStatic {
|
|||
code_too_large
|
||||
};
|
||||
|
||||
// Gets the handle to the loaded JVMCI shared library, loading it
|
||||
// first if not yet loaded and `load` is true. The path from
|
||||
// which the library is loaded is returned in `path`. If
|
||||
// `load` is true then JVMCI_lock must be locked.
|
||||
static void* get_shared_library(char*& path, bool load);
|
||||
|
||||
static void do_unloading(bool unloading_occurred);
|
||||
|
||||
static void metadata_do(void f(Metadata*));
|
||||
|
||||
static void shutdown();
|
||||
|
||||
static bool shutdown_called();
|
||||
// Returns whether JVMCI::shutdown has been called.
|
||||
static bool in_shutdown();
|
||||
|
||||
static bool is_compiler_initialized();
|
||||
|
||||
|
@ -83,16 +99,9 @@ class JVMCI : public AllStatic {
|
|||
|
||||
static void initialize_compiler(TRAPS);
|
||||
|
||||
static jobject make_global(const Handle& obj);
|
||||
static void destroy_global(jobject handle);
|
||||
static bool is_global_handle(jobject handle);
|
||||
|
||||
static jmetadata allocate_handle(const methodHandle& handle);
|
||||
static jmetadata allocate_handle(const constantPoolHandle& handle);
|
||||
|
||||
static void release_handle(jmetadata handle);
|
||||
|
||||
static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; }
|
||||
// Gets the single runtime for JVMCI on the Java heap. This is the only
|
||||
// JVMCI runtime available when !UseJVMCINativeLibrary.
|
||||
static JVMCIRuntime* java_runtime() { return _java_runtime; }
|
||||
};
|
||||
|
||||
|
|
|
@ -99,29 +99,28 @@ void JVMCICompiler::bootstrap(TRAPS) {
|
|||
(jlong)nanos_to_millis(os::javaTimeNanos() - start), _methods_compiled);
|
||||
}
|
||||
_bootstrapping = false;
|
||||
JVMCI::compiler_runtime()->bootstrap_finished(CHECK);
|
||||
JVMCI::java_runtime()->bootstrap_finished(CHECK);
|
||||
}
|
||||
|
||||
bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) {
|
||||
if (UseJVMCINativeLibrary) {
|
||||
// This mechanism exists to force compilation of a JVMCI compiler by C1
|
||||
// to reduces the compilation time spent on the JVMCI compiler itself. In
|
||||
// +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_bootstrapping) {
|
||||
// When bootstrapping, the JVMCI compiler can compile its own methods.
|
||||
return false;
|
||||
}
|
||||
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
if (runtime != NULL && runtime->is_HotSpotJVMCIRuntime_initialized()) {
|
||||
JavaThread* thread = JavaThread::current();
|
||||
HandleMark hm(thread);
|
||||
THREAD_JVMCIENV(thread);
|
||||
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(JVMCIENV);
|
||||
objArrayHandle excludeModules(thread, HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(JVMCIENV, HotSpotJVMCI::resolve(receiver)));
|
||||
if (UseJVMCINativeLibrary) {
|
||||
// This mechanism exists to force compilation of a JVMCI compiler by C1
|
||||
// to reduce the compilation time spent on the JVMCI compiler itself. In
|
||||
// +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled.
|
||||
return false;
|
||||
} else {
|
||||
JVMCIRuntime* runtime = JVMCI::java_runtime();
|
||||
if (runtime != NULL) {
|
||||
JVMCIObject receiver = runtime->probe_HotSpotJVMCIRuntime();
|
||||
if (receiver.is_null()) {
|
||||
return false;
|
||||
}
|
||||
JVMCIEnv* ignored_env = NULL;
|
||||
objArrayHandle excludeModules(JavaThread::current(), HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(ignored_env, HotSpotJVMCI::resolve(receiver)));
|
||||
if (excludeModules.not_null()) {
|
||||
ModuleEntry* moduleEntry = method->method_holder()->module();
|
||||
for (int i = 0; i < excludeModules->length(); i++) {
|
||||
|
@ -133,6 +132,7 @@ bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Compilation entry point for methods
|
||||
void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
|
||||
|
|
|
@ -103,14 +103,10 @@ class JVMCITraceMark : public StackObj {
|
|||
public:
|
||||
JVMCITraceMark(const char* msg) {
|
||||
_msg = msg;
|
||||
if (JVMCITraceLevel >= 1) {
|
||||
tty->print_cr(PTR_FORMAT " JVMCITrace-1: Enter %s", p2i(JavaThread::current()), _msg);
|
||||
}
|
||||
TRACE_jvmci_2("Enter %s", _msg);
|
||||
}
|
||||
~JVMCITraceMark() {
|
||||
if (JVMCITraceLevel >= 1) {
|
||||
tty->print_cr(PTR_FORMAT " JVMCITrace-1: Exit %s", p2i(JavaThread::current()), _msg);
|
||||
}
|
||||
TRACE_jvmci_2(" Exit %s", _msg);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -137,35 +133,37 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
|
|||
ResourceMark rm; \
|
||||
JNI_JVMCIENV(thread, env);
|
||||
|
||||
static Thread* get_current_thread() {
|
||||
return Thread::current_or_null_safe();
|
||||
static JavaThread* get_current_thread(bool allow_null=true) {
|
||||
Thread* thread = Thread::current_or_null_safe();
|
||||
if (thread == NULL) {
|
||||
assert(allow_null, "npe");
|
||||
return NULL;
|
||||
}
|
||||
assert(thread->is_Java_thread(), "must be");
|
||||
return (JavaThread*) thread;
|
||||
}
|
||||
|
||||
// Entry to native method implementation that transitions
|
||||
// current thread to '_thread_in_vm'.
|
||||
#define C2V_VMENTRY(result_type, name, signature) \
|
||||
JNIEXPORT result_type JNICALL c2v_ ## name signature { \
|
||||
Thread* base_thread = get_current_thread(); \
|
||||
if (base_thread == NULL) { \
|
||||
JavaThread* thread = get_current_thread(); \
|
||||
if (thread == NULL) { \
|
||||
env->ThrowNew(JNIJVMCI::InternalError::clazz(), \
|
||||
err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
|
||||
return; \
|
||||
} \
|
||||
assert(base_thread->is_Java_thread(), "just checking");\
|
||||
JavaThread* thread = (JavaThread*) base_thread; \
|
||||
JVMCITraceMark jtm("CompilerToVM::" #name); \
|
||||
C2V_BLOCK(result_type, name, signature)
|
||||
|
||||
#define C2V_VMENTRY_(result_type, name, signature, result) \
|
||||
JNIEXPORT result_type JNICALL c2v_ ## name signature { \
|
||||
Thread* base_thread = get_current_thread(); \
|
||||
if (base_thread == NULL) { \
|
||||
JavaThread* thread = get_current_thread(); \
|
||||
if (thread == NULL) { \
|
||||
env->ThrowNew(JNIJVMCI::InternalError::clazz(), \
|
||||
err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
|
||||
return result; \
|
||||
} \
|
||||
assert(base_thread->is_Java_thread(), "just checking");\
|
||||
JavaThread* thread = (JavaThread*) base_thread; \
|
||||
JVMCITraceMark jtm("CompilerToVM::" #name); \
|
||||
C2V_BLOCK(result_type, name, signature)
|
||||
|
||||
|
@ -176,7 +174,7 @@ static Thread* get_current_thread() {
|
|||
// current thread to '_thread_in_vm'.
|
||||
#define C2V_VMENTRY_PREFIX(result_type, name, signature) \
|
||||
JNIEXPORT result_type JNICALL c2v_ ## name signature { \
|
||||
Thread* base_thread = get_current_thread();
|
||||
JavaThread* thread = get_current_thread();
|
||||
|
||||
#define C2V_END }
|
||||
|
||||
|
@ -1579,7 +1577,7 @@ extern "C" void jio_printf(const char *fmt, ...);
|
|||
class AttachDetach : public StackObj {
|
||||
public:
|
||||
bool _attached;
|
||||
AttachDetach(JNIEnv* env, Thread* current_thread) {
|
||||
AttachDetach(JNIEnv* env, JavaThread* current_thread) {
|
||||
if (current_thread == NULL) {
|
||||
extern struct JavaVM_ main_vm;
|
||||
JNIEnv* hotspotEnv;
|
||||
|
@ -1608,18 +1606,17 @@ class AttachDetach : public StackObj {
|
|||
};
|
||||
|
||||
C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw))
|
||||
AttachDetach ad(env, base_thread);
|
||||
AttachDetach ad(env, thread);
|
||||
bool use_tty = true;
|
||||
if (base_thread == NULL) {
|
||||
if (thread == NULL) {
|
||||
if (!ad._attached) {
|
||||
// Can only use tty if the current thread is attached
|
||||
TRACE_jvmci_1("Cannot write to tty on unattached thread");
|
||||
return 0;
|
||||
}
|
||||
base_thread = get_current_thread();
|
||||
thread = get_current_thread();
|
||||
}
|
||||
JVMCITraceMark jtm("writeDebugOutput");
|
||||
assert(base_thread->is_Java_thread(), "just checking");
|
||||
JavaThread* thread = (JavaThread*) base_thread;
|
||||
C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
|
||||
if (bytes == NULL) {
|
||||
if (can_throw) {
|
||||
|
@ -2229,7 +2226,7 @@ C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long disp
|
|||
C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h))
|
||||
jobject handle = (jobject)(address)h;
|
||||
if (handle != NULL) {
|
||||
JVMCI::destroy_global(handle);
|
||||
JVMCIENV->runtime()->destroy_global(handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2239,31 +2236,24 @@ static void requireJVMCINativeLibrary(JVMCI_TRAPS) {
|
|||
}
|
||||
}
|
||||
|
||||
static JavaVM* requireNativeLibraryJavaVM(const char* caller, JVMCI_TRAPS) {
|
||||
JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm();
|
||||
if (javaVM == NULL) {
|
||||
JVMCI_THROW_MSG_NULL(IllegalStateException, err_msg("Require JVMCI shared library to be initialized in %s", caller));
|
||||
}
|
||||
return javaVM;
|
||||
}
|
||||
|
||||
C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror))
|
||||
requireJVMCINativeLibrary(JVMCI_CHECK_NULL);
|
||||
requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL);
|
||||
void* shared_library = JVMCIEnv::get_shared_library_handle();
|
||||
if (shared_library == NULL) {
|
||||
char* sl_path;
|
||||
void* sl_handle;
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
{
|
||||
// Ensure the JVMCI shared library runtime is initialized.
|
||||
JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__);
|
||||
JVMCIEnv* peerEnv = &__peer_jvmci_env__;
|
||||
HandleMark hm;
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv);
|
||||
if (peerEnv->has_pending_exception()) {
|
||||
peerEnv->describe_pending_exception(true);
|
||||
}
|
||||
shared_library = JVMCIEnv::get_shared_library_handle();
|
||||
if (shared_library == NULL) {
|
||||
JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime");
|
||||
sl_handle = JVMCI::get_shared_library(sl_path, false);
|
||||
if (sl_handle == NULL) {
|
||||
JVMCI_THROW_MSG_0(InternalError, err_msg("Error initializing JVMCI runtime %d", runtime->id()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2293,7 +2283,7 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
|
|||
os::print_jni_name_suffix_on(&st, args_size);
|
||||
char* jni_name = st.as_string();
|
||||
|
||||
address entry = (address) os::dll_lookup(shared_library, jni_name);
|
||||
address entry = (address) os::dll_lookup(sl_handle, jni_name);
|
||||
if (entry == NULL) {
|
||||
// 2) Try JNI long style
|
||||
st.reset();
|
||||
|
@ -2303,11 +2293,11 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
|
|||
st.print_raw(long_name);
|
||||
os::print_jni_name_suffix_on(&st, args_size);
|
||||
char* jni_long_name = st.as_string();
|
||||
entry = (address) os::dll_lookup(shared_library, jni_long_name);
|
||||
entry = (address) os::dll_lookup(sl_handle, jni_long_name);
|
||||
if (entry == NULL) {
|
||||
JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]",
|
||||
method->name_and_sig_as_C_string(),
|
||||
jni_name, jni_long_name, JVMCIEnv::get_shared_library_path()));
|
||||
jni_name, jni_long_name, sl_path));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2316,51 +2306,49 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas
|
|||
method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry)));
|
||||
}
|
||||
method->set_native_function(entry, Method::native_bind_event_is_interesting);
|
||||
log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI]",
|
||||
log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI] @ " PTR_FORMAT,
|
||||
method->method_holder()->external_name(),
|
||||
method->name()->as_C_string());
|
||||
method->name()->as_C_string(),
|
||||
p2i((void*) entry));
|
||||
}
|
||||
}
|
||||
|
||||
JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm();
|
||||
JVMCIPrimitiveArray result = JVMCIENV->new_longArray(4, JVMCI_CHECK_NULL);
|
||||
JVMCIENV->put_long_at(result, 0, (jlong) (address) javaVM);
|
||||
JVMCIENV->put_long_at(result, 1, (jlong) (address) javaVM->functions->reserved0);
|
||||
JVMCIENV->put_long_at(result, 2, (jlong) (address) javaVM->functions->reserved1);
|
||||
JVMCIENV->put_long_at(result, 3, (jlong) (address) javaVM->functions->reserved2);
|
||||
return (jlongArray) JVMCIENV->get_jobject(result);
|
||||
typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0);
|
||||
jlongArray info = (jlongArray) JNIHandles::make_local(info_oop);
|
||||
runtime->init_JavaVM_info(info, JVMCI_CHECK_0);
|
||||
return info;
|
||||
}
|
||||
|
||||
C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm))
|
||||
if (base_thread == NULL) {
|
||||
if (thread == NULL) {
|
||||
// Called from unattached JVMCI shared library thread
|
||||
return false;
|
||||
}
|
||||
JVMCITraceMark jtm("isCurrentThreadAttached");
|
||||
assert(base_thread->is_Java_thread(), "just checking");
|
||||
JavaThread* thread = (JavaThread*) base_thread;
|
||||
if (thread->jni_environment() == env) {
|
||||
C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject))
|
||||
requireJVMCINativeLibrary(JVMCI_CHECK_0);
|
||||
JavaVM* javaVM = requireNativeLibraryJavaVM("isCurrentThreadAttached", JVMCI_CHECK_0);
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
if (runtime == NULL || !runtime->has_shared_library_javavm()) {
|
||||
JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in isCurrentThreadAttached");
|
||||
}
|
||||
JNIEnv* peerEnv;
|
||||
return javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK;
|
||||
return runtime->GetEnv(thread, (void**) &peerEnv, JNI_VERSION_1_2) == JNI_OK;
|
||||
}
|
||||
return true;
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm))
|
||||
if (base_thread == NULL) {
|
||||
if (thread == NULL) {
|
||||
// Called from unattached JVMCI shared library thread
|
||||
return 0L;
|
||||
}
|
||||
JVMCITraceMark jtm("getCurrentJavaThread");
|
||||
assert(base_thread->is_Java_thread(), "just checking");
|
||||
return (jlong) p2i(base_thread);
|
||||
return (jlong) p2i(thread);
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon))
|
||||
if (base_thread == NULL) {
|
||||
if (thread == NULL) {
|
||||
// Called from unattached JVMCI shared library thread
|
||||
extern struct JavaVM_ main_vm;
|
||||
JNIEnv* hotspotEnv;
|
||||
|
@ -2372,25 +2360,29 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb
|
|||
return true;
|
||||
}
|
||||
JVMCITraceMark jtm("attachCurrentThread");
|
||||
assert(base_thread->is_Java_thread(), "just checking");\
|
||||
JavaThread* thread = (JavaThread*) base_thread;
|
||||
if (thread->jni_environment() == env) {
|
||||
// Called from HotSpot
|
||||
C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean))
|
||||
requireJVMCINativeLibrary(JVMCI_CHECK_0);
|
||||
JavaVM* javaVM = requireNativeLibraryJavaVM("attachCurrentThread", JVMCI_CHECK_0);
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
if (runtime == NULL || !runtime->has_shared_library_javavm()) {
|
||||
JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in attachCurrentThread");
|
||||
}
|
||||
|
||||
JavaVMAttachArgs attach_args;
|
||||
attach_args.version = JNI_VERSION_1_2;
|
||||
attach_args.name = thread->name();
|
||||
attach_args.group = NULL;
|
||||
JNIEnv* peerEnv;
|
||||
if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK) {
|
||||
JNIEnv* peerJNIEnv;
|
||||
if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) == JNI_OK) {
|
||||
return false;
|
||||
}
|
||||
jint res = as_daemon ? javaVM->AttachCurrentThreadAsDaemon((void**)&peerEnv, &attach_args) :
|
||||
javaVM->AttachCurrentThread((void**)&peerEnv, &attach_args);
|
||||
jint res = as_daemon ? runtime->AttachCurrentThreadAsDaemon(thread, (void**) &peerJNIEnv, &attach_args) :
|
||||
runtime->AttachCurrentThread(thread, (void**) &peerJNIEnv, &attach_args);
|
||||
|
||||
if (res == JNI_OK) {
|
||||
guarantee(peerEnv != NULL, "must be");
|
||||
guarantee(peerJNIEnv != NULL, "must be");
|
||||
TRACE_jvmci_1("attached to JavaVM for JVMCI runtime %d", runtime->id());
|
||||
return true;
|
||||
}
|
||||
JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name));
|
||||
|
@ -2400,24 +2392,25 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb
|
|||
C2V_END
|
||||
|
||||
C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm))
|
||||
if (base_thread == NULL) {
|
||||
if (thread == NULL) {
|
||||
// Called from unattached JVMCI shared library thread
|
||||
JNI_THROW("detachCurrentThread", IllegalStateException, err_msg("Cannot detach non-attached thread"));
|
||||
JNI_THROW("detachCurrentThread", IllegalStateException, "Cannot detach non-attached thread");
|
||||
}
|
||||
JVMCITraceMark jtm("detachCurrentThread");
|
||||
assert(base_thread->is_Java_thread(), "just checking");\
|
||||
JavaThread* thread = (JavaThread*) base_thread;
|
||||
if (thread->jni_environment() == env) {
|
||||
// Called from HotSpot
|
||||
C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject))
|
||||
requireJVMCINativeLibrary(JVMCI_CHECK);
|
||||
requireInHotSpot("detachCurrentThread", JVMCI_CHECK);
|
||||
JavaVM* javaVM = requireNativeLibraryJavaVM("detachCurrentThread", JVMCI_CHECK);
|
||||
JNIEnv* peerEnv;
|
||||
if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) != JNI_OK) {
|
||||
JVMCIRuntime* runtime = JVMCI::compiler_runtime();
|
||||
if (runtime == NULL || !runtime->has_shared_library_javavm()) {
|
||||
JVMCI_THROW_MSG(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in detachCurrentThread");
|
||||
}
|
||||
JNIEnv* peerJNIEnv;
|
||||
if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) != JNI_OK) {
|
||||
JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name()));
|
||||
}
|
||||
jint res = javaVM->DetachCurrentThread();
|
||||
jint res = runtime->DetachCurrentThread(thread);
|
||||
if (res != JNI_OK) {
|
||||
JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name()));
|
||||
}
|
||||
|
@ -2426,7 +2419,7 @@ C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm))
|
|||
extern struct JavaVM_ main_vm;
|
||||
jint res = main_vm.DetachCurrentThread();
|
||||
if (res != JNI_OK) {
|
||||
JNI_THROW("detachCurrentThread", InternalError, err_msg("Cannot detach non-attached thread"));
|
||||
JNI_THROW("detachCurrentThread", InternalError, "Cannot detach non-attached thread");
|
||||
}
|
||||
}
|
||||
C2V_END
|
||||
|
|
|
@ -77,10 +77,6 @@ bool JVMCICompileState::jvmti_state_changed() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
JavaVM* JVMCIEnv::_shared_library_javavm = NULL;
|
||||
void* JVMCIEnv::_shared_library_handle = NULL;
|
||||
char* JVMCIEnv::_shared_library_path = NULL;
|
||||
|
||||
void JVMCIEnv::copy_saved_properties() {
|
||||
assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
|
||||
|
||||
|
@ -131,7 +127,7 @@ void JVMCIEnv::copy_saved_properties() {
|
|||
// Initialize saved properties in shared library
|
||||
jclass servicesClass = JNIJVMCI::Services::clazz();
|
||||
jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method();
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject());
|
||||
if (jni()->ExceptionCheck()) {
|
||||
jni()->ExceptionDescribe();
|
||||
|
@ -139,67 +135,14 @@ void JVMCIEnv::copy_saved_properties() {
|
|||
}
|
||||
}
|
||||
|
||||
JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) {
|
||||
if (_shared_library_javavm == NULL) {
|
||||
MutexLocker locker(JVMCI_lock);
|
||||
if (_shared_library_javavm == NULL) {
|
||||
char path[JVM_MAXPATHLEN];
|
||||
char ebuf[1024];
|
||||
if (JVMCILibPath != NULL) {
|
||||
if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) {
|
||||
vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath);
|
||||
}
|
||||
} else {
|
||||
if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
|
||||
vm_exit_during_initialization("Unable to create path to JVMCI shared library");
|
||||
}
|
||||
}
|
||||
|
||||
void* handle = os::dll_load(path, ebuf, sizeof ebuf);
|
||||
if (handle == NULL) {
|
||||
vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf);
|
||||
}
|
||||
_shared_library_handle = handle;
|
||||
_shared_library_path = strdup(path);
|
||||
jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
|
||||
typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
|
||||
|
||||
JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM"));
|
||||
JNIEnv* env;
|
||||
if (JNI_CreateJavaVM == NULL) {
|
||||
vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path);
|
||||
}
|
||||
|
||||
ResourceMark rm;
|
||||
JavaVMInitArgs vm_args;
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.ignoreUnrecognized = JNI_TRUE;
|
||||
vm_args.options = NULL;
|
||||
vm_args.nOptions = 0;
|
||||
|
||||
JavaVM* the_javavm = NULL;
|
||||
int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args);
|
||||
if (result == JNI_OK) {
|
||||
guarantee(env != NULL, "missing env");
|
||||
_shared_library_javavm = the_javavm;
|
||||
return env;
|
||||
} else {
|
||||
vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
||||
assert(thread != NULL, "npe");
|
||||
// By default there is only one runtime which is the compiler runtime.
|
||||
_runtime = JVMCI::compiler_runtime();
|
||||
_env = NULL;
|
||||
_pop_frame_on_close = false;
|
||||
_detach_on_close = false;
|
||||
if (!UseJVMCINativeLibrary) {
|
||||
// In HotSpot mode, JNI isn't used at all.
|
||||
_runtime = JVMCI::java_runtime();
|
||||
_is_hotspot = true;
|
||||
return;
|
||||
}
|
||||
|
@ -213,6 +156,8 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
|||
_runtime = JVMCI::java_runtime();
|
||||
return;
|
||||
}
|
||||
_runtime = JVMCI::compiler_runtime();
|
||||
assert(_runtime != NULL, "npe");
|
||||
_env = parent_env;
|
||||
return;
|
||||
}
|
||||
|
@ -220,13 +165,15 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
|||
// Running in JVMCI shared library mode so ensure the shared library
|
||||
// is loaded and initialized and get a shared library JNIEnv
|
||||
_is_hotspot = false;
|
||||
_env = init_shared_library(thread);
|
||||
|
||||
_runtime = JVMCI::compiler_runtime();
|
||||
_env = _runtime->init_shared_library_javavm();
|
||||
|
||||
if (_env != NULL) {
|
||||
// Creating the JVMCI shared library VM also attaches the current thread
|
||||
_detach_on_close = true;
|
||||
} else {
|
||||
_shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2);
|
||||
_runtime->GetEnv(thread, (void**)&parent_env, JNI_VERSION_1_2);
|
||||
if (parent_env != NULL) {
|
||||
// Even though there's a parent JNI env, there's no guarantee
|
||||
// it was opened by a JVMCIEnv scope and thus may not have
|
||||
|
@ -240,7 +187,7 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
|||
attach_args.version = JNI_VERSION_1_2;
|
||||
attach_args.name = thread->name();
|
||||
attach_args.group = NULL;
|
||||
if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) {
|
||||
if (_runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args) != JNI_OK) {
|
||||
fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
|
||||
}
|
||||
_detach_on_close = true;
|
||||
|
@ -250,7 +197,7 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
|
|||
assert(_env != NULL, "missing env");
|
||||
assert(_throw_to_caller == false, "must be");
|
||||
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, thread);
|
||||
jint result = _env->PushLocalFrame(32);
|
||||
if (result != JNI_OK) {
|
||||
char message[256];
|
||||
|
@ -294,6 +241,7 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int l
|
|||
|
||||
// Prints a pending exception (if any) and its stack trace.
|
||||
void JVMCIEnv::describe_pending_exception(bool clear) {
|
||||
Thread* THREAD = Thread::current();
|
||||
if (!is_hotspot()) {
|
||||
JNIAccessMark jni(this);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
|
@ -304,7 +252,6 @@ void JVMCIEnv::describe_pending_exception(bool clear) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Thread* THREAD = Thread::current();
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear);
|
||||
}
|
||||
|
@ -332,7 +279,7 @@ void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD,
|
|||
ResourceMark rm;
|
||||
const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string);
|
||||
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars);
|
||||
jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
|
||||
JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(),
|
||||
|
@ -368,7 +315,7 @@ JVMCIEnv::~JVMCIEnv() {
|
|||
}
|
||||
|
||||
if (_detach_on_close) {
|
||||
get_shared_library_javavm()->DetachCurrentThread();
|
||||
_runtime->DetachCurrentThread(JavaThread::current());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -603,12 +550,12 @@ JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
|
|||
default:
|
||||
JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
|
||||
}
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
|
||||
return HotSpotJVMCI::wrap(box);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
|
||||
assert(box != NULL, "");
|
||||
return wrap(box);
|
||||
|
@ -672,13 +619,13 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...)
|
|||
vsnprintf(msg, max_msg_size, format, ap);
|
||||
msg[max_msg_size-1] = '\0';
|
||||
va_end(ap);
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
Handle h_loader = Handle();
|
||||
Handle h_protection_domain = Handle();
|
||||
Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +682,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
|
|||
JavaValue result(T_VOID);
|
||||
JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method());
|
||||
}
|
||||
if (has_pending_exception()) {
|
||||
|
@ -753,7 +700,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
|
|||
JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
|
@ -770,7 +717,7 @@ JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
|
|||
JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method());
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
|
@ -788,7 +735,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime,
|
|||
JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
|
@ -810,7 +757,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object,
|
|||
vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
|
||||
JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(),
|
||||
object.as_jobject());
|
||||
|
@ -835,7 +782,7 @@ JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value
|
|||
vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(),
|
||||
JNIJVMCI::PrimitiveConstant::forTypeChar_method(),
|
||||
kind, value);
|
||||
|
@ -858,7 +805,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
|
|||
vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
|
||||
JNIJVMCI::JavaConstant::forFloat_method(),
|
||||
value);
|
||||
|
@ -881,7 +828,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) {
|
|||
vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject()));
|
||||
return wrap((oop) result.get_jobject());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
|
||||
JNIJVMCI::JavaConstant::forDouble_method(),
|
||||
value);
|
||||
|
@ -926,7 +873,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci,
|
|||
HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number);
|
||||
return wrap(obj());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject declaring_class = jni()->NewStringUTF(declaring_class_str);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
|
@ -978,7 +925,7 @@ JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char*
|
|||
&jargs, CHECK_(JVMCIObject()));
|
||||
return wrap(obj_h());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject nameStr = name == NULL ? NULL : jni()->NewStringUTF(name);
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
|
@ -1015,18 +962,6 @@ JVMCIObject JVMCIEnv::make_global(JVMCIObject object) {
|
|||
}
|
||||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::make_weak(JVMCIObject object) {
|
||||
if (object.is_null()) {
|
||||
return JVMCIObject();
|
||||
}
|
||||
if (is_hotspot()) {
|
||||
return wrap(JNIHandles::make_weak_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
return wrap(jni()->NewWeakGlobalRef(object.as_jobject()));
|
||||
}
|
||||
}
|
||||
|
||||
void JVMCIEnv::destroy_local(JVMCIObject object) {
|
||||
if (is_hotspot()) {
|
||||
JNIHandles::destroy_local(object.as_jobject());
|
||||
|
@ -1045,15 +980,6 @@ void JVMCIEnv::destroy_global(JVMCIObject object) {
|
|||
}
|
||||
}
|
||||
|
||||
void JVMCIEnv::destroy_weak(JVMCIObject object) {
|
||||
if (is_hotspot()) {
|
||||
JNIHandles::destroy_weak_global(object.as_jweak());
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
jni()->DeleteWeakGlobalRef(object.as_jweak());
|
||||
}
|
||||
}
|
||||
|
||||
const char* JVMCIEnv::klass_name(JVMCIObject object) {
|
||||
if (is_hotspot()) {
|
||||
return HotSpotJVMCI::resolve(object)->klass()->signature_name();
|
||||
|
@ -1076,7 +1002,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
|
|||
}
|
||||
|
||||
Thread* THREAD = Thread::current();
|
||||
jmetadata handle = JVMCI::allocate_handle(method);
|
||||
jmetadata handle = _runtime->allocate_handle(method);
|
||||
jboolean exception = false;
|
||||
if (is_hotspot()) {
|
||||
JavaValue result(T_OBJECT);
|
||||
|
@ -1099,13 +1025,13 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
|
|||
}
|
||||
|
||||
if (exception) {
|
||||
JVMCI::release_handle(handle);
|
||||
_runtime->release_handle(handle);
|
||||
return JVMCIObject();
|
||||
}
|
||||
|
||||
assert(asMethod(method_object) == method(), "must be");
|
||||
if (get_HotSpotResolvedJavaMethodImpl_metadataHandle(method_object) != (jlong) handle) {
|
||||
JVMCI::release_handle(handle);
|
||||
_runtime->release_handle(handle);
|
||||
}
|
||||
assert(!method_object.is_null(), "must be");
|
||||
return method_object;
|
||||
|
@ -1137,7 +1063,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
|
|||
type = wrap((oop)result.get_jobject());
|
||||
}
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
|
||||
|
@ -1155,10 +1081,10 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
|
|||
|
||||
JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
|
||||
JVMCIObject cp_object;
|
||||
jmetadata handle = JVMCI::allocate_handle(cp);
|
||||
jmetadata handle = _runtime->allocate_handle(cp);
|
||||
jboolean exception = false;
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCallArguments args;
|
||||
args.push_long((jlong) handle);
|
||||
|
@ -1172,7 +1098,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC
|
|||
cp_object = wrap((oop)result.get_jobject());
|
||||
}
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
|
||||
JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
|
||||
(jlong) handle));
|
||||
|
@ -1180,7 +1106,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC
|
|||
}
|
||||
|
||||
if (exception) {
|
||||
JVMCI::release_handle(handle);
|
||||
_runtime->release_handle(handle);
|
||||
return JVMCIObject();
|
||||
}
|
||||
|
||||
|
@ -1191,69 +1117,69 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC
|
|||
}
|
||||
|
||||
JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
|
||||
return wrap(result);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jbooleanArray result = jni()->NewBooleanArray(length);
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
|
||||
return wrap(result);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jbyteArray result = jni()->NewByteArray(length);
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlassObj ())->array_klass(CHECK_(JVMCIObject()));
|
||||
objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject()));
|
||||
return wrap(result);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), NULL);
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
|
||||
return wrap(result);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jintArray result = jni()->NewIntArray(length);
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
|
||||
return wrap(result);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jlongArray result = jni()->NewLongArray(length);
|
||||
return wrap(result);
|
||||
}
|
||||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject()));
|
||||
oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject()));
|
||||
HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name));
|
||||
|
@ -1263,7 +1189,7 @@ JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offs
|
|||
HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value));
|
||||
return wrap(obj);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(),
|
||||
JNIJVMCI::VMField::constructor(),
|
||||
get_jobject(name), get_jobject(type), offset, address, get_jobject(value));
|
||||
|
@ -1272,8 +1198,8 @@ JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offs
|
|||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject()));
|
||||
oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject()));
|
||||
HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name));
|
||||
|
@ -1281,7 +1207,7 @@ JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject
|
|||
HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value));
|
||||
return wrap(obj);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(),
|
||||
JNIJVMCI::VMFlag::constructor(),
|
||||
get_jobject(name), get_jobject(type), get_jobject(value));
|
||||
|
@ -1290,8 +1216,8 @@ JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject
|
|||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
|
||||
oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject()));
|
||||
HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass));
|
||||
|
@ -1300,7 +1226,7 @@ JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObj
|
|||
HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
|
||||
return wrap(obj);
|
||||
} else {
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
|
||||
JNIJVMCI::VMIntrinsicMethod::constructor(),
|
||||
get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id);
|
||||
|
@ -1346,7 +1272,7 @@ JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont
|
|||
return wrap(constant);
|
||||
} else {
|
||||
jlong handle = make_handle(obj);
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(),
|
||||
JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(),
|
||||
handle, compressed, dont_register);
|
||||
|
@ -1385,7 +1311,7 @@ JVMCIObject JVMCIEnv::wrap(jobject object) {
|
|||
|
||||
jlong JVMCIEnv::make_handle(const Handle& obj) {
|
||||
assert(!obj.is_null(), "should only create handle for non-NULL oops");
|
||||
jobject handle = JVMCI::make_global(obj);
|
||||
jobject handle = _runtime->make_global(obj);
|
||||
return (jlong) handle;
|
||||
}
|
||||
|
||||
|
@ -1399,15 +1325,15 @@ oop JVMCIEnv::resolve_handle(jlong objectHandle) {
|
|||
}
|
||||
|
||||
JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
|
||||
if (is_hotspot()) {
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
if (is_hotspot()) {
|
||||
Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
|
||||
return HotSpotJVMCI::wrap(result());
|
||||
} else {
|
||||
jobject result;
|
||||
jboolean exception = false;
|
||||
{
|
||||
JNIAccessMark jni(this);
|
||||
JNIAccessMark jni(this, THREAD);
|
||||
result = jni()->NewStringUTF(str);
|
||||
exception = jni()->ExceptionCheck();
|
||||
}
|
||||
|
|
|
@ -44,8 +44,11 @@ class JVMCIRuntime;
|
|||
#define JVMCI_EXCEPTION_CHECK(env, ...) \
|
||||
do { \
|
||||
if (env->ExceptionCheck()) { \
|
||||
if (env != JavaThread::current()->jni_environment() && JVMCIEnv::get_shared_library_path() != NULL) { \
|
||||
tty->print_cr("In JVMCI shared library (%s):", JVMCIEnv::get_shared_library_path()); \
|
||||
if (env != JavaThread::current()->jni_environment()) { \
|
||||
char* sl_path; \
|
||||
if (::JVMCI::get_shared_library(sl_path, false) != NULL) { \
|
||||
tty->print_cr("In JVMCI shared library (%s):", sl_path); \
|
||||
} \
|
||||
} \
|
||||
tty->print_cr(__VA_ARGS__); \
|
||||
return; \
|
||||
|
@ -143,16 +146,6 @@ class JVMCICompileState : public ResourceObj {
|
|||
class JVMCIEnv : public ResourceObj {
|
||||
friend class JNIAccessMark;
|
||||
|
||||
static char* _shared_library_path; // argument to os:dll_load
|
||||
static void* _shared_library_handle; // result of os::dll_load
|
||||
static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
|
||||
|
||||
// Initializes the shared library JavaVM if not already initialized.
|
||||
// Returns the JNI interface pointer for the current thread
|
||||
// if initialization was performed by this call, NULL if
|
||||
// initialization was performed by a previous call.
|
||||
static JNIEnv* init_shared_library(JavaThread* thread);
|
||||
|
||||
// Initializes the _env, _mode and _runtime fields.
|
||||
void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env);
|
||||
|
||||
|
@ -384,10 +377,8 @@ public:
|
|||
// These are analagous to the JNI routines
|
||||
JVMCIObject make_local(JVMCIObject object);
|
||||
JVMCIObject make_global(JVMCIObject object);
|
||||
JVMCIObject make_weak(JVMCIObject object);
|
||||
void destroy_local(JVMCIObject object);
|
||||
void destroy_global(JVMCIObject object);
|
||||
void destroy_weak(JVMCIObject object);
|
||||
|
||||
// Deoptimizes the nmethod (if any) in the HotSpotNmethod.address
|
||||
// field of mirror. The field is subsequently zeroed.
|
||||
|
@ -399,9 +390,6 @@ public:
|
|||
JVMCICompileState* _compile_state;
|
||||
|
||||
public:
|
||||
static JavaVM* get_shared_library_javavm() { return _shared_library_javavm; }
|
||||
static void* get_shared_library_handle() { return _shared_library_handle; }
|
||||
static char* get_shared_library_path() { return _shared_library_path; }
|
||||
|
||||
// Determines if this is for the JVMCI runtime in the HotSpot
|
||||
// heap (true) or the shared library heap (false).
|
||||
|
|
|
@ -83,6 +83,7 @@ void HotSpotJVMCI::compute_offset(int &dest_offset, Klass* klass, const char* na
|
|||
// accessor itself does not include a class initialization check.
|
||||
ik->initialize(CHECK);
|
||||
}
|
||||
TRACE_jvmci_2(" field offset for %s %s.%s = %d", signature, ik->external_name(), name, dest_offset);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -118,6 +119,7 @@ jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method;
|
|||
#define START_CLASS(className, fullClassName) { \
|
||||
Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::fullClassName(), true, CHECK); \
|
||||
className::_klass = InstanceKlass::cast(k); \
|
||||
TRACE_jvmci_2(" klass for %s = " PTR_FORMAT, k->external_name(), p2i(k)); \
|
||||
className::_klass->initialize(CHECK);
|
||||
|
||||
#define END_CLASS }
|
||||
|
@ -286,6 +288,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
if (env->ExceptionCheck()) {
|
||||
return;
|
||||
}
|
||||
jfieldID current = fieldid;
|
||||
if (static_field) {
|
||||
// Class initialization barrier
|
||||
fieldid = env->GetStaticFieldID(clazz, name, signature);
|
||||
|
@ -293,6 +296,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
// Class initialization barrier
|
||||
fieldid = env->GetFieldID(clazz, name, signature);
|
||||
}
|
||||
TRACE_jvmci_2(" jfieldID for %s %s.%s = " PTR_FORMAT, signature, class_name, name, p2i(fieldid));
|
||||
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
|
@ -312,7 +316,9 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
jclass k = env->FindClass(current_class_name); \
|
||||
JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", current_class_name); \
|
||||
assert(k != NULL, #fullClassName " not initialized"); \
|
||||
className::_class = (jclass) env->NewGlobalRef(k); \
|
||||
k = (jclass) env->NewGlobalRef(k); \
|
||||
TRACE_jvmci_2(" jclass for %s = " PTR_FORMAT, current_class_name, p2i(k)); \
|
||||
className::_class = k; \
|
||||
}
|
||||
|
||||
#define END_CLASS current_class_name = NULL; }
|
||||
|
@ -333,9 +339,13 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
fileStream* st = JVMCIGlobals::get_jni_config_file(); \
|
||||
st->print_cr("method %s %s %s", current_class_name, methodName, signature); \
|
||||
} else { \
|
||||
jmethodID current = dst; \
|
||||
dst = env->jniGetMethod(clazz, methodName, signature); \
|
||||
JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", current_class_name, methodName, signature); \
|
||||
JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", \
|
||||
current_class_name, methodName, signature); \
|
||||
assert(dst != NULL, "uninitialized"); \
|
||||
TRACE_jvmci_2(" jmethodID for %s.%s%s = " PTR_FORMAT, \
|
||||
current_class_name, methodName, signature, p2i(dst)); \
|
||||
}
|
||||
|
||||
#define GET_JNI_CONSTRUCTOR(clazz, signature) \
|
||||
|
@ -493,30 +503,30 @@ void JNIJVMCI::initialize_ids(JNIEnv* env) {
|
|||
|
||||
#define CC (char*) /*cast a literal from (const char*)*/
|
||||
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f))
|
||||
}
|
||||
|
||||
static void register_natives_for_class(JNIEnv* env, jclass clazz, const char* name, const JNINativeMethod *methods, jint nMethods) {
|
||||
if (clazz == NULL) {
|
||||
clazz = env->FindClass(name);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
fatal("Could not find class %s", name);
|
||||
}
|
||||
}
|
||||
env->RegisterNatives(clazz, methods, nMethods);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
fatal("Failure registering natives for %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
void JNIJVMCI::register_natives(JNIEnv* env) {
|
||||
if (env != JavaThread::current()->jni_environment()) {
|
||||
jclass clazz = env->FindClass("jdk/vm/ci/hotspot/CompilerToVM");
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
guarantee(false, "Could not find class jdk/vm/ci/hotspot/CompilerToVM");
|
||||
}
|
||||
JNINativeMethod CompilerToVM_native_methods[] = {
|
||||
{ CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) },
|
||||
};
|
||||
env->RegisterNatives(clazz, CompilerToVM_native_methods, 1);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
guarantee(false, "");
|
||||
}
|
||||
JNINativeMethod CompilerToVM_nmethods[] = {{ CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) }};
|
||||
JNINativeMethod JVMCI_nmethods[] = {{ CC"initializeRuntime", CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) }};
|
||||
|
||||
JNINativeMethod JVMCI_native_methods[] = {
|
||||
{ CC"initializeRuntime", CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) },
|
||||
};
|
||||
env->RegisterNatives(JVMCI::clazz(), JVMCI_native_methods, 1);
|
||||
if (env->ExceptionCheck()) {
|
||||
env->ExceptionDescribe();
|
||||
guarantee(false, "");
|
||||
}
|
||||
register_natives_for_class(env, NULL, "jdk/vm/ci/hotspot/CompilerToVM", CompilerToVM_nmethods, 1);
|
||||
register_natives_for_class(env, JVMCI::clazz(), "jdk/vm/ci/runtime/JVMCI", JVMCI_nmethods, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -639,6 +639,7 @@ class JNIJVMCI {
|
|||
|
||||
static void initialize_ids(JNIEnv* env);
|
||||
static void initialize_field_id(JNIEnv* env, jfieldID &dest_offset, jclass klass, const char* klass_name, const char* name, const char* signature, bool static_field);
|
||||
static void register_natives(JNIEnv* env);
|
||||
|
||||
static jobject resolve_handle(JVMCIObject obj) { return obj.as_jobject(); }
|
||||
static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, false); }
|
||||
|
|
|
@ -25,9 +25,12 @@
|
|||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "gc/shared/oopStorage.inline.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
#include "jvmci/jniAccessMark.inline.hpp"
|
||||
#include "jvmci/jvmciCompilerToVM.hpp"
|
||||
#include "jvmci/jvmciRuntime.hpp"
|
||||
#include "jvmci/metadataHandles.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
|
@ -35,11 +38,13 @@
|
|||
#include "oops/method.inline.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/typeArrayOop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/frame.inline.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#if INCLUDE_G1GC
|
||||
#include "gc/g1/g1ThreadLocalData.hpp"
|
||||
|
@ -705,6 +710,156 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
|
|||
}
|
||||
}
|
||||
|
||||
JVMCIRuntime::JVMCIRuntime(int id) {
|
||||
_init_state = uninitialized;
|
||||
_shared_library_javavm = NULL;
|
||||
_id = id;
|
||||
_metadata_handles = new MetadataHandles();
|
||||
TRACE_jvmci_1("created new JVMCI runtime %d (" PTR_FORMAT ")", id, p2i(this));
|
||||
}
|
||||
|
||||
// Handles to objects in the Hotspot heap.
|
||||
static OopStorage* object_handles() {
|
||||
return OopStorageSet::vm_global();
|
||||
}
|
||||
|
||||
jobject JVMCIRuntime::make_global(const Handle& obj) {
|
||||
assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
|
||||
assert(oopDesc::is_oop(obj()), "not an oop");
|
||||
oop* ptr = object_handles()->allocate();
|
||||
jobject res = NULL;
|
||||
if (ptr != NULL) {
|
||||
assert(*ptr == NULL, "invariant");
|
||||
NativeAccess<>::oop_store(ptr, obj());
|
||||
res = reinterpret_cast<jobject>(ptr);
|
||||
} else {
|
||||
vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR,
|
||||
"Cannot create JVMCI oop handle");
|
||||
}
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
void JVMCIRuntime::destroy_global(jobject handle) {
|
||||
// Assert before nulling out, for better debugging.
|
||||
assert(is_global_handle(handle), "precondition");
|
||||
oop* oop_ptr = reinterpret_cast<oop*>(handle);
|
||||
NativeAccess<>::oop_store(oop_ptr, (oop)NULL);
|
||||
object_handles()->release(oop_ptr);
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
}
|
||||
|
||||
bool JVMCIRuntime::is_global_handle(jobject handle) {
|
||||
const oop* ptr = reinterpret_cast<oop*>(handle);
|
||||
return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY;
|
||||
}
|
||||
|
||||
jmetadata JVMCIRuntime::allocate_handle(const methodHandle& handle) {
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
return _metadata_handles->allocate_handle(handle);
|
||||
}
|
||||
|
||||
jmetadata JVMCIRuntime::allocate_handle(const constantPoolHandle& handle) {
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
return _metadata_handles->allocate_handle(handle);
|
||||
}
|
||||
|
||||
void JVMCIRuntime::release_handle(jmetadata handle) {
|
||||
MutexLocker ml(JVMCI_lock);
|
||||
_metadata_handles->chain_free_list(handle);
|
||||
}
|
||||
|
||||
JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
|
||||
JavaVM* javaVM = (JavaVM*) _shared_library_javavm;
|
||||
if (javaVM == NULL) {
|
||||
MutexLocker locker(JVMCI_lock);
|
||||
// Check again under JVMCI_lock
|
||||
javaVM = (JavaVM*) _shared_library_javavm;
|
||||
if (javaVM != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
char* sl_path;
|
||||
void* sl_handle = JVMCI::get_shared_library(sl_path, true);
|
||||
|
||||
jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
|
||||
typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
|
||||
|
||||
JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(sl_handle, "JNI_CreateJavaVM"));
|
||||
if (JNI_CreateJavaVM == NULL) {
|
||||
vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", sl_path);
|
||||
}
|
||||
|
||||
ResourceMark rm;
|
||||
JavaVMInitArgs vm_args;
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.ignoreUnrecognized = JNI_TRUE;
|
||||
JavaVMOption options[1];
|
||||
jlong javaVM_id = 0;
|
||||
|
||||
// Protocol: JVMCI shared library JavaVM should support a non-standard "_javavm_id"
|
||||
// option whose extraInfo info field is a pointer to which a unique id for the
|
||||
// JavaVM should be written.
|
||||
options[0].optionString = (char*) "_javavm_id";
|
||||
options[0].extraInfo = &javaVM_id;
|
||||
|
||||
vm_args.version = JNI_VERSION_1_2;
|
||||
vm_args.options = options;
|
||||
vm_args.nOptions = sizeof(options) / sizeof(JavaVMOption);
|
||||
|
||||
JNIEnv* env = NULL;
|
||||
int result = (*JNI_CreateJavaVM)(&javaVM, (void**) &env, &vm_args);
|
||||
if (result == JNI_OK) {
|
||||
guarantee(env != NULL, "missing env");
|
||||
_shared_library_javavm = javaVM;
|
||||
TRACE_jvmci_1("created JavaVM[%ld]@" PTR_FORMAT " for JVMCI runtime %d", javaVM_id, p2i(javaVM), _id);
|
||||
return env;
|
||||
} else {
|
||||
vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), sl_path);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void JVMCIRuntime::init_JavaVM_info(jlongArray info, JVMCI_TRAPS) {
|
||||
if (info != NULL) {
|
||||
typeArrayOop info_oop = (typeArrayOop) JNIHandles::resolve(info);
|
||||
if (info_oop->length() < 4) {
|
||||
JVMCI_THROW_MSG(ArrayIndexOutOfBoundsException, err_msg("%d < 4", info_oop->length()));
|
||||
}
|
||||
JavaVM* javaVM = (JavaVM*) _shared_library_javavm;
|
||||
info_oop->long_at_put(0, (jlong) (address) javaVM);
|
||||
info_oop->long_at_put(1, (jlong) (address) javaVM->functions->reserved0);
|
||||
info_oop->long_at_put(2, (jlong) (address) javaVM->functions->reserved1);
|
||||
info_oop->long_at_put(3, (jlong) (address) javaVM->functions->reserved2);
|
||||
}
|
||||
}
|
||||
|
||||
#define JAVAVM_CALL_BLOCK \
|
||||
guarantee(thread != NULL && _shared_library_javavm != NULL, "npe"); \
|
||||
ThreadToNativeFromVM ttnfv(thread); \
|
||||
JavaVM* javavm = (JavaVM*) _shared_library_javavm;
|
||||
|
||||
jint JVMCIRuntime::AttachCurrentThread(JavaThread* thread, void **penv, void *args) {
|
||||
JAVAVM_CALL_BLOCK
|
||||
return javavm->AttachCurrentThread(penv, args);
|
||||
}
|
||||
|
||||
jint JVMCIRuntime::AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args) {
|
||||
JAVAVM_CALL_BLOCK
|
||||
return javavm->AttachCurrentThreadAsDaemon(penv, args);
|
||||
}
|
||||
|
||||
jint JVMCIRuntime::DetachCurrentThread(JavaThread* thread) {
|
||||
JAVAVM_CALL_BLOCK
|
||||
return javavm->DetachCurrentThread();
|
||||
}
|
||||
|
||||
jint JVMCIRuntime::GetEnv(JavaThread* thread, void **penv, jint version) {
|
||||
JAVAVM_CALL_BLOCK
|
||||
return javavm->GetEnv(penv, version);
|
||||
}
|
||||
#undef JAVAVM_CALL_BLOCK \
|
||||
|
||||
void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
|
||||
if (is_HotSpotJVMCIRuntime_initialized()) {
|
||||
if (JVMCIENV->is_hotspot() && UseJVMCINativeLibrary) {
|
||||
|
@ -718,29 +873,32 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
|
|||
JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK);
|
||||
|
||||
_HotSpotJVMCIRuntime_instance = JVMCIENV->make_global(result);
|
||||
JVMCI::_is_initialized = true;
|
||||
}
|
||||
|
||||
void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {
|
||||
assert(this != NULL, "sanity");
|
||||
// Check first without JVMCI_lock
|
||||
if (_initialized) {
|
||||
if (_init_state == fully_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
MutexLocker locker(JVMCI_lock);
|
||||
// Check again under JVMCI_lock
|
||||
if (_initialized) {
|
||||
if (_init_state == fully_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (_being_initialized) {
|
||||
while (_init_state == being_initialized) {
|
||||
TRACE_jvmci_1("waiting for initialization of JVMCI runtime %d", _id);
|
||||
JVMCI_lock->wait();
|
||||
if (_initialized) {
|
||||
if (_init_state == fully_initialized) {
|
||||
TRACE_jvmci_1("done waiting for initialization of JVMCI runtime %d", _id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_being_initialized = true;
|
||||
TRACE_jvmci_1("initializing JVMCI runtime %d", _id);
|
||||
_init_state = being_initialized;
|
||||
|
||||
{
|
||||
MutexUnlocker unlock(JVMCI_lock);
|
||||
|
@ -759,6 +917,11 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {
|
|||
fatal("JNI exception during init");
|
||||
}
|
||||
}
|
||||
|
||||
if (!JVMCIENV->is_hotspot()) {
|
||||
JNIAccessMark jni(JVMCIENV, THREAD);
|
||||
JNIJVMCI::register_natives(jni.env());
|
||||
}
|
||||
create_jvmci_primitive_type(T_BOOLEAN, JVMCI_CHECK_EXIT_((void)0));
|
||||
create_jvmci_primitive_type(T_BYTE, JVMCI_CHECK_EXIT_((void)0));
|
||||
create_jvmci_primitive_type(T_CHAR, JVMCI_CHECK_EXIT_((void)0));
|
||||
|
@ -774,8 +937,8 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) {
|
|||
}
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
_being_initialized = false;
|
||||
_init_state = fully_initialized;
|
||||
TRACE_jvmci_1("initialized JVMCI runtime %d", _id);
|
||||
JVMCI_lock->notify_all();
|
||||
}
|
||||
|
||||
|
@ -817,8 +980,7 @@ JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) {
|
|||
return _HotSpotJVMCIRuntime_instance;
|
||||
}
|
||||
|
||||
|
||||
// private void CompilerToVM.registerNatives()
|
||||
// private static void CompilerToVM.registerNatives()
|
||||
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
|
||||
JNI_JVMCIENV(thread, env);
|
||||
|
||||
|
@ -854,16 +1016,17 @@ JVM_END
|
|||
|
||||
|
||||
void JVMCIRuntime::shutdown() {
|
||||
if (is_HotSpotJVMCIRuntime_initialized()) {
|
||||
_shutdown_called = true;
|
||||
|
||||
THREAD_JVMCIENV(JavaThread::current());
|
||||
if (_HotSpotJVMCIRuntime_instance.is_non_null()) {
|
||||
TRACE_jvmci_1("shutting down HotSpotJVMCIRuntime for JVMCI runtime %d", _id);
|
||||
JVMCIEnv __stack_jvmci_env__(JavaThread::current(), _HotSpotJVMCIRuntime_instance.is_hotspot(), __FILE__, __LINE__);
|
||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__;
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance);
|
||||
TRACE_jvmci_1("shut down HotSpotJVMCIRuntime for JVMCI runtime %d", _id);
|
||||
}
|
||||
}
|
||||
|
||||
void JVMCIRuntime::bootstrap_finished(TRAPS) {
|
||||
if (is_HotSpotJVMCIRuntime_initialized()) {
|
||||
if (_HotSpotJVMCIRuntime_instance.is_non_null()) {
|
||||
THREAD_JVMCIENV(JavaThread::current());
|
||||
JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV);
|
||||
}
|
||||
|
@ -1290,10 +1453,10 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c
|
|||
if (compiler->is_bootstrapping() && is_osr) {
|
||||
// no OSR compilations during bootstrap - the compiler is just too slow at this point,
|
||||
// and we know that there are no endless loops
|
||||
compile_state->set_failure(true, "No OSR during boostrap");
|
||||
compile_state->set_failure(true, "No OSR during bootstrap");
|
||||
return;
|
||||
}
|
||||
if (JVMCI::shutdown_called()) {
|
||||
if (JVMCI::in_shutdown()) {
|
||||
compile_state->set_failure(false, "Avoiding compilation during shutdown");
|
||||
return;
|
||||
}
|
||||
|
@ -1521,3 +1684,14 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool JVMCIRuntime::trace_prefix(int level) {
|
||||
Thread* thread = Thread::current_or_null_safe();
|
||||
if (thread != NULL) {
|
||||
ResourceMark rm;
|
||||
tty->print("JVMCITrace-%d[%s]:%*c", level, thread == NULL ? "?" : thread->name(), level, ' ');
|
||||
} else {
|
||||
tty->print("JVMCITrace-%d[?]:%*c", level, level, ' ');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@
|
|||
#include "jvmci/jvmci.hpp"
|
||||
#include "jvmci/jvmciExceptions.hpp"
|
||||
#include "jvmci/jvmciObject.hpp"
|
||||
#include "utilities/linkedlist.hpp"
|
||||
|
||||
class JVMCIEnv;
|
||||
class JVMCICompiler;
|
||||
class JVMCICompileState;
|
||||
class MetadataHandles;
|
||||
|
||||
// Encapsulates the JVMCI metadata for an nmethod.
|
||||
// JVMCINMethodData objects are inlined into nmethods
|
||||
|
@ -86,6 +88,7 @@ public:
|
|||
// A top level class that represents an initialized JVMCI runtime.
|
||||
// There is one instance of this class per HotSpotJVMCIRuntime object.
|
||||
class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
||||
friend class JVMCI;
|
||||
public:
|
||||
// Constants describing whether JVMCI wants to be able to adjust the compilation
|
||||
// level selected for a method by the VM compilation policy and if so, based on
|
||||
|
@ -97,12 +100,28 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||
};
|
||||
|
||||
private:
|
||||
volatile bool _being_initialized;
|
||||
volatile bool _initialized;
|
||||
|
||||
enum InitState {
|
||||
uninitialized,
|
||||
being_initialized,
|
||||
fully_initialized
|
||||
};
|
||||
|
||||
// Initialization state of this JVMCIRuntime.
|
||||
InitState _init_state;
|
||||
|
||||
JVMCIObject _HotSpotJVMCIRuntime_instance;
|
||||
|
||||
bool _shutdown_called;
|
||||
// Result of calling JNI_CreateJavaVM in the JVMCI shared library.
|
||||
// Must only be modified under JVMCI_lock.
|
||||
volatile JavaVM* _shared_library_javavm;
|
||||
|
||||
// The HotSpot heap based runtime will have an id of -1 and the
|
||||
// JVMCI shared library runtime will have an id of 0.
|
||||
int _id;
|
||||
|
||||
// Handles to Metadata objects.
|
||||
MetadataHandles* _metadata_handles;
|
||||
|
||||
JVMCIObject create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS);
|
||||
|
||||
|
@ -131,44 +150,74 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||
constantTag tag);
|
||||
|
||||
public:
|
||||
JVMCIRuntime() {
|
||||
_initialized = false;
|
||||
_being_initialized = false;
|
||||
_shutdown_called = false;
|
||||
}
|
||||
JVMCIRuntime(int id);
|
||||
|
||||
/**
|
||||
* Compute offsets and construct any state required before executing JVMCI code.
|
||||
*/
|
||||
int id() const { return _id; }
|
||||
|
||||
// Ensures that a JVMCI shared library JavaVM exists for this runtime.
|
||||
// If the JavaVM was created by this call, then the thread-local JNI
|
||||
// interface pointer for the JavaVM is returned otherwise NULL is returned.
|
||||
JNIEnv* init_shared_library_javavm();
|
||||
|
||||
// Determines if the JVMCI shared library JavaVM exists for this runtime.
|
||||
bool has_shared_library_javavm() { return _shared_library_javavm != NULL; }
|
||||
|
||||
// Copies info about the JVMCI shared library JavaVM associated with this
|
||||
// runtime into `info` as follows:
|
||||
// {
|
||||
// javaVM, // the {@code JavaVM*} value
|
||||
// javaVM->functions->reserved0,
|
||||
// javaVM->functions->reserved1,
|
||||
// javaVM->functions->reserved2
|
||||
// }
|
||||
void init_JavaVM_info(jlongArray info, JVMCI_TRAPS);
|
||||
|
||||
// Wrappers for calling Invocation Interface functions on the
|
||||
// JVMCI shared library JavaVM associated with this runtime.
|
||||
// These wrappers ensure all required thread state transitions are performed.
|
||||
jint AttachCurrentThread(JavaThread* thread, void **penv, void *args);
|
||||
jint AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args);
|
||||
jint DetachCurrentThread(JavaThread* thread);
|
||||
jint GetEnv(JavaThread* thread, void **penv, jint version);
|
||||
|
||||
// Compute offsets and construct any state required before executing JVMCI code.
|
||||
void initialize(JVMCIEnv* jvmciEnv);
|
||||
|
||||
/**
|
||||
* Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary
|
||||
*/
|
||||
// Allocation and management of JNI global object handles.
|
||||
jobject make_global(const Handle& obj);
|
||||
void destroy_global(jobject handle);
|
||||
bool is_global_handle(jobject handle);
|
||||
|
||||
// Allocation and management of metadata handles.
|
||||
jmetadata allocate_handle(const methodHandle& handle);
|
||||
jmetadata allocate_handle(const constantPoolHandle& handle);
|
||||
void release_handle(jmetadata handle);
|
||||
|
||||
// Gets the HotSpotJVMCIRuntime instance for this runtime,
|
||||
// initializing it first if necessary.
|
||||
JVMCIObject get_HotSpotJVMCIRuntime(JVMCI_TRAPS);
|
||||
|
||||
bool is_HotSpotJVMCIRuntime_initialized() {
|
||||
return _HotSpotJVMCIRuntime_instance.is_non_null();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
|
||||
*/
|
||||
// Gets the current HotSpotJVMCIRuntime instance for this runtime which
|
||||
// may be a "null" JVMCIObject value.
|
||||
JVMCIObject probe_HotSpotJVMCIRuntime() {
|
||||
return _HotSpotJVMCIRuntime_instance;
|
||||
}
|
||||
|
||||
// Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime()
|
||||
void initialize_JVMCI(JVMCI_TRAPS);
|
||||
|
||||
/**
|
||||
* Explicitly initialize HotSpotJVMCIRuntime itself
|
||||
*/
|
||||
// Explicitly initialize HotSpotJVMCIRuntime itself
|
||||
void initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS);
|
||||
|
||||
void call_getCompiler(TRAPS);
|
||||
|
||||
// Shuts down this runtime by calling HotSpotJVMCIRuntime.shutdown().
|
||||
void shutdown();
|
||||
|
||||
bool shutdown_called() {
|
||||
return _shutdown_called;
|
||||
}
|
||||
|
||||
void bootstrap_finished(TRAPS);
|
||||
|
||||
// Look up a klass by name from a particular class loader (the accessor's).
|
||||
|
@ -235,9 +284,7 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||
char* speculations,
|
||||
int speculations_len);
|
||||
|
||||
/**
|
||||
* Exits the VM due to an unexpected exception.
|
||||
*/
|
||||
// Exits the VM due to an unexpected exception.
|
||||
static void exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message);
|
||||
|
||||
static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear);
|
||||
|
@ -339,6 +386,11 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||
|
||||
// Test only function
|
||||
static jint test_deoptimize_call_int(JavaThread* thread, int value);
|
||||
|
||||
// Emits the following on tty:
|
||||
// "JVMCITrace-" <level> "[" <current thread name> "]:" <padding of width `level`>
|
||||
// Returns true.
|
||||
static bool trace_prefix(int level);
|
||||
};
|
||||
|
||||
// Tracing macros.
|
||||
|
@ -349,10 +401,11 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
|
|||
#define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else
|
||||
#define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else
|
||||
|
||||
#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print(PTR_FORMAT " JVMCITrace-1: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print(PTR_FORMAT " JVMCITrace-2: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print(PTR_FORMAT " JVMCITrace-3: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print(PTR_FORMAT " JVMCITrace-4: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print(PTR_FORMAT " JVMCITrace-5: ", p2i(JavaThread::current())), true))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_(n) if (!(JVMCITraceLevel >= n && JVMCIRuntime::trace_prefix(n))) ; else tty->print_cr
|
||||
#define TRACE_jvmci_1 TRACE_jvmci_(1)
|
||||
#define TRACE_jvmci_2 TRACE_jvmci_(2)
|
||||
#define TRACE_jvmci_3 TRACE_jvmci_(3)
|
||||
#define TRACE_jvmci_4 TRACE_jvmci_(4)
|
||||
#define TRACE_jvmci_5 TRACE_jvmci_(5)
|
||||
|
||||
#endif // SHARE_JVMCI_JVMCIRUNTIME_HPP
|
||||
|
|
|
@ -22,19 +22,17 @@
|
|||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jvmci/metadataHandleBlock.hpp"
|
||||
#include "jvmci/metadataHandles.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
|
||||
MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
|
||||
intptr_t MetadataHandleBlock::_free_list = 0;
|
||||
int MetadataHandleBlock::_allocate_before_rebuild = 0;
|
||||
|
||||
jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
|
||||
jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
|
||||
assert(obj->is_valid() && obj->is_metadata(), "must be");
|
||||
|
||||
if (_last == NULL) {
|
||||
if (_head == NULL) {
|
||||
// This is the first allocation.
|
||||
_last = this;
|
||||
_head = new MetadataHandleBlock();
|
||||
_last = _head;
|
||||
_num_blocks++;
|
||||
}
|
||||
|
||||
HandleRecord* handle = get_handle();
|
||||
|
@ -47,7 +45,7 @@ jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
|
|||
return (jmetadata) handle;
|
||||
}
|
||||
|
||||
// Check if unused block follow last
|
||||
// Check if an unused block follows last
|
||||
if (_last->_next != NULL) {
|
||||
// update last and retry
|
||||
_last = _last->_next;
|
||||
|
@ -59,20 +57,20 @@ jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
|
|||
rebuild_free_list(); // updates _allocate_before_rebuild counter
|
||||
} else {
|
||||
// Append new block
|
||||
// This can block, but the caller has a metadata handle around this object.
|
||||
_last->_next = allocate_block();
|
||||
_last->_next = new MetadataHandleBlock();
|
||||
_last = _last->_next;
|
||||
_allocate_before_rebuild--;
|
||||
_num_blocks++;
|
||||
}
|
||||
return allocate_metadata_handle(obj); // retry
|
||||
}
|
||||
|
||||
|
||||
void MetadataHandleBlock::rebuild_free_list() {
|
||||
void MetadataHandles::rebuild_free_list() {
|
||||
assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
|
||||
int free = 0;
|
||||
int blocks = 0;
|
||||
for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
|
||||
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
|
||||
for (int index = 0; index < current->_top; index++) {
|
||||
HandleRecord* handle = &(current->_handles)[index];
|
||||
if (handle->value() == NULL) {
|
||||
|
@ -82,34 +80,48 @@ void MetadataHandleBlock::rebuild_free_list() {
|
|||
}
|
||||
}
|
||||
// we should not rebuild free list if there are unused handles at the end
|
||||
assert(current->_top == block_size_in_handles, "just checking");
|
||||
assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
|
||||
blocks++;
|
||||
}
|
||||
assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
|
||||
assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
|
||||
// Heuristic: if more than half of the handles are NOT free we rebuild next time
|
||||
// as well, otherwise we append a corresponding number of new blocks before
|
||||
// attempting a free list rebuild again.
|
||||
int total = blocks * block_size_in_handles;
|
||||
int total = blocks * MetadataHandleBlock::block_size_in_handles;
|
||||
int extra = total - 2*free;
|
||||
if (extra > 0) {
|
||||
// Not as many free handles as we would like - compute number of new blocks to append
|
||||
_allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
|
||||
_allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
|
||||
}
|
||||
}
|
||||
|
||||
void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
|
||||
for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
|
||||
void MetadataHandles::clear() {
|
||||
_free_list = 0;
|
||||
_last = _head;
|
||||
if (_head != NULL) {
|
||||
for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) {
|
||||
block->_top = 0;
|
||||
}
|
||||
}
|
||||
_num_handles = 0;
|
||||
_num_free_handles = 0;
|
||||
}
|
||||
|
||||
void MetadataHandles::metadata_do(void f(Metadata*)) {
|
||||
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
|
||||
for (int index = 0; index < current->_top; index++) {
|
||||
HandleRecord* root = &(current->_handles)[index];
|
||||
Metadata* value = root->value();
|
||||
// traverse heap pointers only, not deleted handles or free list
|
||||
// pointers
|
||||
if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
|
||||
assert(value->is_valid(), "invalid metadata %s", get_name(index));
|
||||
assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
|
||||
f(value);
|
||||
}
|
||||
}
|
||||
// the next handle block is valid only if current block is full
|
||||
if (current->_top < block_size_in_handles) {
|
||||
if (current->_top < MetadataHandleBlock::block_size_in_handles) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -117,8 +129,8 @@ void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
|
|||
|
||||
// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by
|
||||
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
|
||||
void MetadataHandleBlock::do_unloading() {
|
||||
for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
|
||||
void MetadataHandles::do_unloading() {
|
||||
for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
|
||||
for (int index = 0; index < current->_top; index++) {
|
||||
HandleRecord* handle = &(current->_handles)[index];
|
||||
Metadata* value = handle->value();
|
||||
|
@ -152,7 +164,7 @@ void MetadataHandleBlock::do_unloading() {
|
|||
}
|
||||
}
|
||||
// the next handle block is valid only if current block is full
|
||||
if (current->_top < block_size_in_handles) {
|
||||
if (current->_top < MetadataHandleBlock::block_size_in_handles) {
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -21,8 +21,8 @@
|
|||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
|
||||
#define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
|
||||
#ifndef SHARE_JVMCI_METADATAHANDLES_HPP
|
||||
#define SHARE_JVMCI_METADATAHANDLES_HPP
|
||||
|
||||
#include "oops/constantPool.hpp"
|
||||
#include "oops/metadata.hpp"
|
||||
|
@ -72,22 +72,15 @@ struct _jmetadata {
|
|||
|
||||
typedef struct _jmetadata HandleRecord;
|
||||
typedef struct _jmetadata *jmetadata;
|
||||
class MetadataHandles;
|
||||
|
||||
// JVMCI maintains direct references to metadata. To make these references safe in the face of
|
||||
// class redefinition, they are held in handles so they can be scanned during GC. They are
|
||||
// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
|
||||
// passed back to the Java code which is responsible for setting the handle to NULL when it
|
||||
// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
|
||||
// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
|
||||
class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
|
||||
friend class MetadataHandles;
|
||||
private:
|
||||
enum SomeConstants {
|
||||
block_size_in_handles = 32, // Number of handles per handle block
|
||||
ptr_tag = 1,
|
||||
ptr_mask = ~((intptr_t)ptr_tag)
|
||||
block_size_in_handles = 32 // Number of handles per handle block
|
||||
};
|
||||
|
||||
|
||||
// Free handles always have their low bit set so those pointers can
|
||||
// be distinguished from handles which are in use. The last handle
|
||||
// on the free list has a NULL pointer with the tag bit set, so it's
|
||||
|
@ -98,12 +91,6 @@ class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
|
|||
int _top; // Index of next unused handle
|
||||
MetadataHandleBlock* _next; // Link to next block
|
||||
|
||||
// The following instance variables are only used by the first block in a chain.
|
||||
// Having two types of blocks complicates the code and the space overhead is negligible.
|
||||
static MetadataHandleBlock* _last; // Last block in use
|
||||
static intptr_t _free_list; // Handle free list
|
||||
static int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
|
||||
|
||||
MetadataHandleBlock() {
|
||||
_top = 0;
|
||||
_next = NULL;
|
||||
|
@ -121,20 +108,42 @@ class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
|
|||
return "<missing>";
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
static HandleRecord* get_free_handle() {
|
||||
assert(_free_list != 0, "should check before calling");
|
||||
// JVMCI maintains direct references to metadata. To make these references safe in the face of
|
||||
// class redefinition, they are held in handles so they can be scanned during GC. They are
|
||||
// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
|
||||
// passed back to the Java code which is responsible for setting the handle to NULL when it
|
||||
// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
|
||||
// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
|
||||
class MetadataHandles : public CHeapObj<mtJVMCI> {
|
||||
private:
|
||||
enum SomeConstants {
|
||||
ptr_tag = 1,
|
||||
ptr_mask = ~((intptr_t)ptr_tag)
|
||||
};
|
||||
|
||||
MetadataHandleBlock* _head; // First block
|
||||
MetadataHandleBlock* _last; // Last block in use
|
||||
intptr_t _free_list; // Handle free list
|
||||
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
|
||||
int _num_blocks; // Number of blocks
|
||||
int _num_handles;
|
||||
int _num_free_handles;
|
||||
|
||||
HandleRecord* get_free_handle() {
|
||||
HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
|
||||
_free_list = (ptr_mask & (intptr_t) (handle->value()));
|
||||
assert(_free_list != ptr_tag, "should be null");
|
||||
handle->set_value(NULL);
|
||||
_num_free_handles--;
|
||||
return handle;
|
||||
}
|
||||
|
||||
static HandleRecord* get_handle() {
|
||||
HandleRecord* get_handle() {
|
||||
assert(_last != NULL, "sanity");
|
||||
// Try last block
|
||||
if (_last->_top < block_size_in_handles) {
|
||||
if (_last->_top < MetadataHandleBlock::block_size_in_handles) {
|
||||
_num_handles++;
|
||||
return &(_last->_handles)[_last->_top++];
|
||||
} else if (_free_list != 0) {
|
||||
// Try free list
|
||||
|
@ -148,23 +157,39 @@ class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
|
|||
jmetadata allocate_metadata_handle(Metadata* metadata);
|
||||
|
||||
public:
|
||||
MetadataHandles() {
|
||||
_head = NULL;
|
||||
_last = NULL;
|
||||
_free_list = 0;
|
||||
_allocate_before_rebuild = 0;
|
||||
_num_blocks = 0;
|
||||
_num_handles = 0;
|
||||
_num_free_handles = 0;
|
||||
}
|
||||
|
||||
int num_handles() const { return _num_handles; }
|
||||
int num_free_handles() const { return _num_free_handles; }
|
||||
int num_blocks() const { return _num_blocks; }
|
||||
|
||||
jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); }
|
||||
jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
|
||||
|
||||
static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
|
||||
|
||||
// Adds `handle` to the free list in this block
|
||||
static void chain_free_list(HandleRecord* handle) {
|
||||
// Adds `handle` to the free list
|
||||
void chain_free_list(HandleRecord* handle) {
|
||||
handle->set_value((Metadata*) (ptr_tag | _free_list));
|
||||
#ifdef METADATA_TRACK_NAMES
|
||||
handle->set_name(NULL);
|
||||
#endif
|
||||
_free_list = (intptr_t) handle;
|
||||
_num_free_handles++;
|
||||
}
|
||||
|
||||
// Clears all handles without releasing any handle memory.
|
||||
void clear();
|
||||
|
||||
void metadata_do(void f(Metadata*));
|
||||
|
||||
void do_unloading();
|
||||
};
|
||||
|
||||
#endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
|
||||
#endif // SHARE_JVMCI_METADATAHANDLES_HPP
|
|
@ -65,8 +65,8 @@ final class HandleCleaner extends Cleaner {
|
|||
CompilerToVM.compilerToVM().deleteGlobalHandle(handle);
|
||||
} else {
|
||||
// Setting the target of a jmetadata handle to 0 enables
|
||||
// the handle to be reused. See MetadataHandleBlock in
|
||||
// jvmciRuntime.cpp for more info.
|
||||
// the handle to be reused. See MetadataHandles in
|
||||
// metadataHandles.hpp for more info.
|
||||
long value = UNSAFE.getLong(null, handle);
|
||||
UNSAFE.compareAndSetLong(null, handle, value, 0);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -37,6 +37,7 @@ import java.lang.invoke.MethodHandle;
|
|||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -210,6 +211,15 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
return o.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of recognized {@code "jvmci.*"} system properties. Entries not associated with an
|
||||
* {@link Option} have this object as their value.
|
||||
*/
|
||||
static final Map<String, Object> options = new HashMap<>();
|
||||
static {
|
||||
options.put("jvmci.class.path.append", options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of all supported JVMCI options.
|
||||
*/
|
||||
|
@ -245,7 +255,7 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
private final Class<?> type;
|
||||
@NativeImageReinitialize private Object value;
|
||||
private final Object defaultValue;
|
||||
private boolean isDefault;
|
||||
private boolean isDefault = true;
|
||||
private final String[] helpLines;
|
||||
|
||||
Option(Class<?> type, Object defaultValue, String... helpLines) {
|
||||
|
@ -253,12 +263,13 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
this.type = type;
|
||||
this.defaultValue = defaultValue;
|
||||
this.helpLines = helpLines;
|
||||
Object existing = options.put(getPropertyName(), this);
|
||||
assert existing == null : getPropertyName();
|
||||
}
|
||||
|
||||
@SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
|
||||
private Object getValue() {
|
||||
if (value == null) {
|
||||
String propertyValue = Services.getSavedProperty(getPropertyName());
|
||||
private void init(String propertyValue) {
|
||||
assert value == null : "cannot re-initialize " + name();
|
||||
if (propertyValue == null) {
|
||||
this.value = defaultValue == null ? NULL_VALUE : defaultValue;
|
||||
this.isDefault = true;
|
||||
|
@ -273,7 +284,16 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
this.isDefault = false;
|
||||
}
|
||||
}
|
||||
return value == NULL_VALUE ? null : value;
|
||||
|
||||
@SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum")
|
||||
private Object getValue() {
|
||||
if (value == NULL_VALUE) {
|
||||
return null;
|
||||
}
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,6 +354,61 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute string similarity based on Dice's coefficient.
|
||||
*
|
||||
* Ported from str_similar() in globals.cpp.
|
||||
*/
|
||||
static float stringSimiliarity(String str1, String str2) {
|
||||
int hit = 0;
|
||||
for (int i = 0; i < str1.length() - 1; ++i) {
|
||||
for (int j = 0; j < str2.length() - 1; ++j) {
|
||||
if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) {
|
||||
++hit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 2.0f * hit / (str1.length() + str2.length());
|
||||
}
|
||||
|
||||
private static final float FUZZY_MATCH_THRESHOLD = 0.7F;
|
||||
|
||||
/**
|
||||
* Parses all system properties starting with {@value #JVMCI_OPTION_PROPERTY_PREFIX} and
|
||||
* initializes the options based on their values.
|
||||
*/
|
||||
static void parse() {
|
||||
Map<String, String> savedProps = jdk.vm.ci.services.Services.getSavedProperties();
|
||||
for (Map.Entry<String, String> e : savedProps.entrySet()) {
|
||||
String name = e.getKey();
|
||||
if (name.startsWith(Option.JVMCI_OPTION_PROPERTY_PREFIX)) {
|
||||
Object value = options.get(name);
|
||||
if (value == null) {
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (String pn : options.keySet()) {
|
||||
float score = stringSimiliarity(pn, name);
|
||||
if (score >= FUZZY_MATCH_THRESHOLD) {
|
||||
matches.add(pn);
|
||||
}
|
||||
}
|
||||
Formatter msg = new Formatter();
|
||||
msg.format("Could not find option %s", name);
|
||||
if (!matches.isEmpty()) {
|
||||
msg.format("%nDid you mean one of the following?");
|
||||
for (String match : matches) {
|
||||
msg.format("%n %s=<value>", match);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(msg.toString());
|
||||
} else if (value instanceof Option) {
|
||||
Option option = (Option) value;
|
||||
option.init(e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static HotSpotJVMCIBackendFactory findFactory(String architecture) {
|
||||
|
@ -454,6 +529,9 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
System.setErr(vmLogStream);
|
||||
}
|
||||
|
||||
// Initialize the Option values.
|
||||
Option.parse();
|
||||
|
||||
String hostArchitecture = config.getHostArchitectureName();
|
||||
|
||||
HotSpotJVMCIBackendFactory factory;
|
||||
|
@ -712,11 +790,18 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
return hsResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guard to ensure shut down actions are performed at most once.
|
||||
*/
|
||||
private boolean isShutdown;
|
||||
|
||||
/**
|
||||
* Shuts down the runtime.
|
||||
*/
|
||||
@VMEntryPoint
|
||||
private void shutdown() throws Exception {
|
||||
private synchronized void shutdown() throws Exception {
|
||||
if (!isShutdown) {
|
||||
isShutdown = true;
|
||||
// Cleaners are normally only processed when a new Cleaner is
|
||||
// instantiated so process all remaining cleaners now.
|
||||
Cleaner.clean();
|
||||
|
@ -725,6 +810,7 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
vmEventListener.notifyShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify on completion of a bootstrap.
|
||||
|
@ -914,8 +1000,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
* </pre>
|
||||
*
|
||||
* The implementation of the native {@code JCompile.compile0} method would be in the JVMCI
|
||||
* shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0}
|
||||
* implementation will be exported as the following JNI-compatible symbol:
|
||||
* shared library that contains the JVMCI compiler. The {@code JCompile.compile0} implementation
|
||||
* must be exported as the following JNI-compatible symbol:
|
||||
*
|
||||
* <pre>
|
||||
* Java_com_jcompile_JCompile_compile0
|
||||
|
@ -926,9 +1012,18 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
|
||||
*
|
||||
*
|
||||
* @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
|
||||
* the Java VM in the JVMCI shared library, and the remaining values are the first 3
|
||||
* pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
|
||||
* @return info about the Java VM in the JVMCI shared library {@code JavaVM*}. The info is
|
||||
* encoded in a long array as follows:
|
||||
*
|
||||
* <pre>
|
||||
* long[] info = {
|
||||
* javaVM, // the {@code JavaVM*} value
|
||||
* javaVM->functions->reserved0,
|
||||
* javaVM->functions->reserved1,
|
||||
* javaVM->functions->reserved2
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @throws NullPointerException if {@code clazz == null}
|
||||
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||
* {@code -XX:-UseJVMCINativeLibrary})
|
||||
|
@ -1017,6 +1112,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
|||
* {@code -XX:-UseJVMCINativeLibrary})
|
||||
* @throws IllegalStateException if the peer runtime has not been initialized or there is an
|
||||
* error while trying to attach the thread
|
||||
* @throws ArrayIndexOutOfBoundsException if {@code javaVMInfo} is non-null and is shorter than
|
||||
* the length of the array returned by {@link #registerNativeMethods}
|
||||
*/
|
||||
public boolean attachCurrentThread(boolean asDaemon) {
|
||||
return compilerToVm.attachCurrentThread(asDaemon);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue