Skip to content

Commit ea905bd

Browse files
committedDec 2, 2021
8277924: Small tweaks to foreign function and memory API
Reviewed-by: jvernee, psandoz
1 parent e002bfe commit ea905bd

File tree

7 files changed

+79
-38
lines changed

7 files changed

+79
-38
lines changed
 

‎src/jdk.incubator.foreign/share/classes/jdk/incubator/foreign/FunctionDescriptor.java

+34-12
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) {
9797
* Obtain a specialized variadic function descriptor, by appending given variadic layouts to this
9898
* function descriptor argument layouts. The resulting function descriptor can report the position
9999
* of the {@linkplain #firstVariadicArgumentIndex() first variadic argument}, and cannot be altered
100-
* in any way: for instance, calling {@link #withReturnLayout(MemoryLayout)} on the resulting descriptor
100+
* in any way: for instance, calling {@link #changeReturnLayout(MemoryLayout)} on the resulting descriptor
101101
* will throw an {@link UnsupportedOperationException}.
102102
* @param variadicLayouts the variadic argument layouts to be appended to this descriptor argument layouts.
103103
* @return a new variadic function descriptor, or this descriptor if {@code variadicLayouts.length == 0}.
@@ -123,10 +123,26 @@ public int firstVariadicArgumentIndex() {
123123
* @param addedLayouts the argument layouts to append.
124124
* @return the new function descriptor.
125125
*/
126-
public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) {
127-
Objects.requireNonNull(addedLayouts);
128-
Arrays.stream(addedLayouts).forEach(Objects::requireNonNull);
129-
List<MemoryLayout> newLayouts = Stream.concat(argLayouts.stream(), Stream.of(addedLayouts)).toList();
126+
public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) {
127+
return insertArgumentLayouts(argLayouts.size(), addedLayouts);
128+
}
129+
130+
/**
131+
* Create a new function descriptor with the given argument layouts inserted at the given index, into the argument
132+
* layout array of this function descriptor.
133+
* @param index the index at which to insert the arguments
134+
* @param addedLayouts the argument layouts to insert at given index.
135+
* @return the new function descriptor.
136+
* @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}.
137+
*/
138+
public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) {
139+
if (index < 0 || index > argLayouts.size())
140+
throw new IllegalArgumentException("Index out of bounds: " + index);
141+
List<MemoryLayout> added = List.of(addedLayouts); // null check on array and its elements
142+
List<MemoryLayout> newLayouts = new ArrayList<>(argLayouts.size() + addedLayouts.length);
143+
newLayouts.addAll(argLayouts.subList(0, index));
144+
newLayouts.addAll(added);
145+
newLayouts.addAll(argLayouts.subList(index, argLayouts.size()));
130146
return new FunctionDescriptor(resLayout, newLayouts);
131147
}
132148

@@ -135,16 +151,17 @@ public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayou
135151
* @param newReturn the new return layout.
136152
* @return the new function descriptor.
137153
*/
138-
public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) {
154+
public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) {
139155
Objects.requireNonNull(newReturn);
140156
return new FunctionDescriptor(newReturn, argLayouts);
141157
}
142158

143159
/**
144-
* Create a new function descriptor with the return layout dropped.
160+
* Create a new function descriptor with the return layout dropped. This is useful to model functions
161+
* which return no values.
145162
* @return the new function descriptor.
146163
*/
147-
public FunctionDescriptor withVoidReturnLayout() {
164+
public FunctionDescriptor dropReturnLayout() {
148165
return new FunctionDescriptor(null, argLayouts);
149166
}
150167

@@ -212,7 +229,7 @@ public Optional<DynamicConstantDesc<FunctionDescriptor>> describeConstable() {
212229
constants.add(argLayout.describeConstable().get());
213230
}
214231
return Optional.of(DynamicConstantDesc.ofNamed(
215-
ConstantDescs.BSM_INVOKE, "function", AbstractLayout.CD_FUNCTION_DESC, constants.toArray(new ConstantDesc[0])));
232+
ConstantDescs.BSM_INVOKE, "function", AbstractLayout.CD_FUNCTION_DESC, constants.toArray(new ConstantDesc[0])));
216233
}
217234

