mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8223332: Update JVMCI
Reviewed-by: never, dnsimon
This commit is contained in:
parent
29a4ad9a87
commit
72f082e925
30 changed files with 1038 additions and 345 deletions
|
@ -70,7 +70,6 @@
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
#include "jvmci/jvmciEnv.hpp"
|
#include "jvmci/jvmciEnv.hpp"
|
||||||
#include "jvmci/jvmciRuntime.hpp"
|
#include "jvmci/jvmciRuntime.hpp"
|
||||||
#include "runtime/vframe.hpp"
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
#include "opto/c2compiler.hpp"
|
#include "opto/c2compiler.hpp"
|
||||||
|
@ -1063,12 +1062,13 @@ void CompileBroker::compile_method_base(const methodHandle& method,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
|
if (UseJVMCICompiler && blocking) {
|
||||||
// Don't allow blocking compiles for requests triggered by JVMCI.
|
// Don't allow blocking compiles for requests triggered by JVMCI.
|
||||||
if (thread->is_Compiler_thread()) {
|
if (thread->is_Compiler_thread()) {
|
||||||
blocking = false;
|
blocking = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!UseJVMCINativeLibrary) {
|
||||||
// Don't allow blocking compiles if inside a class initializer or while performing class loading
|
// Don't allow blocking compiles if inside a class initializer or while performing class loading
|
||||||
vframeStream vfst((JavaThread*) thread);
|
vframeStream vfst((JavaThread*) thread);
|
||||||
for (; !vfst.at_end(); vfst.next()) {
|
for (; !vfst.at_end(); vfst.next()) {
|
||||||
|
@ -1079,6 +1079,7 @@ void CompileBroker::compile_method_base(const methodHandle& method,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't allow blocking compilation requests to JVMCI
|
// Don't allow blocking compilation requests to JVMCI
|
||||||
// if JVMCI itself is not yet initialized
|
// if JVMCI itself is not yet initialized
|
||||||
|
@ -2063,7 +2064,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||||
compilable = ciEnv::MethodCompilable_never;
|
compilable = ciEnv::MethodCompilable_never;
|
||||||
} else {
|
} else {
|
||||||
JVMCICompileState compile_state(task, system_dictionary_modification_counter);
|
JVMCICompileState compile_state(task, system_dictionary_modification_counter);
|
||||||
JVMCIEnv env(&compile_state, __FILE__, __LINE__);
|
JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__);
|
||||||
methodHandle method(thread, target_handle);
|
methodHandle method(thread, target_handle);
|
||||||
env.runtime()->compile_method(&env, jvmci, method, osr_bci);
|
env.runtime()->compile_method(&env, jvmci, method, osr_bci);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -160,13 +160,14 @@ class JavaArgumentUnboxer : public SignatureIterator {
|
||||||
};
|
};
|
||||||
|
|
||||||
class JNIHandleMark : public StackObj {
|
class JNIHandleMark : public StackObj {
|
||||||
|
JavaThread* _thread;
|
||||||
public:
|
public:
|
||||||
JNIHandleMark() { push_jni_handle_block(); }
|
JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); }
|
||||||
~JNIHandleMark() { pop_jni_handle_block(); }
|
~JNIHandleMark() { pop_jni_handle_block(_thread); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void push_jni_handle_block();
|
static void push_jni_handle_block(JavaThread* thread);
|
||||||
static void pop_jni_handle_block();
|
static void pop_jni_handle_block(JavaThread* thread);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
|
#endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
|
||||||
|
|
|
@ -129,11 +129,10 @@ void JVMCIEnv::copy_saved_properties() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEnv* JVMCIEnv::attach_shared_library() {
|
JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) {
|
||||||
if (_shared_library_javavm == NULL) {
|
if (_shared_library_javavm == NULL) {
|
||||||
MutexLocker locker(JVMCI_lock);
|
MutexLocker locker(JVMCI_lock);
|
||||||
if (_shared_library_javavm == NULL) {
|
if (_shared_library_javavm == NULL) {
|
||||||
|
|
||||||
char path[JVM_MAXPATHLEN];
|
char path[JVM_MAXPATHLEN];
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
if (JVMCILibPath != NULL) {
|
if (JVMCILibPath != NULL) {
|
||||||
|
@ -179,48 +178,68 @@ JNIEnv* JVMCIEnv::attach_shared_library() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JNIEnv* env;
|
|
||||||
if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) {
|
|
||||||
guarantee(env != NULL, "missing env");
|
|
||||||
return env;
|
|
||||||
}
|
|
||||||
fatal("Error attaching current thread to JVMCI shared library JNI interface");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) {
|
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.
|
// By default there is only one runtime which is the compiler runtime.
|
||||||
_runtime = JVMCI::compiler_runtime();
|
_runtime = JVMCI::compiler_runtime();
|
||||||
|
_env = NULL;
|
||||||
|
_pop_frame_on_close = false;
|
||||||
|
_detach_on_close = false;
|
||||||
if (!UseJVMCINativeLibrary) {
|
if (!UseJVMCINativeLibrary) {
|
||||||
// In HotSpot mode, JNI isn't used at all.
|
// In HotSpot mode, JNI isn't used at all.
|
||||||
_is_hotspot = true;
|
_is_hotspot = true;
|
||||||
_env = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent_env != NULL) {
|
if (parent_env != NULL) {
|
||||||
// If the parent JNI environment is non-null then figure out whether it
|
// If the parent JNI environment is non-null then figure out whether it
|
||||||
// is a HotSpot or shared library JNIEnv and set the state appropriately.
|
// is a HotSpot or shared library JNIEnv and set the state appropriately.
|
||||||
JavaThread* thread = JavaThread::current();
|
_is_hotspot = thread->jni_environment() == parent_env;
|
||||||
if (thread->jni_environment() == parent_env) {
|
if (_is_hotspot) {
|
||||||
// Select the Java runtime
|
// Select the Java runtime
|
||||||
_runtime = JVMCI::java_runtime();
|
_runtime = JVMCI::java_runtime();
|
||||||
_is_hotspot = true;
|
|
||||||
_env = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_env = parent_env;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Running in JVMCI shared library mode so get a shared library JNIEnv
|
// Running in JVMCI shared library mode so ensure the shared library
|
||||||
|
// is loaded and initialized and get a shared library JNIEnv
|
||||||
_is_hotspot = false;
|
_is_hotspot = false;
|
||||||
_env = attach_shared_library();
|
_env = init_shared_library(thread);
|
||||||
assert(parent_env == NULL || _env == parent_env, "must be");
|
|
||||||
|
|
||||||
if (parent_env == NULL) {
|
if (_env != NULL) {
|
||||||
// There is no parent shared library JNI env so push
|
// Creating the JVMCI shared library VM also attaches the current thread
|
||||||
// a JNI local frame to release all local handles in
|
_detach_on_close = true;
|
||||||
// this JVMCIEnv scope when it's closed.
|
} else {
|
||||||
|
_shared_library_javavm->GetEnv((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
|
||||||
|
// pushed a local JNI frame. As such, we use a new JNI local
|
||||||
|
// frame in this scope to ensure local JNI refs are collected
|
||||||
|
// in a timely manner after leaving this scope.
|
||||||
|
_env = parent_env;
|
||||||
|
} else {
|
||||||
|
ResourceMark rm; // Thread name is resource allocated
|
||||||
|
JavaVMAttachArgs attach_args;
|
||||||
|
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) {
|
||||||
|
fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
|
||||||
|
}
|
||||||
|
_detach_on_close = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_env != NULL, "missing env");
|
||||||
assert(_throw_to_caller == false, "must be");
|
assert(_throw_to_caller == false, "must be");
|
||||||
|
|
||||||
JNIAccessMark jni(this);
|
JNIAccessMark jni(this);
|
||||||
jint result = _env->PushLocalFrame(32);
|
jint result = _env->PushLocalFrame(32);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
|
@ -228,36 +247,38 @@ void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) {
|
||||||
jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
|
jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
|
||||||
JVMCIRuntime::exit_on_pending_exception(this, message);
|
JVMCIRuntime::exit_on_pending_exception(this, message);
|
||||||
}
|
}
|
||||||
}
|
_pop_frame_on_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line):
|
JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
|
||||||
_throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
|
_throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
|
||||||
init_env_mode_runtime(NULL);
|
init_env_mode_runtime(thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
|
JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
|
||||||
_throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
|
_throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
|
||||||
init_env_mode_runtime(NULL);
|
init_env_mode_runtime(thread, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line):
|
JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
|
||||||
_throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
|
_throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
|
||||||
init_env_mode_runtime(parent_env);
|
init_env_mode_runtime(thread, parent_env);
|
||||||
assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
|
assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
|
||||||
}
|
}
|
||||||
|
|
||||||
void JVMCIEnv::init(bool is_hotspot, const char* file, int line) {
|
void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
|
||||||
_compile_state = NULL;
|
_compile_state = NULL;
|
||||||
_throw_to_caller = false;
|
_throw_to_caller = false;
|
||||||
_file = file;
|
_file = file;
|
||||||
_line = line;
|
_line = line;
|
||||||
if (is_hotspot) {
|
if (is_hotspot) {
|
||||||
_env = NULL;
|
_env = NULL;
|
||||||
|
_pop_frame_on_close = false;
|
||||||
|
_detach_on_close = false;
|
||||||
_is_hotspot = true;
|
_is_hotspot = true;
|
||||||
_runtime = JVMCI::java_runtime();
|
_runtime = JVMCI::java_runtime();
|
||||||
} else {
|
} else {
|
||||||
init_env_mode_runtime(NULL);
|
init_env_mode_runtime(thread, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +345,7 @@ JVMCIEnv::~JVMCIEnv() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!is_hotspot()) {
|
if (_pop_frame_on_close) {
|
||||||
// Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
|
// Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
|
||||||
JNIAccessMark jni(this);
|
JNIAccessMark jni(this);
|
||||||
jni()->PopLocalFrame(NULL);
|
jni()->PopLocalFrame(NULL);
|
||||||
|
@ -335,6 +356,10 @@ JVMCIEnv::~JVMCIEnv() {
|
||||||
jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
|
jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
|
||||||
JVMCIRuntime::exit_on_pending_exception(this, message);
|
JVMCIRuntime::exit_on_pending_exception(this, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_detach_on_close) {
|
||||||
|
get_shared_library_javavm()->DetachCurrentThread();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,26 +488,38 @@ void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes) {
|
void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
|
||||||
if (size_in_bytes == 0) {
|
if (length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (is_hotspot()) {
|
if (is_hotspot()) {
|
||||||
memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes);
|
memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
|
||||||
} else {
|
} else {
|
||||||
JNIAccessMark jni(this);
|
JNIAccessMark jni(this);
|
||||||
jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest);
|
jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) {
|
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
|
||||||
if (size_in_bytes == 0) {
|
if (length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (is_hotspot()) {
|
if (is_hotspot()) {
|
||||||
memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes);
|
memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
|
||||||
} else {
|
} else {
|
||||||
JNIAccessMark jni(this);
|
JNIAccessMark jni(this);
|
||||||
jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src);
|
jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
|
||||||
|
if (length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_hotspot()) {
|
||||||
|
memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
|
||||||
|
} else {
|
||||||
|
JNIAccessMark jni(this);
|
||||||
|
jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,6 +649,8 @@ DO_THROW(NullPointerException)
|
||||||
DO_THROW(IllegalArgumentException)
|
DO_THROW(IllegalArgumentException)
|
||||||
DO_THROW(InvalidInstalledCodeException)
|
DO_THROW(InvalidInstalledCodeException)
|
||||||
DO_THROW(UnsatisfiedLinkError)
|
DO_THROW(UnsatisfiedLinkError)
|
||||||
|
DO_THROW(UnsupportedOperationException)
|
||||||
|
DO_THROW(ClassNotFoundException)
|
||||||
|
|
||||||
#undef DO_THROW
|
#undef DO_THROW
|
||||||
|
|
||||||
|
@ -888,7 +927,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci,
|
||||||
return JVMCIObject();
|
return JVMCIObject();
|
||||||
}
|
}
|
||||||
jobject file_name = NULL;
|
jobject file_name = NULL;
|
||||||
if (file_name != NULL) {
|
if (file_name_sym != NULL) {
|
||||||
file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
|
file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
|
||||||
if (jni()->ExceptionCheck()) {
|
if (jni()->ExceptionCheck()) {
|
||||||
return JVMCIObject();
|
return JVMCIObject();
|
||||||
|
@ -1323,14 +1362,15 @@ Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
|
||||||
assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
|
assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
|
||||||
oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
|
oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
|
||||||
return Handle(THREAD, obj);
|
return Handle(THREAD, obj);
|
||||||
} else {
|
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
|
||||||
assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type");
|
|
||||||
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
|
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
|
||||||
oop result = resolve_handle(object_handle);
|
oop result = resolve_handle(object_handle);
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
|
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
|
||||||
}
|
}
|
||||||
return Handle(THREAD, result);
|
return Handle(THREAD, result);
|
||||||
|
} else {
|
||||||
|
JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,15 +36,6 @@ class JVMCIPrimitiveArray;
|
||||||
class JVMCICompiler;
|
class JVMCICompiler;
|
||||||
class JVMCIRuntime;
|
class JVMCIRuntime;
|
||||||
|
|
||||||
// Bring the JVMCI compiler thread into the VM state.
|
|
||||||
#define JVMCI_VM_ENTRY_MARK \
|
|
||||||
JavaThread* thread = JavaThread::current(); \
|
|
||||||
ThreadInVMfromNative __tiv(thread); \
|
|
||||||
ResetNoHandleMark rnhm; \
|
|
||||||
HandleMarkCleaner __hm(thread); \
|
|
||||||
Thread* THREAD = thread; \
|
|
||||||
debug_only(VMNativeEntryWrapper __vew;)
|
|
||||||
|
|
||||||
#define JVMCI_EXCEPTION_CONTEXT \
|
#define JVMCI_EXCEPTION_CONTEXT \
|
||||||
JavaThread* thread=JavaThread::current(); \
|
JavaThread* thread=JavaThread::current(); \
|
||||||
Thread* THREAD = thread;
|
Thread* THREAD = thread;
|
||||||
|
@ -154,19 +145,20 @@ class JVMCIEnv : public ResourceObj {
|
||||||
static void* _shared_library_handle; // result of 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
|
static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
|
||||||
|
|
||||||
// Attaches the current thread to the JavaVM in the shared library,
|
// Initializes the shared library JavaVM if not already initialized.
|
||||||
// initializing the shared library VM first if necessary.
|
// Returns the JNI interface pointer for the current thread
|
||||||
// Returns the JNI interface pointer of the current thread.
|
// if initialization was performed by this call, NULL if
|
||||||
// The _shared_library_* fields are initialized by the first
|
// initialization was performed by a previous call.
|
||||||
// call to this method.
|
static JNIEnv* init_shared_library(JavaThread* thread);
|
||||||
static JNIEnv* attach_shared_library();
|
|
||||||
|
|
||||||
// Initializes the _env, _mode and _runtime fields.
|
// Initializes the _env, _mode and _runtime fields.
|
||||||
void init_env_mode_runtime(JNIEnv* parent_env);
|
void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env);
|
||||||
|
|
||||||
void init(bool is_hotspot, const char* file, int line);
|
void init(JavaThread* thread, bool is_hotspot, const char* file, int line);
|
||||||
|
|
||||||
JNIEnv* _env; // JNI env for calling into shared library
|
JNIEnv* _env; // JNI env for calling into shared library
|
||||||
|
bool _pop_frame_on_close; // Must pop frame on close?
|
||||||
|
bool _detach_on_close; // Must detach on close?
|
||||||
JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime
|
JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime
|
||||||
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
|
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
|
||||||
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
|
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
|
||||||
|
@ -185,12 +177,12 @@ public:
|
||||||
// scope closes so that it will be propagated back to Java.
|
// scope closes so that it will be propagated back to Java.
|
||||||
// The JVMCIEnv destructor translates the exception object for the
|
// The JVMCIEnv destructor translates the exception object for the
|
||||||
// Java runtime if necessary.
|
// Java runtime if necessary.
|
||||||
JVMCIEnv(JNIEnv* env, const char* file, int line);
|
JVMCIEnv(JavaThread* thread, JNIEnv* env, const char* file, int line);
|
||||||
|
|
||||||
// Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
|
// Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
|
||||||
// An exception occurring within the scope must not be propagated back to
|
// An exception occurring within the scope must not be propagated back to
|
||||||
// the CompileBroker.
|
// the CompileBroker.
|
||||||
JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line);
|
JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line);
|
||||||
|
|
||||||
// Opens a JNIEnv scope for a call from within the VM. An exception occurring
|
// Opens a JNIEnv scope for a call from within the VM. An exception occurring
|
||||||
// within the scope must not be propagated back to the caller.
|
// within the scope must not be propagated back to the caller.
|
||||||
|
@ -198,20 +190,20 @@ public:
|
||||||
|
|
||||||
// Opens a JNIEnv scope for accessing `for_object`. An exception occurring
|
// Opens a JNIEnv scope for accessing `for_object`. An exception occurring
|
||||||
// within the scope must not be propagated back to the caller.
|
// within the scope must not be propagated back to the caller.
|
||||||
JVMCIEnv(JVMCIObject for_object, const char* file, int line) {
|
JVMCIEnv(JavaThread* thread, JVMCIObject for_object, const char* file, int line) {
|
||||||
// A JNI call to access an object in the shared library heap
|
// A JNI call to access an object in the shared library heap
|
||||||
// can block or take a long time so do not allow such access
|
// can block or take a long time so do not allow such access
|
||||||
// on the VM thread.
|
// on the VM thread.
|
||||||
assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
|
assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
|
||||||
"cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
|
"cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
|
||||||
init(for_object.is_hotspot(), file, line);
|
init(thread, for_object.is_hotspot(), file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
|
// Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
|
||||||
// otherwise for the shared library runtime. An exception occurring
|
// otherwise for the shared library runtime. An exception occurring
|
||||||
// within the scope must not be propagated back to the caller.
|
// within the scope must not be propagated back to the caller.
|
||||||
JVMCIEnv(bool is_hotspot, const char* file, int line) {
|
JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) {
|
||||||
init(is_hotspot, file, line);
|
init(thread, is_hotspot, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
~JVMCIEnv();
|
~JVMCIEnv();
|
||||||
|
@ -247,8 +239,10 @@ public:
|
||||||
long get_long_at(JVMCIPrimitiveArray array, int index);
|
long get_long_at(JVMCIPrimitiveArray array, int index);
|
||||||
void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
|
void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
|
||||||
|
|
||||||
void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes);
|
void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length);
|
||||||
void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes);
|
void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length);
|
||||||
|
|
||||||
|
void copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length);
|
||||||
|
|
||||||
JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
|
JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
|
||||||
|
|
||||||
|
@ -323,6 +317,8 @@ public:
|
||||||
DO_THROW(IllegalArgumentException)
|
DO_THROW(IllegalArgumentException)
|
||||||
DO_THROW(InvalidInstalledCodeException)
|
DO_THROW(InvalidInstalledCodeException)
|
||||||
DO_THROW(UnsatisfiedLinkError)
|
DO_THROW(UnsatisfiedLinkError)
|
||||||
|
DO_THROW(UnsupportedOperationException)
|
||||||
|
DO_THROW(ClassNotFoundException)
|
||||||
|
|
||||||
#undef DO_THROW
|
#undef DO_THROW
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ class JVMCIEnv;
|
||||||
#define JVMCIENV __jvmci_env__
|
#define JVMCIENV __jvmci_env__
|
||||||
#define JVMCI_TRAPS JVMCIEnv* JVMCIENV
|
#define JVMCI_TRAPS JVMCIEnv* JVMCIENV
|
||||||
|
|
||||||
#define JNI_JVMCIENV(env) \
|
#define JNI_JVMCIENV(thread, env) \
|
||||||
JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__); \
|
JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__); \
|
||||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
|
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
|
||||||
|
|
||||||
#define THREAD_JVMCIENV(thread) \
|
#define THREAD_JVMCIENV(thread) \
|
||||||
|
|
|
@ -356,6 +356,43 @@ extern "C" {
|
||||||
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
|
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dumps symbols for public <init>() and <init>(String) methods of
|
||||||
|
// non-abstract Throwable subtypes known by the VM. This is to
|
||||||
|
// support the use of reflection in jdk.vm.ci.hotspot.TranslatedException.create().
|
||||||
|
class ThrowableInitDumper : public SymbolClosure {
|
||||||
|
private:
|
||||||
|
fileStream* _st;
|
||||||
|
public:
|
||||||
|
ThrowableInitDumper(fileStream* st) { _st = st; }
|
||||||
|
void do_symbol(Symbol** p) {
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
Symbol* name = *p;
|
||||||
|
if (name == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Klass* k = SystemDictionary::resolve_or_null(name, CHECK_EXIT);
|
||||||
|
if (k != NULL && k->is_instance_klass()) {
|
||||||
|
InstanceKlass* iklass = InstanceKlass::cast(k);
|
||||||
|
if (iklass->is_subclass_of(SystemDictionary::Throwable_klass()) && iklass->is_public() && !iklass->is_abstract()) {
|
||||||
|
const char* class_name = NULL;
|
||||||
|
Array<Method*>* methods = iklass->methods();
|
||||||
|
for (int i = 0; i < methods->length(); i++) {
|
||||||
|
Method* m = methods->at(i);
|
||||||
|
if (m->name() == vmSymbols::object_initializer_name() &&
|
||||||
|
m->is_public() &&
|
||||||
|
(m->signature() == vmSymbols::void_method_signature() || m->signature() == vmSymbols::string_void_signature())) {
|
||||||
|
if (class_name == NULL) {
|
||||||
|
class_name = name->as_C_string();
|
||||||
|
_st->print_cr("class %s", class_name);
|
||||||
|
}
|
||||||
|
_st->print_cr("method %s %s %s", class_name, m->name()->as_C_string(), m->signature()->as_C_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
|
#define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
|
||||||
/**
|
/**
|
||||||
* Initializes the JNI method and field ids used in JNIJVMCI.
|
* Initializes the JNI method and field ids used in JNIJVMCI.
|
||||||
|
@ -441,6 +478,8 @@ void JNIJVMCI::initialize_ids(JNIEnv* env) {
|
||||||
fileStream* st = JVMCIGlobals::get_jni_config_file();
|
fileStream* st = JVMCIGlobals::get_jni_config_file();
|
||||||
|
|
||||||
DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
|
DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
|
||||||
|
ThrowableInitDumper dumper(st);
|
||||||
|
vmSymbols::symbols_do(&dumper);
|
||||||
|
|
||||||
st->flush();
|
st->flush();
|
||||||
tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
|
tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
|
||||||
|
|
|
@ -381,12 +381,18 @@
|
||||||
start_class(InternalError, java_lang_InternalError) \
|
start_class(InternalError, java_lang_InternalError) \
|
||||||
jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \
|
jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \
|
||||||
end_class \
|
end_class \
|
||||||
|
start_class(ClassNotFoundException, java_lang_ClassNotFoundException) \
|
||||||
|
jvmci_constructor(ClassNotFoundException, "(Ljava/lang/String;)V") \
|
||||||
|
end_class \
|
||||||
start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException) \
|
start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException) \
|
||||||
jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \
|
jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \
|
||||||
end_class \
|
end_class \
|
||||||
start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError) \
|
start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError) \
|
||||||
jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V") \
|
jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V") \
|
||||||
end_class \
|
end_class \
|
||||||
|
start_class(UnsupportedOperationException, java_lang_UnsupportedOperationException) \
|
||||||
|
jvmci_constructor(UnsupportedOperationException, "(Ljava/lang/String;)V") \
|
||||||
|
end_class \
|
||||||
start_class(StackTraceElement, java_lang_StackTraceElement) \
|
start_class(StackTraceElement, java_lang_StackTraceElement) \
|
||||||
object_field(StackTraceElement, declaringClass, "Ljava/lang/String;") \
|
object_field(StackTraceElement, declaringClass, "Ljava/lang/String;") \
|
||||||
object_field(StackTraceElement, methodName, "Ljava/lang/String;") \
|
object_field(StackTraceElement, methodName, "Ljava/lang/String;") \
|
||||||
|
|
|
@ -655,7 +655,7 @@ JRT_END
|
||||||
|
|
||||||
// private static JVMCIRuntime JVMCI.initializeRuntime()
|
// private static JVMCIRuntime JVMCI.initializeRuntime()
|
||||||
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
||||||
JNI_JVMCIENV(env);
|
JNI_JVMCIENV(thread, env);
|
||||||
if (!EnableJVMCI) {
|
if (!EnableJVMCI) {
|
||||||
JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
|
JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
|
||||||
}
|
}
|
||||||
|
@ -877,7 +877,7 @@ JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass))
|
||||||
fatal("check TLAB allocation code for address space conflicts");
|
fatal("check TLAB allocation code for address space conflicts");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JNI_JVMCIENV(env);
|
JNI_JVMCIENV(thread, env);
|
||||||
|
|
||||||
if (!EnableJVMCI) {
|
if (!EnableJVMCI) {
|
||||||
JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
|
JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
|
||||||
|
@ -1353,6 +1353,10 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c
|
||||||
compile_state->set_failure(true, "No OSR during boostrap");
|
compile_state->set_failure(true, "No OSR during boostrap");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (JVMCI::shutdown_called()) {
|
||||||
|
compile_state->set_failure(false, "Avoiding compilation during shutdown");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
|
JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
|
||||||
|
|
|
@ -83,7 +83,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
|
||||||
}
|
}
|
||||||
FLAG_SET_DEFAULT(EnableJVMCI, true);
|
FLAG_SET_DEFAULT(EnableJVMCI, true);
|
||||||
if (BootstrapJVMCI && UseJVMCINativeLibrary) {
|
if (BootstrapJVMCI && UseJVMCINativeLibrary) {
|
||||||
jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary");
|
jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,10 @@
|
||||||
"Prints properties used by the JVMCI compiler and exits") \
|
"Prints properties used by the JVMCI compiler and exits") \
|
||||||
\
|
\
|
||||||
experimental(bool, BootstrapJVMCI, false, \
|
experimental(bool, BootstrapJVMCI, false, \
|
||||||
"Bootstrap JVMCI before running Java main method") \
|
"Bootstrap JVMCI before running Java main method. This " \
|
||||||
|
"initializes the compile queue with a small set of methods " \
|
||||||
|
"and processes the queue until it is empty. Combining this with " \
|
||||||
|
"-XX:-TieredCompilation makes JVMCI compile more of itself.") \
|
||||||
\
|
\
|
||||||
experimental(bool, EagerJVMCI, false, \
|
experimental(bool, EagerJVMCI, false, \
|
||||||
"Force eager JVMCI initialization") \
|
"Force eager JVMCI initialization") \
|
||||||
|
|
|
@ -246,6 +246,10 @@
|
||||||
\
|
\
|
||||||
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \
|
||||||
\
|
\
|
||||||
|
volatile_nonstatic_field(ObjectMonitor, _cxq, ObjectWaiter*) \
|
||||||
|
volatile_nonstatic_field(ObjectMonitor, _EntryList, ObjectWaiter*) \
|
||||||
|
volatile_nonstatic_field(ObjectMonitor, _succ, Thread*) \
|
||||||
|
\
|
||||||
volatile_nonstatic_field(oopDesc, _mark, markOop) \
|
volatile_nonstatic_field(oopDesc, _mark, markOop) \
|
||||||
volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \
|
volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \
|
||||||
\
|
\
|
||||||
|
@ -347,6 +351,7 @@
|
||||||
declare_toplevel_type(JVMCIEnv) \
|
declare_toplevel_type(JVMCIEnv) \
|
||||||
declare_toplevel_type(LocalVariableTableElement) \
|
declare_toplevel_type(LocalVariableTableElement) \
|
||||||
declare_toplevel_type(narrowKlass) \
|
declare_toplevel_type(narrowKlass) \
|
||||||
|
declare_toplevel_type(ObjectWaiter) \
|
||||||
declare_toplevel_type(Symbol*) \
|
declare_toplevel_type(Symbol*) \
|
||||||
declare_toplevel_type(vtableEntry) \
|
declare_toplevel_type(vtableEntry) \
|
||||||
\
|
\
|
||||||
|
|
|
@ -139,6 +139,7 @@ class ObjectMonitor {
|
||||||
friend class ObjectSynchronizer;
|
friend class ObjectSynchronizer;
|
||||||
friend class ObjectWaiter;
|
friend class ObjectWaiter;
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
|
JVMCI_ONLY(friend class JVMCIVMStructs;)
|
||||||
|
|
||||||
volatile markOop _header; // displaced object header word - mark
|
volatile markOop _header; // displaced object header word - mark
|
||||||
void* volatile _object; // backward object pointer - strong root
|
void* volatile _object; // backward object pointer - strong root
|
||||||
|
|
|
@ -1575,18 +1575,15 @@ bool jvmci_counters_include(JavaThread* thread) {
|
||||||
return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
|
return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
|
void JavaThread::collect_counters(jlong* array, int length) {
|
||||||
if (JVMCICounterSize > 0) {
|
assert(length == JVMCICounterSize, "wrong value");
|
||||||
JavaThreadIteratorWithHandle jtiwh;
|
for (int i = 0; i < length; i++) {
|
||||||
int len = jvmci_env->get_length(array);
|
array[i] = _jvmci_old_thread_counters[i];
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
|
|
||||||
}
|
}
|
||||||
for (; JavaThread *tp = jtiwh.next(); ) {
|
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
|
||||||
if (jvmci_counters_include(tp)) {
|
if (jvmci_counters_include(tp)) {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
|
array[i] += tp->_jvmci_counters[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1152,7 +1152,7 @@ class JavaThread: public Thread {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static jlong* _jvmci_old_thread_counters;
|
static jlong* _jvmci_old_thread_counters;
|
||||||
static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
|
static void collect_counters(jlong* array, int length);
|
||||||
private:
|
private:
|
||||||
#endif // INCLUDE_JVMCI
|
#endif // INCLUDE_JVMCI
|
||||||
|
|
||||||
|
|
|
@ -438,14 +438,14 @@ int VM_Exit::wait_for_threads_in_native_to_block() {
|
||||||
if (thr->is_Compiler_thread()) {
|
if (thr->is_Compiler_thread()) {
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
CompilerThread* ct = (CompilerThread*) thr;
|
CompilerThread* ct = (CompilerThread*) thr;
|
||||||
if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) {
|
if (ct->compiler() == NULL || !ct->compiler()->is_jvmci()) {
|
||||||
num_active_compiler_thread++;
|
num_active_compiler_thread++;
|
||||||
} else {
|
} else {
|
||||||
// When using a compiler in a JVMCI shared library, it's possible
|
// A JVMCI compiler thread never accesses VM data structures
|
||||||
// for one compiler thread to grab a lock in the shared library,
|
// while in _thread_in_native state so there's no need to wait
|
||||||
// enter HotSpot and go to sleep on the shutdown safepoint. Another
|
// for it and potentially add a 300 millisecond delay to VM
|
||||||
// JVMCI shared library compiler thread can then attempt to grab the
|
// shutdown.
|
||||||
// lock and thus never make progress.
|
num_active--;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
num_active_compiler_thread++;
|
num_active_compiler_thread++;
|
||||||
|
|
|
@ -612,10 +612,15 @@ final class CompilerToVM {
|
||||||
* Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
|
* Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
|
||||||
* log stream.
|
* log stream.
|
||||||
*
|
*
|
||||||
|
* @param flush specifies if the log stream should be flushed after writing
|
||||||
|
* @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length}
|
||||||
|
* arguments should result in an exception or a negative return value
|
||||||
|
* @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and
|
||||||
|
* copying would cause access of data outside array bounds
|
||||||
* @throws NullPointerException if {@code bytes == null}
|
* @throws NullPointerException if {@code bytes == null}
|
||||||
* @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds
|
* @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds
|
||||||
*/
|
*/
|
||||||
native void writeDebugOutput(byte[] bytes, int offset, int length);
|
native int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush HotSpot's log stream.
|
* Flush HotSpot's log stream.
|
||||||
|
@ -947,4 +952,18 @@ final class CompilerToVM {
|
||||||
*/
|
*/
|
||||||
native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation);
|
native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HotSpotJVMCIRuntime#isCurrentThreadAttached()
|
||||||
|
*/
|
||||||
|
native boolean isCurrentThreadAttached();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HotSpotJVMCIRuntime#attachCurrentThread
|
||||||
|
*/
|
||||||
|
native boolean attachCurrentThread(boolean asDaemon);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HotSpotJVMCIRuntime#detachCurrentThread()
|
||||||
|
*/
|
||||||
|
native void detachCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
|
@ -180,8 +179,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
||||||
|
|
||||||
// Can only do eager initialization of the JVMCI compiler
|
// Can only do eager initialization of the JVMCI compiler
|
||||||
// once the singleton instance is available.
|
// once the singleton instance is available.
|
||||||
if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
|
if (result.config.getFlag("EagerJVMCI", Boolean.class)) {
|
||||||
instance.getCompiler();
|
result.getCompiler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
|
// Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
|
||||||
|
@ -464,7 +463,7 @@ assert factories != null : "sanity";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Option.PrintConfig.getBoolean()) {
|
if (Option.PrintConfig.getBoolean()) {
|
||||||
printConfig(configStore, compilerToVm);
|
configStore.printConfig();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,39 +726,21 @@ assert factories != null : "sanity";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
|
/**
|
||||||
private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
|
* Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
|
||||||
String line = String.format(format, args);
|
* log stream.
|
||||||
byte[] lineBytes = line.getBytes();
|
*
|
||||||
vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
|
* @param flush specifies if the log stream should be flushed after writing
|
||||||
vm.flushDebugOutput();
|
* @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length}
|
||||||
}
|
* arguments should result in an exception or a negative return value. If
|
||||||
|
* {@code false}, this call will not perform any heap allocation
|
||||||
private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
|
* @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and
|
||||||
TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
|
* copying would cause access of data outside array bounds
|
||||||
for (VMField field : fields.values()) {
|
* @throws NullPointerException if {@code bytes == null}
|
||||||
if (!field.isStatic()) {
|
* @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds
|
||||||
printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
|
*/
|
||||||
} else {
|
public int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow) {
|
||||||
String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
|
return compilerToVm.writeDebugOutput(bytes, offset, length, flush, canThrow);
|
||||||
printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
|
|
||||||
for (VMFlag flag : flags.values()) {
|
|
||||||
printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
|
|
||||||
}
|
|
||||||
TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
|
|
||||||
for (Map.Entry<String, Long> e : addresses.entrySet()) {
|
|
||||||
printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
|
|
||||||
}
|
|
||||||
TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
|
|
||||||
for (Map.Entry<String, Long> e : constants.entrySet()) {
|
|
||||||
printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
|
|
||||||
}
|
|
||||||
for (VMIntrinsicMethod e : store.getIntrinsics()) {
|
|
||||||
printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -777,7 +758,7 @@ assert factories != null : "sanity";
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
compilerToVm.writeDebugOutput(b, off, len);
|
compilerToVm.writeDebugOutput(b, off, len, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -907,11 +888,13 @@ assert factories != null : "sanity";
|
||||||
* the Java VM in the JVMCI shared library, and the remaining values are the first 3
|
* 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})
|
* pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
|
||||||
* @throws NullPointerException if {@code clazz == null}
|
* @throws NullPointerException if {@code clazz == null}
|
||||||
* @throws IllegalArgumentException if the current execution context is the JVMCI shared library
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
* or if {@code clazz} is {@link Class#isPrimitive()}
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
* @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
|
* @throws IllegalStateException if the current execution context is the JVMCI shared library
|
||||||
* {@code clazz} is already linked or the JVMCI shared library does not contain a
|
* @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
|
||||||
* JNI-compatible symbol for a native method in {@code clazz}
|
* @throws UnsatisfiedLinkError if there's a problem linking a native method in {@code clazz}
|
||||||
|
* (no matching JNI symbol or the native method is already linked to a different
|
||||||
|
* address)
|
||||||
*/
|
*/
|
||||||
public long[] registerNativeMethods(Class<?> clazz) {
|
public long[] registerNativeMethods(Class<?> clazz) {
|
||||||
return compilerToVm.registerNativeMethods(clazz);
|
return compilerToVm.registerNativeMethods(clazz);
|
||||||
|
@ -935,6 +918,8 @@ assert factories != null : "sanity";
|
||||||
*
|
*
|
||||||
* @param obj an object for which an equivalent instance in the peer runtime is requested
|
* @param obj an object for which an equivalent instance in the peer runtime is requested
|
||||||
* @return a JNI global reference to the mirror of {@code obj} in the peer runtime
|
* @return a JNI global reference to the mirror of {@code obj} in the peer runtime
|
||||||
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
* @throws IllegalArgumentException if {@code obj} is not of a translatable type
|
* @throws IllegalArgumentException if {@code obj} is not of a translatable type
|
||||||
*
|
*
|
||||||
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
|
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
|
||||||
|
@ -950,7 +935,9 @@ assert factories != null : "sanity";
|
||||||
*
|
*
|
||||||
* @param handle a JNI global reference to an object in the current runtime
|
* @param handle a JNI global reference to an object in the current runtime
|
||||||
* @return the object referred to by {@code handle}
|
* @return the object referred to by {@code handle}
|
||||||
* @throws ClassCastException if the returned object cannot be case to {@code type}
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
|
* @throws ClassCastException if the returned object cannot be cast to {@code type}
|
||||||
*
|
*
|
||||||
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
|
* @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
|
||||||
*
|
*
|
||||||
|
@ -959,6 +946,44 @@ assert factories != null : "sanity";
|
||||||
return type.cast(compilerToVm.unhand(handle));
|
return type.cast(compilerToVm.unhand(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the current thread is attached to the peer runtime.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
|
* @throws IllegalStateException if the peer runtime has not been initialized
|
||||||
|
*/
|
||||||
|
public boolean isCurrentThreadAttached() {
|
||||||
|
return compilerToVm.isCurrentThreadAttached();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures the current thread is attached to the peer runtime.
|
||||||
|
*
|
||||||
|
* @param asDaemon if the thread is not yet attached, should it be attached as a daemon
|
||||||
|
* @return {@code true} if this call attached the current thread, {@code false} if the current
|
||||||
|
* thread was already attached
|
||||||
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
|
* @throws IllegalStateException if the peer runtime has not been initialized or there is an
|
||||||
|
* error while trying to attach the thread
|
||||||
|
*/
|
||||||
|
public boolean attachCurrentThread(boolean asDaemon) {
|
||||||
|
return compilerToVm.attachCurrentThread(asDaemon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detaches the current thread from the peer runtime.
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||||
|
* {@code -XX:-UseJVMCINativeLibrary})
|
||||||
|
* @throws IllegalStateException if the peer runtime has not been initialized or if the current
|
||||||
|
* thread is not attached or if there is an error while trying to detach the thread
|
||||||
|
*/
|
||||||
|
public void detachCurrentThread() {
|
||||||
|
compilerToVm.detachCurrentThread();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Informs HotSpot that no method whose module is in {@code modules} is to be compiled
|
* Informs HotSpot that no method whose module is in {@code modules} is to be compiled
|
||||||
* with {@link #compileMethod}.
|
* with {@link #compileMethod}.
|
||||||
|
|
|
@ -193,8 +193,7 @@ public final class HotSpotVMConfigStore {
|
||||||
private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
|
private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
|
||||||
String line = String.format(format, args);
|
String line = String.format(format, args);
|
||||||
byte[] lineBytes = line.getBytes();
|
byte[] lineBytes = line.getBytes();
|
||||||
vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
|
vm.writeDebugOutput(lineBytes, 0, lineBytes.length, true, true);
|
||||||
vm.flushDebugOutput();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,16 +49,23 @@ final class TranslatedException extends Exception {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static Throwable create(String className, String message) {
|
||||||
public String toString() {
|
// Try create with reflection first.
|
||||||
return getMessage();
|
try {
|
||||||
|
Class<?> cls = Class.forName(className);
|
||||||
|
if (message == null) {
|
||||||
|
return (Throwable) cls.getConstructor().newInstance();
|
||||||
|
}
|
||||||
|
cls.getDeclaredConstructor(String.class);
|
||||||
|
return (Throwable) cls.getConstructor(String.class).newInstance(message);
|
||||||
|
} catch (Throwable ignore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TranslatedException create(String className, String message) {
|
|
||||||
if (className.equals(TranslatedException.class.getName())) {
|
if (className.equals(TranslatedException.class.getName())) {
|
||||||
// Chop the class name when boxing another TranslatedException
|
// Chop the class name when boxing another TranslatedException
|
||||||
return new TranslatedException(message);
|
return new TranslatedException(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return new TranslatedException(className);
|
return new TranslatedException(className);
|
||||||
}
|
}
|
||||||
|
@ -147,7 +154,7 @@ final class TranslatedException extends Exception {
|
||||||
Throwable throwable = create(exceptionClassName, exceptionMessage);
|
Throwable throwable = create(exceptionClassName, exceptionMessage);
|
||||||
int stackTraceDepth = Integer.parseInt(parts[i++]);
|
int stackTraceDepth = Integer.parseInt(parts[i++]);
|
||||||
|
|
||||||
StackTraceElement[] suffix = parent == null ? new StackTraceElement[0] : getStackTraceSuffix();
|
StackTraceElement[] suffix = getStackTraceSuffix();
|
||||||
StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
|
StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
|
||||||
for (int j = 0; j < stackTraceDepth; j++) {
|
for (int j = 0; j < stackTraceDepth; j++) {
|
||||||
String className = parts[i++];
|
String className = parts[i++];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -38,13 +38,13 @@ public class MetaUtil {
|
||||||
* @return the simple name
|
* @return the simple name
|
||||||
*/
|
*/
|
||||||
public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) {
|
public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) {
|
||||||
final String simpleName = clazz.getSimpleName();
|
final String simpleName = safeSimpleName(clazz);
|
||||||
if (simpleName.length() != 0) {
|
if (simpleName.length() != 0) {
|
||||||
if (withEnclosingClass) {
|
if (withEnclosingClass) {
|
||||||
String prefix = "";
|
String prefix = "";
|
||||||
Class<?> enclosingClass = clazz;
|
Class<?> enclosingClass = clazz;
|
||||||
while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
|
while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
|
||||||
prefix = enclosingClass.getSimpleName() + "." + prefix;
|
prefix = safeSimpleName(enclosingClass) + "." + prefix;
|
||||||
}
|
}
|
||||||
return prefix + simpleName;
|
return prefix + simpleName;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,29 @@ public class MetaUtil {
|
||||||
return name.substring(index + 1);
|
return name.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String safeSimpleName(Class<?> clazz) {
|
||||||
|
try {
|
||||||
|
return clazz.getSimpleName();
|
||||||
|
} catch (InternalError e) {
|
||||||
|
// Scala inner class names do not always start with '$',
|
||||||
|
// causing Class.getSimpleName to throw an InternalError
|
||||||
|
Class<?> enclosingClass = clazz.getEnclosingClass();
|
||||||
|
String fqn = clazz.getName();
|
||||||
|
if (enclosingClass == null) {
|
||||||
|
// Should never happen given logic in
|
||||||
|
// Class.getSimpleName but best be safe
|
||||||
|
return fqn;
|
||||||
|
}
|
||||||
|
String enclosingFQN = enclosingClass.getName();
|
||||||
|
int length = fqn.length();
|
||||||
|
if (enclosingFQN.length() >= length) {
|
||||||
|
// Should also never happen
|
||||||
|
return fqn;
|
||||||
|
}
|
||||||
|
return fqn.substring(enclosingFQN.length());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a type name in internal form to an external form.
|
* Converts a type name in internal form to an external form.
|
||||||
*
|
*
|
||||||
|
|
|
@ -282,6 +282,17 @@ public final class Services {
|
||||||
return ClassLoader.getSystemClassLoader();
|
return ClassLoader.getSystemClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Java {@code char} has a maximal UTF8 length of 3.
|
||||||
|
*/
|
||||||
|
private static final int MAX_UNICODE_IN_UTF8_LENGTH = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link DataOutputStream#writeUTF(String)} only supports values whose UTF8 encoding length is
|
||||||
|
* less than 65535.
|
||||||
|
*/
|
||||||
|
private static final int MAX_UTF8_PROPERTY_STRING_LENGTH = 65535 / MAX_UNICODE_IN_UTF8_LENGTH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for
|
* Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for
|
||||||
* the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
|
* the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
|
||||||
|
@ -292,26 +303,49 @@ public final class Services {
|
||||||
if (IS_IN_NATIVE_IMAGE) {
|
if (IS_IN_NATIVE_IMAGE) {
|
||||||
throw new InternalError("Can only serialize saved properties in HotSpot runtime");
|
throw new InternalError("Can only serialize saved properties in HotSpot runtime");
|
||||||
}
|
}
|
||||||
Map<String, String> props = Services.getSavedProperties();
|
return serializeProperties(Services.getSavedProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] serializeProperties(Map<String, String> props) throws IOException {
|
||||||
// Compute size of output on the assumption that
|
// Compute size of output on the assumption that
|
||||||
// all system properties have ASCII names and values
|
// all system properties have ASCII names and values
|
||||||
int estimate = 4;
|
int estimate = 4 + 4;
|
||||||
|
int nonUtf8Props = 0;
|
||||||
for (Map.Entry<String, String> e : props.entrySet()) {
|
for (Map.Entry<String, String> e : props.entrySet()) {
|
||||||
String name = e.getKey();
|
String name = e.getKey();
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
estimate += (2 + (name.length())) + (2 + (value.length()));
|
estimate += (2 + (name.length())) + (2 + (value.length()));
|
||||||
|
if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) {
|
||||||
|
nonUtf8Props++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate);
|
||||||
DataOutputStream out = new DataOutputStream(baos);
|
DataOutputStream out = new DataOutputStream(baos);
|
||||||
out.writeInt(props.size());
|
out.writeInt(props.size() - nonUtf8Props);
|
||||||
|
out.writeInt(nonUtf8Props);
|
||||||
for (Map.Entry<String, String> e : props.entrySet()) {
|
for (Map.Entry<String, String> e : props.entrySet()) {
|
||||||
String name = e.getKey();
|
String name = e.getKey();
|
||||||
String value = e.getValue();
|
String value = e.getValue();
|
||||||
|
if (name.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH && value.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH) {
|
||||||
out.writeUTF(name);
|
out.writeUTF(name);
|
||||||
out.writeUTF(value);
|
out.writeUTF(value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (nonUtf8Props != 0) {
|
||||||
|
for (Map.Entry<String, String> e : props.entrySet()) {
|
||||||
|
String name = e.getKey();
|
||||||
|
String value = e.getValue();
|
||||||
|
if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) {
|
||||||
|
byte[] utf8Name = name.getBytes("UTF-8");
|
||||||
|
byte[] utf8Value = value.getBytes("UTF-8");
|
||||||
|
out.writeInt(utf8Name.length);
|
||||||
|
out.write(utf8Name);
|
||||||
|
out.writeInt(utf8Value.length);
|
||||||
|
out.write(utf8Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,13 +359,33 @@ public final class Services {
|
||||||
if (!IS_IN_NATIVE_IMAGE) {
|
if (!IS_IN_NATIVE_IMAGE) {
|
||||||
throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
|
throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
|
||||||
}
|
}
|
||||||
|
savedProperties = Collections.unmodifiableMap(deserializeProperties(serializedProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> deserializeProperties(byte[] serializedProperties) throws IOException {
|
||||||
DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties));
|
DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties));
|
||||||
Map<String, String> props = new HashMap<>(in.readInt());
|
int utf8Props = in.readInt();
|
||||||
|
int nonUtf8Props = in.readInt();
|
||||||
|
Map<String, String> props = new HashMap<>(utf8Props + nonUtf8Props);
|
||||||
|
int index = 0;
|
||||||
while (in.available() != 0) {
|
while (in.available() != 0) {
|
||||||
|
if (index < utf8Props) {
|
||||||
String name = in.readUTF();
|
String name = in.readUTF();
|
||||||
String value = in.readUTF();
|
String value = in.readUTF();
|
||||||
props.put(name, value);
|
props.put(name, value);
|
||||||
|
} else {
|
||||||
|
int nameLen = in.readInt();
|
||||||
|
byte[] nameBytes = new byte[nameLen];
|
||||||
|
in.read(nameBytes);
|
||||||
|
int valueLen = in.readInt();
|
||||||
|
byte[] valueBytes = new byte[valueLen];
|
||||||
|
in.read(valueBytes);
|
||||||
|
String name = new String(nameBytes, "UTF-8");
|
||||||
|
String value = new String(valueBytes, "UTF-8");
|
||||||
|
props.put(name, value);
|
||||||
}
|
}
|
||||||
savedProperties = Collections.unmodifiableMap(props);
|
index++;
|
||||||
|
}
|
||||||
|
return props;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.vm.ci.services;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
|
||||||
|
*/
|
||||||
|
@interface SuppressFBWarnings {
|
||||||
|
/**
|
||||||
|
* The set of FindBugs
|
||||||
|
* <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
|
||||||
|
* suppressed in annotated element. The value can be a bug category, kind or pattern.
|
||||||
|
*/
|
||||||
|
String[] value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reason why the warning is suppressed.
|
||||||
|
*/
|
||||||
|
String justification();
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -30,6 +30,9 @@ module jdk.internal.vm.ci {
|
||||||
exports jdk.vm.ci.runtime to
|
exports jdk.vm.ci.runtime to
|
||||||
jdk.internal.vm.compiler,
|
jdk.internal.vm.compiler,
|
||||||
jdk.internal.vm.compiler.management;
|
jdk.internal.vm.compiler.management;
|
||||||
|
exports jdk.vm.ci.meta to jdk.internal.vm.compiler;
|
||||||
|
exports jdk.vm.ci.code to jdk.internal.vm.compiler;
|
||||||
|
exports jdk.vm.ci.hotspot to jdk.internal.vm.compiler;
|
||||||
|
|
||||||
uses jdk.vm.ci.services.JVMCIServiceLocator;
|
uses jdk.vm.ci.services.JVMCIServiceLocator;
|
||||||
uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
|
uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable;
|
||||||
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||||
|
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||||
import jdk.vm.ci.meta.Constant;
|
import jdk.vm.ci.meta.Constant;
|
||||||
|
@ -83,7 +84,7 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica
|
||||||
public void generate(NodeLIRBuilderTool gen) {
|
public void generate(NodeLIRBuilderTool gen) {
|
||||||
assert constant != null : "Expected the value to fold: " + value;
|
assert constant != null : "Expected the value to fold: " + value;
|
||||||
Value result;
|
Value result;
|
||||||
if (constant instanceof HotSpotObjectConstant) {
|
if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) {
|
||||||
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant);
|
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant);
|
||||||
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
||||||
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action);
|
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action);
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
|
||||||
import org.graalvm.compiler.nodes.util.GraphUtil;
|
import org.graalvm.compiler.nodes.util.GraphUtil;
|
||||||
import org.graalvm.compiler.word.Word;
|
import org.graalvm.compiler.word.Word;
|
||||||
|
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||||
import jdk.vm.ci.meta.Constant;
|
import jdk.vm.ci.meta.Constant;
|
||||||
|
@ -100,7 +101,7 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can
|
||||||
Value result;
|
Value result;
|
||||||
LIRFrameState fs = gen.state(this);
|
LIRFrameState fs = gen.state(this);
|
||||||
assert fs != null : "The stateAfter is null";
|
assert fs != null : "The stateAfter is null";
|
||||||
if (constant instanceof HotSpotObjectConstant) {
|
if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) {
|
||||||
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitObjectConstantRetrieval(constant, stringValue, fs);
|
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitObjectConstantRetrieval(constant, stringValue, fs);
|
||||||
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
||||||
if (action == HotSpotConstantLoadAction.RESOLVE) {
|
if (action == HotSpotConstantLoadAction.RESOLVE) {
|
||||||
|
|
|
@ -301,7 +301,7 @@ public class CompilerToVMHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeDebugOutput(byte[] bytes, int offset, int length) {
|
public static void writeDebugOutput(byte[] bytes, int offset, int length) {
|
||||||
CTVM.writeDebugOutput(bytes, offset, length);
|
CTVM.writeDebugOutput(bytes, offset, length, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void flushDebugOutput() {
|
public static void flushDebugOutput() {
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 2019, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.vm.ci.hotspot.test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
|
||||||
|
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||||
|
|
||||||
|
public class TestHotSpotJVMCIRuntime {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void writeDebugOutputTest() {
|
||||||
|
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
|
||||||
|
|
||||||
|
expectWriteDebugOutputFailure(runtime, null, 0, 0, true, true, NullPointerException.class);
|
||||||
|
expectWriteDebugOutputFailure(runtime, null, 0, 0, true, false, -1);
|
||||||
|
|
||||||
|
byte[] emptyOutput = {};
|
||||||
|
byte[] nonEmptyOutput = String.format("non-empty output%n").getBytes();
|
||||||
|
|
||||||
|
for (boolean canThrow : new boolean[]{true, false}) {
|
||||||
|
for (byte[] output : new byte[][]{emptyOutput, nonEmptyOutput}) {
|
||||||
|
for (int offset = 0; offset < output.length; offset++) {
|
||||||
|
int length = output.length - offset;
|
||||||
|
runtime.writeDebugOutput(output, offset, length, true, canThrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object expect = canThrow ? IndexOutOfBoundsException.class : -2;
|
||||||
|
expectWriteDebugOutputFailure(runtime, output, output.length + 1, 0, true, canThrow, expect);
|
||||||
|
expectWriteDebugOutputFailure(runtime, output, 0, output.length + 1, true, canThrow, expect);
|
||||||
|
expectWriteDebugOutputFailure(runtime, output, -1, 0, true, canThrow, expect);
|
||||||
|
expectWriteDebugOutputFailure(runtime, output, 0, -1, true, canThrow, expect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void expectWriteDebugOutputFailure(HotSpotJVMCIRuntime runtime, byte[] bytes, int offset, int length, boolean flush, boolean canThrow, Object expect) {
|
||||||
|
try {
|
||||||
|
int result = runtime.writeDebugOutput(bytes, offset, length, flush, canThrow);
|
||||||
|
if (expect instanceof Integer) {
|
||||||
|
Assert.assertEquals((int) expect, result);
|
||||||
|
} else {
|
||||||
|
Assert.fail("expected " + expect + ", got " + result + " for bytes == " + Arrays.toString(bytes));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (expect instanceof Integer) {
|
||||||
|
Assert.fail("expected " + expect + ", got " + e + " for bytes == " + Arrays.toString(bytes));
|
||||||
|
} else {
|
||||||
|
Assert.assertTrue(e.toString(), ((Class<?>) expect).isInstance(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getIntrinsificationTrustPredicateTest() throws Exception {
|
||||||
|
HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
|
||||||
|
MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess();
|
||||||
|
Predicate<ResolvedJavaType> predicate = runtime.getIntrinsificationTrustPredicate(HotSpotJVMCIRuntime.class);
|
||||||
|
List<Class<?>> classes = new ArrayList<>(Arrays.asList(
|
||||||
|
Object.class,
|
||||||
|
String.class,
|
||||||
|
Class.class,
|
||||||
|
HotSpotJVMCIRuntime.class,
|
||||||
|
VirtualObjectLayoutTest.class,
|
||||||
|
TestHotSpotJVMCIRuntime.class));
|
||||||
|
try {
|
||||||
|
classes.add(Class.forName("com.sun.crypto.provider.AESCrypt"));
|
||||||
|
classes.add(Class.forName("com.sun.crypto.provider.CipherBlockChaining"));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// Extension classes not available
|
||||||
|
}
|
||||||
|
ClassLoader jvmciLoader = HotSpotJVMCIRuntime.class.getClassLoader();
|
||||||
|
ClassLoader extLoader = getExtensionLoader();
|
||||||
|
for (Class<?> c : classes) {
|
||||||
|
ClassLoader cl = c.getClassLoader();
|
||||||
|
boolean expected = cl == null || cl == jvmciLoader || cl == extLoader;
|
||||||
|
boolean actual = predicate.test(metaAccess.lookupJavaType(c));
|
||||||
|
Assert.assertEquals(c + ": cl=" + cl, expected, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassLoader getExtensionLoader() throws Exception {
|
||||||
|
Object launcher = Class.forName("sun.misc.Launcher").getMethod("getLauncher").invoke(null);
|
||||||
|
ClassLoader appLoader = (ClassLoader) launcher.getClass().getMethod("getClassLoader").invoke(launcher);
|
||||||
|
ClassLoader extLoader = appLoader.getParent();
|
||||||
|
assert extLoader.getClass().getName().equals("sun.misc.Launcher$ExtClassLoader") : extLoader;
|
||||||
|
return extLoader;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.vm.ci.hotspot.test;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import jdk.vm.ci.services.Services;
|
||||||
|
|
||||||
|
public class TestServices {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void serializeSavedPropertiesTest() throws Exception {
|
||||||
|
|
||||||
|
Field f = Services.class.getDeclaredField("MAX_UTF8_PROPERTY_STRING_LENGTH");
|
||||||
|
f.setAccessible(true);
|
||||||
|
int maxUtf8PropertyStringLength = (int) f.get(null);
|
||||||
|
|
||||||
|
Method serializeProperties = Services.class.getDeclaredMethod("serializeProperties", Map.class);
|
||||||
|
Method deserializeProperties = Services.class.getDeclaredMethod("deserializeProperties", byte[].class);
|
||||||
|
serializeProperties.setAccessible(true);
|
||||||
|
deserializeProperties.setAccessible(true);
|
||||||
|
|
||||||
|
Map<String, String> props = new HashMap<>(Services.getSavedProperties());
|
||||||
|
String[] names = {
|
||||||
|
new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', 'x'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', 'x'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength]).replace('\0', 'y'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', 'z'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', 'z')
|
||||||
|
};
|
||||||
|
String[] values = {
|
||||||
|
new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', '1'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', '1'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength]).replace('\0', '2'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', '1'),
|
||||||
|
new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', '3')
|
||||||
|
};
|
||||||
|
for (String name : names) {
|
||||||
|
for (String value : values) {
|
||||||
|
props.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] data = (byte[]) serializeProperties.invoke(null, props);
|
||||||
|
|
||||||
|
Map<String, String> newProps = (Map<String, String>) deserializeProperties.invoke(null, data);
|
||||||
|
|
||||||
|
Assert.assertEquals(props.size(), newProps.size());
|
||||||
|
for (String name : props.keySet()) {
|
||||||
|
String expect = props.get(name);
|
||||||
|
String actual = newProps.get(name);
|
||||||
|
Assert.assertEquals(expect, actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -71,6 +71,9 @@ public class JdkQualifiedExportTest {
|
||||||
static Set<String> KNOWN_EXCEPTIONS =
|
static Set<String> KNOWN_EXCEPTIONS =
|
||||||
Set.of("jdk.internal.vm.ci/jdk.vm.ci.services",
|
Set.of("jdk.internal.vm.ci/jdk.vm.ci.services",
|
||||||
"jdk.internal.vm.ci/jdk.vm.ci.runtime",
|
"jdk.internal.vm.ci/jdk.vm.ci.runtime",
|
||||||
|
"jdk.internal.vm.ci/jdk.vm.ci.hotspot",
|
||||||
|
"jdk.internal.vm.ci/jdk.vm.ci.meta",
|
||||||
|
"jdk.internal.vm.ci/jdk.vm.ci.code",
|
||||||
"jdk.jsobject/jdk.internal.netscape.javascript.spi");
|
"jdk.jsobject/jdk.internal.netscape.javascript.spi");
|
||||||
|
|
||||||
static void checkExports(ModuleDescriptor md) {
|
static void checkExports(ModuleDescriptor md) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue