Search in sources :

Example 1 with GroupLayout

use of jdk.incubator.foreign.GroupLayout in project openj9 by eclipse.

the class LayoutStrPreprocessor method preprocessLayout.

/* Preprocess the layout to generate a concise layout string with all kind symbols
	 * extracted from the layout to simplify parsing the layout string in native.
	 * e.g. a struct layout string with nested struct is as follows: (Only for Java <= 17)
	 * [
	 *   [
	 *    b32(elem1)[abi/kind=INT,layout/name=elem1]
	 *    b32(elem2)[abi/kind=INT,layout/name=elem2]
	 *   ](Struct1_II)[layout/name=Struct1_II]
	 *   [
	 *    b32(elem1)[abi/kind=INT,layout/name=elem1]
	 *    b32(elem2)[abi/kind=INT,layout/name=elem2]
	 *   ](Struct2_II)[layout/name=Struct2_II]
	 * ](nested_struct)[layout/name=nested_struct]
	 *
	 * which ends up with "16#2[#2[II]#2[II]]" by conversion as follows:
	 *
	 *   16#2[  (16 is the byte size of the layout and 2 is the count of the struct elements
	 *        #2[ 2 is the count of the int elements
	 *           I  (INT)
	 *           I  (INT)
	 *          ]
	 *        #2[ 2 is the count of the int elements
	 *           I  (INT)
	 *           I  (INT)
	 *          ]
	 *        ]
	 *  where "#" denotes the start of struct.
	 *
	 *  Note:
	 *  1) the prefix "ByteSize#CountOfElmemnt" and "#CountOfElmemnt" are not required in
	 *  the upcall given the converted layout stirngs are further parsed for the generated
	 *  thunk in native, which is logically different from downcall.
	 *  2) the parsing of primitives in layouts in Java 18 is based on the MemoryLayout.carrier()
	 *  rather than the CLinker.TypeKind which is entirely removed in OpenJDK.
	 */
private static StringBuilder preprocessLayout(MemoryLayout targetLayout, boolean isDownCall) {
    // $NON-NLS-1$
    StringBuilder targetLayoutString = new StringBuilder("");
    /* Directly obtain the kind symbol of the primitive layout */
    if (targetLayout instanceof ValueLayout) {
        targetLayoutString.append(getPrimitiveTypeSymbol((ValueLayout) targetLayout));
    } else if (targetLayout instanceof SequenceLayout) {
        // Intended for nested arrays
        SequenceLayout arrayLayout = (SequenceLayout) targetLayout;
        MemoryLayout elementLayout = arrayLayout.elementLayout();
        long elementCount = arrayLayout.elementCount().getAsLong();
        targetLayoutString.append(elementCount).append(':').append(preprocessLayout(elementLayout, isDownCall));
    } else if (targetLayout instanceof GroupLayout) {
        // Intended for the nested structs
        GroupLayout structLayout = (GroupLayout) targetLayout;
        List<MemoryLayout> elementLayoutList = structLayout.memberLayouts();
        int structElementCount = elementLayoutList.size();
        // $NON-NLS-1$
        StringBuilder elementLayoutStrs = new StringBuilder("");
        int paddingElements = 0;
        for (int elemIndex = 0; elemIndex < structElementCount; elemIndex++) {
            MemoryLayout structElement = elementLayoutList.get(elemIndex);
            /* Ignore any padding element in the struct as it is handled by ffi_call by default */
            if (structElement.isPadding()) {
                paddingElements += 1;
                /* The padding bytes is required in native during the upcall */
                if (!isDownCall) {
                    elementLayoutStrs.append('(').append(structElement.byteSize()).append(')');
                }
            } else {
                elementLayoutStrs.append(preprocessLayout(structElement, isDownCall));
            }
        }
        /* Prefix "#" to denote the start of this layout string in the case of downcall */
        if (isDownCall) {
            targetLayoutString.append('#').append(structElementCount - paddingElements);
        }
        targetLayoutString.append('[').append(elementLayoutStrs).append(']');
    }
    return targetLayoutString;
}
Also used : GroupLayout(jdk.incubator.foreign.GroupLayout) MemoryLayout(jdk.incubator.foreign.MemoryLayout) ValueLayout(jdk.incubator.foreign.ValueLayout) SequenceLayout(jdk.incubator.foreign.SequenceLayout)

Example 2 with GroupLayout

use of jdk.incubator.foreign.GroupLayout in project openj9 by eclipse.

