Skip to content

Commit 54b1e4d

Browse files
author
duke
committed
Backport 9dc62825b5e7300542d22df0b87b79116f3562d3
1 parent 6f74302 commit 54b1e4d

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ private void specialize() {
297297
if (callingSequence.allocationSize() != 0) {
298298
cb.loadConstant(callingSequence.allocationSize())
299299
.invokestatic(CD_SharedUtils, "newBoundedArena", MTD_NEW_BOUNDED_ARENA);
300-
} else if (callingSequence.forUpcall() && needsSession()) {
300+
} else if (callingSequence.forUpcall() && anyArgNeedsScope()) {
301301
cb.invokestatic(CD_SharedUtils, "newEmptyArena", MTD_NEW_EMPTY_ARENA);
302302
} else {
303303
cb.getstatic(CD_SharedUtils, "DUMMY_ARENA", CD_Arena);
@@ -437,7 +437,7 @@ private void specialize() {
437437
cb.exceptionCatchAll(tryStart, tryEnd, catchStart);
438438
}
439439

440-
private boolean needsSession() {
440+
private boolean anyArgNeedsScope() {
441441
return callingSequence.argumentBindings()
442442
.filter(BoxAddress.class::isInstance)
443443
.map(BoxAddress.class::cast)
@@ -590,7 +590,7 @@ private void emitBoxAddress(BoxAddress boxAddress) {
590590
popType(long.class);
591591
cb.loadConstant(boxAddress.size())
592592
.loadConstant(boxAddress.align());
593-
if (needsSession()) {
593+
if (boxAddress.needsScope()) {
594594
emitLoadInternalSession();
595595
cb.invokestatic(CD_Utils, "longToAddress", MTD_LONG_TO_ADDRESS_SCOPE);
596596
} else {

test/jdk/java/foreign/TestUpcallStructScope.java

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,31 +43,48 @@
4343
import java.lang.invoke.MethodHandles;
4444
import java.lang.invoke.MethodType;
4545
import java.util.concurrent.atomic.AtomicReference;
46+
import java.util.function.BiConsumer;
4647
import java.util.function.Consumer;
4748

4849
import static org.testng.Assert.assertFalse;
50+
import static org.testng.Assert.assertTrue;
51+
import static org.testng.Assert.assertEquals;
4952

5053
public class TestUpcallStructScope extends NativeTestHelper {
5154
static final MethodHandle MH_do_upcall;
55+
static final MethodHandle MH_do_upcall_ptr;
5256
static final MethodHandle MH_Consumer_accept;
57+
static final MethodHandle MH_BiConsumer_accept;
5358

5459
static {
5560
System.loadLibrary("TestUpcallStructScope");
5661
MH_do_upcall = LINKER.downcallHandle(
5762
findNativeOrThrow("do_upcall"),
5863
FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT)
5964
);
65+
MH_do_upcall_ptr = LINKER.downcallHandle(
66+
findNativeOrThrow("do_upcall_ptr"),
67+
FunctionDescriptor.ofVoid(C_POINTER, S_PDI_LAYOUT, C_POINTER)
68+
);
6069

6170
try {
6271
MH_Consumer_accept = MethodHandles.publicLookup().findVirtual(Consumer.class, "accept",
6372
MethodType.methodType(void.class, Object.class));
73+
MH_BiConsumer_accept = MethodHandles.publicLookup().findVirtual(BiConsumer.class, "accept",
74+
MethodType.methodType(void.class, Object.class, Object.class));
6475
} catch (NoSuchMethodException | IllegalAccessException e) {
6576
throw new RuntimeException(e);
6677
}
6778
}
6879

69-
private static MethodHandle methodHandle (Consumer<MemorySegment> callback) {
70-
return MH_Consumer_accept.bindTo(callback).asType(MethodType.methodType(void.class, MemorySegment.class));
80+
private static MethodHandle methodHandle(Consumer<MemorySegment> callback) {
81+
return MH_Consumer_accept.bindTo(callback)
82+
.asType(MethodType.methodType(void.class, MemorySegment.class));
83+
}
84+
85+
private static MethodHandle methodHandle(BiConsumer<MemorySegment, MemorySegment> callback) {
86+
return MH_BiConsumer_accept.bindTo(callback)
87+
.asType(MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class));
7188
}
7289

7390
@Test
@@ -85,4 +102,22 @@ public void testUpcall() throws Throwable {
85102
assertFalse(captured.scope().isAlive());
86103
}
87104

105+
@Test
106+
public void testOtherPointer() throws Throwable {
107+
AtomicReference<MemorySegment> capturedSegment = new AtomicReference<>();
108+
MethodHandle target = methodHandle((_, addr) -> capturedSegment.set(addr));
109+
FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(S_PDI_LAYOUT, C_POINTER);
110+
MemorySegment argAddr = MemorySegment.ofAddress(42);
111+
try (Arena arena = Arena.ofConfined()) {
112+
MemorySegment upcallStub = LINKER.upcallStub(target, upcallDesc, arena);
113+
MemorySegment argSegment = arena.allocate(S_PDI_LAYOUT);
114+
MH_do_upcall_ptr.invoke(upcallStub, argSegment, argAddr);
115+
}
116+
117+
// We've captured the address '42' from the upcall. This should have
118+
// the global scope, so it should still be alive here.
119+
MemorySegment captured = capturedSegment.get();
120+
assertEquals(argAddr, captured);
121+
assertTrue(captured.scope().isAlive());
122+
}
88123
}

test/jdk/java/foreign/libTestUpcallStructScope.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,7 @@ struct S_PDI { void* p0; double p1; int p2; };
2828
EXPORT void do_upcall(void (*cb)(struct S_PDI), struct S_PDI a0) {
2929
cb(a0);
3030
}
31+
32+
EXPORT void do_upcall_ptr(void (*cb)(struct S_PDI, void*), struct S_PDI a0, void* ptr) {
33+
cb(a0, ptr);
34+
}

0 commit comments

Comments
 (0)