1 /* 2 * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @run testng/othervm 27 * -Djdk.internal.foreign.DowncallLinker.USE_SPEC=true 28 * --enable-native-access=ALL-UNNAMED 29 * -Xbatch 30 * TestIntrinsics 31 */ 32 33 import java.lang.foreign.Linker; 34 import java.lang.foreign.FunctionDescriptor; 35 36 import java.lang.foreign.MemorySegment; 37 import java.lang.invoke.MethodHandle; 38 import java.util.ArrayList; 39 import java.util.List; 40 41 import java.lang.foreign.MemoryLayout; 42 import org.testng.annotations.*; 43 44 import static java.lang.foreign.Linker.Option.firstVariadicArg; 45 import static java.lang.invoke.MethodType.methodType; 46 import static java.lang.foreign.ValueLayout.JAVA_CHAR; 47 import static org.testng.Assert.assertEquals; 48 49 public class TestIntrinsics extends NativeTestHelper { 50 51 static final Linker abi = Linker.nativeLinker(); 52 static { 53 System.loadLibrary("Intrinsics"); 54 } 55 56 private interface RunnableX { 57 void run() throws Throwable; 58 } 59 60 @Test(dataProvider = "tests") 61 public void testIntrinsics(RunnableX test) throws Throwable { 62 for (int i = 0; i < 20_000; i++) { 63 test.run(); 64 } 65 } 66 67 @DataProvider 68 public Object[][] tests() { 69 List<RunnableX> testsList = new ArrayList<>(); 70 71 interface AddTest { 72 void add(MethodHandle target, Object expectedResult, Object... args); 73 } 74 75 AddTest tests = (mh, expectedResult, args) -> testsList.add(() -> { 76 Object actual = mh.invokeWithArguments(args); 77 assertEquals(actual, expectedResult); 78 }); 79 80 interface AddIdentity { 81 void add(String name, Class<?> carrier, MemoryLayout layout, Object arg); 82 } 83 84 AddIdentity addIdentity = (name, carrier, layout, arg) -> { 85 MemorySegment ma = findNativeOrThrow(name); 86 FunctionDescriptor fd = FunctionDescriptor.of(layout, layout); 87 88 tests.add(abi.downcallHandle(ma, fd), arg, arg); 89 tests.add(abi.downcallHandle(fd), arg, ma, arg); 90 }; 91 92 { // empty 93 MemorySegment ma = findNativeOrThrow("empty"); 94 FunctionDescriptor fd = FunctionDescriptor.ofVoid(); 95 tests.add(abi.downcallHandle(ma, fd), null); 96 } 97 98 addIdentity.add("identity_bool", boolean.class, C_BOOL, true); 99 addIdentity.add("identity_char", byte.class, C_CHAR, (byte) 10); 100 addIdentity.add("identity_short", short.class, C_SHORT, (short) 10); 101 addIdentity.add("identity_int", int.class, C_INT, 10); 102 addIdentity.add("identity_long", long.class, C_LONG_LONG, 10L); 103 addIdentity.add("identity_float", float.class, C_FLOAT, 10F); 104 addIdentity.add("identity_double", double.class, C_DOUBLE, 10D); 105 106 { // identity_va 107 MemorySegment ma = findNativeOrThrow("identity_va"); 108 FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, 109 C_DOUBLE, C_INT, C_DOUBLE, C_LONG_LONG); 110 tests.add(abi.downcallHandle(ma, fd, firstVariadicArg(1)), 1, 1, 10D, 2, 3D, 4L); 111 } 112 113 { // high_arity 114 FunctionDescriptor baseFD = FunctionDescriptor.ofVoid(C_INT, C_DOUBLE, C_LONG_LONG, C_FLOAT, C_CHAR, 115 C_SHORT, JAVA_CHAR); 116 Object[] args = {1, 10D, 2L, 3F, (byte) 0, (short) 13, 'a'}; 117 for (int i = 0; i < args.length; i++) { 118 MemorySegment ma = findNativeOrThrow("invoke_high_arity" + i); 119 FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i)); 120 Object expected = args[i]; 121 tests.add(abi.downcallHandle(ma, fd), expected, args); 122 } 123 } 124 125 return testsList.stream().map(rx -> new Object[]{ rx }).toArray(Object[][]::new); 126 } 127 }