the class StructTests method test_addCharAndCharsFromNestedStruct_reverseOrder.

@Test
public void test_addCharAndCharsFromNestedStruct_reverseOrder() throws Throwable {
    GroupLayout nestedStructLayout = MemoryLayout.ofStruct(C_SHORT.withName("elem1"), C_SHORT.withName("elem2"));
    GroupLayout structLayout = MemoryLayout.ofStruct(C_SHORT.withName("elem1"), nestedStructLayout.withName("struct_elem2"), MemoryLayout.ofPaddingBits(C_SHORT.bitSize()));
    MethodType mt = MethodType.methodType(char.class, char.class, MemorySegment.class);
    FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout);
    Symbol functionSymbol = nativeLib.lookup("addCharAndCharsFromNestedStruct_reverseOrder").get();
    MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd);
    MemorySegment structSegmt = MemorySegment.allocateNative(structLayout);
    MemoryAccess.setCharAtOffset(structSegmt, 0, 'E');
    MemoryAccess.setCharAtOffset(structSegmt, 2, 'F');
    MemoryAccess.setCharAtOffset(structSegmt, 4, 'G');
    char result = (char) mh.invokeExact('H', structSegmt);
    Assert.assertEquals(result, 'W');
    structSegmt.close();
}
Also used : MethodType(java.lang.invoke.MethodType) Symbol(jdk.incubator.foreign.LibraryLookup.Symbol) GroupLayout(jdk.incubator.foreign.GroupLayout) FunctionDescriptor(jdk.incubator.foreign.FunctionDescriptor) MemorySegment(jdk.incubator.foreign.MemorySegment) MethodHandle(java.lang.invoke.MethodHandle) Test(org.testng.annotations.Test)

Example 3 with GroupLayout

use of jdk.incubator.foreign.GroupLayout in project openj9 by eclipse.

the class StructTests method test_addLongAndLongsFromStructWithNestedLongArray.

@Test
public void test_addLongAndLongsFromStructWithNestedLongArray() throws Throwable {
    SequenceLayout longArray = MemoryLayout.ofSequence(2, longLayout);
    GroupLayout structLayout = MemoryLayout.ofStruct(longArray.withName("array_elem1"), longLayout.withName("elem2"));
    MethodType mt = MethodType.methodType(long.class, long.class, MemorySegment.class);
    FunctionDescriptor fd = FunctionDescriptor.of(longLayout, longLayout, structLayout);
    Symbol functionSymbol = nativeLib.lookup("addLongAndLongsFromStructWithNestedLongArray").get();
    MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd);
    MemorySegment structSegmt = MemorySegment.allocateNative(structLayout);
    MemoryAccess.setLongAtOffset(structSegmt, 0, 111111111L);
    MemoryAccess.setLongAtOffset(structSegmt, 8, 222222222L);
    MemoryAccess.setLongAtOffset(structSegmt, 16, 333333333L);
    long result = (long) mh.invokeExact(444444444L, structSegmt);
    Assert.assertEquals(result, 1111111110L);
    structSegmt.close();
}
Also used : MethodType(java.lang.invoke.MethodType) Symbol(jdk.incubator.foreign.LibraryLookup.Symbol) GroupLayout(jdk.incubator.foreign.GroupLayout) FunctionDescriptor(jdk.incubator.foreign.FunctionDescriptor) MemorySegment(jdk.incubator.foreign.MemorySegment) SequenceLayout(jdk.incubator.foreign.SequenceLayout) MethodHandle(java.lang.invoke.MethodHandle) Test(org.testng.annotations.Test)

Example 4 with GroupLayout

use of jdk.incubator.foreign.GroupLayout in project openj9 by eclipse.

the class StructTests method test_addShortAndShortsFromStructWithNestedShortArray.

