diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index 42669d9a92e..aac62916df5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -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 DOWNCALL_CACHE = new SoftReferenceCache<>(); + private final SoftReferenceCache 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() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 828726e033c..5b436b53fd2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -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 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, diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java index 7d0295d993f..8aced592ad4 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java @@ -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 argIndexMap = SharedUtils.indexMap(argMoves); Map retIndexMap = SharedUtils.indexMap(retMoves); @@ -198,4 +198,3 @@ public class DowncallLinker { } } } - diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index 803994745e5..26a1ee2262c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -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); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java index da42eb53584..ecc14b5ff33 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java @@ -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 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 argIndices = SharedUtils.indexMap(argMoves); Map 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 argIndexMap, + private record InvocationData(Map argIndexMap, Map 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); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index d3270cc5380..44be50175d7 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -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 returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java index acf57f12f0c..4b1cf064202 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java @@ -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 actions, SegmentScope scope) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index d63adc4c247..05264c4505c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -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 actions, SegmentScope scope) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java index 0c2a28098fe..4fd2da93bdd 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/windows/WindowsAArch64Linker.java @@ -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 actions, SegmentScope scope) { @@ -76,4 +75,4 @@ public final class WindowsAArch64Linker extends AbstractLinker { return WindowsAArch64VaList.empty(); } -} \ No newline at end of file +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java index 62881527b0e..93605675a22 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64CallArranger.java @@ -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 returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java index 69d72677326..861e833a0b2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/riscv64/linux/LinuxRISCV64Linker.java @@ -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 actions, SegmentScope scope) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index f00025698a1..749872d2776 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -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 returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index d4694d2fa10..19410f500a6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -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 actions, SegmentScope scope) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index c7475ff1354..209830a354e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -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 returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java index 8725063fbac..9bf3b30ea0c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java @@ -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 actions, SegmentScope scope) { @@ -76,4 +76,3 @@ public final class Windowsx64Linker extends AbstractLinker { return WinVaList.empty(); } } - diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java index 57b42a0e24a..2b0b1935863 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java @@ -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() {}