218235
static final class VariadicFunction extends FunctionDescriptor {
@@ -231,17 +248,22 @@ public int firstVariadicArgumentIndex() {
231248
}
232249

233250
@Override
234-
public FunctionDescriptor withAppendedArgumentLayouts(MemoryLayout... addedLayouts) {
251+
public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) {
252+
throw new UnsupportedOperationException();
253+
}
254+
255+
@Override
256+
public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) {
235257
throw new UnsupportedOperationException();
236258
}
237259

238260
@Override
239-
public FunctionDescriptor withReturnLayout(MemoryLayout newReturn) {
261+
public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) {
240262
throw new UnsupportedOperationException();
241263
}
242264

243265
@Override
244-
public FunctionDescriptor withVoidReturnLayout() {
266+
public FunctionDescriptor dropReturnLayout() {
245267
throw new UnsupportedOperationException();
246268
}
247269

‎src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public final CallingSequenceBuilder addArgumentBindings(Class<?> carrier, Memory
5959
verifyBindings(true, carrier, bindings);
6060
inputBindings.add(bindings);
6161
mt = mt.appendParameterTypes(carrier);
62-
desc = desc.withAppendedArgumentLayouts(layout);
62+
desc = desc.appendArgumentLayouts(layout);
6363
return this;
6464
}
6565

@@ -68,7 +68,7 @@ public CallingSequenceBuilder setReturnBindings(Class<?> carrier, MemoryLayout l
6868
verifyBindings(false, carrier, bindings);
6969
this.outputBindings = bindings;
7070
mt = mt.changeReturnType(carrier);
71-
desc = desc.withReturnLayout(layout);
71+
desc = desc.changeReturnLayout(layout);
7272
return this;
7373
}
7474

‎test/jdk/java/foreign/TestFunctionDescriptor.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@
3232
import jdk.incubator.foreign.MemoryLayout;
3333
import org.testng.annotations.Test;
3434

35-
import java.lang.constant.Constable;
3635
import java.util.List;
3736
import java.util.Optional;
38-
import java.util.stream.Collectors;
3937

4038
import static org.testng.Assert.assertEquals;
4139
import static org.testng.Assert.assertFalse;
@@ -67,7 +65,7 @@ public void testOfVoid() {
6765
@Test
6866
public void testAppendArgumentLayouts() {
6967
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
70-
fd = fd.withAppendedArgumentLayouts(C_POINTER);
68+
fd = fd.appendArgumentLayouts(C_POINTER);
7169

7270
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG, C_POINTER));
7371
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();
@@ -78,7 +76,7 @@ public void testAppendArgumentLayouts() {
7876
@Test
7977
public void testChangeReturnLayout() {
8078
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
81-
fd = fd.withReturnLayout(C_INT);
79+
fd = fd.changeReturnLayout(C_INT);
8280

8381
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG));
8482
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();
@@ -89,7 +87,7 @@ public void testChangeReturnLayout() {
8987
@Test
9088
public void testDropReturnLayout() {
9189
FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_DOUBLE, C_LONG_LONG);
92-
fd = fd.withVoidReturnLayout();
90+
fd = fd.dropReturnLayout();
9391

9492
assertEquals(fd.argumentLayouts(), List.of(C_DOUBLE, C_LONG_LONG));
9593
Optional<MemoryLayout> returnLayoutOp = fd.returnLayout();

‎test/jdk/java/foreign/TestIntrinsics.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import java.util.ArrayList;
4141
import java.util.List;
4242

43-
import jdk.incubator.foreign.MemoryAddress;
4443
import jdk.incubator.foreign.MemoryLayout;
4544
import jdk.incubator.foreign.NativeSymbol;
4645
import jdk.incubator.foreign.SymbolLookup;
@@ -127,7 +126,7 @@ interface AddIdentity {
127126
for (int i = 0; i < args.length; i++) {
128127
NativeSymbol ma = LOOKUP.lookup("invoke_high_arity" + i).get();
129128
MethodType mt = baseMT.changeReturnType(baseMT.parameterType(i));
130-
FunctionDescriptor fd = baseFD.withReturnLayout(baseFD.argumentLayouts().get(i));
129+
FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i));
131130
Object expected = args[i];
132131
tests.add(abi.downcallHandle(ma, fd), expected, args);
133132
}

‎test/jdk/java/foreign/TestUpcall.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,30 @@
2222
*
2323
*/
2424

25+
/*
26+
* @test id=scope
27+
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
28+
* @modules jdk.incubator.foreign/jdk.internal.foreign
29+
* @build NativeTestHelper CallGeneratorHelper TestUpcall
30+
*
31+
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
32+
* --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17
33+
* -DUPCALL_TEST_TYPE=SCOPE
34+
* TestUpcall
35+
*/
36+
37+
/*
38+
* @test id=no_scope
39+
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
40+
* @modules jdk.incubator.foreign/jdk.internal.foreign
41+
* @build NativeTestHelper CallGeneratorHelper TestUpcall
42+
*
43+
* @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
44+
* --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17
45+
* -DUPCALL_TEST_TYPE=NO_SCOPE
46+
* TestUpcall
47+
*/
48+
2549
/*
2650
* @test id=async
2751
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
@@ -34,13 +58,11 @@
3458
* TestUpcall
3559
*/
3660

37-
import jdk.incubator.foreign.Addressable;
3861
import jdk.incubator.foreign.CLinker;
3962
import jdk.incubator.foreign.FunctionDescriptor;
4063
import jdk.incubator.foreign.NativeSymbol;
4164
import jdk.incubator.foreign.SegmentAllocator;
4265
import jdk.incubator.foreign.SymbolLookup;
43-
import jdk.incubator.foreign.MemoryAddress;
4466
import jdk.incubator.foreign.MemoryLayout;
4567
import jdk.incubator.foreign.MemorySegment;
4668

@@ -104,7 +126,7 @@ void setup() {
104126

105127
private static void checkSelected(TestType type) {
106128
if (UPCALL_TEST_TYPE != type)
107-
return;//throw new SkipException("Skipping tests that were not selected");
129+
throw new SkipException("Skipping tests that were not selected");
108130
}
109131

110132
@Test(dataProvider="functions", dataProviderClass=CallGeneratorHelper.class)

‎test/jdk/java/foreign/callarranger/TestSysVCallArranger.java

+12-12
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public void testEmpty() {
6262
assertFalse(bindings.isInMemoryReturn);
6363
CallingSequence callingSequence = bindings.callingSequence;
6464
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
65-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
65+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
6666

6767
checkArgumentBindings(callingSequence, new Binding[][]{
6868
{ vmStore(rax, long.class) }
@@ -89,7 +89,7 @@ public void testNestedStructs() {
8989
assertFalse(bindings.isInMemoryReturn);
9090
CallingSequence callingSequence = bindings.callingSequence;
9191
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
92-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
92+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
9393

9494
checkArgumentBindings(callingSequence, new Binding[][]{
9595
{ dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
@@ -119,7 +119,7 @@ public void testNestedUnion() {
119119
assertFalse(bindings.isInMemoryReturn);
120120
CallingSequence callingSequence = bindings.callingSequence;
121121
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
122-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
122+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
123123

124124
checkArgumentBindings(callingSequence, new Binding[][]{
125125
{ dup(), bufferLoad(0, long.class), vmStore(rdi, long.class),
@@ -148,7 +148,7 @@ public void testNestedStructsUnaligned() {
148148
assertFalse(bindings.isInMemoryReturn);
149149
CallingSequence callingSequence = bindings.callingSequence;
150150
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
151-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
151+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
152152

153153
checkArgumentBindings(callingSequence, new Binding[][]{
154154
{ dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
@@ -177,7 +177,7 @@ public void testNestedUnionUnaligned() {
177177
assertFalse(bindings.isInMemoryReturn);
178178
CallingSequence callingSequence = bindings.callingSequence;
179179
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
180-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
180+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
181181

182182
checkArgumentBindings(callingSequence, new Binding[][]{
183183
{ dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class),
@@ -201,7 +201,7 @@ public void testIntegerRegs() {
201201
assertFalse(bindings.isInMemoryReturn);
202202
CallingSequence callingSequence = bindings.callingSequence;
203203
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
204-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
204+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
205205

206206
checkArgumentBindings(callingSequence, new Binding[][]{
207207
{ vmStore(rdi, int.class) },
@@ -231,7 +231,7 @@ public void testDoubleRegs() {
231231
assertFalse(bindings.isInMemoryReturn);
232232
CallingSequence callingSequence = bindings.callingSequence;
233233
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
234-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
234+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
235235

236236
checkArgumentBindings(callingSequence, new Binding[][]{
237237
{ vmStore(xmm0, double.class) },
@@ -265,7 +265,7 @@ public void testMixed() {
265265
assertFalse(bindings.isInMemoryReturn);
266266
CallingSequence callingSequence = bindings.callingSequence;
267267
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
268-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
268+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
269269

270270
checkArgumentBindings(callingSequence, new Binding[][]{
271271
{ vmStore(rdi, long.class) },
@@ -321,7 +321,7 @@ public void testAbiExample() {
321321
assertFalse(bindings.isInMemoryReturn);
322322
CallingSequence callingSequence = bindings.callingSequence;
323323
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
324-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
324+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
325325

326326
checkArgumentBindings(callingSequence, new Binding[][]{
327327
{ vmStore(rdi, int.class) },
@@ -363,7 +363,7 @@ public void testMemoryAddress() {
363363
assertFalse(bindings.isInMemoryReturn);
364364
CallingSequence callingSequence = bindings.callingSequence;
365365
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
366-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
366+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
367367

368368
checkArgumentBindings(callingSequence, new Binding[][]{
369369
{ unboxAddress(), vmStore(rdi, long.class) },
@@ -384,7 +384,7 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) {
384384
assertFalse(bindings.isInMemoryReturn);
385385
CallingSequence callingSequence = bindings.callingSequence;
386386
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
387-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
387+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
388388

389389
checkArgumentBindings(callingSequence, new Binding[][]{
390390
expectedBindings,
@@ -442,7 +442,7 @@ public void testReturnRegisterStruct() {
442442
assertFalse(bindings.isInMemoryReturn);
443443
CallingSequence callingSequence = bindings.callingSequence;
444444
assertEquals(callingSequence.methodType(), mt.appendParameterTypes(long.class));
445-
assertEquals(callingSequence.functionDesc(), fd.withAppendedArgumentLayouts(C_LONG));
445+
assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG));
446446

447447
checkArgumentBindings(callingSequence, new Binding[][]{
448448
{ vmStore(rax, long.class) }

‎test/micro/org/openjdk/bench/jdk/incubator/foreign/Upcalls.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public class Upcalls extends CLayouts {
124124
static MethodHandle linkFunc(String name, FunctionDescriptor baseDesc) {
125125
return abi.downcallHandle(
126126
SymbolLookup.loaderLookup().lookup(name).orElseThrow(),
127-
baseDesc.withAppendedArgumentLayouts(C_POINTER)
127+
baseDesc.appendArgumentLayouts(C_POINTER)
128128
);
129129
}
130130

0 commit comments

Comments
 (0)
Please sign in to comment.