@Test
public void test_addShortAndShortsFromStructWithNestedShortArray() throws Throwable {
    SequenceLayout shortArray = MemoryLayout.ofSequence(2, C_SHORT);
    GroupLayout structLayout = MemoryLayout.ofStruct(shortArray.withName("array_elem1"), C_SHORT.withName("elem2"), MemoryLayout.ofPaddingBits(C_SHORT.bitSize()));
    MethodType mt = MethodType.methodType(short.class, short.class, MemorySegment.class);
    FunctionDescriptor fd = FunctionDescriptor.of(C_SHORT, C_SHORT, structLayout);
    Symbol functionSymbol = nativeLib.lookup("addShortAndShortsFromStructWithNestedShortArray").get();
    MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd);
    MemorySegment structSegmt = MemorySegment.allocateNative(structLayout);
    MemoryAccess.setShortAtOffset(structSegmt, 0, (short) 111);
    MemoryAccess.setShortAtOffset(structSegmt, 2, (short) 222);
    MemoryAccess.setShortAtOffset(structSegmt, 4, (short) 333);
    short result = (short) mh.invokeExact((short) 444, structSegmt);
    Assert.assertEquals(result, 1110);
    structSegmt.close();
}
Also used : MethodType(java.lang.invoke.MethodType) Symbol(jdk.incubator.foreign.LibraryLookup.Symbol) GroupLayout(jdk.incubator.foreign.GroupLayout) FunctionDescriptor(jdk.incubator.foreign.FunctionDescriptor) MemorySegment(jdk.incubator.foreign.MemorySegment) SequenceLayout(jdk.incubator.foreign.SequenceLayout) MethodHandle(java.lang.invoke.MethodHandle) Test(org.testng.annotations.Test)

Example 5 with GroupLayout

use of jdk.incubator.foreign.GroupLayout in project openj9 by eclipse.

the class StructTests method test_addDoubleAndDoublesFromStructWithNestedStructArray.

@Test
public void test_addDoubleAndDoublesFromStructWithNestedStructArray() throws Throwable {
    GroupLayout doubleStruct = MemoryLayout.ofStruct(C_DOUBLE.withName("elem1"), C_DOUBLE.withName("elem2"));
    SequenceLayout structArray = MemoryLayout.ofSequence(2, doubleStruct);
    GroupLayout structLayout = MemoryLayout.ofStruct(structArray.withName("struct_array_elem1"), C_DOUBLE.withName("elem2"));
    MethodType mt = MethodType.methodType(double.class, double.class, MemorySegment.class);
    FunctionDescriptor fd = FunctionDescriptor.of(C_DOUBLE, C_DOUBLE, structLayout);
    Symbol functionSymbol = nativeLib.lookup("addDoubleAndDoublesFromStructWithNestedStructArray").get();
    MethodHandle mh = clinker.downcallHandle(functionSymbol, mt, fd);
    MemorySegment structSegmt = MemorySegment.allocateNative(structLayout);
    MemoryAccess.setDoubleAtOffset(structSegmt, 0, 111.111D);
    MemoryAccess.setDoubleAtOffset(structSegmt, 8, 222.222D);
    MemoryAccess.setDoubleAtOffset(structSegmt, 16, 333.333D);
    MemoryAccess.setDoubleAtOffset(structSegmt, 24, 444.444D);
    MemoryAccess.setDoubleAtOffset(structSegmt, 32, 555.555D);
    double result = (double) mh.invokeExact(666.666D, structSegmt);
    Assert.assertEquals(result, 2333.331D, 0.001D);
    structSegmt.close();
}
Also used : MethodType(java.lang.invoke.MethodType) Symbol(jdk.incubator.foreign.LibraryLookup.Symbol) GroupLayout(jdk.incubator.foreign.GroupLayout) FunctionDescriptor(jdk.incubator.foreign.FunctionDescriptor) MemorySegment(jdk.incubator.foreign.MemorySegment) SequenceLayout(jdk.incubator.foreign.SequenceLayout) MethodHandle(java.lang.invoke.MethodHandle) Test(org.testng.annotations.Test)

Aggregations

GroupLayout (jdk.incubator.foreign.GroupLayout)677 MethodHandle (java.lang.invoke.MethodHandle)675 FunctionDescriptor (jdk.incubator.foreign.FunctionDescriptor)675 MemorySegment (jdk.incubator.foreign.MemorySegment)675 Test (org.testng.annotations.Test)675 ResourceScope (jdk.incubator.foreign.ResourceScope)540 SegmentAllocator (jdk.incubator.foreign.SegmentAllocator)540 MethodType (java.lang.invoke.MethodType)405 VarHandle (java.lang.invoke.VarHandle)318 Addressable (jdk.incubator.foreign.Addressable)270 NativeSymbol (jdk.incubator.foreign.NativeSymbol)270 SequenceLayout (jdk.incubator.foreign.SequenceLayout)241 Symbol (jdk.incubator.foreign.LibraryLookup.Symbol)135 MemoryAddress (jdk.incubator.foreign.MemoryAddress)80 MemoryLayout (jdk.incubator.foreign.MemoryLayout)2 ValueLayout (jdk.incubator.foreign.ValueLayout)1