diff --git a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalDowncallHandler.java b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalDowncallHandler.java index 1a05927c054..830558b9af8 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalDowncallHandler.java +++ b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalDowncallHandler.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/ /******************************************************************************* * Copyright IBM Corp. and others 2022 * @@ -24,9 +24,9 @@ import java.util.HashMap; import java.util.List; -/*[IF JAVA_SPEC_VERSION >= 20]*/ +/*[IF JAVA_SPEC_VERSION >= 21]*/ import java.util.Objects; -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ +/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.util.concurrent.ConcurrentHashMap; import java.util.Set; @@ -37,27 +37,20 @@ import static java.lang.invoke.MethodType.methodType; import java.lang.invoke.WrongMethodTypeException; -/*[IF JAVA_SPEC_VERSION >= 20]*/ /*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.AddressLayout; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -/*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.MemorySegment.Scope; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.lang.foreign.SegmentAllocator; -/*[IF JAVA_SPEC_VERSION == 20]*/ -import java.lang.foreign.SegmentScope; -/*[ENDIF] JAVA_SPEC_VERSION == 20 */ import java.lang.foreign.ValueLayout; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.MemorySessionImpl; -/*[ELSE] JAVA_SPEC_VERSION >= 20 */ +/*[ELSE] JAVA_SPEC_VERSION >= 21 */ import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; @@ -68,14 +61,12 @@ import jdk.incubator.foreign.ResourceScope.Handle; import jdk.incubator.foreign.SegmentAllocator; import jdk.incubator.foreign.ValueLayout; -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ +/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ -/*[IF JAVA_SPEC_VERSION >= 20]*/ -import static java.lang.foreign.ValueLayout.*; /*[IF JAVA_SPEC_VERSION >= 21]*/ +import static java.lang.foreign.ValueLayout.*; import static jdk.internal.foreign.abi.SharedUtils.*; /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ /** * The internal implementation of downcall handler wraps up a method handle enabling @@ -86,9 +77,9 @@ public class InternalDowncallHandler { private final MethodType funcMethodType; private final FunctionDescriptor funcDescriptor; - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private final LinkerOptions linkerOpts; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ private long cifNativeThunkAddr; private long argTypesAddr; private MemoryLayout[] argLayoutArray; @@ -100,8 +91,6 @@ public class InternalDowncallHandler { */ /*[IF JAVA_SPEC_VERSION >= 21]*/ private Set memArgScopeSet; - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private Set memArgScopeSet; /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private Set memArgScopeSet; /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -124,11 +113,11 @@ public class InternalDowncallHandler { private static final MethodHandle intToLongArgFilter; private static final MethodHandle floatToLongArgFilter; private static final MethodHandle doubleToLongArgFilter; - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private MethodHandle memSegmtOfPtrToLongArgFilter; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private MethodHandle memAddrToLongArgFilter; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ private MethodHandle memSegmtToLongArgFilter; /* Return value filters that convert the Long object to the primitive types/MemoryAddress/MemorySegment. */ @@ -141,20 +130,20 @@ public class InternalDowncallHandler { private static final MethodHandle longObjToLongRetFilter; private static final MethodHandle longObjToFloatRetFilter; private static final MethodHandle longObjToDoubleRetFilter; - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private MethodHandle longObjToMemSegmtRetFilter; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private static final MethodHandle longObjToMemAddrRetFilter; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ private static final MethodHandle objToMemSegmtRetFilter; private static synchronized native void resolveRequiredFields(); private native void initCifNativeThunkData(String[] argLayouts, String retLayout, boolean newArgTypes, int varArgIndex); - /*[IF JAVA_SPEC_VERSION >= 20]*/ - private native long invokeNative(long returnStateMemAddr, long returnStructMemAddr, long functionAddress, long calloutThunk, long[] argValues); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[IF JAVA_SPEC_VERSION >= 21]*/ + private native long invokeNative(boolean isInTrivialDownCall, long returnStateMemAddr, long returnStructMemAddr, long functionAddress, long calloutThunk, long[] argValues); + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private native long invokeNative(long returnStructMemAddr, long functionAddress, long calloutThunk, long[] argValues); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ private static final class PrivateClassLock { PrivateClassLock() {} @@ -239,8 +228,6 @@ private static final long floatToLongArg(float argValue) { */ /*[IF JAVA_SPEC_VERSION >= 21]*/ private final void addMemArgScope(Scope memArgScope) throws IllegalStateException - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private final void addMemArgScope(SegmentScope memArgScope) throws IllegalStateException /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private final void addMemArgScope(ResourceScope memArgScope) throws IllegalStateException /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -254,8 +241,6 @@ private final void addMemArgScope(ResourceScope memArgScope) throws IllegalState /* Validate the memory related scope to ensure that it is kept alive during the downcall. */ /*[IF JAVA_SPEC_VERSION >= 21]*/ private void validateMemScope(Scope memScope) throws IllegalStateException - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private void validateMemScope(SegmentScope memScope) throws IllegalStateException /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private void validateMemScope(ResourceScope memScope) throws IllegalStateException /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -265,7 +250,7 @@ private void validateMemScope(ResourceScope memScope) throws IllegalStateExcepti } } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Intended for memSegmtOfPtrToLongArgFilter that converts the memory segment * of the passed-in pointer argument to long. */ @@ -274,23 +259,23 @@ private final long memSegmtOfPtrToLongArg(MemorySegment argValue) throws Illegal addMemArgScope(argValue.scope()); return argValue.address(); } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /* Intended for memAddrToLongArgFilter that converts the memory address to long. */ private final long memAddrToLongArg(MemoryAddress argValue) throws IllegalStateException { UpcallMHMetaData.validateNativeArgRetAddrOfPtr(argValue); addMemArgScope(argValue.scope()); return argValue.toRawLongValue(); } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* Intended for memSegmtToLongArgFilter that converts the memory segment to long. */ private final long memSegmtToLongArg(MemorySegment argValue) throws IllegalStateException { addMemArgScope(argValue.scope()); - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ return UpcallMHMetaData.getNativeArgRetSegment(argValue).address(); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ return UpcallMHMetaData.getNativeArgRetSegment(argValue).address().toRawLongValue(); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ } /* Intended for longObjToVoidRetFilter that converts the Long object to void. */ @@ -341,31 +326,22 @@ private static final double longObjToDoubleRet(Object retValue) { return Double.longBitsToDouble(tmpValue); } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Intended for longObjToMemSegmtRetFilter that converts the Long object to the memory segment. */ private MemorySegment longObjToMemSegmtRet(Object retValue) { long tmpValue = ((Long)retValue).longValue(); - /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Return the created segment with the given pointer address when the address is valid * against the specified target layout if exists. */ return UpcallMHMetaData.getArgRetAlignedSegmentOfPtr(tmpValue, realReturnLayout); - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - /* Utils.pointeeSize() introduced in JDK20 calls isUnbounded() for the ADDRESS layout - * to determine whether the specified address layout is an unbounded address or not. - * For an unbounded address, it returns Long.MAX_VALUE for direct access; otherwise, - * it returns zero in which case the address can't be directly accessed. - */ - return MemorySegment.ofAddress(tmpValue, Utils.pointeeSize(realReturnLayout)); - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /* Intended for longObjToMemAddrRetFilter that converts the Long object to the memory address. */ private static final MemoryAddress longObjToMemAddrRet(Object retValue) { long tmpValue = ((Long)retValue).longValue(); return MemoryAddress.ofLong(tmpValue); } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* Intended for objToMemSegmtRetFilter that simply casts the passed-in object to the memory segment * given the requested the memory segment is directly returned from runNativeMethod(). @@ -376,7 +352,7 @@ private static final MemorySegment objToMemSegmtRet(Object retValue) { return (MemorySegment)retValue; } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /** * The internal constructor is responsible for mapping the preprocessed layouts * of return type & argument types to the underlying prep_cif in native. @@ -386,7 +362,7 @@ private static final MemorySegment objToMemSegmtRet(Object retValue) { * @param options the linker options indicating additional linking requirements to the linker */ public InternalDowncallHandler(MethodType functionMethodType, FunctionDescriptor functionDescriptor, LinkerOptions options) - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /** * The internal constructor is responsible for mapping the preprocessed layouts * of return type & argument types to the underlying prep_cif in native. @@ -395,7 +371,7 @@ public InternalDowncallHandler(MethodType functionMethodType, FunctionDescriptor * @param funcDesc the function descriptor of the specified native function */ public InternalDowncallHandler(MethodType functionMethodType, FunctionDescriptor functionDescriptor) - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { realReturnLayout = functionDescriptor.returnLayout().orElse(null); // set to null for void List argLayouts = functionDescriptor.argumentLayouts(); @@ -414,9 +390,9 @@ public InternalDowncallHandler(MethodType functionMethodType, FunctionDescriptor funcMethodType = functionMethodType; funcDescriptor = functionDescriptor; - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ linkerOpts = options; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ cifNativeThunkAddr = 0; argTypesAddr = 0; @@ -427,12 +403,12 @@ public InternalDowncallHandler(MethodType functionMethodType, FunctionDescriptor /*[ENDIF] JAVA_SPEC_VERSION == 17 */ try { - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ longObjToMemSegmtRetFilter = lookup.bind(this, "longObjToMemSegmtRet", methodType(MemorySegment.class, Object.class)); memSegmtOfPtrToLongArgFilter = lookup.bind(this, "memSegmtOfPtrToLongArg", methodType(long.class, MemorySegment.class)); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ memAddrToLongArgFilter = lookup.bind(this, "memAddrToLongArg", methodType(long.class, MemoryAddress.class)); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ memSegmtToLongArgFilter = lookup.bind(this, "memSegmtToLongArg", methodType(long.class, MemorySegment.class)); } catch (ReflectiveOperationException e) { throw new InternalError(e); @@ -475,11 +451,11 @@ private void generateAdapter() { * e.g. C_INT without the layout name = b32[abi/kind=INT] * and C_INT with the layout name = b32(int)[abi/kind=INT,layout/name=int] */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ int varArgIdx = LayoutStrPreprocessor.getVarArgIndex(funcDescriptor, linkerOpts); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ int varArgIdx = LayoutStrPreprocessor.getVarArgIndex(funcDescriptor); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ String argRetLayoutStrsLine = ((varArgIdx >= 0) ? varArgIdx : "") + argLayoutStrsLine.toString() + retLayoutStr; Integer argRetLayoutStrLineHash = Integer.valueOf(argRetLayoutStrsLine.hashCode()); Integer argLayoutStrsLineHash = Integer.valueOf(argLayoutStrsLine.toString().hashCode()); @@ -513,17 +489,11 @@ private void generateAdapter() { */ public MethodHandle getBoundMethodHandle() { try { - /*[IF JAVA_SPEC_VERSION >= 20]*/ - Class downcallAddrClass = MemorySegment.class; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ - Class downcallAddrClass = Addressable.class; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ - - /*[IF JAVA_SPEC_VERSION >= 20]*/ - MethodType nativeMethodType = methodType(Object.class, downcallAddrClass, SegmentAllocator.class, MemorySegment.class, long[].class); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ - MethodType nativeMethodType = methodType(Object.class, downcallAddrClass, SegmentAllocator.class, long[].class); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[IF JAVA_SPEC_VERSION >= 21]*/ + MethodType nativeMethodType = methodType(Object.class, MemorySegment.class, SegmentAllocator.class, MemorySegment.class, long[].class); + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ + MethodType nativeMethodType = methodType(Object.class, Addressable.class, SegmentAllocator.class, long[].class); + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ MethodHandle boundHandle = lookup.bind(this, "runNativeMethod", nativeMethodType); @@ -539,15 +509,15 @@ public MethodHandle getBoundMethodHandle() { private MethodHandle permuteMH(MethodHandle targetHandle, MethodType nativeMethodType) throws NullPointerException, WrongMethodTypeException { Class[] argTypeClasses = nativeMethodType.parameterArray(); int nativeArgCount = argTypeClasses.length; - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Skip the native function address, the segment allocator and the segment * for the execution state to the native function's arguments. */ int argPosition = 3; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /* Skip the native function address and the segment allocator to the native function's arguments. */ int argPosition = 2; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ MethodHandle resultHandle = targetHandle.asCollector(argPosition, long[].class, nativeArgCount); /* Convert the argument values to long via filterArguments() prior to the native call. */ @@ -561,14 +531,14 @@ private MethodHandle permuteMH(MethodHandle targetHandle, MethodType nativeMetho MethodHandle retFilter = getReturnValFilter(nativeMethodType.returnType()); resultHandle = MethodHandles.filterReturnValue(resultHandle, retFilter); - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Set a placeholder with a NULL segment if there is no request * for the execution state from downcall in the linker options. */ if (!linkerOpts.hasCapturedCallState()) { resultHandle = MethodHandles.insertArguments(resultHandle, 2, MemorySegment.NULL); } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ return resultHandle; } @@ -599,20 +569,14 @@ private MethodHandle getArgumentFilter(Class argTypeClass, MemoryLayout argLa } else /*[ENDIF] JAVA_SPEC_VERSION == 17 */ if (argTypeClass == MemorySegment.class) { - /*[IF JAVA_SPEC_VERSION >= 20]*/ /*[IF JAVA_SPEC_VERSION >= 21]*/ /* The address layout for pointer might come with different representations of ADDRESS. * Note: AddressLayout is introduced in JDK21 to replace OfAddress. */ - if (argLayout instanceof AddressLayout) - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - /* The address layout for pointer might come with different representations of ADDRESS. */ - if (argLayout instanceof OfAddress) - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - { + if (argLayout instanceof AddressLayout) { filterMH = memSegmtOfPtrToLongArgFilter; } else - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { filterMH = memSegmtToLongArgFilter; } @@ -651,24 +615,17 @@ private MethodHandle getReturnValFilter(Class returnType) { } else /*[ENDIF] JAVA_SPEC_VERSION == 17 */ if (returnType == MemorySegment.class) { - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* A returned pointer is wrapped as a zero-sized memory segment given all * MemoryAdress related classes are removed against the latest APIs as - * specified in JDK20+. - */ - /*[IF JAVA_SPEC_VERSION >= 21]*/ - /* The address layout for pointer might come with different representations of ADDRESS. + * specified in JDK20+ in which case the address layout for pointer might + * come with different representations of ADDRESS. * Note: AddressLayout is introduced in JDK21 to replace OfAddress. */ - if ((realReturnLayout != null) && (realReturnLayout instanceof AddressLayout)) - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - /* The address layout for pointer might come with different representations of ADDRESS. */ - if ((realReturnLayout != null) && (realReturnLayout instanceof OfAddress)) - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - { + if ((realReturnLayout != null) && (realReturnLayout instanceof AddressLayout)) { filterMH = longObjToMemSegmtRetFilter; } else - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { filterMH = objToMemSegmtRetFilter; } @@ -677,23 +634,13 @@ private MethodHandle getReturnValFilter(Class returnType) { return filterMH; } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* Set up the dependency from the sessions of memory related arguments to the specified session * so as to keep these arguments' session alive till the specified session is closed. */ - /*[IF JAVA_SPEC_VERSION >= 21]*/ - private void SetDependency(Scope session) - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - private void SetDependency(SegmentScope session) - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - { + private void SetDependency(Scope session) { Objects.requireNonNull(session); - /*[IF JAVA_SPEC_VERSION >= 21]*/ - for (Scope memArgSession : memArgScopeSet) - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - for (SegmentScope memArgSession : memArgScopeSet) - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - { + for (Scope memArgSession : memArgScopeSet) { if (memArgSession.isAlive()) { MemorySessionImpl memArgSessionImpl = (MemorySessionImpl)memArgSession; Thread owner = memArgSessionImpl.ownerThread(); @@ -707,7 +654,7 @@ private void SetDependency(SegmentScope session) } } } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /* Occupy the scope by setting the scope's state in downcall so as to keep these * arguments' scope alive till the specified session is closed. */ @@ -741,37 +688,37 @@ private void releaseScope() { } } } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* Return the valid downcall related memory address by doing the validity check * on the address's scope in OpenJ9 since the related code and APIs were adjusted * in JDK20 in which case the scope check on the downcall in address() in OpenJDK * was entirely removed. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private long getValidDowncallMemAddr(MemorySegment memAddr) { validateMemScope(memAddr.scope()); return memAddr.address(); } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private long getValidDowncallMemAddr(Addressable memAddr) { validateMemScope(memAddr.address().scope()); return memAddr.address().toRawLongValue(); } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* The method (bound by the method handle to the native code) intends to invoke the C function via the inlined code. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ Object runNativeMethod(MemorySegment downcallAddr, SegmentAllocator segmtAllocator, MemorySegment stateSegmt, long[] args) throws IllegalArgumentException, IllegalStateException - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ Object runNativeMethod(Addressable downcallAddr, SegmentAllocator segmtAllocator, long[] args) throws IllegalArgumentException, IllegalStateException - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ if (downcallAddr == MemorySegment.NULL) - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ if (downcallAddr.address() == MemoryAddress.NULL) - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { throw new IllegalArgumentException("A non-null memory address is expected for downcall"); } @@ -791,44 +738,39 @@ Object runNativeMethod(Addressable downcallAddr, SegmentAllocator segmtAllocator if (retStruSegmt == null) { throw new OutOfMemoryError("Failed to allocate native memory for the returned memory segment"); } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ retMemAddr = retStruSegmt.address(); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ retMemAddr = retStruSegmt.address().toRawLongValue(); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ } /* Add the scopes of the downcall related memory addresses to the set * to ensure they are kept alive till the downcall is finished. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ addMemArgScope(downcallAddr.scope()); addMemArgScope(stateSegmt.scope()); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ addMemArgScope(downcallAddr.address().scope()); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - long returnVal = 0; + long returnVal; /* The scope associated with memory specific arguments must be kept alive * during the downcall since JDK17, including the downcall adddress. * - *Note: memArgScopeSet is not empty with the downcall address added to the set. + * Note: memArgScopeSet is not empty with the downcall address added to the set. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ /*[IF JAVA_SPEC_VERSION >= 21]*/ - try (Arena arena = Arena.ofConfined()) - /*[ELSE] JAVA_SPEC_VERSION >= 21 */ - try (Arena arena = Arena.openConfined()) - /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ - { + try (Arena arena = Arena.ofConfined()) { SetDependency(arena.scope()); - returnVal = invokeNative(getValidDowncallMemAddr(stateSegmt), retMemAddr, getValidDowncallMemAddr(downcallAddr), cifNativeThunkAddr, args); + returnVal = invokeNative(linkerOpts.isTrivial(), getValidDowncallMemAddr(stateSegmt), retMemAddr, getValidDowncallMemAddr(downcallAddr), cifNativeThunkAddr, args); } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ acquireScope(); returnVal = invokeNative(retMemAddr, getValidDowncallMemAddr(downcallAddr), cifNativeThunkAddr, args); releaseScope(); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* This struct specific MemorySegment object returns to the current thread in the multithreading environment, * in which case the native invocations from threads end up with distinct returned structs. diff --git a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalUpcallHandler.java b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalUpcallHandler.java index 68bd70b0324..f8e6894a507 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalUpcallHandler.java +++ b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/InternalUpcallHandler.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/ /******************************************************************************* * Copyright IBM Corp. and others 2022 * @@ -32,25 +32,16 @@ import java.util.List; import java.util.Set; -/*[IF JAVA_SPEC_VERSION >= 20]*/ /*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.AddressLayout; import java.lang.foreign.Arena; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -/*[IF JAVA_SPEC_VERSION >= 21]*/ import jdk.internal.foreign.abi.LinkerOptions; -/*[ELSE] JAVA_SPEC_VERSION >= 21 */ -import java.lang.foreign.SegmentScope; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.lang.foreign.ValueLayout; -/*[IF JAVA_SPEC_VERSION == 20]*/ -import java.lang.foreign.ValueLayout.OfAddress; -/*[ENDIF] JAVA_SPEC_VERSION == 20 */ -/*[ELSE] JAVA_SPEC_VERSION >= 20 */ +/*[ELSE] JAVA_SPEC_VERSION >= 21 */ import jdk.incubator.foreign.FunctionDescriptor; import jdk.incubator.foreign.GroupLayout; import jdk.incubator.foreign.MemoryAddress; @@ -58,7 +49,7 @@ import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; import jdk.incubator.foreign.ValueLayout; -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ +/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /** * The internal implementation of upcall handler wraps up an upcall handle @@ -75,19 +66,17 @@ public final class InternalUpcallHandler { static final Lookup lookup = MethodHandles.lookup(); /* The argument filters intended to validate the pointer/struct arguments/return value of the upcall method. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private static final MethodHandle argRetSegmtOfPtrFilter; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private static final MethodHandle argRetAddrOfPtrFilter; - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ private static final MethodHandle argRetSegmtFilter; static { try { /*[IF JAVA_SPEC_VERSION >= 21]*/ argRetSegmtOfPtrFilter = lookup.findStatic(InternalUpcallHandler.class, "argRetSegmtOfPtr", methodType(MemorySegment.class, MemorySegment.class, MemoryLayout.class)); - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - argRetSegmtOfPtrFilter = lookup.findStatic(InternalUpcallHandler.class, "argRetSegmtOfPtr", methodType(MemorySegment.class, MemorySegment.class)); /*[ELSE] JAVA_SPEC_VERSION >= 21 */ argRetAddrOfPtrFilter = lookup.findStatic(InternalUpcallHandler.class, "argRetAddrOfPtr", methodType(MemoryAddress.class, MemoryAddress.class)); /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -105,11 +94,6 @@ private static MemorySegment argRetSegmtOfPtr(MemorySegment argValue, MemoryLayo UpcallMHMetaData.validateNativeArgRetSegmentOfPtr(argValue); return UpcallMHMetaData.getArgRetAlignedSegmentOfPtr(argValue.address(), layout); } - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private static MemorySegment argRetSegmtOfPtr(MemorySegment argValue) throws IllegalStateException { - UpcallMHMetaData.validateNativeArgRetSegmentOfPtr(argValue); - return argValue; - } /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private static MemoryAddress argRetAddrOfPtr(MemoryAddress argValue) throws IllegalStateException { UpcallMHMetaData.validateNativeArgRetAddrOfPtr(argValue); @@ -136,17 +120,6 @@ private static MemorySegment argRetSegmt(MemorySegment argValue) throws IllegalS * @param options the LinkerOptions indicating additional linking requirements to the linker */ public InternalUpcallHandler(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, Arena arena, LinkerOptions options) - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - /** - * The constructor creates an upcall handler specific to the requested java method - * by generating a native thunk in upcall on a given platform. - * - * @param target the target method handle in upcall - * @param mt the method type of the target method handle - * @param cDesc the function descriptor of the target method handle - * @param scope the segment scope related to the upcall handler - */ - public InternalUpcallHandler(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) /*[ELSE] JAVA_SPEC_VERSION >= 21 */ /** * The constructor creates an upcall handler specific to the requested java method @@ -196,8 +169,6 @@ public long upcallThunkAddr() { */ /*[IF JAVA_SPEC_VERSION >= 21]*/ private long getUpcallThunkAddr(MethodHandle target, Arena arena, LinkerOptions options) - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private long getUpcallThunkAddr(MethodHandle target, SegmentScope scope) /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private long getUpcallThunkAddr(MethodHandle target, ResourceScope scope) /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -275,10 +246,6 @@ else if (argLayout instanceof ValueLayout) { if (argLayout instanceof AddressLayout) { filterMH = MethodHandles.insertArguments(argRetSegmtOfPtrFilter, 1, argLayout); } else - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - if (argLayout instanceof OfAddress) { - filterMH = argRetSegmtOfPtrFilter; - } else /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { /* The filter for primitive is a placeholder without any conversion involved. */ diff --git a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/LayoutStrPreprocessor.java b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/LayoutStrPreprocessor.java index a1a64420ba1..63b22136184 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/LayoutStrPreprocessor.java +++ b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/LayoutStrPreprocessor.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/ /******************************************************************************* * Copyright IBM Corp. and others 2022 * @@ -24,7 +24,7 @@ import java.util.List; -/*[IF JAVA_SPEC_VERSION >= 20]*/ +/*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; @@ -33,7 +33,7 @@ import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import jdk.internal.foreign.abi.LinkerOptions; -/*[ELSE] JAVA_SPEC_VERSION >= 20 */ +/*[ELSE] JAVA_SPEC_VERSION >= 21 */ import jdk.incubator.foreign.CLinker.TypeKind; import static jdk.incubator.foreign.CLinker.TypeKind.*; import jdk.incubator.foreign.FunctionDescriptor; @@ -42,7 +42,7 @@ import jdk.incubator.foreign.MemoryLayout; import jdk.incubator.foreign.SequenceLayout; import jdk.incubator.foreign.ValueLayout; -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ +/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /** * The methods of the class are used to preprocess the layout specified in the function @@ -87,11 +87,11 @@ final class LayoutStrPreprocessor { /*[ENDIF] JAVA_SPEC_VERSION == 17 */ /* Get the index of the variadic argument layout in the function descriptor if exists. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ static int getVarArgIndex(FunctionDescriptor funcDesc, LinkerOptions options) - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ static int getVarArgIndex(FunctionDescriptor funcDesc) - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { List argLayouts = funcDesc.argumentLayouts(); int argLayoutsSize = argLayouts.size(); @@ -101,11 +101,11 @@ static int getVarArgIndex(FunctionDescriptor funcDesc) int varArgIdx = -1; for (int argIndex = 0; argIndex < argLayoutsSize; argIndex++) { - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ if (options.isVarargsIndex(argIndex)) - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ if (argLayouts.get(argIndex).attribute(VARARGS_ATTR_NAME).isPresent()) - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ { varArgIdx = argIndex; break; @@ -201,11 +201,11 @@ private static StringBuilder preprocessLayout(MemoryLayout targetLayout, boolean targetLayoutString.append(getPrimitiveTypeSymbol(valueLayout)); } else if (targetLayout instanceof SequenceLayout arrayLayout) { /* Intended for nested arrays. */ MemoryLayout elementLayout = arrayLayout.elementLayout(); - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ long elementCount = arrayLayout.elementCount(); - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ long elementCount = arrayLayout.elementCount().getAsLong(); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* The padding bytes is required in the native signature for upcall thunk generation. */ if (isPaddingLayout(elementLayout) && !isDownCall) { @@ -243,15 +243,15 @@ private static StringBuilder preprocessLayout(MemoryLayout targetLayout, boolean /* Determine whether the specfied layout is a padding layout or not. */ private static boolean isPaddingLayout(MemoryLayout targetLayout) { - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ return targetLayout instanceof PaddingLayout; - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ return targetLayout.isPadding(); - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ } /* Map the specified primitive layout's kind to the symbol for primitive type in VM Spec. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ private static String getPrimitiveTypeSymbol(ValueLayout targetLayout) { Class javaType = targetLayout.carrier(); String typeSymbol = ""; @@ -274,7 +274,7 @@ private static String getPrimitiveTypeSymbol(ValueLayout targetLayout) { return typeSymbol; } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private static String getPrimitiveTypeSymbol(ValueLayout targetLayout) { /* Extract the kind from the specified layout with the ATTR_NAME "abi/kind". * e.g. b32[abi/kind=INT] @@ -313,5 +313,5 @@ private static String getPrimitiveTypeSymbol(ValueLayout targetLayout) { return typeSymbol; } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ } diff --git a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/UpcallMHMetaData.java b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/UpcallMHMetaData.java index babdf95372f..407bb558881 100644 --- a/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/UpcallMHMetaData.java +++ b/jcl/src/java.base/share/classes/openj9/internal/foreign/abi/UpcallMHMetaData.java @@ -1,4 +1,4 @@ -/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/ +/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/ /******************************************************************************* * Copyright IBM Corp. and others 2022 * @@ -28,27 +28,21 @@ import java.util.Optional; /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ -/*[IF JAVA_SPEC_VERSION >= 20]*/ /*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.AddressLayout; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -/*[IF JAVA_SPEC_VERSION >= 21]*/ import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment.Scope; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.LinkerOptions; -/*[ELSE] JAVA_SPEC_VERSION >= 21 */ -import java.lang.foreign.SegmentScope; -/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ import jdk.internal.foreign.MemorySessionImpl; -/*[ELSE] JAVA_SPEC_VERSION >= 20 */ +/*[ELSE] JAVA_SPEC_VERSION >= 21 */ import jdk.incubator.foreign.Addressable; import jdk.incubator.foreign.MemoryAddress; import jdk.incubator.foreign.MemorySegment; import jdk.incubator.foreign.ResourceScope; -/*[ENDIF] JAVA_SPEC_VERSION >= 20 */ +/*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /** * The meta data consists of the callee MH and a cache of 2 elements for MH resolution, @@ -78,8 +72,6 @@ final class UpcallMHMetaData { /*[IF JAVA_SPEC_VERSION >= 21]*/ private Scope scope; - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - private SegmentScope scope; /*[ELSE] JAVA_SPEC_VERSION >= 21 */ private ResourceScope scope; /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -96,8 +88,6 @@ final class UpcallMHMetaData { /*[IF JAVA_SPEC_VERSION >= 21]*/ UpcallMHMetaData(MethodHandle targetHandle, int nativeArgCount, Scope scope, LinkerOptions options) - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - UpcallMHMetaData(MethodHandle targetHandle, int nativeArgCount, SegmentScope scope) /*[ELSE] JAVA_SPEC_VERSION >= 21 */ UpcallMHMetaData(MethodHandle targetHandle, int nativeArgCount, ResourceScope scope) /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -112,8 +102,6 @@ final class UpcallMHMetaData { */ /*[IF JAVA_SPEC_VERSION >= 21]*/ this.scope = ((scope != null) && (((MemorySessionImpl)scope).ownerThread() != null)) ? scope : Arena.global().scope(); - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - this.scope = ((scope != null) && (((MemorySessionImpl)scope).ownerThread() != null)) ? scope : SegmentScope.global(); /*[ELSE] JAVA_SPEC_VERSION >= 21 */ this.scope = ((scope != null) && (scope.ownerThread() != null)) ? scope : ResourceScope.globalScope(); /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ @@ -144,7 +132,7 @@ static MemorySegment getArgRetAlignedSegmentOfPtr(long addrValue, MemoryLayout l * Note: * The method is shared in downcall and upcall. */ - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ static void validateNativeArgRetSegmentOfPtr(MemorySegment argRetSegmentOfPtr) { if (argRetSegmentOfPtr == null) { throw new NullPointerException("A null pointer is not allowed."); @@ -153,7 +141,7 @@ static void validateNativeArgRetSegmentOfPtr(MemorySegment argRetSegmentOfPtr) { throw new IllegalArgumentException("Heap segment not allowed: " + argRetSegmentOfPtr); } } - /*[ELSE] JAVA_SPEC_VERSION >= 20 */ + /*[ELSE] JAVA_SPEC_VERSION >= 21 */ static void validateNativeArgRetAddrOfPtr(MemoryAddress argRetAddrOfPtr) { if (argRetAddrOfPtr == null) { throw new NullPointerException("A null pointer is not allowed."); @@ -162,7 +150,7 @@ static void validateNativeArgRetAddrOfPtr(MemoryAddress argRetAddrOfPtr) { throw new IllegalArgumentException("A heap address is not allowed: " + argRetAddrOfPtr); } } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ /* Determine whether the passed-in/returned segment is allocated in the native memory or not * and return the segment if valid; otherwise, return the newly allocated native segment with @@ -175,12 +163,12 @@ static MemorySegment getNativeArgRetSegment(MemorySegment argRetSegment) { if (argRetSegment == null) { throw new NullPointerException("A null value is not allowed for struct."); } - /*[IF JAVA_SPEC_VERSION >= 20]*/ + /*[IF JAVA_SPEC_VERSION >= 21]*/ /* MemorySegment.NULL is introduced since JDK20+. */ if (argRetSegment == MemorySegment.NULL) { throw new NullPointerException("A NULL memory segment is not allowed for struct."); } - /*[ENDIF] JAVA_SPEC_VERSION >= 20 */ + /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ MemorySegment nativeSegment = argRetSegment; /* Copy all values in the heap segment to a newly allocated native segment @@ -192,8 +180,6 @@ static MemorySegment getNativeArgRetSegment(MemorySegment argRetSegment) { * MemorySegment.allocateNative() is removed since JDK21+. */ nativeSegment = Arena.global().allocate(argRetSegment.byteSize()); - /*[ELSEIF JAVA_SPEC_VERSION == 20]*/ - nativeSegment = MemorySegment.allocateNative(argRetSegment.byteSize(), SegmentScope.global()); /*[ELSE] JAVA_SPEC_VERSION >= 21 */ nativeSegment = MemorySegment.allocateNative(argRetSegment.byteSize(), ResourceScope.globalScope()); /*[ENDIF] JAVA_SPEC_VERSION >= 21 */ diff --git a/runtime/nls/j9vm/j9vm.nls b/runtime/nls/j9vm/j9vm.nls index 29ead402dab..8bde591732a 100644 --- a/runtime/nls/j9vm/j9vm.nls +++ b/runtime/nls/j9vm/j9vm.nls @@ -2145,3 +2145,10 @@ J9NLS_VM_CRIU_RESTORE_INITIALIZE_DUMP_FAILED.explanation=CRIUSupport::checkpoint J9NLS_VM_CRIU_RESTORE_INITIALIZE_DUMP_FAILED.system_action=The JVM will throw a JVMRestoreException. J9NLS_VM_CRIU_RESTORE_INITIALIZE_DUMP_FAILED.user_response=Check documentation for CRIUSupport restore options. # END NON-TRANSLATABLE + +J9NLS_VM_ILLEGAL_THREAD_STATE_UPCALL=The JVM failed to proceed due to the wrong thread state for upcall +# START NON-TRANSLATABLE +J9NLS_VM_ILLEGAL_THREAD_STATE_UPCALL.explanation=An error occurred when the JVM attempted to perform upcall in the trivial downcall +J9NLS_VM_ILLEGAL_THREAD_STATE_UPCALL.system_action=The JVM will throw a IllegalThreadStateException. +J9NLS_VM_ILLEGAL_THREAD_STATE_UPCALL.user_response=Ensure the specified linker options for downcall are valid. +# END NON-TRANSLATABLE diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 70cb94f2422..1188fe6b9e7 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -5384,6 +5384,9 @@ typedef struct J9VMThread { j9object_t scopedValueCache; J9VMContinuation **continuationT1Cache; #endif /* JAVA_SPEC_VERSION >= 19 */ +#if JAVA_SPEC_VERSION >= 21 + BOOLEAN isInTrivialDownCall; +#endif /* JAVA_SPEC_VERSION >= 21 */ } J9VMThread; #define J9VMTHREAD_ALIGNMENT 0x100 diff --git a/runtime/tests/clinkerffi/CMakeLists.txt b/runtime/tests/clinkerffi/CMakeLists.txt index 6ac5983ab51..813d001c8f9 100644 --- a/runtime/tests/clinkerffi/CMakeLists.txt +++ b/runtime/tests/clinkerffi/CMakeLists.txt @@ -165,6 +165,7 @@ omr_add_exports(clinkerffitests add2DoubleStructs_returnStructPointer add3DoubleStructs_returnStruct validateNullAddrArgument + validateTrivialOption add2BoolsWithOrByUpcallMH addBoolAndBoolFromPointerWithOrByUpcallMH addBoolAndBoolFromNativePtrWithOrByUpcallMH @@ -407,6 +408,7 @@ omr_add_exports(clinkerffitests addDoubleFloatOfStructsFromVaListByUpcallMH addNegBytesFromStructByUpcallMH addNegShortsFromStructByUpcallMH + captureTrivialOptionByUpcallMH ) install( diff --git a/runtime/tests/clinkerffi/downcall.c b/runtime/tests/clinkerffi/downcall.c index 0ced25e220f..e79e2c04fbb 100644 --- a/runtime/tests/clinkerffi/downcall.c +++ b/runtime/tests/clinkerffi/downcall.c @@ -2007,3 +2007,15 @@ validateNullAddrArgument(int arg1, stru_Int_Int *arg2) { return arg1; } + +/** + * Validate the linker option for the trivial downcall. + * + * @param arg1 an integer + * @return the passed-in argument + */ +int +validateTrivialOption(int arg1) +{ + return arg1; +} diff --git a/runtime/tests/clinkerffi/module.xml b/runtime/tests/clinkerffi/module.xml index 919cb47f714..f725535edc2 100644 --- a/runtime/tests/clinkerffi/module.xml +++ b/runtime/tests/clinkerffi/module.xml @@ -156,6 +156,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex + @@ -398,6 +399,7 @@ SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-ex + diff --git a/runtime/tests/clinkerffi/upcall.c b/runtime/tests/clinkerffi/upcall.c index 6b1112c4f4a..5d9fa4add46 100644 --- a/runtime/tests/clinkerffi/upcall.c +++ b/runtime/tests/clinkerffi/upcall.c @@ -2896,3 +2896,18 @@ addNegShortsFromStructByUpcallMH(short arg1, stru_Short_Short arg2, short (*upca short shortSum = (*upcallMH)(arg1, arg2, arg2.elem1, arg2.elem2); return shortSum; } + +/** + * Capture the linker option for the trivial downcall during the upcall. + * + * @param arg1 an integer + * @return the passed-in argument + * + * Note: + * The upcall is invalid in the case of the trivial downcall. + */ +int +captureTrivialOptionByUpcallMH(int arg1, int (*upcallMH)(int)) +{ + return (*upcallMH)(arg1); +} diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index a7494fb90e8..ee1029792b7 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -5109,15 +5109,15 @@ class INTERPRETER_CLASS } #if JAVA_SPEC_VERSION >= 16 -#if JAVA_SPEC_VERSION >= 20 +#if JAVA_SPEC_VERSION >= 21 /* openj9.internal.foreign.abi.InternalDowncallHandler: - * private native long invokeNative(long returnStateMemAddr, long returnStructMemAddr, long functionAddr, long calloutThunk, long[] argValues); + * private native long invokeNative(boolean isInTrivialDownCall, long returnStateMemAddr, long returnStructMemAddr, long functionAddr, long calloutThunk, long[] argValues); */ -#else /* JAVA_SPEC_VERSION >= 20 */ +#else /* JAVA_SPEC_VERSION >= 21 */ /* openj9.internal.foreign.abi.InternalDowncallHandler: * private native long invokeNative(long returnStructMemAddr, long functionAddr, long calloutThunk, long[] argValues); */ -#endif /* JAVA_SPEC_VERSION >= 20 */ +#endif /* JAVA_SPEC_VERSION >= 21 */ VMINLINE VM_BytecodeAction inlInternalDowncallHandlerInvokeNative(REGISTER_ARGS_LIST) { @@ -5146,12 +5146,12 @@ class INTERPRETER_CLASS UDATA *returnStorage = &(_currentThread->returnValue); U_64 *ffiArgs = _currentThread->ffiArgs; U_64 sFfiArgs[16]; -#if JAVA_SPEC_VERSION >= 20 - UDATA argSlots = 10; +#if JAVA_SPEC_VERSION >= 21 + UDATA argSlots = 11; I_32 *returnState = NULL; -#else /* JAVA_SPEC_VERSION >= 20 */ +#else /* JAVA_SPEC_VERSION >= 21 */ UDATA argSlots = 8; -#endif /* JAVA_SPEC_VERSION >= 20 */ +#endif /* JAVA_SPEC_VERSION >= 21 */ j9object_t argValues = *(j9object_t *)_sp; /* argValues */ ffi_cif *cif = (ffi_cif *)(UDATA)*(I_64 *)(_sp + 1); /* calloutThunk */ @@ -5175,6 +5175,11 @@ class INTERPRETER_CLASS returnState = (I_32 *)(UDATA)*(I_64 *)(_sp + 7); /* returnStateMemAddr */ #endif /* JAVA_SPEC_VERSION >= 20 */ +#if JAVA_SPEC_VERSION >= 21 + /* Set the linker option to the current thread for the trivial downcall. */ + _currentThread->isInTrivialDownCall = (0 == *(U_32*)(_sp + 9)) ? FALSE : TRUE; +#endif /* JAVA_SPEC_VERSION >= 21 */ + if (isMinimal) { values = sValues; pointerValues = spValues; @@ -5253,7 +5258,13 @@ class INTERPRETER_CLASS _currentThread->callOutCount += 1; #endif /* JAVA_SPEC_VERSION >= 19 */ updateVMStruct(REGISTER_ARGS); - VM_VMAccess::inlineExitVMToJNI(_currentThread); +#if JAVA_SPEC_VERSION >= 21 + /* Only exit to JNI for non-trivial downcalls for better performance. */ + if (!_currentThread->isInTrivialDownCall) +#endif /* JAVA_SPEC_VERSION >= 21 */ + { + VM_VMAccess::inlineExitVMToJNI(_currentThread); + } VM_VMHelpers::beforeJNICall(_currentThread); #if FFI_NATIVE_RAW_API ffiCallWithSetJmpForUpcall(_currentThread, cif, function, returnStorage, values, values_raw); @@ -5261,7 +5272,13 @@ class INTERPRETER_CLASS ffiCallWithSetJmpForUpcall(_currentThread, cif, function, returnStorage, values); #endif /* FFI_NATIVE_RAW_API */ VM_VMHelpers::afterJNICall(_currentThread); - VM_VMAccess::inlineEnterVMFromJNI(_currentThread); +#if JAVA_SPEC_VERSION >= 21 + /* Re-enter VM after non-trivial downcalls. */ + if (!_currentThread->isInTrivialDownCall) +#endif /* JAVA_SPEC_VERSION >= 21 */ + { + VM_VMAccess::inlineEnterVMFromJNI(_currentThread); + } VMStructHasBeenUpdated(REGISTER_ARGS); #if JAVA_SPEC_VERSION >= 19 _currentThread->callOutCount -= 1; @@ -5283,6 +5300,11 @@ class INTERPRETER_CLASS returnDoubleFromINL(REGISTER_ARGS, _currentThread->returnValue, argSlots); done: +#if JAVA_SPEC_VERSION >= 21 + /* Clear the trivial downcall flag. */ + _currentThread->isInTrivialDownCall = FALSE; +#endif /* JAVA_SPEC_VERSION >= 21 */ + if (!isMinimal) { j9mem_free_memory(values); j9mem_free_memory(pointerValues); diff --git a/runtime/vm/UpcallVMHelpers.cpp b/runtime/vm/UpcallVMHelpers.cpp index a456d726f8e..6da24c8ca89 100644 --- a/runtime/vm/UpcallVMHelpers.cpp +++ b/runtime/vm/UpcallVMHelpers.cpp @@ -289,6 +289,17 @@ native2InterpJavaUpcallImpl(J9UpcallMetaData *data, void *argsListPointer) bool isCurThrdAllocated = false; U_64 returnStorage = 0; +#if JAVA_SPEC_VERSION >= 21 + /* Capture the invalid linker option (intended for the trivial downcall as specified in JDK21) in upcall + * by throwing out an exception so as to remind users of the incorrect behavior in applications rather + * than ending up with an assertion failure by crashing the JVM in the RI implementation. + */ + if (downCallThread->isInTrivialDownCall) { + setCurrentExceptionNLS(downCallThread, J9VMCONSTANTPOOL_JAVALANGILLEGALTHREADSTATEEXCEPTION, J9NLS_VM_ILLEGAL_THREAD_STATE_UPCALL); + goto illegalState; + } +#endif /* JAVA_SPEC_VERSION => 21 */ + /* Determine whether to use the current thread or create a new one * when there is no java thread attached to the native thread * created directly in native. @@ -435,6 +446,9 @@ native2InterpJavaUpcallImpl(J9UpcallMetaData *data, void *argsListPointer) currentThread = NULL; } +#if JAVA_SPEC_VERSION >= 21 +illegalState: +#endif /* JAVA_SPEC_VERSION => 21 */ /* Restore back to the setjump site in the call-out native * to handle the captured exception. * diff --git a/runtime/vm/bindnatv.cpp b/runtime/vm/bindnatv.cpp index f9373fc1ed3..a594d3e27bf 100644 --- a/runtime/vm/bindnatv.cpp +++ b/runtime/vm/bindnatv.cpp @@ -298,11 +298,11 @@ static inlMapping mappings[] = { #else /* JAVA_SPEC_VERSION >= 11 */ { "Java_sun_reflect_Reflection_getClassAccessFlags__Ljava_lang_Class_2", J9_BCLOOP_SEND_TARGET_INL_REFLECTION_GETCLASSACCESSFLAGS }, #endif /* JAVA_SPEC_VERSION >= 11 */ -#if JAVA_SPEC_VERSION >= 20 - { "Java_openj9_internal_foreign_abi_InternalDowncallHandler_invokeNative__JJJJ_3J", J9_BCLOOP_SEND_TARGET_INL_INTERNALDOWNCALLHANDLER_INVOKENATIVE }, +#if JAVA_SPEC_VERSION >= 21 + { "Java_openj9_internal_foreign_abi_InternalDowncallHandler_invokeNative__ZJJJJ_3J", J9_BCLOOP_SEND_TARGET_INL_INTERNALDOWNCALLHANDLER_INVOKENATIVE }, #elif JAVA_SPEC_VERSION >= 16 { "Java_openj9_internal_foreign_abi_InternalDowncallHandler_invokeNative__JJJ_3J", J9_BCLOOP_SEND_TARGET_INL_INTERNALDOWNCALLHANDLER_INVOKENATIVE }, -#endif /* JAVA_SPEC_VERSION >= 20 */ +#endif /* JAVA_SPEC_VERSION >= 21 */ #if JAVA_SPEC_VERSION >= 19 { "Java_jdk_internal_vm_Continuation_enterImpl__", J9_BCLOOP_SEND_TARGET_ENTER_CONTINUATION }, { "Java_jdk_internal_vm_Continuation_yieldImpl__Z", J9_BCLOOP_SEND_TARGET_YIELD_CONTINUATION }, diff --git a/runtime/vm/vmthread.cpp b/runtime/vm/vmthread.cpp index b2a080a0f44..c071ccb8313 100644 --- a/runtime/vm/vmthread.cpp +++ b/runtime/vm/vmthread.cpp @@ -267,6 +267,9 @@ allocateVMThread(J9JavaVM * vm, omrthread_t osThread, UDATA privateFlags, void * newThread->ffiArgCount = 0; newThread->jmpBufEnvPtr = NULL; #endif /* JAVA_SPEC_VERSION >= 16 */ +#if JAVA_SPEC_VERSION >= 21 + newThread->isInTrivialDownCall = FALSE; +#endif /* JAVA_SPEC_VERSION >= 21 */ #if JAVA_SPEC_VERSION >= 19 newThread->currentContinuation = NULL; diff --git a/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests1.java b/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests1.java index 7217aaf9126..8b56aed80bf 100644 --- a/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests1.java +++ b/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests1.java @@ -301,4 +301,13 @@ public void test_printfFromDefaultLibWithMemAddr_LinkerOption_1() throws Throwab MemorySegment formatSegmt = arena.allocateUtf8String("\n%d + %d = %d\n"); mh.invoke(formatSegmt, 15, 27, 42); } + + @Test + public void test_validateTrivialOption_1() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT); + MemorySegment functionSymbol = nativeLibLookup.find("validateTrivialOption").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd, Linker.Option.isTrivial()); + int result = (int)mh.invokeExact(111); + Assert.assertEquals(result, 111); + } } diff --git a/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests2.java b/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests2.java index a4633aa2aba..5f88bb145eb 100644 --- a/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests2.java +++ b/test/functional/Java21andUp/src/org/openj9/test/jep442/downcall/PrimitiveTypeTests2.java @@ -301,4 +301,13 @@ public void test_printfFromDefaultLibWithMemAddr_LinkerOption_2() throws Throwab MemorySegment formatSegmt = arena.allocateUtf8String("\n%d + %d = %d\n"); mh.invoke(functionSymbol, formatSegmt, 15, 27, 42); } + + @Test + public void test_validateTrivialOption_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT); + MemorySegment functionSymbol = nativeLibLookup.find("validateTrivialOption").get(); + MethodHandle mh = linker.downcallHandle(fd, Linker.Option.isTrivial()); + int result = (int)mh.invokeExact(functionSymbol, 111); + Assert.assertEquals(result, 111); + } } diff --git a/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/InvalidUpCallTests.java b/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/InvalidUpCallTests.java index 08cea407cdc..65bd24dcb81 100644 --- a/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/InvalidUpCallTests.java +++ b/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/InvalidUpCallTests.java @@ -291,7 +291,7 @@ public void test_InvalidLinkerOptions_captureCallState() throws Throwable { } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Not supported for upcall.*") - public void test_InvalidLinkerOptions_isTrivial() throws Throwable { + public void test_InvalidLinkerOptions_isTrivial_1() throws Throwable { GroupLayout structLayout = MemoryLayout.structLayout(JAVA_INT.withName("elem1"), JAVA_INT.withName("elem2")); VarHandle intHandle1 = structLayout.varHandle(PathElement.groupElement("elem1")); VarHandle intHandle2 = structLayout.varHandle(PathElement.groupElement("elem2")); @@ -306,4 +306,18 @@ public void test_InvalidLinkerOptions_isTrivial() throws Throwable { fail("Failed to throw out IllegalArgumentException in the case of the invalid linker option for upcall."); } } + + @Test(expectedExceptions = IllegalThreadStateException.class, expectedExceptionsMessageRegExp = ".* wrong thread state for upcall") + public void test_InvalidLinkerOptions_isTrivial_2() throws Throwable { + FunctionDescriptor fd = FunctionDescriptor.of(JAVA_INT, JAVA_INT, ADDRESS); + MemorySegment functionSymbol = nativeLibLookup.find("captureTrivialOptionByUpcallMH").get(); + MethodHandle mh = linker.downcallHandle(functionSymbol, fd, Linker.Option.isTrivial()); + + try (Arena arena = Arena.ofConfined()) { + MemorySegment upcallFuncAddr = linker.upcallStub(UpcallMethodHandles.MH_captureTrivialOption, + FunctionDescriptor.of(JAVA_INT, JAVA_INT), arena); + int result = (int)mh.invoke(111, upcallFuncAddr); + fail("Failed to throw out IllegalThreadStateException in the case of the invalid upcall during the trivial downcall."); + } + } } diff --git a/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/UpcallMethodHandles.java b/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/UpcallMethodHandles.java index 327061f61c7..9847aac23a6 100644 --- a/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/UpcallMethodHandles.java +++ b/test/functional/Java21andUp/src/org/openj9/test/jep442/upcall/UpcallMethodHandles.java @@ -273,6 +273,7 @@ public class UpcallMethodHandles { public static final MethodHandle MH_addNegBytesFromStruct; public static final MethodHandle MH_addNegShortsFromStruct; + public static final MethodHandle MH_captureTrivialOption; private static Linker linker = Linker.nativeLinker(); @@ -486,6 +487,7 @@ public class UpcallMethodHandles { MH_addNegBytesFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addNegBytesFromStruct", MT_Byte_Byte_MemSegmt.appendParameterTypes(byte.class, byte.class)); //$NON-NLS-1$ MH_addNegShortsFromStruct = lookup.findStatic(UpcallMethodHandles.class, "addNegShortsFromStruct", MT_Short_Short_MemSegmt.appendParameterTypes(short.class, short.class)); //$NON-NLS-1$ + MH_captureTrivialOption = lookup.findStatic(UpcallMethodHandles.class, "captureTrivialOption", methodType(int.class, int.class)); //$NON-NLS-1$ } catch (IllegalAccessException | NoSuchMethodException e) { throw new InternalError(e); @@ -2067,4 +2069,9 @@ public static short addNegShortsFromStruct(short arg1, MemorySegment arg2, shor short shortSum = (short)(arg1 + arg2_elem1 + arg2_elem2 + arg3 + arg4); return shortSum; } + + public static int captureTrivialOption(int intArg1) { + Assert.fail("The method shouldn't be invoked during the trivial downcall."); + return intArg1; + } }