8223332: Update JVMCI

Reviewed-by: never, dnsimon
This commit is contained in:
Vladimir Kozlov 2019-05-06 20:05:19 -07:00
parent 29a4ad9a87
commit 72f082e925
30 changed files with 1038 additions and 345 deletions
src
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;
}
}

@ -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() {

@ -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.
*
* 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) {