8309390: [JVMCI] improve copying system properties into libgraal

Reviewed-by: never, kvn
This commit is contained in:
Doug Simon 2023-06-13 14:45:33 +00:00
parent 63843b1153
commit c0aa6bf4fe
19 changed files with 453 additions and 197 deletions

View file

@ -754,7 +754,6 @@
do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \ do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \
template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \ template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \
template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \ template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
template(serializeSavedPropertiesToByteArray_name, "serializeSavedPropertiesToByteArray") \
template(encodeThrowable_name, "encodeThrowable") \ template(encodeThrowable_name, "encodeThrowable") \
template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \ template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \
template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \

View file

@ -37,6 +37,7 @@
#include "oops/typeArrayOop.inline.hpp" #include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp" #include "prims/jvmtiExport.hpp"
#include "runtime/deoptimization.hpp" #include "runtime/deoptimization.hpp"
#include "runtime/fieldDescriptor.inline.hpp"
#include "runtime/jniHandles.inline.hpp" #include "runtime/jniHandles.inline.hpp"
#include "runtime/javaCalls.hpp" #include "runtime/javaCalls.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
@ -45,9 +46,6 @@
#include "jvmci/jvmciCompiler.hpp" #include "jvmci/jvmciCompiler.hpp"
#include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciRuntime.hpp"
jbyte* JVMCIEnv::_serialized_saved_properties = nullptr;
int JVMCIEnv::_serialized_saved_properties_len = 0;
JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler): JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):
_task(task), _task(task),
_compiler(compiler), _compiler(compiler),
@ -117,76 +115,6 @@ bool JVMCICompileState::jvmti_state_changed() const {
return false; 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) { void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env, bool jni_enomem_is_fatal) {
assert(thread != nullptr, "npe"); assert(thread != nullptr, "npe");
_env = nullptr; _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_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 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) #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) 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)

View file

@ -183,12 +183,6 @@ class JVMCIEnv : public ResourceObj {
// The translated exception is pending in hotspot_env upon returning. // 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); 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: public:
// Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM). // 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 // An exception occurring within the scope is left pending when the
@ -237,14 +231,6 @@ public:
return _runtime; 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(); jboolean has_pending_exception();
void clear_pending_exception(); void clear_pending_exception();
@ -509,7 +495,7 @@ public:
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_FIELD(className, name, jboolean) #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_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 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) #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) 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)

View file

@ -151,10 +151,10 @@ jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method;
#define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true) #define STATIC_INT_FIELD(className, name) FIELD(className, name, "I", true)
#define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true) #define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true)
#ifdef PRODUCT #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) #define CONSTRUCTOR(className, signature)
#else #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); check_resolve_method(#hsCallType, k, vmSymbols::methodName##_name(), vmSymbols::signatureSymbolName(), CHECK);
#define CONSTRUCTOR(className, signature) { \ #define CONSTRUCTOR(className, signature) { \
TempNewSymbol sig = SymbolTable::new_symbol(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_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint)
#define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean) #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) #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) \ #define GET_JNI_CONSTRUCTOR(clazz, signature) \
GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "<init>", 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, \ GET_JNI_METHOD(jniGetMethod, \
className::_##methodName##_method, \ className::_##methodName##_method, \
className::clazz(), \ className::clazz(), \
@ -406,6 +406,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz,
extern "C" { extern "C" {
void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass); void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c); 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 // 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()) { if (env != JavaThread::current()->jni_environment()) {
JNINativeMethod CompilerToVM_nmethods[] = {{ CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) }}; 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 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, 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, 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) \ #define FIELD2(className, name) \
jfieldID JNIJVMCI::className::_##name##_field_id = 0; \ jfieldID JNIJVMCI::className::_##name##_field_id = 0; \
int HotSpotJVMCI::className::_##name##_offset = 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) #define CONSTRUCTOR(className, signature)
// Generates the definitions of static fields used by the accessors. For example: // 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_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 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; jmethodID JNIJVMCI::className::_##methodName##_method;
#define CONSTRUCTOR(className, signature) \ #define CONSTRUCTOR(className, signature) \

View file

