From 0b1df2a6817a1a3fd10ea54dbbb253b4f789f355 Mon Sep 17 00:00:00 2001 From: Tomas Zezula Date: Wed, 17 Jul 2024 19:03:34 +0200 Subject: [PATCH] JDK-8336663: [JVMCI] VM Crash on ZGC due to incompatible handle returned by HotSpotJVMCIRuntime#getConstantValue. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 15 +++++++++++++++ .../classes/jdk/vm/ci/hotspot/CompilerToVM.java | 6 ++++++ .../jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java | 14 ++++---------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 5583ad8a6f5be..f28a69de200c0 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -94,6 +94,12 @@ static void requireInHotSpot(const char* caller, JVMCI_TRAPS) { } } +static void requireNotInHotSpot(const char* caller, JVMCI_TRAPS) { + if (JVMCIENV->is_hotspot()) { + JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot call %s from HotSpot", caller)); + } +} + class JVMCITraceMark : public StackObj { const char* _msg; public: @@ -702,6 +708,14 @@ C2V_VMENTRY_NULL(jobject, lookupJClass, (JNIEnv* env, jobject, jlong jclass_valu return JVMCIENV->get_jobject(result); C2V_END +C2V_VMENTRY_0(jlong, getJObjectValue, (JNIEnv* env, jobject, jobject constant_jobject)) + requireNotInHotSpot("getJObjectValue", JVMCI_CHECK_0); + JVMCIObject constant = JVMCIENV->wrap(constant_jobject); + Handle constant_value = JVMCIENV->asConstant(constant, JVMCI_CHECK_0); + jobject jni_handle = JNIHandles::make_local(THREAD, constant_value()); + return reinterpret_cast(jni_handle); +C2V_END + C2V_VMENTRY_NULL(jobject, getUncachedStringInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index)) constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp)); constantTag tag = cp->tag_at(index); @@ -3254,6 +3268,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "shouldInlineMethod", CC "(" HS_METHOD2 ")Z", FN_PTR(shouldInlineMethod)}, {CC "lookupType", CC "(" STRING HS_KLASS2 "IZ)" HS_RESOLVED_TYPE, FN_PTR(lookupType)}, {CC "lookupJClass", CC "(J)" HS_RESOLVED_TYPE, FN_PTR(lookupJClass)}, + {CC "getJObjectValue", CC "(" OBJECTCONSTANT ")J", FN_PTR(getJObjectValue)}, {CC "getArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getArrayType)}, {CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)}, {CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL2 "II)" STRING, FN_PTR(lookupNameInPool)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 14646fd027521..593697545266d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -289,6 +289,12 @@ HotSpotResolvedJavaType lookupType(ClassLoader classLoader, String name) throws native HotSpotResolvedJavaType lookupJClass(long jclass); + /** + * Gets the {@code jobject} value wrapped by {@code peerObject}. + * Must not be called if {@link Services#IS_IN_NATIVE_IMAGE} is {@code false}. + */ + native long getJObjectValue(HotSpotObjectConstantImpl peerObject); + /** * Resolves the entry at index {@code cpi} in {@code constantPool} to an interned String object. * diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 3dcf855ff230f..48b3b20daaf2d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -926,22 +926,16 @@ JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType /** * Gets the {@code jobject} value wrapped by {@code peerObject}. The returned "naked" value is - * only valid as long as {@code peerObject} is valid. Note that the latter may be shorter than - * the lifetime of {@code peerObject}. As such, this method should only be used to pass an - * object parameter across a JNI call from the JVMCI shared library to HotSpot. This method must - * only be called from within the JVMCI shared library. - * + * a JNI local reference, which is valid for the duration of a JVMCI shared library call. This + * method must only be called from within the JVMCI shared library. * @param peerObject a reference to an object in the peer runtime * @return the {@code jobject} value wrapped by {@code peerObject} * @throws IllegalArgumentException if the current runtime is not the JVMCI shared library or * {@code peerObject} is not a peer object reference + * @throws IllegalStateException if not called from within the JVMCI shared library */ public long getJObjectValue(HotSpotObjectConstant peerObject) { - if (peerObject instanceof IndirectHotSpotObjectConstantImpl) { - IndirectHotSpotObjectConstantImpl remote = (IndirectHotSpotObjectConstantImpl) peerObject; - return remote.getHandle(); - } - throw new IllegalArgumentException("Cannot get jobject value for " + peerObject + " (" + peerObject.getClass().getName() + ")"); + return compilerToVm.getJObjectValue((HotSpotObjectConstantImpl)peerObject); } @Override