8223332: Update JVMCI
Reviewed-by: never, dnsimon
This commit is contained in:
parent
29a4ad9a87
commit
72f082e925
src
hotspot/share
compiler
jvmci
jvmciCompilerToVM.cppjvmciCompilerToVM.hppjvmciEnv.cppjvmciEnv.hppjvmciExceptions.hppjvmciJavaClasses.cppjvmciJavaClasses.hppjvmciRuntime.cppjvmci_globals.cppjvmci_globals.hppvmStructs_jvmci.cpp
runtime
jdk.internal.vm.ci/share/classes
jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot
jdk.vm.ci.meta/src/jdk/vm/ci/meta
jdk.vm.ci.services/src/jdk/vm/ci/services
module-info.javajdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot
test
hotspot/jtreg/compiler/jvmci
common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot
jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test
jdk/jdk/modules/etc
@ -70,7 +70,6 @@
|
||||
#if INCLUDE_JVMCI
|
||||
#include "jvmci/jvmciEnv.hpp"
|
||||
#include "jvmci/jvmciRuntime.hpp"
|
||||
#include "runtime/vframe.hpp"
|
||||
#endif
|
||||
#ifdef COMPILER2
|
||||
#include "opto/c2compiler.hpp"
|
||||
@ -1063,20 +1062,22 @@ void CompileBroker::compile_method_base(const methodHandle& method,
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
|
||||
if (UseJVMCICompiler && blocking) {
|
||||
// Don't allow blocking compiles for requests triggered by JVMCI.
|
||||
if (thread->is_Compiler_thread()) {
|
||||
blocking = false;
|
||||
}
|
||||
|
||||
// Don't allow blocking compiles if inside a class initializer or while performing class loading
|
||||
vframeStream vfst((JavaThread*) thread);
|
||||
for (; !vfst.at_end(); vfst.next()) {
|
||||
if (vfst.method()->is_static_initializer() ||
|
||||
(vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
|
||||
vfst.method()->name() == vmSymbols::loadClass_name())) {
|
||||
blocking = false;
|
||||
break;
|
||||
if (!UseJVMCINativeLibrary) {
|
||||
// Don't allow blocking compiles if inside a class initializer or while performing class loading
|
||||
vframeStream vfst((JavaThread*) thread);
|
||||
for (; !vfst.at_end(); vfst.next()) {
|
||||
if (vfst.method()->is_static_initializer() ||
|
||||
(vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
|
||||
vfst.method()->name() == vmSymbols::loadClass_name())) {
|
||||
blocking = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2063,7 +2064,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
compilable = ciEnv::MethodCompilable_never;
|
||||
} else {
|
||||
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);
|
||||
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 {
|
||||
JavaThread* _thread;
|
||||
public:
|
||||
JNIHandleMark() { push_jni_handle_block(); }
|
||||
~JNIHandleMark() { pop_jni_handle_block(); }
|
||||
JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); }
|
||||
~JNIHandleMark() { pop_jni_handle_block(_thread); }
|
||||
|
||||
private:
|
||||
static void push_jni_handle_block();
|
||||
static void pop_jni_handle_block();
|
||||
static void push_jni_handle_block(JavaThread* thread);
|
||||
static void pop_jni_handle_block(JavaThread* thread);
|
||||
};
|
||||
|
||||
#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) {
|
||||
MutexLocker locker(JVMCI_lock);
|
||||
if (_shared_library_javavm == NULL) {
|
||||
|
||||
char path[JVM_MAXPATHLEN];
|
||||
char ebuf[1024];
|
||||
if (JVMCILibPath != NULL) {
|
||||
@ -179,85 +178,107 @@ 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;
|
||||
}
|
||||
|
||||
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.
|
||||
_runtime = JVMCI::compiler_runtime();
|
||||
_env = NULL;
|
||||
_pop_frame_on_close = false;
|
||||
_detach_on_close = false;
|
||||
if (!UseJVMCINativeLibrary) {
|
||||
// In HotSpot mode, JNI isn't used at all.
|
||||
_is_hotspot = true;
|
||||
_env = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent_env != NULL) {
|
||||
// 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.
|
||||
JavaThread* thread = JavaThread::current();
|
||||
if (thread->jni_environment() == parent_env) {
|
||||
_is_hotspot = thread->jni_environment() == parent_env;
|
||||
if (_is_hotspot) {
|
||||
// Select the Java runtime
|
||||
_runtime = JVMCI::java_runtime();
|
||||
_is_hotspot = true;
|
||||
_env = NULL;
|
||||
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;
|
||||
_env = attach_shared_library();
|
||||
assert(parent_env == NULL || _env == parent_env, "must be");
|
||||
_env = init_shared_library(thread);
|
||||
|
||||
if (parent_env == NULL) {
|
||||
// There is no parent shared library JNI env so push
|
||||
// a JNI local frame to release all local handles in
|
||||
// this JVMCIEnv scope when it's closed.
|
||||
assert(_throw_to_caller == false, "must be");
|
||||
JNIAccessMark jni(this);
|
||||
jint result = _env->PushLocalFrame(32);
|
||||
if (result != JNI_OK) {
|
||||
char message[256];
|
||||
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);
|
||||
if (_env != NULL) {
|
||||
// Creating the JVMCI shared library VM also attaches the current thread
|
||||
_detach_on_close = true;
|
||||
} else {
|
||||
_shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2);
|
||||
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");
|
||||
|
||||
JNIAccessMark jni(this);
|
||||
jint result = _env->PushLocalFrame(32);
|
||||
if (result != JNI_OK) {
|
||||
char message[256];
|
||||
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);
|
||||
}
|
||||
_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) {
|
||||
init_env_mode_runtime(NULL);
|
||||
init_env_mode_runtime(thread, NULL);
|
||||
}
|
||||
|
||||
JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
|
||||
_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) {
|
||||
init_env_mode_runtime(parent_env);
|
||||
init_env_mode_runtime(thread, parent_env);
|
||||
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;
|
||||
_throw_to_caller = false;
|
||||
_file = file;
|
||||
_line = line;
|
||||
if (is_hotspot) {
|
||||
_env = NULL;
|
||||
_pop_frame_on_close = false;
|
||||
_detach_on_close = false;
|
||||
_is_hotspot = true;
|
||||
_runtime = JVMCI::java_runtime();
|
||||
} else {
|
||||
init_env_mode_runtime(NULL);
|
||||
init_env_mode_runtime(thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +345,7 @@ JVMCIEnv::~JVMCIEnv() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!is_hotspot()) {
|
||||
if (_pop_frame_on_close) {
|
||||
// Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
|
||||
JNIAccessMark jni(this);
|
||||
jni()->PopLocalFrame(NULL);
|
||||
@ -335,6 +356,10 @@ JVMCIEnv::~JVMCIEnv() {
|
||||
jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
|
||||
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) {
|
||||
if (size_in_bytes == 0) {
|
||||
void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
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 {
|
||||
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) {
|
||||
if (size_in_bytes == 0) {
|
||||
void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
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 {
|
||||
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(InvalidInstalledCodeException)
|
||||
DO_THROW(UnsatisfiedLinkError)
|
||||
DO_THROW(UnsupportedOperationException)
|
||||
DO_THROW(ClassNotFoundException)
|
||||
|
||||
#undef DO_THROW
|
||||
|
||||
@ -888,7 +927,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci,
|
||||
return JVMCIObject();
|
||||
}
|
||||
jobject file_name = NULL;
|
||||
if (file_name != NULL) {
|
||||
if (file_name_sym != NULL) {
|
||||
file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
|
||||
if (jni()->ExceptionCheck()) {
|
||||
return JVMCIObject();
|
||||
@ -1323,14 +1362,15 @@ Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
|
||||
assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
|
||||
oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
|
||||
return Handle(THREAD, obj);
|
||||
} else {
|
||||
assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type");
|
||||
} else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
|
||||
jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
|
||||
oop result = resolve_handle(object_handle);
|
||||
if (result == NULL) {
|
||||
JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
|
||||
}
|
||||
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 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 \
|
||||
JavaThread* thread=JavaThread::current(); \
|
||||
Thread* THREAD = thread;
|
||||
@ -154,24 +145,25 @@ class JVMCIEnv : public ResourceObj {
|
||||
static void* _shared_library_handle; // result of os::dll_load
|
||||
static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
|
||||
|
||||
// Attaches the current thread to the JavaVM in the shared library,
|
||||
// initializing the shared library VM first if necessary.
|
||||
// Returns the JNI interface pointer of the current thread.
|
||||
// The _shared_library_* fields are initialized by the first
|
||||
// call to this method.
|
||||
static JNIEnv* attach_shared_library();
|
||||
// Initializes the shared library JavaVM if not already initialized.
|
||||
// Returns the JNI interface pointer for the current thread
|
||||
// if initialization was performed by this call, NULL if
|
||||
// initialization was performed by a previous call.
|
||||
static JNIEnv* init_shared_library(JavaThread* thread);
|
||||
|
||||
// Initializes the _env, _mode and _runtime fields.
|
||||
void init_env_mode_runtime(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
|
||||
JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime
|
||||
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
|
||||
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
|
||||
const char* _file; // The file and ...
|
||||
int _line; // ... line where this JNIEnv was created
|
||||
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
|
||||
bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in
|
||||
bool _throw_to_caller; // Propagate an exception raised in this env to the caller?
|
||||
const char* _file; // The file and ...
|
||||
int _line; // ... line where this JNIEnv was created
|
||||
|
||||
// Translates an exception on the HotSpot heap to an exception on
|
||||
// the shared library heap. The translation includes the stack and
|
||||
@ -185,12 +177,12 @@ public:
|
||||
// scope closes so that it will be propagated back to Java.
|
||||
// The JVMCIEnv destructor translates the exception object for the
|
||||
// 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.
|
||||
// An exception occurring within the scope must not be propagated back to
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// can block or take a long time so do not allow such access
|
||||
// on the 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");
|
||||
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
|
||||
// otherwise for the shared library runtime. An exception occurring
|
||||
// within the scope must not be propagated back to the caller.
|
||||
JVMCIEnv(bool is_hotspot, const char* file, int line) {
|
||||
init(is_hotspot, file, line);
|
||||
JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) {
|
||||
init(thread, is_hotspot, file, line);
|
||||
}
|
||||
|
||||
~JVMCIEnv();
|
||||
@ -247,8 +239,10 @@ public:
|
||||
long get_long_at(JVMCIPrimitiveArray array, int index);
|
||||
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_from(jbyte* src, JVMCIPrimitiveArray 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, jsize length);
|
||||
|
||||
void copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length);
|
||||
|
||||
JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
|
||||
|
||||
@ -323,6 +317,8 @@ public:
|
||||
DO_THROW(IllegalArgumentException)
|
||||
DO_THROW(InvalidInstalledCodeException)
|
||||
DO_THROW(UnsatisfiedLinkError)
|
||||
DO_THROW(UnsupportedOperationException)
|
||||
DO_THROW(ClassNotFoundException)
|
||||
|
||||
#undef DO_THROW
|
||||
|
||||
|
@ -32,8 +32,8 @@ class JVMCIEnv;
|
||||
#define JVMCIENV __jvmci_env__
|
||||
#define JVMCI_TRAPS JVMCIEnv* JVMCIENV
|
||||
|
||||
#define JNI_JVMCIENV(env) \
|
||||
JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__); \
|
||||
#define JNI_JVMCIENV(thread, env) \
|
||||
JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__); \
|
||||
JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
|
||||
|
||||
#define THREAD_JVMCIENV(thread) \
|
||||
|
@ -356,6 +356,43 @@ extern "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()
|
||||
/**
|
||||
* 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();
|
||||
|
||||
DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
|
||||
ThrowableInitDumper dumper(st);
|
||||
vmSymbols::symbols_do(&dumper);
|
||||
|
||||
st->flush();
|
||||
tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
|
||||
|
@ -381,12 +381,18 @@
|
||||
start_class(InternalError, java_lang_InternalError) \
|
||||
jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \
|
||||
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) \
|
||||
jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \
|
||||
end_class \
|
||||
start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError) \
|
||||
jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V") \
|
||||
end_class \
|
||||
start_class(UnsupportedOperationException, java_lang_UnsupportedOperationException) \
|
||||
jvmci_constructor(UnsupportedOperationException, "(Ljava/lang/String;)V") \
|
||||
end_class \
|
||||
start_class(StackTraceElement, java_lang_StackTraceElement) \
|
||||
object_field(StackTraceElement, declaringClass, "Ljava/lang/String;") \
|
||||
object_field(StackTraceElement, methodName, "Ljava/lang/String;") \
|
||||
|
@ -655,7 +655,7 @@ JRT_END
|
||||
|
||||
// private static JVMCIRuntime JVMCI.initializeRuntime()
|
||||
JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
||||
JNI_JVMCIENV(env);
|
||||
JNI_JVMCIENV(thread, env);
|
||||
if (!EnableJVMCI) {
|
||||
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");
|
||||
#endif
|
||||
|
||||
JNI_JVMCIENV(env);
|
||||
JNI_JVMCIENV(thread, env);
|
||||
|
||||
if (!EnableJVMCI) {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
if (JVMCI::shutdown_called()) {
|
||||
compile_state->set_failure(false, "Avoiding compilation during shutdown");
|
||||
return;
|
||||
}
|
||||
|
||||
HandleMark hm;
|
||||
JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
|
||||
|
@ -83,7 +83,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() {
|
||||
}
|
||||
FLAG_SET_DEFAULT(EnableJVMCI, true);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,10 @@
|
||||
"Prints properties used by the JVMCI compiler and exits") \
|
||||
\
|
||||
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, \
|
||||
"Force eager JVMCI initialization") \
|
||||
|
@ -246,6 +246,10 @@
|
||||
\
|
||||
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, _metadata._klass, Klass*) \
|
||||
\
|
||||
@ -347,6 +351,7 @@
|
||||
declare_toplevel_type(JVMCIEnv) \
|
||||
declare_toplevel_type(LocalVariableTableElement) \
|
||||
declare_toplevel_type(narrowKlass) \
|
||||
declare_toplevel_type(ObjectWaiter) \
|
||||
declare_toplevel_type(Symbol*) \
|
||||
declare_toplevel_type(vtableEntry) \
|
||||
\
|
||||
|
@ -139,6 +139,7 @@ class ObjectMonitor {
|
||||
friend class ObjectSynchronizer;
|
||||
friend class ObjectWaiter;
|
||||
friend class VMStructs;
|
||||
JVMCI_ONLY(friend class JVMCIVMStructs;)
|
||||
|
||||
volatile markOop _header; // displaced object header word - mark
|
||||
void* volatile _object; // backward object pointer - strong root
|
||||
|
@ -1575,18 +1575,15 @@ bool jvmci_counters_include(JavaThread* thread) {
|
||||
return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
|
||||
}
|
||||
|
||||
void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
|
||||
if (JVMCICounterSize > 0) {
|
||||
JavaThreadIteratorWithHandle jtiwh;
|
||||
int len = jvmci_env->get_length(array);
|
||||
for (int i = 0; i < len; i++) {
|
||||
jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
|
||||
}
|
||||
for (; JavaThread *tp = jtiwh.next(); ) {
|
||||
if (jvmci_counters_include(tp)) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
|
||||
}
|
||||
void JavaThread::collect_counters(jlong* array, int length) {
|
||||
assert(length == JVMCICounterSize, "wrong value");
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] = _jvmci_old_thread_counters[i];
|
||||
}
|
||||
for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
|
||||
if (jvmci_counters_include(tp)) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] += tp->_jvmci_counters[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1152,7 +1152,7 @@ class JavaThread: public Thread {
|
||||
|
||||
public:
|
||||
static jlong* _jvmci_old_thread_counters;
|
||||
static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
|
||||
static void collect_counters(jlong* array, int length);
|
||||
private:
|
||||
#endif // INCLUDE_JVMCI
|
||||
|
||||
|
@ -438,14 +438,14 @@ int VM_Exit::wait_for_threads_in_native_to_block() {
|
||||
if (thr->is_Compiler_thread()) {
|
||||
#if INCLUDE_JVMCI
|
||||
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++;
|
||||
} else {
|
||||
// When using a compiler in a JVMCI shared library, it's possible
|
||||
// for one compiler thread to grab a lock in the shared library,
|
||||
// enter HotSpot and go to sleep on the shutdown safepoint. Another
|
||||
// JVMCI shared library compiler thread can then attempt to grab the
|
||||
// lock and thus never make progress.
|
||||
// A JVMCI compiler thread never accesses VM data structures
|
||||
// while in _thread_in_native state so there's no need to wait
|
||||
// for it and potentially add a 300 millisecond delay to VM
|
||||
// shutdown.
|
||||
num_active--;
|
||||
}
|
||||
#else
|
||||
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
|
||||
* 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 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.
|
||||
@ -947,4 +952,18 @@ final class CompilerToVM {
|
||||
*/
|
||||
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.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
@ -180,8 +179,8 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
|
||||
|
||||
// Can only do eager initialization of the JVMCI compiler
|
||||
// once the singleton instance is available.
|
||||
if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
|
||||
instance.getCompiler();
|
||||
if (result.config.getFlag("EagerJVMCI", Boolean.class)) {
|
||||
result.getCompiler();
|
||||
}
|
||||
}
|
||||
// Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
|
||||
@ -464,7 +463,7 @@ assert factories != null : "sanity";
|
||||
}
|
||||
|
||||
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) {
|
||||
String line = String.format(format, args);
|
||||
byte[] lineBytes = line.getBytes();
|
||||
vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
|
||||
vm.flushDebugOutput();
|
||||
}
|
||||
|
||||
private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
|
||||
TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
|
||||
for (VMField field : fields.values()) {
|
||||
if (!field.isStatic()) {
|
||||
printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
|
||||
} else {
|
||||
String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
|
||||
* 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. If
|
||||
* {@code false}, this call will not perform any heap allocation
|
||||
* @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 IndexOutOfBoundsException if copying would cause access of data outside array bounds
|
||||
*/
|
||||
public int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow) {
|
||||
return compilerToVm.writeDebugOutput(bytes, offset, length, flush, canThrow);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -777,7 +758,7 @@ assert factories != null : "sanity";
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
compilerToVm.writeDebugOutput(b, off, len);
|
||||
compilerToVm.writeDebugOutput(b, off, len, false, true);
|
||||
}
|
||||
|
||||
@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
|
||||
* pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
|
||||
* @throws NullPointerException if {@code clazz == null}
|
||||
* @throws IllegalArgumentException if the current execution context is the JVMCI shared library
|
||||
* or if {@code clazz} is {@link Class#isPrimitive()}
|
||||
* @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
|
||||
* {@code clazz} is already linked or the JVMCI shared library does not contain a
|
||||
* JNI-compatible symbol for a native method in {@code clazz}
|
||||
* @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
|
||||
* {@code -XX:-UseJVMCINativeLibrary})
|
||||
* @throws IllegalStateException if the current execution context is the JVMCI shared library
|
||||
* @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
|
||||
* @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) {
|
||||
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
|
||||
* @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
|
||||
*
|
||||
* @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
|
||||
* @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"
|
||||
*
|
||||
@ -959,6 +946,44 @@ assert factories != null : "sanity";
|
||||
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
|
||||
* with {@link #compileMethod}.
|
||||
|
@ -193,8 +193,7 @@ public final class HotSpotVMConfigStore {
|
||||
private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
|
||||
String line = String.format(format, args);
|
||||
byte[] lineBytes = line.getBytes();
|
||||
vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
|
||||
vm.flushDebugOutput();
|
||||
vm.writeDebugOutput(lineBytes, 0, lineBytes.length, true, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,16 +49,23 @@ final class TranslatedException extends Exception {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMessage();
|
||||
}
|
||||
private static Throwable create(String className, String message) {
|
||||
// Try create with reflection first.
|
||||
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())) {
|
||||
// Chop the class name when boxing another TranslatedException
|
||||
return new TranslatedException(message);
|
||||
}
|
||||
|
||||
if (message == null) {
|
||||
return new TranslatedException(className);
|
||||
}
|
||||
@ -147,7 +154,7 @@ final class TranslatedException extends Exception {
|
||||
Throwable throwable = create(exceptionClassName, exceptionMessage);
|
||||
int stackTraceDepth = Integer.parseInt(parts[i++]);
|
||||
|
||||
StackTraceElement[] suffix = parent == null ? new StackTraceElement[0] : getStackTraceSuffix();
|
||||
StackTraceElement[] suffix = getStackTraceSuffix();
|
||||
StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length];
|
||||
for (int j = 0; j < stackTraceDepth; j++) {
|
||||
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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,13 +38,13 @@ public class MetaUtil {
|
||||
* @return the simple name
|
||||
*/
|
||||
public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) {
|
||||
final String simpleName = clazz.getSimpleName();
|
||||
final String simpleName = safeSimpleName(clazz);
|
||||
if (simpleName.length() != 0) {
|
||||
if (withEnclosingClass) {
|
||||
String prefix = "";
|
||||
Class<?> enclosingClass = clazz;
|
||||
while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) {
|
||||
prefix = enclosingClass.getSimpleName() + "." + prefix;
|
||||
prefix = safeSimpleName(enclosingClass) + "." + prefix;
|
||||
}
|
||||
return prefix + simpleName;
|
||||
}
|
||||
@ -63,6 +63,29 @@ public class MetaUtil {
|
||||
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.
|
||||
*
|
||||
|
@ -282,6 +282,17 @@ public final class Services {
|
||||
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
|
||||
* the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial
|
||||
@ -292,25 +303,48 @@ public final class Services {
|
||||
if (IS_IN_NATIVE_IMAGE) {
|
||||
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
|
||||
// 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()) {
|
||||
String name = e.getKey();
|
||||
String value = e.getValue();
|
||||
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);
|
||||
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()) {
|
||||
String name = e.getKey();
|
||||
String value = e.getValue();
|
||||
out.writeUTF(name);
|
||||
out.writeUTF(value);
|
||||
if (name.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH && value.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH) {
|
||||
out.writeUTF(name);
|
||||
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();
|
||||
}
|
||||
@ -325,13 +359,33 @@ public final class Services {
|
||||
if (!IS_IN_NATIVE_IMAGE) {
|
||||
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));
|
||||
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) {
|
||||
String name = in.readUTF();
|
||||
String value = in.readUTF();
|
||||
props.put(name, value);
|
||||
if (index < utf8Props) {
|
||||
String name = in.readUTF();
|
||||
String value = in.readUTF();
|
||||
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);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
savedProperties = Collections.unmodifiableMap(props);
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
42
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/SuppressFBWarnings.java
Normal file
42
src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/SuppressFBWarnings.java
Normal file
@ -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.
|
||||
*
|
||||
* 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
|
||||
jdk.internal.vm.compiler,
|
||||
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.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.util.GraphUtil;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
@ -83,7 +84,7 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica
|
||||
public void generate(NodeLIRBuilderTool gen) {
|
||||
assert constant != null : "Expected the value to fold: " + value;
|
||||
Value result;
|
||||
if (constant instanceof HotSpotObjectConstant) {
|
||||
if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) {
|
||||
result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant);
|
||||
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
||||
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.word.Word;
|
||||
|
||||
import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
|
||||
import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
|
||||
import jdk.vm.ci.hotspot.HotSpotObjectConstant;
|
||||
import jdk.vm.ci.meta.Constant;
|
||||
@ -100,7 +101,7 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can
|
||||
Value result;
|
||||
LIRFrameState fs = gen.state(this);
|
||||
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);
|
||||
} else if (constant instanceof HotSpotMetaspaceConstant) {
|
||||
if (action == HotSpotConstantLoadAction.RESOLVE) {
|
||||
|
@ -301,7 +301,7 @@ public class CompilerToVMHelper {
|
||||
}
|
||||
|
||||
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() {
|
||||
|
117
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java
Normal file
117
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
82
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java
Normal file
82
test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java
Normal file
@ -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.
|
||||
*
|
||||
* 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 =
|
||||
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.hotspot",
|
||||
"jdk.internal.vm.ci/jdk.vm.ci.meta",
|
||||
"jdk.internal.vm.ci/jdk.vm.ci.code",
|
||||
"jdk.jsobject/jdk.internal.netscape.javascript.spi");
|
||||
|
||||
static void checkExports(ModuleDescriptor md) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user