8277924: Small tweaks to foreign function and memory API
Reviewed-by: jvernee, psandoz
This commit is contained in:
parent
e002bfec8c
commit
ea905bd3da
@ -97,7 +97,7 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc
|
||||
* Obtain a specialized variadic function descriptor, by appending given variadic layouts to this
|
||||
* function descriptor argument layouts. The resulting function descriptor can report the position
|
||||
* of the {@linkplain #firstVariadicArgumentIndex() first variadic argument}, and cannot be altered
|
||||
* in any way: for instance, calling {@link #withReturnLayout(MemoryLayout)} on the resulting descriptor
|
||||
* in any way: for instance, calling {@link #changeReturnLayout(MemoryLayout)} on the resulting descriptor
|
||||
* will throw an {@link UnsupportedOperationException}.
|
||||
* @param variadicLayouts the variadic argument layouts to be appended to this descriptor argument layouts.
|
||||
* @return a new variadic function descriptor, or this descriptor if {@code variadicLayouts.length == 0}.
|
||||
@ -123,10 +123,26 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc
|
||||
* @param addedLayouts the argument layouts to append.
|
||||
* @return the new function descriptor.
|
||||
*/
|
||||
public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) {
|
||||
Objects.requireNonNull(addedLayouts);
|
||||
Arrays.stream(addedLayouts).forEach(Objects::requireNonNull);
|
||||
List<MemoryLayout> newLayouts = Stream.concat(argLayouts.stream(), Stream.of(addedLayouts)).toList();
|
||||
public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) {
|
||||
return insertArgumentLayouts(argLayouts.size(), addedLayouts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new function descriptor with the given argument layouts inserted at the given index, into the argument
|
||||
* layout array of this function descriptor.
|
||||
* @param index the index at which to insert the arguments
|
||||
* @param addedLayouts the argument layouts to insert at given index.
|
||||
* @return the new function descriptor.
|
||||
* @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}.
|
||||
*/
|
||||
public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) {
|
||||
if (index < 0 || index > argLayouts.size())
|
||||
throw new IllegalArgumentException("Index out of bounds: " + index);
|
||||
List<MemoryLayout> added = List.of(addedLayouts); // null check on array and its elements
|
||||
List<MemoryLayout> newLayouts = new ArrayList<>(argLayouts.size() + addedLayouts.length);
|
||||
newLayouts.addAll(argLayouts.subList(0, index));
|
||||
newLayouts.addAll(added);
|
||||
newLayouts.addAll(argLayouts.subList(index, argLayouts.size()));
|
||||
return new FunctionDescriptor(resLayout, newLayouts);
|
||||
}
|
||||
|
||||
@ -135,16 +151,17 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc
|
||||
* @param newReturn the new return layout.
|
||||
* @return the new function descriptor.
|
||||
*/
|
||||
public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) {
|
||||
public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) {
|
||||
Objects.requireNonNull(newReturn);
|
||||
return new FunctionDescriptor(newReturn, argLayouts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new function descriptor with the return layout dropped.
|
||||
* Create a new function descriptor with the return layout dropped. This is useful to model functions
|
||||
* which return no values.
|
||||
* @return the new function descriptor.
|
||||
*/
|
||||
public FunctionDescriptor withVoidReturnLayout() {
|
||||
public FunctionDescriptor dropReturnLayout() {
|
||||
return new FunctionDescriptor(null, argLayouts);
|
||||
}
|
||||
|
||||
@ -231,17 +248,22 @@ public sealed class FunctionDescriptor implements Constable permits FunctionDesc
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) {
|
||||
public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) {
|
||||
public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor withVoidReturnLayout() {
|
||||
public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionDescriptor dropReturnLayout() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class CallingSequenceBuilder {
|
||||
verifyBindings(true, carrier, bindings);
|
||||
inputBindings.add(bindings);
|
||||
mt = mt.appendParameterTypes(carrier);
|
||||
desc = desc.withAppendedArgumentLayouts(layout);
|
||||
desc = desc.appendArgumentLayouts(layout);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public class CallingSequenceBuilder {
|
||||
verifyBindings(false, carrier, bindings);
|
||||
this.outputBindings = bindings;
|
||||
mt = mt.changeReturnType(carrier);
|
||||
desc = desc.withReturnLayout(layout);
|
||||
desc = desc.changeReturnLayout(layout);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,8 @@ import jdk.incubator.foreign.FunctionDescriptor;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.lang.constant.Constable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
@ -67,7 +65,7 @@ public class TestFunctionDescriptor extends NativeTestHelper {
|
||||
@Test
|
||||
public void testAppendArgumentLayouts() {
|
||||
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
|
||||
fd = fd.withAppendedArgumentLayouts(C_POINTER);
|
||||
fd = fd.appendArgumentLayouts(C_POINTER);
|
||||
|
||||
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG, C_POINTER));
|
||||
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();
|
||||
@ -78,7 +76,7 @@ public class TestFunctionDescriptor extends NativeTestHelper {
|
||||
@Test
|
||||
public void testChangeReturnLayout() {
|
||||
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
|
||||
fd = fd.withReturnLayout(C_INT);
|
||||
fd = fd.changeReturnLayout(C_INT);
|
||||
|
||||
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG));
|
||||
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();
|
||||
@ -89,7 +87,7 @@ public class TestFunctionDescriptor extends NativeTestHelper {
|
||||
@Test
|
||||
public void testDropReturnLayout() {
|
||||
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
|
||||
fd = fd.withVoidReturnLayout();
|
||||
fd = fd.dropReturnLayout();
|
||||
|
||||
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG));
|
||||
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();
|
||||
|
@ -40,7 +40,6 @@ import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.NativeSymbol;
|
||||
import jdk.incubator.foreign.SymbolLookup;
|
||||
@ -127,7 +126,7 @@ public class TestIntrinsics extends NativeTestHelper {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
NativeSymbol ma = LOOKUP.lookup("invoke_high_arity" + i).get();
|
||||
MethodType mt = baseMT.changeReturnType(baseMT.parameterType(i));
|
||||
FunctionDescriptor fd = baseFD.withReturnLayout(baseFD.argumentLayouts().get(i));
|
||||
FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i));
|
||||
Object expected = args[i];
|
||||
tests.add(abi.downcallHandle(ma, fd), expected, args);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,6 +22,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=scope
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
* @modules jdk.incubator.foreign/jdk.internal.foreign
|
||||
* @build NativeTestHelper CallGeneratorHelper TestUpcall
|
||||
*
|
||||
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
|
||||
* --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17
|
||||
* -DUPCALL_TEST_TYPE=SCOPE
|
||||
* TestUpcall
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=no_scope
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
* @modules jdk.incubator.foreign/jdk.internal.foreign
|
||||
* @build NativeTestHelper CallGeneratorHelper TestUpcall
|
||||
*
|
||||
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
|
||||
* --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17
|
||||
* -DUPCALL_TEST_TYPE=NO_SCOPE
|
||||
* TestUpcall
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test id=async
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
@ -34,13 +58,11 @@
|
||||
* TestUpcall
|
||||
*/
|
||||
|
||||
import jdk.incubator.foreign.Addressable;
|
||||
import jdk.incubator.foreign.CLinker;
|
||||
import jdk.incubator.foreign.FunctionDescriptor;
|
||||
import jdk.incubator.foreign.NativeSymbol;
|
||||
import jdk.incubator.foreign.SegmentAllocator;
|
||||
import jdk.incubator.foreign.SymbolLookup;
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
|
||||
@ -104,7 +126,7 @@ public class TestUpcall extends CallGeneratorHelper {
|
||||
|
||||
private static void checkSelected(TestType type) {
|
||||
if (UPCALL_TEST_TYPE != type)
|
||||
return;//throw new SkipException("Skipping tests that were not selected");
|
||||
throw new SkipException("Skipping tests that were not selected");
|
||||
}
|
||||
|
||||
@Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class)
|
||||
|
@ -62,7 +62,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(rax, long.class) }
|
||||
@ -89,7 +89,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
|
||||
@ -119,7 +119,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
|
||||
@ -148,7 +148,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
|
||||
@ -177,7 +177,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
|
||||
@ -201,7 +201,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(rdi, int.class) },
|
||||
@ -231,7 +231,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(xmm0, double.class) },
|
||||
@ -265,7 +265,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(rdi, long.class) },
|
||||
@ -321,7 +321,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(rdi, int.class) },
|
||||
@ -363,7 +363,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ unboxAddress(), vmStore(rdi, long.class) },
|
||||
@ -384,7 +384,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
expectedBindings,
|
||||
@ -442,7 +442,7 @@ public class TestSysVCallArranger extends CallArrangerTestBase {
|
||||
assertFalse(bindings.isInMemoryReturn);
|
||||
CallingSequence callingSequence = bindings.callingSequence;
|
||||
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
|
||||
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
|
||||
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
|
||||
|
||||
checkArgumentBindings(callingSequence, new Binding[][]{
|
||||
{ vmStore(rax, long.class) }
|
||||
|
@ -124,7 +124,7 @@ public class Upcalls extends CLayouts {
|
||||
static MethodHandle linkFunc(String name, FunctionDescriptor baseDesc) {
|
||||
return abi.downcallHandle(
|
||||
SymbolLookup.loaderLookup().lookup(name).orElseThrow(),
|
||||
baseDesc.withAppendedArgumentLayouts(C_POINTER)
|
||||
baseDesc.appendArgumentLayouts(C_POINTER)
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user