< prev index next >

test/jdk/java/foreign/StdLibTest.java

Print this page
@@ -37,30 +37,26 @@
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.LinkedHashSet;
  import java.util.List;
- import java.util.Optional;
  import java.util.Set;
  import java.util.function.BiConsumer;
  import java.util.function.Function;
  import java.util.stream.Collectors;
  import java.util.stream.Stream;
  
  import jdk.incubator.foreign.*;
  
- import static jdk.incubator.foreign.MemoryAccess.*;
- 
  import org.testng.annotations.*;
  
- import static jdk.incubator.foreign.CLinker.*;
  import static org.testng.Assert.*;
  
  @Test
- public class StdLibTest {
+ public class StdLibTest extends NativeTestHelper {
  
-     final static CLinker abi = CLinker.getInstance();
+     final static CLinker abi = CLinker.systemCLinker();
  
      private StdLibHelper stdLibHelper = new StdLibHelper();
  
      @Test(dataProvider = "stringPairs")
      void test_strcat(String s1, String s2) throws Throwable {

@@ -153,102 +149,93 @@
          assertEquals(found, expected.length());
      }
  
      static class StdLibHelper {
  
-         static final SymbolLookup LOOKUP = CLinker.systemLookup();
- 
-         final static MethodHandle strcat = abi.downcallHandle(LOOKUP.lookup("strcat").get(),
-                 MethodType.methodType(MemoryAddress.class, MemoryAddress.class, MemoryAddress.class),
-                 FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER));
+         final static MethodHandle strcat = abi.downcallHandle(abi.lookup("strcat").get(),
+                 FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER))
+                 .asType(MethodType.methodType(MemoryAddress.class, MemorySegment.class, MemorySegment.class)); // exact signature match
  
-         final static MethodHandle strcmp = abi.downcallHandle(LOOKUP.lookup("strcmp").get(),
-                 MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class),
+         final static MethodHandle strcmp = abi.downcallHandle(abi.lookup("strcmp").get(),
                  FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER));
  
-         final static MethodHandle puts = abi.downcallHandle(LOOKUP.lookup("puts").get(),
-                 MethodType.methodType(int.class, MemoryAddress.class),
+         final static MethodHandle puts = abi.downcallHandle(abi.lookup("puts").get(),
                  FunctionDescriptor.of(C_INT, C_POINTER));
  
-         final static MethodHandle strlen = abi.downcallHandle(LOOKUP.lookup("strlen").get(),
-                 MethodType.methodType(int.class, MemoryAddress.class),
+         final static MethodHandle strlen = abi.downcallHandle(abi.lookup("strlen").get(),
                  FunctionDescriptor.of(C_INT, C_POINTER));
  
-         final static MethodHandle gmtime = abi.downcallHandle(LOOKUP.lookup("gmtime").get(),
-                 MethodType.methodType(MemoryAddress.class, MemoryAddress.class),
+         final static MethodHandle gmtime = abi.downcallHandle(abi.lookup("gmtime").get(),
                  FunctionDescriptor.of(C_POINTER, C_POINTER));
  
-         final static MethodHandle qsort = abi.downcallHandle(LOOKUP.lookup("qsort").get(),
-                 MethodType.methodType(void.class, MemoryAddress.class, long.class, long.class, MemoryAddress.class),
+         final static MethodHandle qsort = abi.downcallHandle(abi.lookup("qsort").get(),
                  FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER));
  
          final static FunctionDescriptor qsortComparFunction = FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER);
  
          final static MethodHandle qsortCompar;
  
-         final static MethodHandle rand = abi.downcallHandle(LOOKUP.lookup("rand").get(),
-                 MethodType.methodType(int.class),
+         final static MethodHandle rand = abi.downcallHandle(abi.lookup("rand").get(),
                  FunctionDescriptor.of(C_INT));
  
-         final static MethodHandle vprintf = abi.downcallHandle(LOOKUP.lookup("vprintf").get(),
-                 MethodType.methodType(int.class, MemoryAddress.class, VaList.class),
-                 FunctionDescriptor.of(C_INT, C_POINTER, C_VA_LIST));
+         final static MethodHandle vprintf = abi.downcallHandle(abi.lookup("vprintf").get(),
+                 FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER));
  
-         final static MemoryAddress printfAddr = LOOKUP.lookup("printf").get();
+         final static NativeSymbol printfAddr = abi.lookup("printf").get();
  
          final static FunctionDescriptor printfBase = FunctionDescriptor.of(C_INT, C_POINTER);
  
          static {
              try {
                  //qsort upcall handle
                  qsortCompar = MethodHandles.lookup().findStatic(StdLibTest.StdLibHelper.class, "qsortCompare",
-                         MethodType.methodType(int.class, MemorySegment.class, MemoryAddress.class, MemoryAddress.class));
+                         MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class));
              } catch (ReflectiveOperationException ex) {
                  throw new IllegalStateException(ex);
              }
          }
  
          String strcat(String s1, String s2) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment buf = MemorySegment.allocateNative(s1.length() + s2.length() + 1, scope);
