mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8309390: [JVMCI] improve copying system properties into libgraal
Reviewed-by: never, kvn
This commit is contained in:
parent
63843b1153
commit
c0aa6bf4fe
19 changed files with 453 additions and 197 deletions
|
@ -754,7 +754,6 @@
|
|||
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
|
||||
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
|
||||
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
|
||||
template(serializeSavedPropertiesToByteArray_name, "serializeSavedPropertiesToByteArray") \
|
||||
template(encodeThrowable_name, "encodeThrowable") \
|
||||
template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \
|
||||
template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "oops/typeArrayOop.inline.hpp"
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/jniHandles.inline.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
@ -45,9 +46,6 @@
|
|||
#include "jvmci/jvmciCompiler.hpp"
|
||||
#include "jvmci/jvmciRuntime.hpp"
|
||||
|
||||
jbyte* JVMCIEnv::_serialized_saved_properties = nullptr;
|
||||
int JVMCIEnv::_serialized_saved_properties_len = 0;
|
||||
|
||||
JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):
|
||||
_task(task),
|
||||
_compiler(compiler),
|
||||
|
@ -117,76 +115,6 @@ bool JVMCICompileState::jvmti_state_changed() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
jbyte* JVMCIEnv::get_serialized_saved_properties(int& props_len, TRAPS) {
|
||||
jbyte* props = _serialized_saved_properties;
|
||||
if (props == nullptr) {
|
||||
// load VMSupport
|
||||
Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport();
|
||||
Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK_NULL);
|
||||
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
if (ik->should_be_initialized()) {
|
||||
ik->initialize(CHECK_NULL);
|
||||
}
|
||||
|
||||
// invoke the serializeSavedPropertiesToByteArray method
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCallArguments args;
|
||||
|
||||
Symbol* signature = vmSymbols::void_byte_array_signature();
|
||||
JavaCalls::call_static(&result,
|
||||
ik,
|
||||
vmSymbols::serializeSavedPropertiesToByteArray_name(),
|
||||
signature,
|
||||
&args,
|
||||
CHECK_NULL);
|
||||
|
||||
oop res = result.get_oop();
|
||||
assert(res->is_typeArray(), "must be");
|
||||
assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be");
|
||||
typeArrayOop ba = typeArrayOop(res);
|
||||
props_len = ba->length();
|
||||
|
||||
// Copy serialized saved properties from HotSpot object into C heap
|
||||
props = NEW_C_HEAP_ARRAY(jbyte, props_len, mtJVMCI);
|
||||
memcpy(props, ba->byte_at_addr(0), props_len);
|
||||
|
||||
_serialized_saved_properties_len = props_len;
|
||||
_serialized_saved_properties = props;
|
||||
} else {
|
||||
props_len = _serialized_saved_properties_len;
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
void JVMCIEnv::copy_saved_properties(jbyte* properties, int properties_len, JVMCI_TRAPS) {
|
||||
assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
|
||||
JavaThread* thread = JavaThread::current(); // For exception macros.
|
||||
|
||||
// Copy native buffer into shared library object
|
||||
JVMCIPrimitiveArray buf = new_byteArray(properties_len, this);
|
||||
if (has_pending_exception()) {
|
||||
_runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties");
|
||||
}
|
||||
copy_bytes_from(properties, buf, 0, properties_len);
|
||||
if (has_pending_exception()) {
|
||||
_runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties");
|
||||
}
|
||||
|
||||
// Initialize saved properties in shared library
|
||||
jclass servicesClass = JNIJVMCI::Services::clazz();
|
||||
jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method();
|
||||
bool exception = false;
|
||||
{
|
||||
JNIAccessMark jni(this, thread);
|
||||
jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject());
|
||||
exception = jni()->ExceptionCheck();
|
||||
}
|
||||
if (exception) {
|
||||
_runtime->fatal_exception(JVMCIENV, "Error calling jdk.vm.ci.services.Services.initializeSavedProperties");
|
||||
}
|
||||
}
|
||||
|
||||
void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, bool jni_enomem_is_fatal) {
|
||||
assert(thread != nullptr, "npe");
|
||||
_env = nullptr;
|
||||
|
@ -1937,7 +1865,7 @@ nmethod* JVMCIEnv::get_nmethod(JVMCIObject obj) {
|
|||
}
|
||||
#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
|
||||
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
|
||||
JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
|
||||
|
|
|
@ -183,12 +183,6 @@ class JVMCIEnv : public ResourceObj {
|
|||
// The translated exception is pending in hotspot_env upon returning.
|
||||
static void translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env);
|
||||
|
||||
// Used by copy_saved_properties() to avoid OutOfMemoryErrors when
|
||||
// initializing a libjvmci runtime in low HotSpot heap conditions.
|
||||
// Must hold JVMCI_lock when initializing.
|
||||
static jbyte* _serialized_saved_properties;
|
||||
static int _serialized_saved_properties_len;
|
||||
|
||||
public:
|
||||
// Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM).
|
||||
// An exception occurring within the scope is left pending when the
|
||||
|
@ -237,14 +231,6 @@ public:
|
|||
return _runtime;
|
||||
}
|
||||
|
||||
// Gets the serialized saved properties from the HotSpot heap.
|
||||
// The length of the returned array is saved in `len`.
|
||||
jbyte* get_serialized_saved_properties(int& len, TRAPS);
|
||||
|
||||
// Initializes Services.savedProperties in the shared library from the given
|
||||
// properties in the format produced by `get_serialized_saved_properties`.
|
||||
void copy_saved_properties(jbyte* properties, int properties_len, JVMCI_TRAPS);
|
||||
|
||||
jboolean has_pending_exception();
|
||||
void clear_pending_exception();
|
||||
|
||||
|
@ -509,7 +495,7 @@ public:
|
|||
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_FIELD(className, name, jboolean)
|
||||
#define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, oop)
|
||||
#define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, objArrayOop)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
|
||||
JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
|
||||
|
|
|
@ -151,10 +151,10 @@ jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method;
|
|||
#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
|
||||
#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
|
||||
#ifdef PRODUCT
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
#else
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName) \
|
||||
check_resolve_method(#hsCallType, k, vmSymbols::methodName##_name(), vmSymbols::signatureSymbolName(), CHECK);
|
||||
#define CONSTRUCTOR(className, signature) { \
|
||||
TempNewSymbol sig = SymbolTable::new_symbol(signature); \
|
||||
|
@ -254,7 +254,7 @@ void HotSpotJVMCI::compute_offsets(TRAPS) {
|
|||
|
||||
#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint)
|
||||
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
|
||||
/**
|
||||
|
@ -393,7 +393,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
#define GET_JNI_CONSTRUCTOR(clazz, signature) \
|
||||
GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "<init>", signature) \
|
||||
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName) \
|
||||
GET_JNI_METHOD(jniGetMethod, \
|
||||
className::_##methodName##_method, \
|
||||
className::clazz(), \
|
||||
|
@ -406,6 +406,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
|
|||
extern "C" {
|
||||
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
|
||||
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
|
||||
jlong JNICALL JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets_handle);
|
||||
}
|
||||
|
||||
// Dumps symbols for public <init>() and <init>(String) methods of
|
||||
|
@ -566,9 +567,11 @@ void JNIJVMCI::register_natives(JNIEnv* env) {
|
|||
if (env != JavaThread::current()->jni_environment()) {
|
||||
JNINativeMethod CompilerToVM_nmethods[] = {{ CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) }};
|
||||
JNINativeMethod JVMCI_nmethods[] = {{ CC"initializeRuntime", CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) }};
|
||||
JNINativeMethod Services_nmethods[] = {{ CC"readSystemPropertiesInfo", CC"([I)J", FN_PTR(JVM_ReadSystemPropertiesInfo) }};
|
||||
|
||||
register_natives_for_class(env, nullptr, "jdk/vm/ci/hotspot/CompilerToVM", CompilerToVM_nmethods, 1);
|
||||
register_natives_for_class(env, JVMCI::clazz(), "jdk/vm/ci/runtime/JVMCI", JVMCI_nmethods, 1);
|
||||
register_natives_for_class(env, Services::clazz(), "jdk/vm/ci/services/Services", Services_nmethods, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,7 +586,7 @@ void JNIJVMCI::register_natives(JNIEnv* env) {
|
|||
#define FIELD2(className, name) \
|
||||
jfieldID JNIJVMCI::className::_##name##_field_id = 0; \
|
||||
int HotSpotJVMCI::className::_##name##_offset = 0;
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
|
||||
// Generates the definitions of static fields used by the accessors. For example:
|
||||
|
@ -689,7 +692,7 @@ JVMCI_CLASSES_DO(EMPTY2, EMPTY0, FIELD2, FIELD2, FIELD2, FIELD2, FIELD2, FIELD3,
|
|||
|
||||
#define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
|
||||
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName) \
|
||||
jmethodID JNIJVMCI::className::_##methodName##_method;
|
||||
|
||||
#define CONSTRUCTOR(className, signature) \
|
||||
|
|
|
@ -56,9 +56,6 @@
|
|||
static_boolean_field, \
|
||||
jvmci_method, \
|
||||
jvmci_constructor) \
|
||||
start_class(Services, jdk_vm_ci_services_Services) \
|
||||
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, Services, initializeSavedProperties, byte_array_void_signature, (JVMCIObject serializedProperties)) \
|
||||
end_class \
|
||||
start_class(Architecture, jdk_vm_ci_code_Architecture) \
|
||||
object_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;") \
|
||||
end_class \
|
||||
|
@ -160,7 +157,7 @@
|
|||
start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant) \
|
||||
static_object_field(JavaConstant, ILLEGAL, "Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
static_object_field(JavaConstant, NULL_POINTER, "Ljdk/vm/ci/meta/JavaConstant;") \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forPrimitive, forPrimitive_signature, (JVMCIObject kind, jlong value, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JavaConstant, forPrimitive, forPrimitive_signature) \
|
||||
end_class \
|
||||
start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod) \
|
||||
end_class \
|
||||
|
@ -200,34 +197,36 @@
|
|||
end_class \
|
||||
start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime) \
|
||||
objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;") \
|
||||
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \
|
||||
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature, (JVMCIObject runtime, int gcIdentifier)) \
|
||||
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \
|
||||
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature, (JVMCIObject object, bool toString, bool stackTrace, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature, (JVMCIObject object, JVMCI_TRAPS)) \
|
||||
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature) \
|
||||
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature) \
|
||||
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature) \
|
||||
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature) \
|
||||
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature) \
|
||||
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature) \
|
||||
end_class \
|
||||
start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \
|
||||
jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V") \
|
||||
end_class \
|
||||
start_class(InspectedFrameVisitor, jdk_vm_ci_code_stack_InspectedFrameVisitor) \
|
||||
end_class \
|
||||
start_class(Services, jdk_vm_ci_services_Services) \
|
||||
end_class \
|
||||
start_class(JVMCI, jdk_vm_ci_runtime_JVMCI) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, getRuntime, getRuntime_signature, (JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature, (JVMCI_TRAPS)) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, getRuntime, getRuntime_signature) \
|
||||
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature) \
|
||||
end_class \
|
||||
start_class(Object, java_lang_Object) \
|
||||
end_class \
|
||||
start_class(String, java_lang_String) \
|
||||
end_class \
|
||||
start_class(Class, java_lang_Class) \
|
||||
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, Class, getName, void_string_signature, (JVMCI_TRAPS)) \
|
||||
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, Class, getName, void_string_signature) \
|
||||
end_class \
|
||||
start_class(VMSupport, jdk_internal_vm_VMSupport) \
|
||||
jvmci_method(CallStaticIntMethod, GetStaticMethodID, call_static, int, VMSupport, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable, jlong buffer, int buffer_size)) \
|
||||
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, VMSupport, decodeAndThrowThrowable, decodeAndThrowThrowable_signature, (jlong buffer)) \
|
||||
jvmci_method(CallStaticIntMethod, GetStaticMethodID, call_static, int, VMSupport, encodeThrowable, encodeThrowable_signature) \
|
||||
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, VMSupport, decodeAndThrowThrowable, decodeAndThrowThrowable_signature) \
|
||||
end_class \
|
||||
start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException) \
|
||||
jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V") \
|
||||
|
@ -342,7 +341,7 @@ class JVMCIEnv;
|
|||
static hstype name(JVMCIEnv* env); \
|
||||
static void set_ ## name(JVMCIEnv* env, hstype hstype);
|
||||
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, simpleClassName, methodName, signatureSymbolName, args)
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, simpleClassName, methodName, signatureSymbolName)
|
||||
#define CONSTRUCTOR(className, signature)
|
||||
|
||||
/**
|
||||
|
@ -435,7 +434,7 @@ public:
|
|||
#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype) \
|
||||
STATIC_FIELD(simpleClassName, name, type)
|
||||
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args) \
|
||||
#define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName) \
|
||||
public: \
|
||||
static jmethodID methodName##_method() { return _##methodName##_method; } \
|
||||
private: \
|
||||
|
|
|
@ -754,6 +754,21 @@ JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
|
|||
return JVMCIENV->get_jobject(runtime);
|
||||
JVM_END
|
||||
|
||||
// private static long Services.readSystemPropertiesInfo(int[] offsets)
|
||||
JVM_ENTRY_NO_ENV(jlong, JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets_handle))
|
||||
JNI_JVMCIENV(thread, env);
|
||||
if (!EnableJVMCI) {
|
||||
JVMCI_THROW_MSG_0(InternalError, "JVMCI is not enabled");
|
||||
}
|
||||
JVMCIPrimitiveArray offsets = JVMCIENV->wrap(offsets_handle);
|
||||
JVMCIENV->put_int_at(offsets, 0, SystemProperty::next_offset_in_bytes());
|
||||
JVMCIENV->put_int_at(offsets, 1, SystemProperty::key_offset_in_bytes());
|
||||
JVMCIENV->put_int_at(offsets, 2, PathString::value_offset_in_bytes());
|
||||
|
||||
return (jlong) Arguments::system_properties();
|
||||
JVM_END
|
||||
|
||||
|
||||
void JVMCIRuntime::call_getCompiler(TRAPS) {
|
||||
THREAD_JVMCIENV(JavaThread::current());
|
||||
JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);
|
||||
|
@ -1399,9 +1414,6 @@ void JVMCIRuntime::initialize(JVMCI_TRAPS) {
|
|||
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
|
||||
int properties_len = 0;
|
||||
jbyte* properties = nullptr;
|
||||
|
||||
MutexLocker locker(_lock);
|
||||
// Check again under _lock
|
||||
if (_init_state == fully_initialized) {
|
||||
|
@ -1464,16 +1476,6 @@ void JVMCIRuntime::initialize(JVMCI_TRAPS) {
|
|||
create_jvmci_primitive_type(T_VOID, JVMCI_CHECK_EXIT_((void)0));
|
||||
|
||||
DEBUG_ONLY(CodeInstaller::verify_bci_constants(JVMCIENV);)
|
||||
|
||||
if (!JVMCIENV->is_hotspot()) {
|
||||
Handle properties_exception;
|
||||
properties = JVMCIENV->get_serialized_saved_properties(properties_len, THREAD);
|
||||
if (JVMCIEnv::transfer_pending_exception_to_jni(THREAD, nullptr, JVMCIENV)) {
|
||||
JVMCI_event_1("error initializing system properties for JVMCI runtime %d", _id);
|
||||
return;
|
||||
}
|
||||
JVMCIENV->copy_saved_properties(properties, properties_len, JVMCI_CHECK);
|
||||
}
|
||||
}
|
||||
|
||||
_init_state = fully_initialized;
|
||||
|
|
|
@ -102,7 +102,6 @@
|
|||
template(forPrimitive_name, "forPrimitive") \
|
||||
template(forPrimitive_signature, "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;") \
|
||||
template(method_string_bool_long_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
|
||||
template(initializeSavedProperties_name, "initializeSavedProperties") \
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -210,6 +210,7 @@ extern "C" {
|
|||
void JNICALL JVM_RegisterVectorSupportMethods(JNIEnv *env, jclass vsclass);
|
||||
#if INCLUDE_JVMCI
|
||||
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
|
||||
jlong JNICALL JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets);
|
||||
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
|
||||
#endif
|
||||
}
|
||||
|
@ -229,6 +230,7 @@ static JNINativeMethod lookup_special_native_methods[] = {
|
|||
{ CC"Java_jdk_internal_vm_vector_VectorSupport_registerNatives", nullptr, FN_PTR(JVM_RegisterVectorSupportMethods)},
|
||||
#if INCLUDE_JVMCI
|
||||
{ CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", nullptr, FN_PTR(JVM_GetJVMCIRuntime) },
|
||||
{ CC"Java_jdk_vm_ci_services_Services_readSystemPropertiesInfo", nullptr, FN_PTR(JVM_ReadSystemPropertiesInfo) },
|
||||
{ CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", nullptr, FN_PTR(JVM_RegisterJVMCINatives) },
|
||||
#endif
|
||||
#if INCLUDE_JFR
|
||||
|
|
|
@ -75,6 +75,9 @@ class PathString : public CHeapObj<mtArguments> {
|
|||
|
||||
PathString(const char* value);
|
||||
~PathString();
|
||||
|
||||
// for JVM_ReadSystemPropertiesInfo
|
||||
static int value_offset_in_bytes() { return (int)offset_of(PathString, _value); }
|
||||
};
|
||||
|
||||
// ModulePatchPath records the module/path pair as specified to --patch-module.
|
||||
|
@ -136,6 +139,10 @@ class SystemProperty : public PathString {
|
|||
|
||||
// Constructor
|
||||
SystemProperty(const char* key, const char* value, bool writeable, bool internal = false);
|
||||
|
||||
// for JVM_ReadSystemPropertiesInfo
|
||||
static int key_offset_in_bytes() { return (int)offset_of(SystemProperty, _key); }
|
||||
static int next_offset_in_bytes() { return (int)offset_of(SystemProperty, _next); }
|
||||
};
|
||||
|
||||
// Helper class for controlling the lifetime of JavaVMInitArgs objects.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2023, 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
|
||||
|
@ -101,19 +101,6 @@ public class VMSupport {
|
|||
return serializePropertiesToByteArray(onlyStrings(getAgentProperties()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes {@link VM#getSavedProperties()} to a byte array.
|
||||
*
|
||||
* Used by JVMCI to copy properties into libjvmci.
|
||||
*/
|
||||
public static byte[] serializeSavedPropertiesToByteArray() throws IOException {
|
||||
Properties props = new Properties();
|
||||
for (var e : VM.getSavedProperties().entrySet()) {
|
||||
props.put(e.getKey(), e.getValue());
|
||||
}
|
||||
return serializePropertiesToByteArray(props);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the temporary directory that the VM uses for the attach
|
||||
* and perf data files.
|
||||
|
|
|
@ -278,6 +278,7 @@ module java.base {
|
|||
java.security.jgss,
|
||||
java.smartcardio,
|
||||
jdk.charsets,
|
||||
jdk.internal.vm.ci,
|
||||
jdk.jlink,
|
||||
jdk.jpackage,
|
||||
jdk.net;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2009, 2023, 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
|
||||
|
@ -26,6 +26,7 @@ import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
|
|||
|
||||
import jdk.vm.ci.meta.JavaKind;
|
||||
import jdk.vm.ci.services.Services;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
/**
|
||||
* Represents the target machine for a compiler, including the CPU architecture, the size of
|
||||
|
@ -33,8 +34,8 @@ import jdk.vm.ci.services.Services;
|
|||
*/
|
||||
public class TargetDescription {
|
||||
|
||||
public final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux");
|
||||
public final boolean macOs = Services.getSavedProperty("os.name", "").startsWith("Mac");
|
||||
public final boolean linuxOs = OperatingSystem.isLinux();
|
||||
public final boolean macOs = OperatingSystem.isMacOS();
|
||||
|
||||
public final Architecture arch;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, 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
|
||||
|
|
|
@ -28,6 +28,7 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
|
|||
import jdk.vm.ci.common.JVMCIError;
|
||||
import jdk.vm.ci.services.Services;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.util.Architecture;
|
||||
|
||||
/**
|
||||
* Used to access native configuration details.
|
||||
|
@ -43,8 +44,6 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
return runtime().getConfig();
|
||||
}
|
||||
|
||||
private final String osArch = getHostArchitectureName();
|
||||
|
||||
HotSpotVMConfig(HotSpotVMConfigStore store) {
|
||||
super(store);
|
||||
|
||||
|
@ -57,13 +56,10 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
* {@linkplain HotSpotJVMCIBackendFactory backend}.
|
||||
*/
|
||||
String getHostArchitectureName() {
|
||||
String arch = Services.getSavedProperty("os.arch");
|
||||
Architecture arch = Architecture.current();
|
||||
switch (arch) {
|
||||
case "x86_64":
|
||||
return "amd64";
|
||||
|
||||
default:
|
||||
return arch;
|
||||
case X64: return "amd64";
|
||||
default: return arch.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +130,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
final int jvmMiscFlagsDeclaresDefaultMethods = getConstant("InstanceKlassFlags::_misc_declares_nonstatic_concrete_methods", Integer.class);
|
||||
|
||||
// This is only valid on AMD64.
|
||||
final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, osArch.equals("amd64") ? null : 0);
|
||||
final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, Architecture.isX64() ? null : 0);
|
||||
|
||||
private final int markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Integer.class);
|
||||
private final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, 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
|
||||
|
@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot.amd64;
|
|||
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
|
||||
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
|
||||
import jdk.vm.ci.services.Services;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
/**
|
||||
* Used to access AMD64 specific native configuration details.
|
||||
|
@ -35,7 +36,7 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
super(config);
|
||||
}
|
||||
|
||||
final boolean windowsOs = Services.getSavedProperty("os.name", "").startsWith("Windows");
|
||||
final boolean windowsOs = OperatingSystem.isWindows();
|
||||
|
||||
final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
|
||||
final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
|
@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot.riscv64;
|
|||
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
|
||||
import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
|
||||
import jdk.vm.ci.services.Services;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
/**
|
||||
* Used to access native configuration details.
|
||||
|
@ -37,7 +38,7 @@ class RISCV64HotSpotVMConfig extends HotSpotVMConfigAccess {
|
|||
super(config);
|
||||
}
|
||||
|
||||
final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux");
|
||||
final boolean linuxOs = OperatingSystem.isLinux();
|
||||
|
||||
final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2023, 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
|
||||
|
@ -22,16 +22,12 @@
|
|||
*/
|
||||
package jdk.vm.ci.services;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Formatter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
@ -39,6 +35,9 @@ import java.util.function.Supplier;
|
|||
|
||||
import jdk.internal.misc.TerminatingThreadLocal;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.internal.util.Architecture;
|
||||
import jdk.internal.util.OperatingSystem;
|
||||
|
||||
/**
|
||||
* Provides utilities needed by JVMCI clients.
|
||||
|
@ -71,7 +70,7 @@ public final class Services {
|
|||
}
|
||||
|
||||
/**
|
||||
* In a native image, this field is initialized by {@link #initializeSavedProperties(byte[])}.
|
||||
* Lazily initialized in {@link #getSavedProperties}.
|
||||
*/
|
||||
private static volatile Map<String, String> savedProperties;
|
||||
|
||||
|
@ -87,25 +86,17 @@ public final class Services {
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an unmodifiable copy of the system properties saved when {@link System} is initialized.
|
||||
* Gets an unmodifiable copy of the system properties parsed by {@code arguments.cpp}
|
||||
* plus {@code java.specification.version}, {@code os.name} and {@code os.arch}.
|
||||
* The latter two are forced to be the real OS and architecture. That is, values
|
||||
* for these two properties set on the command line are ignored.
|
||||
*/
|
||||
public static Map<String, String> getSavedProperties() {
|
||||
checkJVMCIEnabled();
|
||||
if (IS_IN_NATIVE_IMAGE) {
|
||||
if (savedProperties == null) {
|
||||
throw new InternalError("Saved properties not initialized");
|
||||
}
|
||||
} else {
|
||||
if (savedProperties == null) {
|
||||
synchronized (Services.class) {
|
||||
if (savedProperties == null) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new JVMCIPermission());
|
||||
}
|
||||
savedProperties = VM.getSavedProperties();
|
||||
}
|
||||
savedProperties = initProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -261,22 +252,128 @@ public final class Services {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes {@link #savedProperties} from the byte array returned by
|
||||
* {@code jdk.internal.vm.VMSupport.serializeSavedPropertiesToByteArray()}.
|
||||
*/
|
||||
@VMEntryPoint
|
||||
private static void initializeSavedProperties(byte[] serializedProperties) throws IOException {
|
||||
if (!IS_IN_NATIVE_IMAGE) {
|
||||
throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime");
|
||||
static String toJavaString(Unsafe unsafe, long cstring) {
|
||||
if (cstring == 0) {
|
||||
return null;
|
||||
}
|
||||
Properties props = new Properties();
|
||||
props.load(new ByteArrayInputStream(serializedProperties));
|
||||
Map<String, String> map = new HashMap<>(props.size());
|
||||
for (var e : props.entrySet()) {
|
||||
map.put((String) e.getKey(), (String) e.getValue());
|
||||
int len = 0;
|
||||
for (long p = cstring; unsafe.getByte(p) != 0; p++) {
|
||||
len++;
|
||||
}
|
||||
byte[] buf = new byte[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
buf[i] = unsafe.getByte(cstring + i);
|
||||
}
|
||||
return new String(buf, java.nio.charset.StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
savedProperties = Collections.unmodifiableMap(map);
|
||||
/**
|
||||
* Gets the value of {@code Arguments::systemProperties()} and puts the offsets
|
||||
* of {@code SystemProperty} fields into {@code offsets}. The values returned in
|
||||
* {@code offsets} are:
|
||||
*
|
||||
* <pre>
|
||||
* [ next, // SystemProperty::next_offset_in_bytes()
|
||||
* key, // SystemProperty::key_offset_in_bytes()
|
||||
* value // PathString::value_offset_in_bytes()
|
||||
* ]
|
||||
* </pre>
|
||||
*
|
||||
* Ideally this would be done with vmstructs but that code is in {@code jdk.vm.ci.hotspot}.
|
||||
*/
|
||||
private static native long readSystemPropertiesInfo(int[] offsets);
|
||||
|
||||
/**
|
||||
* Parses the native {@code Arguments::systemProperties()} data structure using Unsafe to
|
||||
* create a properties map. This parsing is safe as argument parsing in completed in
|
||||
* early VM start before this code can be executed, making {@code Arguments::systemProperties()}
|
||||
* effectively read-only by now.
|
||||
*/
|
||||
private static Map<String, String> initProperties() {
|
||||
int[] offsets = new int[3];
|
||||
long systemProperties = readSystemPropertiesInfo(offsets);
|
||||
int nextOffset = offsets[0];
|
||||
int keyOffset = offsets[1];
|
||||
int valueOffset = offsets[2];
|
||||
|
||||
int count = 0;
|
||||
Unsafe unsafe = Unsafe.getUnsafe();
|
||||
for (long prop = systemProperties; prop != 0; prop = unsafe.getLong(prop + nextOffset)) {
|
||||
if (unsafe.getLong(prop + valueOffset) != 0) {
|
||||
count++;
|
||||
} else {
|
||||
// Some internal properties (e.g. jdk.boot.class.path.append) can have a null
|
||||
// value and should just be ignored. Note that null is different than the empty string.
|
||||
}
|
||||
}
|
||||
Map<String, SystemProperties.Value> props = new HashMap<>(count + 1);
|
||||
int i = 0;
|
||||
for (long prop = systemProperties; prop != 0; prop = unsafe.getLong(prop + nextOffset)) {
|
||||
String key = toJavaString(unsafe, unsafe.getLong(prop + keyOffset));
|
||||
long valueAddress = unsafe.getLong(prop + valueOffset);
|
||||
if (valueAddress != 0) {
|
||||
props.put(key, new SystemProperties.Value(unsafe, valueAddress));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i != count) {
|
||||
throw new InternalError(i + " != " + count);
|
||||
}
|
||||
if (!props.containsKey("java.specification.version")) {
|
||||
SystemProperties.Value v = Objects.requireNonNull(props.get("java.vm.specification.version"));
|
||||
props.put("java.specification.version", v);
|
||||
}
|
||||
|
||||
SystemProperties res = new SystemProperties(unsafe, sanitizeOSArch(props));
|
||||
if ("true".equals(res.get("debug.jvmci.PrintSavedProperties"))) {
|
||||
System.out.println("[Saved system properties]");
|
||||
for (Map.Entry<String, String> e : res.entrySet()) {
|
||||
System.out.printf("%s=%s%n", e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Force os.name and os.arch to reflect the actual OS and architecture.
|
||||
// JVMCI configures itself based on these values and needs to be isolated
|
||||
// from apps that set them on the command line.
|
||||
private static Map<String, SystemProperties.Value> sanitizeOSArch(Map<String, SystemProperties.Value> props) {
|
||||
props.put("os.arch", new SystemProperties.Value(realArch()));
|
||||
props.put("os.name", new SystemProperties.Value(realOS()));
|
||||
return props;
|
||||
}
|
||||
|
||||
private static String realOS() {
|
||||
OperatingSystem os = OperatingSystem.current();
|
||||
switch (os) {
|
||||
case LINUX: return "Linux";
|
||||
case MACOS: return "Mac OS X";
|
||||
case AIX: return "AIX";
|
||||
case WINDOWS: {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.startsWith("Windows")) {
|
||||
// Use original value which is often more "complete"
|
||||
// E.g. "Windows Server 2012"
|
||||
return osName;
|
||||
}
|
||||
return "Windows";
|
||||
}
|
||||
default: throw new InternalError("missing case for " + os);
|
||||
}
|
||||
}
|
||||
|
||||
private static String realArch() {
|
||||
Architecture arch = Architecture.current();
|
||||
switch (arch) {
|
||||
case X64: return "x86_64";
|
||||
case X86: return "x86";
|
||||
case AARCH64: return "aarch64";
|
||||
case RISCV64: return "riscv64";
|
||||
case ARM: return "arm";
|
||||
case S390: return "s390";
|
||||
case PPC64: return "ppc64";
|
||||
case OTHER: return "other";
|
||||
default: throw new InternalError("missing case for " + arch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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.services;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
/**
|
||||
* Unmodifiable map for storing system properties read from native memory whose values have their
|
||||
* string representation constructed on first access.
|
||||
*/
|
||||
final class SystemProperties implements Map<String, String> {
|
||||
|
||||
private final Unsafe unsafe;
|
||||
private final Map<String, Value> entries;
|
||||
private Set<Entry<String, String>> entrySet;
|
||||
private Collection<String> values;
|
||||
|
||||
SystemProperties(Unsafe unsafe, Map<String, Value> entries) {
|
||||
this.unsafe = unsafe;
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return entries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return entries.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return entries.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
for (Value v : entries.values()) {
|
||||
if (v.getString(unsafe).equals(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(Object key) {
|
||||
Value v = entries.get(key);
|
||||
if (v != null) {
|
||||
return v.getString(unsafe);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String put(String key, String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends String> m) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
return entries.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> values() {
|
||||
if (values == null) {
|
||||
values = entries.values().stream().map(v -> v.getString(unsafe)).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
static class Property implements Map.Entry<String, String> {
|
||||
private final Unsafe unsafe;
|
||||
private final String key;
|
||||
private final Value value;
|
||||
|
||||
Property(Unsafe unsafe, Map.Entry<String, Value> e) {
|
||||
this.unsafe = unsafe;
|
||||
this.key = e.getKey();
|
||||
this.value = e.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value.getString(unsafe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String setValue(String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Set<Entry<String, String>> entrySet() {
|
||||
if (entrySet == null) {
|
||||
entrySet = entries.entrySet().stream().map(e -> new Property(unsafe, e)).collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a value in {@link SystemProperties}.
|
||||
*/
|
||||
static class Value {
|
||||
private final long cstring;
|
||||
private volatile String string;
|
||||
|
||||
/**
|
||||
* Creates a value whose string representation will be lazily constructed from {@code cstring}.
|
||||
*/
|
||||
Value(Unsafe unsafe, long cstring) {
|
||||
this.cstring = cstring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a value whose string representation is known at construction time.
|
||||
*/
|
||||
Value(String string) {
|
||||
this.cstring = 0;
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
String getString(Unsafe unsafe) {
|
||||
if (string == null) {
|
||||
// Racy but it doesn't matter.
|
||||
string = Services.toJavaString(unsafe, cstring);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2023, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test TestJVMCISavedProperties
|
||||
* @bug 8309390
|
||||
* @summary Ensures Services.getSavedProperties() includes properties set on
|
||||
* the command line as well some specified properties but not
|
||||
* properties set programmatically.
|
||||
* @requires vm.flagless
|
||||
* @requires vm.jvmci
|
||||
* @library /test/lib
|
||||
* @run driver TestJVMCISavedProperties
|
||||
*/
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class TestJVMCISavedProperties {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 0) {
|
||||
System.setProperty("app3.NotPresentInSavedProperties", "42");
|
||||
System.out.println("DONE IN MAIN");
|
||||
return;
|
||||
}
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+EagerJVMCI",
|
||||
"-XX:+UseJVMCICompiler",
|
||||
"-Djvmci.Compiler=null",
|
||||
"-Ddebug.jvmci.PrintSavedProperties=true",
|
||||
"-Dapp1.propX=true",
|
||||
"-Dapp2.propY=SomeStringValue",
|
||||
"TestJVMCISavedProperties", "true");
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.stdoutShouldContain("debug.jvmci.PrintSavedProperties=true");
|
||||
output.stdoutShouldContain("jvmci.Compiler=null");
|
||||
output.stdoutShouldContain("app1.propX=true");
|
||||
output.stdoutShouldContain("app2.propY=SomeStringValue");
|
||||
output.stdoutShouldContain("java.specification.version=" + Runtime.version().feature());
|
||||
output.stdoutShouldContain("os.name=");
|
||||
output.stdoutShouldContain("os.arch=");
|
||||
output.stdoutShouldNotContain("NotPresentInSavedProperties");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue