Skip to content

Commit

Permalink
Merge pull request #17847 from ChengJin01/ffi_update_code_for_jep442_…
Browse files Browse the repository at this point in the history
…jdk21_v6_jtregs_3_trivial

[FFI/Jtreg_JDK21] Detect the downcall linker option in upcall
  • Loading branch information
tajila authored Jul 28, 2023
2 parents d5c4ab6 + 5929664 commit 2739d22
Show file tree
Hide file tree
Showing 18 changed files with 247 additions and 233 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/
/*******************************************************************************
* Copyright IBM Corp. and others 2022
*
Expand Down Expand Up @@ -32,33 +32,24 @@
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;
import jdk.incubator.foreign.MemoryLayout;
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
Expand All @@ -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 */
Expand All @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/
/*******************************************************************************
* Copyright IBM Corp. and others 2022
*
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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<MemoryLayout> argLayouts = funcDesc.argumentLayouts();
int argLayoutsSize = argLayouts.size();
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 = "";
Expand All @@ -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]
Expand Down Expand Up @@ -313,5 +313,5 @@ private static String getPrimitiveTypeSymbol(ValueLayout targetLayout) {

return typeSymbol;
}
/*[ENDIF] JAVA_SPEC_VERSION >= 20 */
/*[ENDIF] JAVA_SPEC_VERSION >= 21 */
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 20]*/
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 21]*/
/*******************************************************************************
* Copyright IBM Corp. and others 2022
*
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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.");
Expand All @@ -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.");
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 */
Expand Down
7 changes: 7 additions & 0 deletions runtime/nls/j9vm/j9vm.nls
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions runtime/tests/clinkerffi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ omr_add_exports(clinkerffitests
add2DoubleStructs_returnStructPointer
add3DoubleStructs_returnStruct
validateNullAddrArgument
validateTrivialOption
add2BoolsWithOrByUpcallMH
addBoolAndBoolFromPointerWithOrByUpcallMH
addBoolAndBoolFromNativePtrWithOrByUpcallMH
Expand Down Expand Up @@ -407,6 +408,7 @@ omr_add_exports(clinkerffitests
addDoubleFloatOfStructsFromVaListByUpcallMH
addNegBytesFromStructByUpcallMH
addNegShortsFromStructByUpcallMH
captureTrivialOptionByUpcallMH
)

install(
Expand Down
12 changes: 12 additions & 0 deletions runtime/tests/clinkerffi/downcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Loading

0 comments on commit 2739d22

Please sign in to comment.