-                 MemorySegment other = toCString(s2, scope);
-                 char[] chars = s1.toCharArray();
-                 for (long i = 0 ; i < chars.length ; i++) {
-                     setByteAtOffset(buf, i, (byte)chars[(int)i]);
-                 }
-                 setByteAtOffset(buf, chars.length, (byte)'\0');
-                 return toJavaString(((MemoryAddress)strcat.invokeExact(buf.address(), other.address())));
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment buf = malloc.allocate(s1.length() + s2.length() + 1);
+                 buf.setUtf8String(0, s1);
+                 MemorySegment other = malloc.allocateUtf8String(s2);
+                 return ((MemoryAddress)strcat.invokeExact(buf, other)).getUtf8String(0);
              }
          }
  
          int strcmp(String s1, String s2) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment ns1 = toCString(s1, scope);
-                 MemorySegment ns2 = toCString(s2, scope);
-                 return (int)strcmp.invokeExact(ns1.address(), ns2.address());
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment ns1 = malloc.allocateUtf8String(s1);
+                 MemorySegment ns2 = malloc.allocateUtf8String(s2);
+                 return (int)strcmp.invoke(ns1, ns2);
              }
          }
  
          int puts(String msg) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment s = toCString(msg, scope);
-                 return (int)puts.invokeExact(s.address());
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment s = malloc.allocateUtf8String(msg);
+                 return (int)puts.invoke(s);
              }
          }
  
          int strlen(String msg) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment s = toCString(msg, scope);
-                 return (int)strlen.invokeExact(s.address());
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment s = malloc.allocateUtf8String(msg);
+                 return (int)strlen.invoke(s);
              }
          }
  
          Tm gmtime(long arg) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
                  MemorySegment time = MemorySegment.allocateNative(8, scope);
-                 setLong(time, arg);
-                 return new Tm((MemoryAddress)gmtime.invokeExact(time.address()));
+                 time.set(C_LONG_LONG, 0, arg);
+                 return new Tm((MemoryAddress)gmtime.invoke(time));
              }
          }
  
          static class Tm {
  

@@ -256,93 +243,96 @@
              private final MemorySegment base;
  
              static final long SIZE = 56;
  
              Tm(MemoryAddress addr) {
-                 this.base = addr.asSegment(SIZE, ResourceScope.globalScope());
+                 this.base = MemorySegment.ofAddressNative(addr, SIZE, ResourceScope.globalScope());
              }
  
              int sec() {
-                 return getIntAtOffset(base, 0);
+                 return base.get(C_INT, 0);
              }
              int min() {
-                 return getIntAtOffset(base, 4);
+                 return base.get(C_INT, 4);
              }
              int hour() {
-                 return getIntAtOffset(base, 8);
+                 return base.get(C_INT, 8);
              }
              int mday() {
-                 return getIntAtOffset(base, 12);
+                 return base.get(C_INT, 12);
              }
              int mon() {
-                 return getIntAtOffset(base, 16);
+                 return base.get(C_INT, 16);
              }
              int year() {
-                 return getIntAtOffset(base, 20);
+                 return base.get(C_INT, 20);
              }
              int wday() {
-                 return getIntAtOffset(base, 24);
+                 return base.get(C_INT, 24);
              }
              int yday() {
-                 return getIntAtOffset(base, 28);
+                 return base.get(C_INT, 28);
              }
              boolean isdst() {
-                 byte b = getByteAtOffset(base, 32);
-                 return b != 0;
+                 return base.get(C_BOOL, 32);
              }
          }
  
          int[] qsort(int[] arr) throws Throwable {
              //init native array
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 SegmentAllocator allocator = SegmentAllocator.ofScope(scope);
-                 MemorySegment nativeArr = allocator.allocateArray(C_INT, arr);
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment nativeArr = malloc.allocateArray(C_INT, arr);
  
                  //call qsort
-                 MemoryAddress qsortUpcallStub = abi.upcallStub(qsortCompar.bindTo(nativeArr), qsortComparFunction, scope);
+                 NativeSymbol qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, scope);
  
-                 qsort.invokeExact(nativeArr.address(), (long)arr.length, C_INT.byteSize(), qsortUpcallStub);
+                 qsort.invoke(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub);
  
                  //convert back to Java array
-                 return nativeArr.toIntArray();
+                 return nativeArr.toArray(C_INT);
              }
          }
  
