< prev index next >
src/hotspot/share/jvmci/jvmciRuntime.cpp
Print this page
@@ -21,21 +21,24 @@
* questions.
*/
#include "precompiled.hpp"
#include "compiler/compileBroker.hpp"
+#include "gc/shared/oopStorage.inline.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 "oops/constantPool.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/frame.inline.hpp"
+#include "runtime/jniHandles.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1ThreadLocalData.hpp"
#endif // INCLUDE_G1GC
@@ -711,10 +714,162 @@
HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0);
}
}
}
+OopStorage* JVMCIRuntime::create_object_handles(int id) {
+ FormatBuffer<> name("JVMCI %s Runtime %d Global Oop Handles", id == -1 ? "Java" : "Shared Library", id);
+ return new OopStorage(name, JVMCIGlobalAlloc_lock, JVMCIGlobalActive_lock);
+}
+
+JVMCIRuntime::JVMCIRuntime(int id) {
+ _init_state = uninitialized;
+ _shared_library_javavm = NULL;
+ _id = id;
+ _object_handles = new OopStorage(id == -1 ? "JVMCI Java Runtime Global Oop Handles" :
+ "JVMCI Shared Library Runtime Global Oop Handles",
+ JVMCIGlobalAlloc_lock,
+ JVMCIGlobalActive_lock);
+ _metadata_handles = new MetadataHandles();
+ TRACE_jvmci_1("created new JVMCI runtime %d (" PTR_FORMAT ")", id, p2i(this));
+}
+
+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");
+ }
+ 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);
+}
+
+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) {
JVMCI_THROW_MSG(InternalError, "JVMCI has already been enabled in the JVMCI shared library");
}
@@ -724,33 +879,36 @@
// This should only be called in the context of the JVMCI class being initialized
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);
HandleMark hm;
@@ -765,10 +923,15 @@
if (jni()->ExceptionCheck()) {
jni()->ExceptionDescribe();
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));
create_jvmci_primitive_type(T_SHORT, JVMCI_CHECK_EXIT_((void)0));
create_jvmci_primitive_type(T_INT, JVMCI_CHECK_EXIT_((void)0));
@@ -780,12 +943,12 @@
if (!JVMCIENV->is_hotspot()) {
JVMCIENV->copy_saved_properties();
}
}
- _initialized = true;
- _being_initialized = false;
+ _init_state = fully_initialized;
+ TRACE_jvmci_1("initialized JVMCI runtime %d", _id);
JVMCI_lock->notify_all();
}
JVMCIObject JVMCIRuntime::create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS) {
Thread* THREAD = Thread::current();
@@ -823,12 +986,11 @@
initialize(JVMCIENV);
initialize_JVMCI(JVMCI_CHECK_(JVMCIObject()));
return _HotSpotJVMCIRuntime_instance;
}
-
-// private void CompilerToVM.registerNatives()
+// private static void CompilerToVM.registerNatives()
JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
#ifdef _LP64
#ifndef TARGET_ARCH_sparc
uintptr_t heap_end = (uintptr_t) Universe::heap()->reserved_region().end();
@@ -871,20 +1033,21 @@
}
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);
}
}
@@ -1320,14 +1483,14 @@
bool is_osr = entry_bci != InvocationEntryBci;
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;
}
HandleMark hm;
@@ -1548,5 +1711,16 @@
nm->post_compiled_method_load_event();
}
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;
+}
< prev index next >