Skip to content

Commit 3abe8a6

Browse files
author
Tomas Zezula
committed
8336663: [JVMCI] VM Crash on ZGC due to incompatible handle returned by HotSpotJVMCIRuntime#getJObjectValue
Reviewed-by: dnsimon, never
1 parent 5ff7c57 commit 3abe8a6

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ static void requireInHotSpot(const char* caller, JVMCI_TRAPS) {
9494
}
9595
}
9696

97+
static void requireNotInHotSpot(const char* caller, JVMCI_TRAPS) {
98+
if (JVMCIENV->is_hotspot()) {
99+
JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot call %s from HotSpot", caller));
100+
}
101+
}
102+
97103
class JVMCITraceMark : public StackObj {
98104
const char* _msg;
99105
public:
@@ -702,6 +708,17 @@ C2V_VMENTRY_NULL(jobject, lookupJClass, (JNIEnv* env, jobject, jlong jclass_valu
702708
return JVMCIENV->get_jobject(result);
703709
C2V_END
704710

711+
C2V_VMENTRY_0(jlong, getJObjectValue, (JNIEnv* env, jobject, jobject constant_jobject))
712+
requireNotInHotSpot("getJObjectValue", JVMCI_CHECK_0);
713+
if (!THREAD->has_last_Java_frame()) {
714+
JVMCI_THROW_MSG_0(IllegalStateException, err_msg("Cannot call getJObjectValue without Java frame anchor"));
715+
}
716+
JVMCIObject constant = JVMCIENV->wrap(constant_jobject);
717+
Handle constant_value = JVMCIENV->asConstant(constant, JVMCI_CHECK_0);
718+
jobject jni_handle = JNIHandles::make_local(THREAD, constant_value());
719+
return reinterpret_cast<jlong>(jni_handle);
720+
C2V_END
721+
705722
C2V_VMENTRY_NULL(jobject, getUncachedStringInPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(cp), jint index))
706723
constantPoolHandle cp(THREAD, UNPACK_PAIR(ConstantPool, cp));
707724
constantTag tag = cp->tag_at(index);
@@ -3254,6 +3271,7 @@ JNINativeMethod CompilerToVM::methods[] = {
32543271
{CC "shouldInlineMethod", CC "(" HS_METHOD2 ")Z", FN_PTR(shouldInlineMethod)},
32553272
{CC "lookupType", CC "(" STRING HS_KLASS2 "IZ)" HS_RESOLVED_TYPE, FN_PTR(lookupType)},
32563273
{CC "lookupJClass", CC "(J)" HS_RESOLVED_TYPE, FN_PTR(lookupJClass)},
3274+
{CC "getJObjectValue", CC "(" OBJECTCONSTANT ")J", FN_PTR(getJObjectValue)},
32573275
{CC "getArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getArrayType)},
32583276
{CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)},
32593277
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL2 "II)" STRING, FN_PTR(lookupNameInPool)},

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ HotSpotResolvedJavaType lookupType(ClassLoader classLoader, String name) throws
289289

290290
native HotSpotResolvedJavaType lookupJClass(long jclass);
291291

292+
/**
293+
* Gets the {@code jobject} value wrapped by {@code peerObject}.
294+
* Must not be called if {@link Services#IS_IN_NATIVE_IMAGE} is {@code false}.
295+
*/
296+
native long getJObjectValue(HotSpotObjectConstantImpl peerObject);
297+
292298
/**
293299
* Resolves the entry at index {@code cpi} in {@code constantPool} to an interned String object.
294300
*

src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -925,23 +925,23 @@ JavaType lookupTypeInternal(String name, HotSpotResolvedObjectType accessingType
925925
}
926926

927927
/**
928-
* Gets the {@code jobject} value wrapped by {@code peerObject}. The returned "naked" value is
929-
* only valid as long as {@code peerObject} is valid. Note that the latter may be shorter than
930-
* the lifetime of {@code peerObject}. As such, this method should only be used to pass an
931-
* object parameter across a JNI call from the JVMCI shared library to HotSpot. This method must
932-
* only be called from within the JVMCI shared library.
928+
* Gets the {@code jobject} value wrapped by {@code peerObject}. The returned value is
929+
* a JNI local reference whose lifetime is scoped by the nearest Java caller (from
930+
* HotSpot's perspective). You can use {@code PushLocalFrame} and {@code PopLocalFrame} to
931+
* shorten the lifetime of the reference. The current thread's state must be
932+
* {@code _thread_in_native}. A call from the JVMCI shared library (e.g. libgraal) is in such
933+
* a state.
933934
*
934-
* @param peerObject a reference to an object in the peer runtime
935-
* @return the {@code jobject} value wrapped by {@code peerObject}
935+
* @param peerObject a reference to an object in the HotSpot heap
936+
* @return the {@code jobject} value unpacked from {@code peerObject}
936937
* @throws IllegalArgumentException if the current runtime is not the JVMCI shared library or
937-
* {@code peerObject} is not a peer object reference
938+
* {@code peerObject} is not a HotSpot heap object reference
939+
* @throws IllegalStateException if not called from within the JVMCI shared library
940+
* or if there is no Java caller frame on the stack
941+
* (i.e., JavaThread::has_last_Java_frame returns false)
938942
*/
939943
public long getJObjectValue(HotSpotObjectConstant peerObject) {
940-
if (peerObject instanceof IndirectHotSpotObjectConstantImpl) {
941-
IndirectHotSpotObjectConstantImpl remote = (IndirectHotSpotObjectConstantImpl) peerObject;
942-
return remote.getHandle();
943-
}
944-
throw new IllegalArgumentException("Cannot get jobject value for " + peerObject + " (" + peerObject.getClass().getName() + ")");
944+
return compilerToVm.getJObjectValue((HotSpotObjectConstantImpl)peerObject);
945945
}
946946

947947
@Override

0 commit comments

Comments
 (0)