diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index aa341b5a632..1d9bbbb787e 100644
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -25,7 +25,7 @@
/*
* ===========================================================================
- * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved
+ * (c) Copyright IBM Corp. 2022, 2024 All Rights Reserved
* ===========================================================================
*/
@@ -1580,7 +1580,7 @@ public VarHandle memorySegmentViewHandle(Class> carrier, long alignmentMask, B
}
@Override
- public MethodHandle nativeMethodHandle(NativeEntryPoint nep) {
+ public MethodHandle nativeMethodHandle(MethodHandle nep) {
return NativeMethodHandle.make(nep);
}
diff --git a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java
index 4d09b96775d..52909dd63aa 100644
--- a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java
+++ b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java
@@ -23,8 +23,17 @@
* questions.
*/
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2023, 2024 All Rights Reserved
+ * ===========================================================================
+ */
+
package java.lang.invoke;
+import java.lang.foreign.MemorySegment;
+import java.lang.foreign.SegmentAllocator;
+
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.foreign.abi.NativeEntryPoint;
@@ -34,23 +43,29 @@
import static java.lang.invoke.MethodHandleStatics.newInternalError;
/**
- * This class models a method handle to a native function. A native method handle is made up of a {@link NativeEntryPoint},
+ * This class models a method handle to a native function. A native method handle is made up of a bound {@link MethodHandle},
* which is used to capture the characteristics of the native call (such as calling convention to be used,
* or whether a native transition is required) and a fallback method handle, which can be used
* when intrinsification of this method handle is not possible.
*/
/*non-public*/ final class NativeMethodHandle extends MethodHandle {
- final NativeEntryPoint nep;
+ /* The native entry point is literally the bound MethodHandle implemented in OpenJ9. */
+ final MethodHandle nep;
+
+ /* The cache array for the bound MethodHandle stores MemberName and appendix which are populated
+ * by MethodHandleResolver.ffiCallLinkCallerMethod().
+ */
+ private Object[] invokeCache;
- private NativeMethodHandle(MethodType type, LambdaForm form, NativeEntryPoint nep) {
+ private NativeMethodHandle(MethodType type, LambdaForm form, MethodHandle nep) {
super(type, form);
this.nep = nep;
}
/**
- * Creates a new native method handle with given {@link NativeEntryPoint} and fallback method handle.
+ * Creates a new native method handle with given {@link MethodHandle} and fallback method handle.
*/
- public static MethodHandle make(NativeEntryPoint nep) {
+ public static MethodHandle make(MethodHandle nep) {
MethodType type = nep.type();
if (hasIllegalType(type))
throw new IllegalArgumentException("Illegal type(s) found: " + type);
@@ -78,7 +93,9 @@ private static boolean isIllegalType(Class> pType) {
|| pType == float.class
|| pType == double.class
|| pType == void.class
- || pType == Object.class);
+ || pType == Object.class
+ || pType == MemorySegment.class // Skip checking the argument preset in OpenJ9 for the moment.
+ || pType == SegmentAllocator.class); // Skip checking the argument preset OpenJ9 for the moment.
}
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
@@ -93,8 +110,12 @@ private static LambdaForm preparedLambdaForm(MethodType mtype) {
}
private static LambdaForm makePreparedLambdaForm(MethodType mtype) {
+ /* The NativeMethodHandle object must be appended to the end of the argument
+ * list to ensure the invoke cache of the bound MH is correctly fetched
+ * from linkToNative in the interpreter.
+ */
MethodType linkerType = mtype
- .appendParameterTypes(Object.class); // NEP
+ .appendParameterTypes(Object.class); // the NativeMethodHandle object
MemberName linker = new MemberName(MethodHandle.class, "linkToNative", linkerType, REF_invokeStatic);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED, NoSuchMethodException.class);
@@ -137,8 +158,11 @@ BoundMethodHandle rebind() {
}
@ForceInline
- static Object internalNativeEntryPoint(Object mh) {
- return ((NativeMethodHandle)mh).nep;
+ static Object internalNativeEntryPoint(Object nativeMH) {
+ /* Return the nativeMH object as the argument passed over
+ * to linkToNative in the LambdaForm-generated bytecode.
+ */
+ return nativeMH;
}
/**
diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
index 563870381fe..a090a8ea4da 100644
--- a/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
+++ b/src/java.base/share/classes/jdk/internal/access/JavaLangInvokeAccess.java
@@ -23,6 +23,12 @@
* questions.
*/
+/*
+ * ===========================================================================
+ * (c) Copyright IBM Corp. 2023, 2024 All Rights Reserved
+ * ===========================================================================
+ */
+
package jdk.internal.access;
import jdk.internal.foreign.abi.NativeEntryPoint;
@@ -121,7 +127,7 @@ public interface JavaLangInvokeAccess {
* @param nep the native entry point
* @return the native method handle
*/
- MethodHandle nativeMethodHandle(NativeEntryPoint nep);
+ MethodHandle nativeMethodHandle(MethodHandle nep);
/**
* Produces a method handle unreflecting from a {@code Constructor} with