-         static int qsortCompare(MemorySegment base, MemoryAddress addr1, MemoryAddress addr2) {
-             return getIntAtOffset(base, addr1.segmentOffset(base)) -
-                    getIntAtOffset(base, addr2.segmentOffset(base));
+         static int qsortCompare(MemoryAddress addr1, MemoryAddress addr2) {
+             return addr1.get(C_INT, 0) -
+                    addr2.get(C_INT, 0);
          }
  
          int rand() throws Throwable {
              return (int)rand.invokeExact();
          }
  
          int printf(String format, List<PrintfArg> args) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment formatStr = toCString(format, scope);
-                 return (int)specializedPrintf(args).invokeExact(formatStr.address(),
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment formatStr = malloc.allocateUtf8String(format);
+                 return (int)specializedPrintf(args).invoke(formatStr,
                          args.stream().map(a -> a.nativeValue(scope)).toArray());
              }
          }
  
          int vprintf(String format, List<PrintfArg> args) throws Throwable {
              try (ResourceScope scope = ResourceScope.newConfinedScope()) {
-                 MemorySegment formatStr = toCString(format, scope);
+                 var malloc = SegmentAllocator.nativeAllocator(scope);
+                 MemorySegment formatStr = malloc.allocateUtf8String(format);
                  VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, scope)), scope);
-                 return (int)vprintf.invokeExact(formatStr.address(), vaList);
+                 return (int)vprintf.invoke(formatStr, vaList);
              }
          }
  
          private MethodHandle specializedPrintf(List<PrintfArg> args) {
              //method type
              MethodType mt = MethodType.methodType(int.class, MemoryAddress.class);
              FunctionDescriptor fd = printfBase;
+             List<MemoryLayout> variadicLayouts = new ArrayList<>(args.size());
              for (PrintfArg arg : args) {
                  mt = mt.appendParameterTypes(arg.carrier);
-                 fd = fd.withAppendedArgumentLayouts(arg.layout);
+                 variadicLayouts.add(arg.layout);
              }
-             MethodHandle mh = abi.downcallHandle(printfAddr, mt, fd);
+             MethodHandle mh = abi.downcallHandle(printfAddr,
+                     fd.asVariadic(variadicLayouts.toArray(new MemoryLayout[args.size()])));
              return mh.asSpreader(1, Object[].class, args.size());
          }
      }
  
      /*** data providers ***/

@@ -399,24 +389,28 @@
                  .toArray(Object[][]::new);
      }
  
      enum PrintfArg implements BiConsumer<VaList.Builder, ResourceScope> {
  
-         INTEGRAL(int.class, asVarArg(C_INT), "%d", scope -> 42, 42, VaList.Builder::vargFromInt),
-         STRING(MemoryAddress.class, asVarArg(C_POINTER), "%s", scope -> toCString("str", scope).address(), "str", VaList.Builder::vargFromAddress),
-         CHAR(byte.class, asVarArg(C_CHAR), "%c", scope -> (byte) 'h', 'h', (builder, layout, value) -> builder.vargFromInt(C_INT, (int)value)),
-         DOUBLE(double.class, asVarArg(C_DOUBLE), "%.4f", scope ->1.2345d, 1.2345d, VaList.Builder::vargFromDouble);
+         INTEGRAL(int.class, C_INT, "%d", scope -> 42, 42, VaList.Builder::addVarg),
+         STRING(MemoryAddress.class, C_POINTER, "%s", scope -> {
+             var segment = MemorySegment.allocateNative(4, scope);
+             segment.setUtf8String(0, "str");
+             return segment.address();
+         }, "str", VaList.Builder::addVarg),
+         CHAR(byte.class, C_CHAR, "%c", scope -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)),
+         DOUBLE(double.class, C_DOUBLE, "%.4f", scope ->1.2345d, 1.2345d, VaList.Builder::addVarg);
  
          final Class<?> carrier;
          final ValueLayout layout;
          final String format;
          final Function<ResourceScope, ?> nativeValueFactory;
          final Object javaValue;
          @SuppressWarnings("rawtypes")
          final VaListBuilderCall builderCall;
  
-         <Z> PrintfArg(Class<?> carrier, ValueLayout layout, String format, Function<ResourceScope, Z> nativeValueFactory, Object javaValue, VaListBuilderCall<Z> builderCall) {
+         <Z, L extends ValueLayout> PrintfArg(Class<?> carrier, L layout, String format, Function<ResourceScope, Z> nativeValueFactory, Object javaValue, VaListBuilderCall<Z, L> builderCall) {
              this.carrier = carrier;
              this.layout = layout;
              this.format = format;
              this.nativeValueFactory = nativeValueFactory;
              this.javaValue = javaValue;

@@ -427,12 +421,12 @@
          @SuppressWarnings("unchecked")
          public void accept(VaList.Builder builder, ResourceScope scope) {
              builderCall.build(builder, layout, nativeValueFactory.apply(scope));
          }
  
-         interface VaListBuilderCall<V> {
-             void build(VaList.Builder builder, ValueLayout layout, V value);
+         interface VaListBuilderCall<V, L> {
+             void build(VaList.Builder builder, L layout, V value);
          }
  
          public Object nativeValue(ResourceScope scope) {
              return nativeValueFactory.apply(scope);
          }
< prev index next >