> Certain signatures for foreign function calls require allocation of an > intermediate buffer to adapt the FFM's to the native stub's calling > convention ("needsReturnBuffer"). In the current implementation, this buffer > is malloced and freed on every FFM invocation, a non-negligible overhead. > > Sample stack trace: > > java.lang.Thread.State: RUNNABLE > at jdk.internal.misc.Unsafe.allocateMemory0(java.base@25-ea/Native > Method) > at > jdk.internal.misc.Unsafe.allocateMemory(java.base@25-ea/Unsafe.java:636) > at > jdk.internal.foreign.SegmentFactories.allocateMemoryWrapper(java.base@25-ea/SegmentFactories.java:215) > at > jdk.internal.foreign.SegmentFactories.allocateSegment(java.base@25-ea/SegmentFactories.java:193) > at > jdk.internal.foreign.ArenaImpl.allocateNoInit(java.base@25-ea/ArenaImpl.java:55) > at > jdk.internal.foreign.ArenaImpl.allocate(java.base@25-ea/ArenaImpl.java:60) > at > jdk.internal.foreign.ArenaImpl.allocate(java.base@25-ea/ArenaImpl.java:34) > at > java.lang.foreign.SegmentAllocator.allocate(java.base@25-ea/SegmentAllocator.java:645) > at > jdk.internal.foreign.abi.SharedUtils$2.<init>(java.base@25-ea/SharedUtils.java:388) > at > jdk.internal.foreign.abi.SharedUtils.newBoundedArena(java.base@25-ea/SharedUtils.java:386) > at > jdk.internal.foreign.abi.DowncallStub/0x000001f001084c00.invoke(java.base@25-ea/Unknown > Source) > at > java.lang.invoke.DirectMethodHandle$Holder.invokeStatic(java.base@25-ea/DirectMethodHandle$Holder) > at > java.lang.invoke.LambdaForm$MH/0x000001f00109a400.invoke(java.base@25-ea/LambdaForm$MH) > at > java.lang.invoke.Invokers$Holder.invokeExact_MT(java.base@25-ea/Invokers$Holder) > > > When does this happen? A fairly easy way to trigger this is through returning > a small aggregate like the following: > > struct Vector2D { > double x, y; > }; > Vector2D Origin() { > return {0, 0}; > } > > > On AArch64, such a struct is returned in two 128 bit registers v0/v1. > The VM's calling convention for the native stub consequently expects an 32 > byte output segment argument. > The FFM downcall method handle instead expects to create a 16 byte result > segment through the application-provided SegmentAllocator, and needs to > perform an appropriate adaptation, roughly like so: > > MemorySegment downcallMH(SegmentAllocator a) { > MemorySegment tmp = SharedUtils.allocate(32); > try { > nativeStub.invoke(tmp); // leaves v0, v1 in tmp > MemorySegment result = a.allocate(16); > result.setDouble(0, tmp.getDouble(0)); > result.setDouble(8, tmp.getDouble(16)); > return result; > ...
Matthias Ernst has updated the pull request incrementally with one additional commit since the last revision: Implementation notes. ------------- Changes: - all: https://git.openjdk.org/jdk/pull/23142/files - new: https://git.openjdk.org/jdk/pull/23142/files/4a2210df..35a3a156 Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=23142&range=01 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=23142&range=00-01 Stats: 5 lines in 2 files changed: 4 ins; 0 del; 1 mod Patch: https://git.openjdk.org/jdk/pull/23142.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/23142/head:pull/23142 PR: https://git.openjdk.org/jdk/pull/23142