8303684: Lift upcall sharing mechanism to AbstractLinker (mainline)

Reviewed-by: mcimadamore
This commit is contained in:
Jorn Vernee 2023-03-16 12:27:25 +00:00
parent dfc7214a3e
commit d4eb395335
16 changed files with 120 additions and 100 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, 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
@ -45,10 +45,16 @@ import java.lang.invoke.MethodType;
import java.util.Objects;
public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker,
SysVx64Linker, WindowsAArch64Linker, Windowsx64Linker, LinuxRISCV64Linker {
SysVx64Linker, WindowsAArch64Linker,
Windowsx64Linker, LinuxRISCV64Linker {
public interface UpcallStubFactory {
MemorySegment makeStub(MethodHandle target, SegmentScope arena);
}
private record LinkRequest(FunctionDescriptor descriptor, LinkerOptions options) {}
private final SoftReferenceCache<LinkRequest, MethodHandle> DOWNCALL_CACHE = new SoftReferenceCache<>();
private final SoftReferenceCache<FunctionDescriptor, UpcallStubFactory> UPCALL_CACHE = new SoftReferenceCache<>();
@Override
public MethodHandle downcallHandle(FunctionDescriptor function, Option... options) {
@ -79,11 +85,12 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch
if (!type.equals(target.type())) {
throw new IllegalArgumentException("Wrong method handle type: " + target.type());
}
return arrangeUpcall(target, target.type(), function, scope);
UpcallStubFactory factory = UPCALL_CACHE.get(function, f -> arrangeUpcall(type, f));
return factory.makeStub(target, scope);
}
protected abstract MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType,
FunctionDescriptor function, SegmentScope scope);
protected abstract UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function);
@Override
public SystemLookup defaultLookup() {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023, 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
@ -126,8 +126,6 @@ public class BindingSpecializer {
private static final String SUPER_NAME = OBJECT_INTRN;
private static final SoftReferenceCache<FunctionDescriptor, MethodHandle> UPCALL_WRAPPER_CACHE = new SoftReferenceCache<>();
// Instance fields start here
private final MethodVisitor mv;
private final MethodType callerMethodType;
@ -157,16 +155,7 @@ public class BindingSpecializer {
this.leafType = leafType;
}
static MethodHandle specialize(MethodHandle leafHandle, CallingSequence callingSequence, ABIDescriptor abi) {
if (callingSequence.forUpcall()) {
MethodHandle wrapper = UPCALL_WRAPPER_CACHE.get(callingSequence.functionDesc(), fd -> specializeUpcall(leafHandle, callingSequence, abi));
return MethodHandles.insertArguments(wrapper, 0, leafHandle); // lazily customized for leaf handle instances
} else {
return specializeDowncall(leafHandle, callingSequence, abi);
}
}
private static MethodHandle specializeDowncall(MethodHandle leafHandle, CallingSequence callingSequence, ABIDescriptor abi) {
static MethodHandle specializeDowncall(MethodHandle leafHandle, CallingSequence callingSequence, ABIDescriptor abi) {
MethodType callerMethodType = callingSequence.callerMethodType();
if (callingSequence.needsReturnBuffer()) {
callerMethodType = callerMethodType.dropParameterTypes(0, 1); // Return buffer does not appear in the parameter list
@ -183,11 +172,11 @@ public class BindingSpecializer {
}
}
private static MethodHandle specializeUpcall(MethodHandle leafHandle, CallingSequence callingSequence, ABIDescriptor abi) {
static MethodHandle specializeUpcall(MethodType targetType, CallingSequence callingSequence, ABIDescriptor abi) {
MethodType callerMethodType = callingSequence.callerMethodType();
callerMethodType = callerMethodType.insertParameterTypes(0, MethodHandle.class); // target
byte[] bytes = specializeHelper(leafHandle.type(), callerMethodType, callingSequence, abi);
byte[] bytes = specializeHelper(targetType, callerMethodType, callingSequence, abi);
try {
// For upcalls, we must initialize the class since the upcall stubs don't have a clinit barrier,

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
@ -91,7 +91,7 @@ public class DowncallLinker {
MethodHandle handle = JLIA.nativeMethodHandle(nep);
if (USE_SPEC) {
handle = BindingSpecializer.specialize(handle, callingSequence, abi);
handle = BindingSpecializer.specializeDowncall(handle, callingSequence, abi);
} else {
Map<VMStorage, Integer> argIndexMap = SharedUtils.indexMap(argMoves);
Map<VMStorage, Integer> retIndexMap = SharedUtils.indexMap(retMoves);
@ -198,4 +198,3 @@ public class DowncallLinker {
}
}
}

@ -28,6 +28,7 @@ import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.JavaLangInvokeAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.foreign.CABI;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker;
@ -137,7 +138,7 @@ public final class SharedUtils {
* @param target the target handle to adapt
* @return the adapted handle
*/
public static MethodHandle adaptUpcallForIMR(MethodHandle target, boolean dropReturn) {
private static MethodHandle adaptUpcallForIMR(MethodHandle target, boolean dropReturn) {
if (target.type().returnType() != MemorySegment.class)
throw new IllegalArgumentException("Must return MemorySegment for IMR");
@ -154,6 +155,27 @@ public final class SharedUtils {
return target;
}
public static UpcallStubFactory arrangeUpcallHelper(MethodType targetType, boolean isInMemoryReturn, boolean dropReturn,
ABIDescriptor abi, CallingSequence callingSequence) {
if (isInMemoryReturn) {
// simulate the adaptation to get the type
MethodHandle fakeTarget = MethodHandles.empty(targetType);
targetType = adaptUpcallForIMR(fakeTarget, dropReturn).type();
}
UpcallStubFactory factory = UpcallLinker.makeFactory(targetType, abi, callingSequence);
if (isInMemoryReturn) {
final UpcallStubFactory finalFactory = factory;
factory = (target, scope) -> {
target = adaptUpcallForIMR(target, dropReturn);
return finalFactory.makeStub(target, scope);
};
}
return factory;
}
private static MemorySegment bufferCopy(MemorySegment dest, MemorySegment buffer) {
return dest.copyFrom(buffer);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
@ -25,6 +25,7 @@
package jdk.internal.foreign.abi;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import sun.security.action.GetPropertyAction;
import java.lang.foreign.MemorySegment;
@ -35,6 +36,7 @@ import java.lang.invoke.MethodType;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import static java.lang.invoke.MethodHandles.exactInvoker;
@ -55,23 +57,27 @@ public class UpcallLinker {
try {
MethodHandles.Lookup lookup = lookup();
MH_invokeInterpBindings = lookup.findStatic(UpcallLinker.class, "invokeInterpBindings",
methodType(Object.class, Object[].class, InvocationData.class));
methodType(Object.class, MethodHandle.class, Object[].class, InvocationData.class));
} catch (ReflectiveOperationException e) {
throw new InternalError(e);
}
}
public static MemorySegment make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, SegmentScope scope) {
public static UpcallStubFactory makeFactory(MethodType targetType, ABIDescriptor abi, CallingSequence callingSequence) {
assert callingSequence.forUpcall();
Binding.VMLoad[] argMoves = argMoveBindings(callingSequence);
Binding.VMStore[] retMoves = retMoveBindings(callingSequence);
MethodType llType = callingSequence.callerMethodType();
MethodHandle doBindings;
UnaryOperator<MethodHandle> doBindingsMaker;
if (USE_SPEC) {
doBindings = BindingSpecializer.specialize(target, callingSequence, abi);
assert doBindings.type() == llType;
MethodHandle doBindings = BindingSpecializer.specializeUpcall(targetType, callingSequence, abi);
doBindingsMaker = target -> {
MethodHandle handle = MethodHandles.insertArguments(doBindings, 0, target);
assert handle.type() == llType;
return handle;
};
} else {
Map<VMStorage, Integer> argIndices = SharedUtils.indexMap(argMoves);
Map<VMStorage, Integer> retIndices = SharedUtils.indexMap(retMoves);
@ -79,21 +85,29 @@ public class UpcallLinker {
if (callingSequence.needsReturnBuffer()) {
spreaderCount--; // return buffer is dropped from the argument list
}
target = target.asSpreader(Object[].class, spreaderCount);
InvocationData invData = new InvocationData(target, argIndices, retIndices, callingSequence, retMoves, abi);
doBindings = insertArguments(MH_invokeInterpBindings, 1, invData);
doBindings = doBindings.asCollector(Object[].class, llType.parameterCount());
doBindings = doBindings.asType(llType);
final int finalSpreaderCount = spreaderCount;
InvocationData invData = new InvocationData(argIndices, retIndices, callingSequence, retMoves, abi);
MethodHandle doBindings = insertArguments(MH_invokeInterpBindings, 2, invData);
doBindingsMaker = target -> {
target = target.asSpreader(Object[].class, finalSpreaderCount);
MethodHandle handle = MethodHandles.insertArguments(doBindings, 0, target);
handle = handle.asCollector(Object[].class, llType.parameterCount());
return handle.asType(llType);
};
}
checkPrimitive(doBindings.type());
doBindings = insertArguments(exactInvoker(doBindings.type()), 0, doBindings);
VMStorage[] args = Arrays.stream(argMoves).map(Binding.Move::storage).toArray(VMStorage[]::new);
VMStorage[] rets = Arrays.stream(retMoves).map(Binding.Move::storage).toArray(VMStorage[]::new);
CallRegs conv = new CallRegs(args, rets);
long entryPoint = makeUpcallStub(doBindings, abi, conv,
callingSequence.needsReturnBuffer(), callingSequence.returnBufferSize());
return UpcallStubs.makeUpcall(entryPoint, scope);
return (target, scope) -> {
assert target.type() == targetType;
MethodHandle doBindings = doBindingsMaker.apply(target);
checkPrimitive(doBindings.type());
doBindings = insertArguments(exactInvoker(doBindings.type()), 0, doBindings);
long entryPoint = makeUpcallStub(doBindings, abi, conv,
callingSequence.needsReturnBuffer(), callingSequence.returnBufferSize());
return UpcallStubs.makeUpcall(entryPoint, scope);
};
}
private static void checkPrimitive(MethodType type) {
@ -120,14 +134,13 @@ public class UpcallLinker {
.toArray(Binding.VMStore[]::new);
}
private record InvocationData(MethodHandle leaf,
Map<VMStorage, Integer> argIndexMap,
private record InvocationData(Map<VMStorage, Integer> argIndexMap,
Map<VMStorage, Integer> retIndexMap,
CallingSequence callingSequence,
Binding.VMStore[] retMoves,
ABIDescriptor abi) {}
private static Object invokeInterpBindings(Object[] lowLevelArgs, InvocationData invData) throws Throwable {
private static Object invokeInterpBindings(MethodHandle leaf, Object[] lowLevelArgs, InvocationData invData) throws Throwable {
Binding.Context allocator = invData.callingSequence.allocationSize() != 0
? Binding.Context.ofBoundedAllocator(invData.callingSequence.allocationSize())
: Binding.Context.ofScope();
@ -154,7 +167,7 @@ public class UpcallLinker {
}
// invoke our target
Object o = invData.leaf.invoke(highLevelArgs);
Object o = leaf.invoke(highLevelArgs);
if (DEBUG) {
System.err.println("Java return:");
@ -162,7 +175,7 @@ public class UpcallLinker {
}
Object[] returnValues = new Object[invData.retIndexMap.size()];
if (invData.leaf.type().returnType() != void.class) {
if (leaf.type().returnType() != void.class) {
BindingInterpreter.unbox(o, invData.callingSequence.returnBindings(),
(storage, type, value) -> returnValues[invData.retIndexMap.get(storage)] = value, null);
}

@ -30,6 +30,7 @@ import java.lang.foreign.GroupLayout;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import jdk.internal.foreign.abi.Binding;
import jdk.internal.foreign.abi.CallingSequence;
import jdk.internal.foreign.abi.CallingSequenceBuilder;
@ -189,14 +190,11 @@ public abstract class CallArranger {
return handle;
}
public MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) {
public UpcallStubFactory arrangeUpcall(MethodType mt, FunctionDescriptor cDesc) {
Bindings bindings = getBindings(mt, cDesc, true);
if (bindings.isInMemoryReturn) {
target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */);
}
return UpcallLinker.make(abiDescriptor(), target, bindings.callingSequence, session);
final boolean dropReturn = true; /* drop return, since we don't have bindings for it */
return SharedUtils.arrangeUpcallHelper(mt, bindings.isInMemoryReturn, dropReturn, abiDescriptor(),
bindings.callingSequence);
}
private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2021, Arm Limited. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -31,7 +31,6 @@ import jdk.internal.foreign.abi.aarch64.CallArranger;
import java.lang.foreign.SegmentScope;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.VaList;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
@ -61,8 +60,8 @@ public final class LinuxAArch64Linker extends AbstractLinker {
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return CallArranger.LINUX.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return CallArranger.LINUX.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, Arm Limited. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -30,7 +30,6 @@ import jdk.internal.foreign.abi.LinkerOptions;
import jdk.internal.foreign.abi.aarch64.CallArranger;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentScope;
import java.lang.foreign.VaList;
import java.lang.invoke.MethodHandle;
@ -61,8 +60,8 @@ public final class MacOsAArch64Linker extends AbstractLinker {
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return CallArranger.MACOS.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return CallArranger.MACOS.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021, Arm Limited. All rights reserved.
* Copyright (c) 2021, 2022, Microsoft. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -31,7 +31,6 @@ import jdk.internal.foreign.abi.LinkerOptions;
import jdk.internal.foreign.abi.aarch64.CallArranger;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentScope;
import java.lang.foreign.VaList;
import java.lang.invoke.MethodHandle;
@ -58,8 +57,8 @@ public final class WindowsAArch64Linker extends AbstractLinker {
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return CallArranger.WINDOWS.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return CallArranger.WINDOWS.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {
@ -76,4 +75,4 @@ public final class WindowsAArch64Linker extends AbstractLinker {
return WindowsAArch64VaList.empty();
}
}
}

@ -31,6 +31,7 @@ import java.lang.foreign.GroupLayout;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import jdk.internal.foreign.abi.Binding;
import jdk.internal.foreign.abi.CallingSequence;
import jdk.internal.foreign.abi.CallingSequenceBuilder;
@ -120,15 +121,11 @@ public class LinuxRISCV64CallArranger {
return handle;
}
public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) {
public static UpcallStubFactory arrangeUpcall(MethodType mt, FunctionDescriptor cDesc) {
Bindings bindings = getBindings(mt, cDesc, true);
if (bindings.isInMemoryReturn) {
target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */);
}
return UpcallLinker.make(CLinux, target, bindings.callingSequence, scope);
final boolean dropReturn = true; /* drop return, since we don't have bindings for it */
return SharedUtils.arrangeUpcallHelper(mt, bindings.isInMemoryReturn, dropReturn, CLinux,
bindings.callingSequence);
}
private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Institute of Software, Chinese Academy of Sciences.
* All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@ -57,8 +57,8 @@ public final class LinuxRISCV64Linker extends AbstractLinker {
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return LinuxRISCV64CallArranger.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return LinuxRISCV64CallArranger.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
@ -27,6 +27,7 @@ package jdk.internal.foreign.abi.x64.sysv;
import jdk.internal.foreign.Utils;
import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import jdk.internal.foreign.abi.Binding;
import jdk.internal.foreign.abi.CallingSequence;
import jdk.internal.foreign.abi.CallingSequenceBuilder;
@ -132,14 +133,11 @@ public class CallArranger {
return handle;
}
public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) {
public static UpcallStubFactory arrangeUpcall(MethodType mt, FunctionDescriptor cDesc) {
Bindings bindings = getBindings(mt, cDesc, true);
if (bindings.isInMemoryReturn) {
target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */);
}
return UpcallLinker.make(CSysV, target, bindings.callingSequence, scope);
final boolean dropReturn = true; /* drop return, since we don't have bindings for it */
return SharedUtils.arrangeUpcallHelper(mt, bindings.isInMemoryReturn, dropReturn, CSysV,
bindings.callingSequence);
}
private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
@ -30,7 +30,6 @@ import jdk.internal.foreign.abi.LinkerOptions;
import java.lang.foreign.SegmentScope;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.VaList;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
@ -52,14 +51,15 @@ public final class SysVx64Linker extends AbstractLinker {
private SysVx64Linker() {
// Ensure there is only one instance
}
@Override
protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) {
return CallArranger.arrangeDowncall(inferredMethodType, function, options);
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return CallArranger.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return CallArranger.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {

@ -26,6 +26,7 @@ package jdk.internal.foreign.abi.x64.windows;
import jdk.internal.foreign.Utils;
import jdk.internal.foreign.abi.ABIDescriptor;
import jdk.internal.foreign.abi.AbstractLinker.UpcallStubFactory;
import jdk.internal.foreign.abi.Binding;
import jdk.internal.foreign.abi.CallingSequence;
import jdk.internal.foreign.abi.CallingSequenceBuilder;
@ -131,14 +132,11 @@ public class CallArranger {
return handle;
}
public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) {
public static UpcallStubFactory arrangeUpcall(MethodType mt, FunctionDescriptor cDesc) {
Bindings bindings = getBindings(mt, cDesc, true);
if (bindings.isInMemoryReturn) {
target = SharedUtils.adaptUpcallForIMR(target, false /* need the return value as well */);
}
return UpcallLinker.make(CWindows, target, bindings.callingSequence, scope);
final boolean dropReturn = false; /* need the return value as well */
return SharedUtils.arrangeUpcallHelper(mt, bindings.isInMemoryReturn, dropReturn, CWindows,
bindings.callingSequence);
}
private static boolean isInMemoryReturn(Optional<MemoryLayout> returnLayout) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2023, 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
@ -58,8 +58,8 @@ public final class Windowsx64Linker extends AbstractLinker {
}
@Override
protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) {
return CallArranger.arrangeUpcall(target, targetType, function, scope);
protected UpcallStubFactory arrangeUpcall(MethodType targetType, FunctionDescriptor function) {
return CallArranger.arrangeUpcall(targetType, function);
}
public static VaList newVaList(Consumer<VaList.Builder> actions, SegmentScope scope) {
@ -76,4 +76,3 @@ public final class Windowsx64Linker extends AbstractLinker {
return WinVaList.empty();
}
}

@ -36,6 +36,7 @@ import java.lang.foreign.Linker;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentScope;
import java.lang.foreign.Arena;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.util.concurrent.TimeUnit;
@ -64,7 +65,9 @@ public class LinkUpcall extends CLayouts {
@Benchmark
public MemorySegment link_blank() {
return LINKER.upcallStub(BLANK, BLANK_DESC, SegmentScope.auto());
try (Arena arena = Arena.openConfined()) {
return LINKER.upcallStub(BLANK, BLANK_DESC, arena.scope());
}
}
static void blank() {}