@ -56,9 +56,6 @@
static_boolean_field, \ static_boolean_field, \
jvmci_method, \ jvmci_method, \
jvmci_constructor) \ 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) \ start_class(Architecture, jdk_vm_ci_code_Architecture) \
object_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;") \ object_field(Architecture, wordKind, "Ljdk/vm/ci/meta/PlatformKind;") \
end_class \ end_class \
@ -160,7 +157,7 @@
start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant) \ start_class(JavaConstant, jdk_vm_ci_meta_JavaConstant) \
static_object_field(JavaConstant, ILLEGAL, "Ljdk/vm/ci/meta/PrimitiveConstant;") \ static_object_field(JavaConstant, ILLEGAL, "Ljdk/vm/ci/meta/PrimitiveConstant;") \
static_object_field(JavaConstant, NULL_POINTER, "Ljdk/vm/ci/meta/JavaConstant;") \ 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 \ end_class \
start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod) \ start_class(ResolvedJavaMethod, jdk_vm_ci_meta_ResolvedJavaMethod) \
end_class \ end_class \
@ -200,34 +197,36 @@
end_class \ end_class \
start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime) \ start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime) \
objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;") \ 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, compileMethod, compileMethod_signature) \
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature, (JVMCIObject runtime, int gcIdentifier)) \ jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature) \
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature) \
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature) \
jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \ jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, HotSpotJVMCIRuntime, getCompiler, getCompiler_signature) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature, (JVMCIObject object, bool toString, bool stackTrace, JVMCI_TRAPS)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, exceptionToString, exceptionToString_signature) \
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature, (JVMCIObject object, JVMCI_TRAPS)) \ jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, postTranslation, object_void_signature) \
end_class \ end_class \
start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \ start_class(JVMCIError, jdk_vm_ci_common_JVMCIError) \
jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V") \ jvmci_constructor(JVMCIError, "(Ljava/lang/String;)V") \
end_class \ end_class \
start_class(InspectedFrameVisitor, jdk_vm_ci_code_stack_InspectedFrameVisitor) \ start_class(InspectedFrameVisitor, jdk_vm_ci_code_stack_InspectedFrameVisitor) \
end_class \ end_class \
start_class(Services, jdk_vm_ci_services_Services) \
end_class \
start_class(JVMCI, jdk_vm_ci_runtime_JVMCI) \ 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, getRuntime, getRuntime_signature) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature, (JVMCI_TRAPS)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, JVMCI, initializeRuntime, initializeRuntime_signature) \
end_class \ end_class \
start_class(Object, java_lang_Object) \ start_class(Object, java_lang_Object) \
end_class \ end_class \
start_class(String, java_lang_String) \ start_class(String, java_lang_String) \
end_class \ end_class \
start_class(Class, java_lang_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 \ end_class \
start_class(VMSupport, jdk_internal_vm_VMSupport) \ 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(CallStaticIntMethod, GetStaticMethodID, call_static, int, VMSupport, encodeThrowable, encodeThrowable_signature) \
jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, VMSupport, decodeAndThrowThrowable, decodeAndThrowThrowable_signature, (jlong buffer)) \ jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, VMSupport, decodeAndThrowThrowable, decodeAndThrowThrowable_signature) \
end_class \ end_class \
start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException) \ start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException) \
jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V") \ jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V") \
@ -342,7 +341,7 @@ class JVMCIEnv;
static hstype name(JVMCIEnv* env); \ static hstype name(JVMCIEnv* env); \
static void set_ ## name(JVMCIEnv* env, hstype hstype); 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) #define CONSTRUCTOR(className, signature)
/** /**
@ -435,7 +434,7 @@ public:
#define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype) \ #define STATIC_OOPISH_FIELD(simpleClassName, name, type, hstype) \
STATIC_FIELD(simpleClassName, name, type) 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: \ public: \
static jmethodID methodName##_method() { return _##methodName##_method; } \ static jmethodID methodName##_method() { return _##methodName##_method; } \
private: \ private: \

View file

@ -754,6 +754,21 @@ JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
return JVMCIENV->get_jobject(runtime); return JVMCIENV->get_jobject(runtime);
JVM_END 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) { void JVMCIRuntime::call_getCompiler(TRAPS) {
THREAD_JVMCIENV(JavaThread::current()); THREAD_JVMCIENV(JavaThread::current());
JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK); JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK);
@ -1399,9 +1414,6 @@ void JVMCIRuntime::initialize(JVMCI_TRAPS) {
JavaThread* THREAD = JavaThread::current(); JavaThread* THREAD = JavaThread::current();
int properties_len = 0;
jbyte* properties = nullptr;
MutexLocker locker(_lock); MutexLocker locker(_lock);
// Check again under _lock // Check again under _lock
if (_init_state == fully_initialized) { 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)); create_jvmci_primitive_type(T_VOID, JVMCI_CHECK_EXIT_((void)0));
DEBUG_ONLY(CodeInstaller::verify_bci_constants(JVMCIENV);) 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; _init_state = fully_initialized;

View file

@ -102,7 +102,6 @@
template(forPrimitive_name, "forPrimitive") \ template(forPrimitive_name, "forPrimitive") \
template(forPrimitive_signature, "(CJ)Ljdk/vm/ci/meta/PrimitiveConstant;") \ 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(method_string_bool_long_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \
template(initializeSavedProperties_name, "initializeSavedProperties") \
#endif #endif

View file

@ -210,6 +210,7 @@ extern "C" {
void JNICALL JVM_RegisterVectorSupportMethods(JNIEnv *env, jclass vsclass); void JNICALL JVM_RegisterVectorSupportMethods(JNIEnv *env, jclass vsclass);
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c); 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); void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
#endif #endif
} }
@ -229,6 +230,7 @@ static JNINativeMethod lookup_special_native_methods[] = {
{ CC"Java_jdk_internal_vm_vector_VectorSupport_registerNatives", nullptr, FN_PTR(JVM_RegisterVectorSupportMethods)}, { CC"Java_jdk_internal_vm_vector_VectorSupport_registerNatives", nullptr, FN_PTR(JVM_RegisterVectorSupportMethods)},
#if INCLUDE_JVMCI #if INCLUDE_JVMCI
{ CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", nullptr, FN_PTR(JVM_GetJVMCIRuntime) }, { 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) }, { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", nullptr, FN_PTR(JVM_RegisterJVMCINatives) },
#endif #endif
#if INCLUDE_JFR #if INCLUDE_JFR

View file

@ -75,6 +75,9 @@ class PathString : public CHeapObj<mtArguments> {
PathString(const char* value); PathString(const char* value);
~PathString(); ~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. // ModulePatchPath records the module/path pair as specified to --patch-module.
@ -136,6 +139,10 @@ class SystemProperty : public PathString {
// Constructor // Constructor
SystemProperty(const char* key, const char* value, bool writeable, bool internal = false); 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. // Helper class for controlling the lifetime of JavaVMInitArgs objects.

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -101,19 +101,6 @@ public class VMSupport {
return serializePropertiesToByteArray(onlyStrings(getAgentProperties())); 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 * Return the temporary directory that the VM uses for the attach
* and perf data files. * and perf data files.

View file

@ -278,6 +278,7 @@ module java.base {
java.security.jgss, java.security.jgss,
java.smartcardio, java.smartcardio,
jdk.charsets, jdk.charsets,
jdk.internal.vm.ci,
jdk.jlink, jdk.jlink,
jdk.jpackage, jdk.jpackage,
jdk.net; jdk.net;

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@ import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.services.Services; 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 * 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 class TargetDescription {
public final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux"); public final boolean linuxOs = OperatingSystem.isLinux();
public final boolean macOs = Services.getSavedProperty("os.name", "").startsWith("Mac"); public final boolean macOs = OperatingSystem.isMacOS();
public final Architecture arch; public final Architecture arch;

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it

View file

@ -28,6 +28,7 @@ import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.common.JVMCIError;
import jdk.vm.ci.services.Services; import jdk.vm.ci.services.Services;
import jdk.internal.misc.Unsafe; import jdk.internal.misc.Unsafe;
import jdk.internal.util.Architecture;
/** /**
* Used to access native configuration details. * Used to access native configuration details.
@ -43,8 +44,6 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
return runtime().getConfig(); return runtime().getConfig();
} }
private final String osArch = getHostArchitectureName();
HotSpotVMConfig(HotSpotVMConfigStore store) { HotSpotVMConfig(HotSpotVMConfigStore store) {
super(store); super(store);
@ -57,13 +56,10 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
* {@linkplain HotSpotJVMCIBackendFactory backend}. * {@linkplain HotSpotJVMCIBackendFactory backend}.
*/ */
String getHostArchitectureName() { String getHostArchitectureName() {
String arch = Services.getSavedProperty("os.arch"); Architecture arch = Architecture.current();
switch (arch) { switch (arch) {
case "x86_64": case X64: return "amd64";
return "amd64"; default: return arch.name().toLowerCase();
default:
return arch;
} }
} }
@ -134,7 +130,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int jvmMiscFlagsDeclaresDefaultMethods = getConstant("InstanceKlassFlags::_misc_declares_nonstatic_concrete_methods", Integer.class); final int jvmMiscFlagsDeclaresDefaultMethods = getConstant("InstanceKlassFlags::_misc_declares_nonstatic_concrete_methods", Integer.class);
// This is only valid on AMD64. // 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 markWordNoHashInPlace = getConstant("markWord::no_hash_in_place", Integer.class);
private final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class); private final int markWordNoLockInPlace = getConstant("markWord::no_lock_in_place", Integer.class);

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot.amd64;
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.services.Services; import jdk.vm.ci.services.Services;
import jdk.internal.util.OperatingSystem;
/** /**
* Used to access AMD64 specific native configuration details. * Used to access AMD64 specific native configuration details.
@ -35,7 +36,7 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess {
super(config); 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 useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class);

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot.riscv64;
import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
import jdk.vm.ci.services.Services; import jdk.vm.ci.services.Services;
import jdk.internal.util.OperatingSystem;
/** /**
* Used to access native configuration details. * Used to access native configuration details.
@ -37,7 +38,7 @@ class RISCV64HotSpotVMConfig extends HotSpotVMConfigAccess {
super(config); super(config);
} }
final boolean linuxOs = Services.getSavedProperty("os.name", "").startsWith("Linux"); final boolean linuxOs = OperatingSystem.isLinux();
final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,16 +22,12 @@
*/ */
package jdk.vm.ci.services; package jdk.vm.ci.services;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter; import java.util.Formatter;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Properties;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -39,6 +35,9 @@ import java.util.function.Supplier;
import jdk.internal.misc.TerminatingThreadLocal; import jdk.internal.misc.TerminatingThreadLocal;
import jdk.internal.misc.VM; 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. * 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; 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() { public static Map<String, String> getSavedProperties() {
checkJVMCIEnabled(); checkJVMCIEnabled();
if (IS_IN_NATIVE_IMAGE) {
if (savedProperties == null) {
throw new InternalError("Saved properties not initialized");
}
} else {
if (savedProperties == null) { if (savedProperties == null) {
synchronized (Services.class) { synchronized (Services.class) {
if (savedProperties == null) { if (savedProperties == null) {
@SuppressWarnings("removal") savedProperties = initProperties();
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new JVMCIPermission());
}
savedProperties = VM.getSavedProperties();
}
} }
} }
} }
@ -261,22 +252,128 @@ public final class Services {
}; };
} }
/** static String toJavaString(Unsafe unsafe, long cstring) {
* Initializes {@link #savedProperties} from the byte array returned by if (cstring == 0) {
* {@code jdk.internal.vm.VMSupport.serializeSavedPropertiesToByteArray()}. return null;
*/
@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");
} }
Properties props = new Properties(); int len = 0;
props.load(new ByteArrayInputStream(serializedProperties)); for (long p = cstring; unsafe.getByte(p) != 0; p++) {
Map<String, String> map = new HashMap<>(props.size()); len++;
for (var e : props.entrySet()) { }
map.put((String) e.getKey(), (String) e.getValue()); 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);
}
} }
} }

View file

@ -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;
}
}
}

View file

@ -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");
}
}