8263512: [macos_aarch64] issues with calling va_args functions from invoke_native
Reviewed-by: jvernee
This commit is contained in:
parent
4e6748c543
commit
76b54a1995
@ -30,7 +30,8 @@ import jdk.internal.foreign.NativeMemorySegmentImpl;
|
||||
import jdk.internal.foreign.PlatformLayouts;
|
||||
import jdk.internal.foreign.SystemLookup;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.aarch64.AArch64VaList;
|
||||
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64VaList;
|
||||
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64VaList;
|
||||
import jdk.internal.foreign.abi.x64.sysv.SysVVaList;
|
||||
import jdk.internal.foreign.abi.x64.windows.WinVaList;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
@ -523,7 +524,7 @@ public sealed interface CLinker permits AbstractCLinker {
|
||||
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
|
||||
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
|
||||
*/
|
||||
sealed interface VaList extends Addressable permits WinVaList, SysVVaList, AArch64VaList, SharedUtils.EmptyVaList {
|
||||
sealed interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList {
|
||||
|
||||
/**
|
||||
* Reads the next value as an {@code int} and advances this va list's position.
|
||||
@ -729,7 +730,7 @@ public sealed interface CLinker permits AbstractCLinker {
|
||||
* <p> Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
|
||||
* elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
|
||||
*/
|
||||
sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, AArch64VaList.Builder {
|
||||
sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, LinuxAArch64VaList.Builder, MacOsAArch64VaList.Builder {
|
||||
|
||||
/**
|
||||
* Adds a native value represented as an {@code int} to the C {@code va_list} being constructed.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -32,7 +32,8 @@ import static jdk.incubator.foreign.MemoryLayouts.ADDRESS;
|
||||
public enum CABI {
|
||||
SysV,
|
||||
Win64,
|
||||
AArch64;
|
||||
LinuxAArch64,
|
||||
MacOsAArch64;
|
||||
|
||||
private static final CABI current;
|
||||
|
||||
@ -49,7 +50,12 @@ public enum CABI {
|
||||
current = SysV;
|
||||
}
|
||||
} else if (arch.equals("aarch64")) {
|
||||
current = AArch64;
|
||||
if (os.startsWith("Mac")) {
|
||||
current = MacOsAArch64;
|
||||
} else {
|
||||
// The Linux ABI follows the standard AAPCS ABI
|
||||
current = LinuxAArch64;
|
||||
}
|
||||
} else {
|
||||
throw new ExceptionInInitializerError(
|
||||
"Unsupported os, arch, or address size: " + os + ", " + arch + ", " + addressSize);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -38,15 +38,16 @@ public class PlatformLayouts {
|
||||
return switch (CABI.current()) {
|
||||
case SysV -> sysv;
|
||||
case Win64 -> win64;
|
||||
case AArch64 -> aarch64;
|
||||
case LinuxAArch64, MacOsAArch64 -> aarch64;
|
||||
};
|
||||
}
|
||||
|
||||
public static MemoryLayout asVarArg(MemoryLayout ml) {
|
||||
if (CABI.current() == CABI.Win64) {
|
||||
return Win64.asVarArg(ml);
|
||||
}
|
||||
return ml;
|
||||
return switch (CABI.current()) {
|
||||
case Win64 -> Win64.asVarArg(ml);
|
||||
case MacOsAArch64 -> AArch64.asVarArg(ml);
|
||||
default -> ml;
|
||||
};
|
||||
}
|
||||
|
||||
private static ValueLayout ofChar(ByteOrder order, long bitSize) {
|
||||
@ -158,7 +159,7 @@ public class PlatformLayouts {
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the layout attribute (see {@link MemoryLayout#attributes()} used to mark variadic parameters. The
|
||||
* The name of the layout attribute (see {@link MemoryLayout#attributes()}) used to mark variadic parameters. The
|
||||
* attribute value must be a boolean.
|
||||
*/
|
||||
public static final String VARARGS_ATTRIBUTE_NAME = "abi/windows/varargs";
|
||||
@ -271,5 +272,25 @@ public class PlatformLayouts {
|
||||
* The {@code va_list} native type, as it is passed to a function.
|
||||
*/
|
||||
public static final MemoryLayout C_VA_LIST = AArch64.C_POINTER;
|
||||
|
||||
/**
|
||||
* The name of the layout attribute (see {@link MemoryLayout#attributes()})
|
||||
* used to mark variadic parameters on systems such as macOS which pass these
|
||||
* entirely on the stack. The attribute value must be a boolean.
|
||||
*/
|
||||
public final static String STACK_VARARGS_ATTRIBUTE_NAME = "abi/aarch64/stack_varargs";
|
||||
|
||||
/**
|
||||
* Return a new memory layout which describes a variadic parameter to be
|
||||
* passed to a function. This is only required on platforms such as macOS
|
||||
* which pass variadic parameters entirely on the stack.
|
||||
* @param layout the original parameter layout.
|
||||
* @return a layout which is the same as {@code layout}, except for
|
||||
* the extra attribute {@link #STACK_VARARGS_ATTRIBUTE_NAME}, which is set
|
||||
* to {@code true}.
|
||||
*/
|
||||
public static MemoryLayout asVarArg(MemoryLayout layout) {
|
||||
return layout.withAttribute(STACK_VARARGS_ATTRIBUTE_NAME, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class SystemLookup implements SymbolLookup {
|
||||
* on Windows. For this reason, on Windows we do not generate any side-library, and load msvcrt.dll directly instead.
|
||||
*/
|
||||
final NativeLibrary syslookup = switch (CABI.current()) {
|
||||
case SysV, AArch64 -> NativeLibraries.rawNativeLibraries(SystemLookup.class, false).loadLibrary("syslookup");
|
||||
case SysV, LinuxAArch64, MacOsAArch64 -> NativeLibraries.rawNativeLibraries(SystemLookup.class, false).loadLibrary("syslookup");
|
||||
case Win64 -> {
|
||||
Path system32 = Path.of(System.getenv("SystemRoot"), "System32");
|
||||
Path ucrtbase = system32.resolve("ucrtbase.dll");
|
||||
|
@ -40,7 +40,8 @@ import jdk.incubator.foreign.ValueLayout;
|
||||
import jdk.internal.foreign.CABI;
|
||||
import jdk.internal.foreign.MemoryAddressImpl;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.foreign.abi.aarch64.AArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
|
||||
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
|
||||
|
||||
@ -269,7 +270,8 @@ public class SharedUtils {
|
||||
return switch (CABI.current()) {
|
||||
case Win64 -> Windowsx64Linker.getInstance();
|
||||
case SysV -> SysVx64Linker.getInstance();
|
||||
case AArch64 -> AArch64Linker.getInstance();
|
||||
case LinuxAArch64 -> LinuxAArch64Linker.getInstance();
|
||||
case MacOsAArch64 -> MacOsAArch64Linker.getInstance();
|
||||
};
|
||||
}
|
||||
|
||||
@ -454,7 +456,8 @@ public class SharedUtils {
|
||||
return switch (CABI.current()) {
|
||||
case Win64 -> Windowsx64Linker.newVaList(actions, scope);
|
||||
case SysV -> SysVx64Linker.newVaList(actions, scope);
|
||||
case AArch64 -> AArch64Linker.newVaList(actions, scope);
|
||||
case LinuxAArch64 -> LinuxAArch64Linker.newVaList(actions, scope);
|
||||
case MacOsAArch64 -> MacOsAArch64Linker.newVaList(actions, scope);
|
||||
};
|
||||
}
|
||||
|
||||
@ -468,7 +471,8 @@ public class SharedUtils {
|
||||
return switch (CABI.current()) {
|
||||
case Win64 -> Windowsx64Linker.newVaListOfAddress(ma, scope);
|
||||
case SysV -> SysVx64Linker.newVaListOfAddress(ma, scope);
|
||||
case AArch64 -> AArch64Linker.newVaListOfAddress(ma, scope);
|
||||
case LinuxAArch64 -> LinuxAArch64Linker.newVaListOfAddress(ma, scope);
|
||||
case MacOsAArch64 -> MacOsAArch64Linker.newVaListOfAddress(ma, scope);
|
||||
};
|
||||
}
|
||||
|
||||
@ -476,7 +480,8 @@ public class SharedUtils {
|
||||
return switch (CABI.current()) {
|
||||
case Win64 -> Windowsx64Linker.emptyVaList();
|
||||
case SysV -> SysVx64Linker.emptyVaList();
|
||||
case AArch64 -> AArch64Linker.emptyVaList();
|
||||
case LinuxAArch64 -> LinuxAArch64Linker.emptyVaList();
|
||||
case MacOsAArch64 -> MacOsAArch64Linker.emptyVaList();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Arm Limited. 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
|
||||
@ -96,7 +96,7 @@ public class CallArranger {
|
||||
}
|
||||
|
||||
public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) {
|
||||
SharedUtils.checkFunctionTypes(mt, cDesc, AArch64Linker.ADDRESS_SIZE);
|
||||
SharedUtils.checkFunctionTypes(mt, cDesc, AArch64.C_POINTER.bitSize());
|
||||
|
||||
CallingSequenceBuilder csb = new CallingSequenceBuilder(forUpcall);
|
||||
|
||||
@ -207,6 +207,16 @@ public class CallArranger {
|
||||
|
||||
return storage[0];
|
||||
}
|
||||
|
||||
void adjustForVarArgs(MemoryLayout layout) {
|
||||
if (layout.attribute(AArch64.STACK_VARARGS_ATTRIBUTE_NAME)
|
||||
.map(Boolean.class::cast).orElse(false)) {
|
||||
// This system passes all variadic parameters on the stack. Ensure
|
||||
// no further arguments are allocated to registers.
|
||||
nRegs[StorageClasses.INTEGER] = MAX_REGISTER_ARGUMENTS;
|
||||
nRegs[StorageClasses.VECTOR] = MAX_REGISTER_ARGUMENTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class BindingCalculator {
|
||||
@ -278,6 +288,7 @@ public class CallArranger {
|
||||
List<Binding> getBindings(Class<?> carrier, MemoryLayout layout) {
|
||||
TypeClass argumentClass = TypeClass.classifyLayout(layout);
|
||||
Binding.Builder bindings = Binding.builder();
|
||||
storageCalculator.adjustForVarArgs(layout);
|
||||
switch (argumentClass) {
|
||||
case STRUCT_REGISTER: {
|
||||
assert carrier == MemorySegment.class;
|
||||
@ -380,6 +391,7 @@ public class CallArranger {
|
||||
List<Binding> getBindings(Class<?> carrier, MemoryLayout layout) {
|
||||
TypeClass argumentClass = TypeClass.classifyLayout(layout);
|
||||
Binding.Builder bindings = Binding.builder();
|
||||
assert !layout.attribute(AArch64.STACK_VARARGS_ATTRIBUTE_NAME).isPresent() : "no variadic upcalls";
|
||||
switch (argumentClass) {
|
||||
case STRUCT_REGISTER: {
|
||||
assert carrier == MemorySegment.class;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Arm Limited. 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
|
||||
@ -31,7 +31,7 @@ import jdk.incubator.foreign.SequenceLayout;
|
||||
import jdk.incubator.foreign.ValueLayout;
|
||||
import jdk.internal.foreign.PlatformLayouts;
|
||||
|
||||
enum TypeClass {
|
||||
public enum TypeClass {
|
||||
STRUCT_REGISTER,
|
||||
STRUCT_REFERENCE,
|
||||
STRUCT_HFA,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2019, 2021, Arm Limited. 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
|
||||
@ -23,7 +23,7 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.aarch64;
|
||||
package jdk.internal.foreign.abi.aarch64.linux;
|
||||
|
||||
import jdk.incubator.foreign.FunctionDescriptor;
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
@ -33,6 +33,7 @@ import jdk.internal.foreign.AbstractCLinker;
|
||||
import jdk.internal.foreign.ResourceScopeImpl;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.UpcallStubs;
|
||||
import jdk.internal.foreign.abi.aarch64.CallArranger;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
@ -44,8 +45,8 @@ import java.util.function.Consumer;
|
||||
* ABI implementation based on ARM document "Procedure Call Standard for
|
||||
* the ARM 64-bit Architecture".
|
||||
*/
|
||||
public final class AArch64Linker extends AbstractCLinker {
|
||||
private static AArch64Linker instance;
|
||||
public final class LinuxAArch64Linker extends AbstractCLinker {
|
||||
private static LinuxAArch64Linker instance;
|
||||
|
||||
static final long ADDRESS_SIZE = 64; // bits
|
||||
|
||||
@ -57,16 +58,16 @@ public final class AArch64Linker extends AbstractCLinker {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MH_unboxVaList = lookup.findVirtual(VaList.class, "address",
|
||||
MethodType.methodType(MemoryAddress.class));
|
||||
MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(AArch64Linker.class, "newVaListOfAddress",
|
||||
MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(LinuxAArch64Linker.class, "newVaListOfAddress",
|
||||
MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static AArch64Linker getInstance() {
|
||||
public static LinuxAArch64Linker getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new AArch64Linker();
|
||||
instance = new LinuxAArch64Linker();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
@ -75,7 +76,7 @@ public final class AArch64Linker extends AbstractCLinker {
|
||||
public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) {
|
||||
Objects.requireNonNull(type);
|
||||
Objects.requireNonNull(function);
|
||||
MethodType llMt = SharedUtils.convertVaListCarriers(type, AArch64VaList.CARRIER);
|
||||
MethodType llMt = SharedUtils.convertVaListCarriers(type, LinuxAArch64VaList.CARRIER);
|
||||
MethodHandle handle = CallArranger.arrangeDowncall(llMt, function);
|
||||
if (!type.returnType().equals(MemorySegment.class)) {
|
||||
// not returning segment, just insert a throwing allocator
|
||||
@ -95,17 +96,17 @@ public final class AArch64Linker extends AbstractCLinker {
|
||||
}
|
||||
|
||||
public static VaList newVaList(Consumer<VaList.Builder> actions, ResourceScope scope) {
|
||||
AArch64VaList.Builder builder = AArch64VaList.builder(scope);
|
||||
LinuxAArch64VaList.Builder builder = LinuxAArch64VaList.builder(scope);
|
||||
actions.accept(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static VaList newVaListOfAddress(MemoryAddress ma, ResourceScope scope) {
|
||||
return AArch64VaList.ofAddress(ma, scope);
|
||||
return LinuxAArch64VaList.ofAddress(ma, scope);
|
||||
}
|
||||
|
||||
public static VaList emptyVaList() {
|
||||
return AArch64VaList.empty();
|
||||
return LinuxAArch64VaList.empty();
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, Arm Limited. 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
|
||||
@ -23,11 +23,12 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.aarch64;
|
||||
package jdk.internal.foreign.abi.aarch64.linux;
|
||||
|
||||
import jdk.incubator.foreign.*;
|
||||
import jdk.internal.foreign.Utils;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.aarch64.*;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
@ -46,7 +47,11 @@ import static jdk.internal.foreign.abi.SharedUtils.checkCompatibleType;
|
||||
import static jdk.internal.foreign.abi.SharedUtils.vhPrimitiveOrAddress;
|
||||
import static jdk.internal.foreign.abi.aarch64.CallArranger.MAX_REGISTER_ARGUMENTS;
|
||||
|
||||
public non-sealed class AArch64VaList implements VaList {
|
||||
/**
|
||||
* Standard va_list implementation as defined by AAPCS document and used on
|
||||
* Linux. Variadic parameters may be passed in registers or on the stack.
|
||||
*/
|
||||
public non-sealed class LinuxAArch64VaList implements VaList {
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
|
||||
static final Class<?> CARRIER = MemoryAddress.class;
|
||||
@ -105,26 +110,26 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
private final MemorySegment gpRegsArea;
|
||||
private final MemorySegment fpRegsArea;
|
||||
|
||||
private AArch64VaList(MemorySegment segment, MemorySegment gpRegsArea, MemorySegment fpRegsArea) {
|
||||
private LinuxAArch64VaList(MemorySegment segment, MemorySegment gpRegsArea, MemorySegment fpRegsArea) {
|
||||
this.segment = segment;
|
||||
this.gpRegsArea = gpRegsArea;
|
||||
this.fpRegsArea = fpRegsArea;
|
||||
}
|
||||
|
||||
private static AArch64VaList readFromSegment(MemorySegment segment) {
|
||||
private static LinuxAArch64VaList readFromSegment(MemorySegment segment) {
|
||||
MemorySegment gpRegsArea = grTop(segment).addOffset(-MAX_GP_OFFSET).asSegment(
|
||||
MAX_GP_OFFSET, segment.scope());
|
||||
|
||||
MemorySegment fpRegsArea = vrTop(segment).addOffset(-MAX_FP_OFFSET).asSegment(
|
||||
MAX_FP_OFFSET, segment.scope());
|
||||
return new AArch64VaList(segment, gpRegsArea, fpRegsArea);
|
||||
return new LinuxAArch64VaList(segment, gpRegsArea, fpRegsArea);
|
||||
}
|
||||
|
||||
private static MemoryAddress emptyListAddress() {
|
||||
long ptr = U.allocateMemory(LAYOUT.byteSize());
|
||||
MemorySegment ms = MemoryAddress.ofLong(ptr).asSegment(
|
||||
LAYOUT.byteSize(), () -> U.freeMemory(ptr), ResourceScope.newSharedScope());
|
||||
cleaner.register(AArch64VaList.class, () -> ms.scope().close());
|
||||
cleaner.register(LinuxAArch64VaList.class, () -> ms.scope().close());
|
||||
VH_stack.set(ms, MemoryAddress.NULL);
|
||||
VH_gr_top.set(ms, MemoryAddress.NULL);
|
||||
VH_vr_top.set(ms, MemoryAddress.NULL);
|
||||
@ -246,7 +251,7 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
|
||||
private Object read(Class<?> carrier, MemoryLayout layout, SegmentAllocator allocator) {
|
||||
Objects.requireNonNull(layout);
|
||||
checkCompatibleType(carrier, layout, AArch64Linker.ADDRESS_SIZE);
|
||||
checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE);
|
||||
|
||||
TypeClass typeClass = TypeClass.classifyLayout(layout);
|
||||
if (isRegOverflow(currentGPOffset(), currentFPOffset(), typeClass, layout)) {
|
||||
@ -346,8 +351,8 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
}
|
||||
}
|
||||
|
||||
static AArch64VaList.Builder builder(ResourceScope scope) {
|
||||
return new AArch64VaList.Builder(scope);
|
||||
static LinuxAArch64VaList.Builder builder(ResourceScope scope) {
|
||||
return new LinuxAArch64VaList.Builder(scope);
|
||||
}
|
||||
|
||||
public static VaList ofAddress(MemoryAddress ma, ResourceScope scope) {
|
||||
@ -363,7 +368,7 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
public VaList copy() {
|
||||
MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.scope());
|
||||
copy.copyFrom(segment);
|
||||
return new AArch64VaList(copy, gpRegsArea, fpRegsArea);
|
||||
return new LinuxAArch64VaList(copy, gpRegsArea, fpRegsArea);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -388,7 +393,7 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AArch64VaList{"
|
||||
return "LinuxAArch64VaList{"
|
||||
+ "__stack=" + stackPtr()
|
||||
+ ", __gr_top=" + grTop()
|
||||
+ ", __vr_top=" + vrTop()
|
||||
@ -440,7 +445,7 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
|
||||
Objects.requireNonNull(layout);
|
||||
Objects.requireNonNull(value);
|
||||
checkCompatibleType(carrier, layout, AArch64Linker.ADDRESS_SIZE);
|
||||
checkCompatibleType(carrier, layout, LinuxAArch64Linker.ADDRESS_SIZE);
|
||||
|
||||
TypeClass typeClass = TypeClass.classifyLayout(layout);
|
||||
if (isRegOverflow(currentGPOffset, currentFPOffset, typeClass, layout)) {
|
||||
@ -533,7 +538,7 @@ public non-sealed class AArch64VaList implements VaList {
|
||||
|
||||
assert gpRegs.scope().ownerThread() == vaListSegment.scope().ownerThread();
|
||||
assert fpRegs.scope().ownerThread() == vaListSegment.scope().ownerThread();
|
||||
return new AArch64VaList(vaListSegment, gpRegs, fpRegs);
|
||||
return new LinuxAArch64VaList(vaListSegment, gpRegs, fpRegs);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.aarch64.macos;
|
||||
|
||||
import jdk.incubator.foreign.Addressable;
|
||||
import jdk.incubator.foreign.FunctionDescriptor;
|
||||
import jdk.incubator.foreign.MemoryAddress;
|
||||
import jdk.incubator.foreign.MemoryLayout;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
import jdk.internal.foreign.AbstractCLinker;
|
||||
import jdk.internal.foreign.ResourceScopeImpl;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.UpcallStubs;
|
||||
import jdk.internal.foreign.abi.aarch64.CallArranger;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static jdk.internal.foreign.PlatformLayouts.*;
|
||||
|
||||
/**
|
||||
* ABI implementation for macOS on Apple silicon. Based on AAPCS with
|
||||
* changes to va_list and passing arguments on the stack.
|
||||
*/
|
||||
public final class MacOsAArch64Linker extends AbstractCLinker {
|
||||
private static MacOsAArch64Linker instance;
|
||||
|
||||
static final long ADDRESS_SIZE = 64; // bits
|
||||
|
||||
private static final MethodHandle MH_unboxVaList;
|
||||
private static final MethodHandle MH_boxVaList;
|
||||
|
||||
static {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
MH_unboxVaList = lookup.findVirtual(VaList.class, "address",
|
||||
MethodType.methodType(MemoryAddress.class));
|
||||
MH_boxVaList = MethodHandles.insertArguments(lookup.findStatic(MacOsAArch64Linker.class, "newVaListOfAddress",
|
||||
MethodType.methodType(VaList.class, MemoryAddress.class, ResourceScope.class)), 1, ResourceScope.globalScope());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static MacOsAArch64Linker getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new MacOsAArch64Linker();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MethodHandle downcallHandle(MethodType type, FunctionDescriptor function) {
|
||||
Objects.requireNonNull(type);
|
||||
Objects.requireNonNull(function);
|
||||
MethodType llMt = SharedUtils.convertVaListCarriers(type, MacOsAArch64VaList.CARRIER);
|
||||
MethodHandle handle = CallArranger.arrangeDowncall(llMt, function);
|
||||
if (!type.returnType().equals(MemorySegment.class)) {
|
||||
// not returning segment, just insert a throwing allocator
|
||||
handle = MethodHandles.insertArguments(handle, 1, SharedUtils.THROWING_ALLOCATOR);
|
||||
}
|
||||
handle = SharedUtils.unboxVaLists(type, handle, MH_unboxVaList);
|
||||
return handle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final MemoryAddress upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope) {
|
||||
Objects.requireNonNull(scope);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(function);
|
||||
target = SharedUtils.boxVaLists(target, MH_boxVaList);
|
||||
return UpcallStubs.upcallAddress(CallArranger.arrangeUpcall(target, target.type(), function), (ResourceScopeImpl) scope);
|
||||
}
|
||||
|
||||
public static VaList newVaList(Consumer<VaList.Builder> actions, ResourceScope scope) {
|
||||
MacOsAArch64VaList.Builder builder = MacOsAArch64VaList.builder(scope);
|
||||
actions.accept(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static VaList newVaListOfAddress(MemoryAddress ma, ResourceScope scope) {
|
||||
return MacOsAArch64VaList.ofAddress(ma, scope);
|
||||
}
|
||||
|
||||
public static VaList emptyVaList() {
|
||||
return MacOsAArch64VaList.empty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright (c) 2021, 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.internal.foreign.abi.aarch64.macos;
|
||||
|
||||
import jdk.incubator.foreign.*;
|
||||
import jdk.incubator.foreign.CLinker.VaList;
|
||||
import jdk.internal.foreign.ResourceScopeImpl;
|
||||
import jdk.internal.foreign.abi.SharedUtils;
|
||||
import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg;
|
||||
import jdk.internal.foreign.abi.aarch64.*;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static jdk.internal.foreign.PlatformLayouts.AArch64.C_POINTER;
|
||||
import static jdk.internal.foreign.abi.SharedUtils.alignUp;
|
||||
|
||||
/**
|
||||
* Simplified va_list implementation used on macOS where all variadic
|
||||
* parameters are passed on the stack and the type of va_list decays to
|
||||
* char* instead of the structure defined in the AAPCS.
|
||||
*/
|
||||
public non-sealed class MacOsAArch64VaList implements VaList {
|
||||
public static final Class<?> CARRIER = MemoryAddress.class;
|
||||
private static final long VA_SLOT_SIZE_BYTES = 8;
|
||||
private static final VarHandle VH_address = MemoryHandles.asAddressVarHandle(C_POINTER.varHandle(long.class));
|
||||
|
||||
private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL);
|
||||
|
||||
private MemorySegment segment;
|
||||
private final ResourceScope scope;
|
||||
|
||||
private MacOsAArch64VaList(MemorySegment segment, ResourceScope scope) {
|
||||
this.segment = segment;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public static final VaList empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vargAsInt(MemoryLayout layout) {
|
||||
return (int) read(int.class, layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long vargAsLong(MemoryLayout layout) {
|
||||
return (long) read(long.class, layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double vargAsDouble(MemoryLayout layout) {
|
||||
return (double) read(double.class, layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryAddress vargAsAddress(MemoryLayout layout) {
|
||||
return (MemoryAddress) read(MemoryAddress.class, layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySegment vargAsSegment(MemoryLayout layout, SegmentAllocator allocator) {
|
||||
Objects.requireNonNull(allocator);
|
||||
return (MemorySegment) read(MemorySegment.class, layout, allocator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemorySegment vargAsSegment(MemoryLayout layout, ResourceScope scope) {
|
||||
return vargAsSegment(layout, SegmentAllocator.ofScope(scope));
|
||||
}
|
||||
|
||||
private Object read(Class<?> carrier, MemoryLayout layout) {
|
||||
return read(carrier, layout, SharedUtils.THROWING_ALLOCATOR);
|
||||
}
|
||||
|
||||
private Object read(Class<?> carrier, MemoryLayout layout, SegmentAllocator allocator) {
|
||||
Objects.requireNonNull(layout);
|
||||
SharedUtils.checkCompatibleType(carrier, layout, MacOsAArch64Linker.ADDRESS_SIZE);
|
||||
Object res;
|
||||
if (carrier == MemorySegment.class) {
|
||||
TypeClass typeClass = TypeClass.classifyLayout(layout);
|
||||
res = switch (typeClass) {
|
||||
case STRUCT_REFERENCE -> {
|
||||
MemoryAddress structAddr = (MemoryAddress) VH_address.get(segment);
|
||||
MemorySegment struct = structAddr.asSegment(layout.byteSize(), scope());
|
||||
MemorySegment seg = allocator.allocate(layout);
|
||||
seg.copyFrom(struct);
|
||||
segment = segment.asSlice(VA_SLOT_SIZE_BYTES);
|
||||
yield seg;
|
||||
}
|
||||
case STRUCT_REGISTER, STRUCT_HFA -> {
|
||||
MemorySegment struct = allocator.allocate(layout);
|
||||
struct.copyFrom(segment.asSlice(0L, layout.byteSize()));
|
||||
segment = segment.asSlice(alignUp(layout.byteSize(), VA_SLOT_SIZE_BYTES));
|
||||
yield struct;
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);
|
||||
};
|
||||
} else {
|
||||
VarHandle reader = SharedUtils.vhPrimitiveOrAddress(carrier, layout);
|
||||
res = reader.get(segment);
|
||||
segment = segment.asSlice(VA_SLOT_SIZE_BYTES);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skip(MemoryLayout... layouts) {
|
||||
Objects.requireNonNull(layouts);
|
||||
|
||||
for (MemoryLayout layout : layouts) {
|
||||
Objects.requireNonNull(layout);
|
||||
segment = segment.asSlice(switch (TypeClass.classifyLayout(layout)) {
|
||||
case STRUCT_REGISTER, STRUCT_HFA -> alignUp(layout.byteSize(), VA_SLOT_SIZE_BYTES);
|
||||
default -> VA_SLOT_SIZE_BYTES;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static MacOsAArch64VaList ofAddress(MemoryAddress addr, ResourceScope scope) {
|
||||
MemorySegment segment = addr.asSegment(Long.MAX_VALUE, scope);
|
||||
return new MacOsAArch64VaList(segment, scope);
|
||||
}
|
||||
|
||||
static Builder builder(ResourceScope scope) {
|
||||
return new Builder(scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceScope scope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VaList copy() {
|
||||
((ResourceScopeImpl)scope).checkValidStateSlow();
|
||||
return new MacOsAArch64VaList(segment, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryAddress address() {
|
||||
return segment.address();
|
||||
}
|
||||
|
||||
public static non-sealed class Builder implements VaList.Builder {
|
||||
|
||||
private final ResourceScope scope;
|
||||
private final List<SimpleVaArg> args = new ArrayList<>();
|
||||
|
||||
public Builder(ResourceScope scope) {
|
||||
((ResourceScopeImpl)scope).checkValidStateSlow();
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
private Builder arg(Class<?> carrier, MemoryLayout layout, Object value) {
|
||||
Objects.requireNonNull(layout);
|
||||
Objects.requireNonNull(value);
|
||||
SharedUtils.checkCompatibleType(carrier, layout, MacOsAArch64Linker.ADDRESS_SIZE);
|
||||
args.add(new SimpleVaArg(carrier, layout, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder vargFromInt(ValueLayout layout, int value) {
|
||||
return arg(int.class, layout, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder vargFromLong(ValueLayout layout, long value) {
|
||||
return arg(long.class, layout, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder vargFromDouble(ValueLayout layout, double value) {
|
||||
return arg(double.class, layout, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder vargFromAddress(ValueLayout layout, Addressable value) {
|
||||
return arg(MemoryAddress.class, layout, value.address());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder vargFromSegment(GroupLayout layout, MemorySegment value) {
|
||||
return arg(MemorySegment.class, layout, value);
|
||||
}
|
||||
|
||||
public VaList build() {
|
||||
if (args.isEmpty()) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
SegmentAllocator allocator = SegmentAllocator.arenaAllocator(scope);
|
||||
|
||||
// Each argument may occupy up to four slots
|
||||
MemorySegment segment = allocator.allocate(VA_SLOT_SIZE_BYTES * args.size() * 4);
|
||||
|
||||
List<MemorySegment> attachedSegments = new ArrayList<>();
|
||||
attachedSegments.add(segment);
|
||||
MemorySegment cursor = segment;
|
||||
|
||||
for (SimpleVaArg arg : args) {
|
||||
if (arg.carrier == MemorySegment.class) {
|
||||
MemorySegment msArg = ((MemorySegment) arg.value);
|
||||
TypeClass typeClass = TypeClass.classifyLayout(arg.layout);
|
||||
switch (typeClass) {
|
||||
case STRUCT_REFERENCE -> {
|
||||
MemorySegment copy = allocator.allocate(arg.layout);
|
||||
copy.copyFrom(msArg); // by-value
|
||||
attachedSegments.add(copy);
|
||||
VH_address.set(cursor, copy.address());
|
||||
cursor = cursor.asSlice(VA_SLOT_SIZE_BYTES);
|
||||
}
|
||||
case STRUCT_REGISTER, STRUCT_HFA -> {
|
||||
cursor.copyFrom(msArg.asSlice(0, arg.layout.byteSize()));
|
||||
cursor = cursor.asSlice(alignUp(arg.layout.byteSize(), VA_SLOT_SIZE_BYTES));
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected TypeClass: " + typeClass);
|
||||
}
|
||||
} else {
|
||||
VarHandle writer = arg.varHandle();
|
||||
writer.set(cursor, arg.value);
|
||||
cursor = cursor.asSlice(VA_SLOT_SIZE_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
return new MacOsAArch64VaList(segment, scope);
|
||||
}
|
||||
}
|
||||
}
|
@ -542,10 +542,6 @@ java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all
|
||||
|
||||
java/foreign/TestMismatch.java 8249684 macosx-all
|
||||
|
||||
java/foreign/StdLibTest.java 8263512 macosx-aarch64
|
||||
java/foreign/TestVarArgs.java 8263512 macosx-aarch64
|
||||
java/foreign/valist/VaListTest.java 8263512 macosx-aarch64
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_lang
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -28,7 +28,8 @@
|
||||
* @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64"
|
||||
* @modules jdk.incubator.foreign/jdk.internal.foreign
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi.aarch64
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi.aarch64.linux
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi.aarch64.macos
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi.x64.windows
|
||||
* jdk.incubator.foreign/jdk.internal.foreign.abi.x64.sysv
|
||||
* @run testng/othervm --enable-native-access=ALL-UNNAMED VaListTest
|
||||
@ -36,7 +37,8 @@
|
||||
|
||||
import jdk.incubator.foreign.*;
|
||||
import jdk.incubator.foreign.CLinker.VaList;
|
||||
import jdk.internal.foreign.abi.aarch64.AArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
|
||||
import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
|
||||
import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
|
||||
import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
|
||||
import org.testng.annotations.DataProvider;
|
||||
@ -56,6 +58,7 @@ import java.util.stream.IntStream;
|
||||
import static jdk.incubator.foreign.CLinker.C_DOUBLE;
|
||||
import static jdk.incubator.foreign.CLinker.C_FLOAT;
|
||||
import static jdk.incubator.foreign.CLinker.C_INT;
|
||||
import static jdk.incubator.foreign.CLinker.C_LONG;
|
||||
import static jdk.incubator.foreign.CLinker.C_LONG_LONG;
|
||||
import static jdk.incubator.foreign.CLinker.C_POINTER;
|
||||
import static jdk.incubator.foreign.CLinker.C_VA_LIST;
|
||||
@ -113,8 +116,10 @@ public class VaListTest extends NativeTestHelper {
|
||||
= actions -> Windowsx64Linker.newVaList(actions, ResourceScope.newConfinedScope());
|
||||
private static final Function<Consumer<VaList.Builder>, VaList> sysvVaListFactory
|
||||
= actions -> SysVx64Linker.newVaList(actions, ResourceScope.newConfinedScope());
|
||||
private static final Function<Consumer<VaList.Builder>, VaList> aarch64VaListFactory
|
||||
= actions -> AArch64Linker.newVaList(actions, ResourceScope.newConfinedScope());
|
||||
private static final Function<Consumer<VaList.Builder>, VaList> linuxAArch64VaListFactory
|
||||
= actions -> LinuxAArch64Linker.newVaList(actions, ResourceScope.newConfinedScope());
|
||||
private static final Function<Consumer<VaList.Builder>, VaList> macAArch64VaListFactory
|
||||
= actions -> MacOsAArch64Linker.newVaList(actions, ResourceScope.newConfinedScope());
|
||||
private static final Function<Consumer<VaList.Builder>, VaList> platformVaListFactory
|
||||
= (builder) -> VaList.make(builder, ResourceScope.newConfinedScope());
|
||||
|
||||
@ -122,8 +127,10 @@ public class VaListTest extends NativeTestHelper {
|
||||
= (builder, scope) -> Windowsx64Linker.newVaList(builder, scope.scope());
|
||||
private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> sysvVaListScopedFactory
|
||||
= (builder, scope) -> SysVx64Linker.newVaList(builder, scope.scope());
|
||||
private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> aarch64VaListScopedFactory
|
||||
= (builder, scope) -> AArch64Linker.newVaList(builder, scope.scope());
|
||||
private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> linuxAArch64VaListScopedFactory
|
||||
= (builder, scope) -> LinuxAArch64Linker.newVaList(builder, scope.scope());
|
||||
private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> macAArch64VaListScopedFactory
|
||||
= (builder, scope) -> MacOsAArch64Linker.newVaList(builder, scope.scope());
|
||||
private static final BiFunction<Consumer<VaList.Builder>, NativeScope, VaList> platformVaListScopedFactory
|
||||
= (builder, scope) -> VaList.make(builder, scope.scope());
|
||||
|
||||
@ -135,10 +142,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
BiFunction<Integer, VaList, Integer> sumIntsNative
|
||||
= MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumInts);
|
||||
return new Object[][]{
|
||||
{ winVaListFactory, sumIntsJavaFact.apply(Win64.C_INT), Win64.C_INT },
|
||||
{ sysvVaListFactory, sumIntsJavaFact.apply(SysV.C_INT), SysV.C_INT },
|
||||
{ aarch64VaListFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ platformVaListFactory, sumIntsNative, C_INT },
|
||||
{ winVaListFactory, sumIntsJavaFact.apply(Win64.C_INT), Win64.C_INT },
|
||||
{ sysvVaListFactory, sumIntsJavaFact.apply(SysV.C_INT), SysV.C_INT },
|
||||
{ linuxAArch64VaListFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ macAArch64VaListFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ platformVaListFactory, sumIntsNative, C_INT },
|
||||
};
|
||||
}
|
||||
|
||||
@ -163,10 +171,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
BiFunction<Integer, VaList, Double> sumDoublesNative
|
||||
= MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumDoubles);
|
||||
return new Object[][]{
|
||||
{ winVaListFactory, sumDoublesJavaFact.apply(Win64.C_DOUBLE), Win64.C_DOUBLE },
|
||||
{ sysvVaListFactory, sumDoublesJavaFact.apply(SysV.C_DOUBLE), SysV.C_DOUBLE },
|
||||
{ aarch64VaListFactory, sumDoublesJavaFact.apply(AArch64.C_DOUBLE), AArch64.C_DOUBLE },
|
||||
{ platformVaListFactory, sumDoublesNative, C_DOUBLE },
|
||||
{ winVaListFactory, sumDoublesJavaFact.apply(Win64.C_DOUBLE), Win64.C_DOUBLE },
|
||||
{ sysvVaListFactory, sumDoublesJavaFact.apply(SysV.C_DOUBLE), SysV.C_DOUBLE },
|
||||
{ linuxAArch64VaListFactory, sumDoublesJavaFact.apply(AArch64.C_DOUBLE), AArch64.C_DOUBLE },
|
||||
{ macAArch64VaListFactory, sumDoublesJavaFact.apply(AArch64.C_DOUBLE), AArch64.C_DOUBLE },
|
||||
{ platformVaListFactory, sumDoublesNative, C_DOUBLE },
|
||||
};
|
||||
}
|
||||
|
||||
@ -193,10 +202,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
};
|
||||
Function<VaList, Integer> getIntNative = MethodHandleProxies.asInterfaceInstance(Function.class, MH_getInt);
|
||||
return new Object[][]{
|
||||
{ winVaListFactory, getIntJavaFact.apply(Win64.C_POINTER), Win64.C_POINTER },
|
||||
{ sysvVaListFactory, getIntJavaFact.apply(SysV.C_POINTER), SysV.C_POINTER },
|
||||
{ aarch64VaListFactory, getIntJavaFact.apply(AArch64.C_POINTER), AArch64.C_POINTER },
|
||||
{ platformVaListFactory, getIntNative, C_POINTER },
|
||||
{ winVaListFactory, getIntJavaFact.apply(Win64.C_POINTER), Win64.C_POINTER },
|
||||
{ sysvVaListFactory, getIntJavaFact.apply(SysV.C_POINTER), SysV.C_POINTER },
|
||||
{ linuxAArch64VaListFactory, getIntJavaFact.apply(AArch64.C_POINTER), AArch64.C_POINTER },
|
||||
{ macAArch64VaListFactory, getIntJavaFact.apply(AArch64.C_POINTER), AArch64.C_POINTER },
|
||||
{ platformVaListFactory, getIntNative, C_POINTER },
|
||||
};
|
||||
}
|
||||
|
||||
@ -247,10 +257,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
pointLayout, VH_Point_x, VH_Point_y };
|
||||
};
|
||||
return new Object[][]{
|
||||
argsFact.apply(winVaListFactory, Win64.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(aarch64VaListFactory, AArch64.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_INT, sumStructNativeFact),
|
||||
argsFact.apply(winVaListFactory, Win64.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(linuxAArch64VaListFactory, AArch64.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(macAArch64VaListFactory, AArch64.C_INT, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_INT, sumStructNativeFact),
|
||||
};
|
||||
}
|
||||
|
||||
@ -299,10 +310,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y };
|
||||
};
|
||||
return new Object[][]{
|
||||
argsFact.apply(winVaListFactory, Win64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(aarch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_LONG_LONG, sumStructNativeFact),
|
||||
argsFact.apply(winVaListFactory, Win64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(linuxAArch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(macAArch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_LONG_LONG, sumStructNativeFact),
|
||||
};
|
||||
}
|
||||
|
||||
@ -351,10 +363,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y };
|
||||
};
|
||||
return new Object[][]{
|
||||
argsFact.apply(winVaListFactory, Win64.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(aarch64VaListFactory, AArch64.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_FLOAT, sumStructNativeFact),
|
||||
argsFact.apply(winVaListFactory, Win64.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(linuxAArch64VaListFactory, AArch64.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(macAArch64VaListFactory, AArch64.C_FLOAT, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_FLOAT, sumStructNativeFact),
|
||||
};
|
||||
}
|
||||
|
||||
@ -412,10 +425,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z };
|
||||
};
|
||||
return new Object[][]{
|
||||
argsFact.apply(winVaListFactory, Win64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(aarch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_LONG_LONG, sumStructNativeFact),
|
||||
argsFact.apply(winVaListFactory, Win64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(sysvVaListFactory, SysV.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(linuxAArch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(macAArch64VaListFactory, AArch64.C_LONG_LONG, sumStructJavaFact),
|
||||
argsFact.apply(platformVaListFactory, C_LONG_LONG, sumStructNativeFact),
|
||||
};
|
||||
}
|
||||
|
||||
@ -466,10 +480,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
}
|
||||
};
|
||||
return new Object[][]{
|
||||
{ winVaListFactory, sumStackJavaFact.apply(Win64.C_LONG_LONG, Win64.C_DOUBLE), Win64.C_LONG_LONG, Win64.C_DOUBLE },
|
||||
{ sysvVaListFactory, sumStackJavaFact.apply(SysV.C_LONG_LONG, SysV.C_DOUBLE), SysV.C_LONG_LONG, SysV.C_DOUBLE },
|
||||
{ aarch64VaListFactory, sumStackJavaFact.apply(AArch64.C_LONG_LONG, AArch64.C_DOUBLE), AArch64.C_LONG_LONG, AArch64.C_DOUBLE },
|
||||
{ platformVaListFactory, sumStackNative, C_LONG_LONG, C_DOUBLE },
|
||||
{ winVaListFactory, sumStackJavaFact.apply(Win64.C_LONG_LONG, Win64.C_DOUBLE), Win64.C_LONG_LONG, Win64.C_DOUBLE },
|
||||
{ sysvVaListFactory, sumStackJavaFact.apply(SysV.C_LONG_LONG, SysV.C_DOUBLE), SysV.C_LONG_LONG, SysV.C_DOUBLE },
|
||||
{ linuxAArch64VaListFactory, sumStackJavaFact.apply(AArch64.C_LONG_LONG, AArch64.C_DOUBLE), AArch64.C_LONG_LONG, AArch64.C_DOUBLE },
|
||||
{ macAArch64VaListFactory, sumStackJavaFact.apply(AArch64.C_LONG_LONG, AArch64.C_DOUBLE), AArch64.C_LONG_LONG, AArch64.C_DOUBLE },
|
||||
{ platformVaListFactory, sumStackNative, C_LONG_LONG, C_DOUBLE },
|
||||
};
|
||||
}
|
||||
|
||||
@ -519,12 +534,14 @@ public class VaListTest extends NativeTestHelper {
|
||||
@DataProvider
|
||||
public Object[][] emptyVaLists() {
|
||||
return new Object[][] {
|
||||
{ Windowsx64Linker.emptyVaList() },
|
||||
{ winVaListFactory.apply(b -> {}) },
|
||||
{ SysVx64Linker.emptyVaList() },
|
||||
{ sysvVaListFactory.apply(b -> {}) },
|
||||
{ AArch64Linker.emptyVaList() },
|
||||
{ aarch64VaListFactory.apply(b -> {}) },
|
||||
{ Windowsx64Linker.emptyVaList() },
|
||||
{ winVaListFactory.apply(b -> {}) },
|
||||
{ SysVx64Linker.emptyVaList() },
|
||||
{ sysvVaListFactory.apply(b -> {}) },
|
||||
{ LinuxAArch64Linker.emptyVaList() },
|
||||
{ linuxAArch64VaListFactory.apply(b -> {}) },
|
||||
{ MacOsAArch64Linker.emptyVaList() },
|
||||
{ macAArch64VaListFactory.apply(b -> {}) },
|
||||
};
|
||||
}
|
||||
|
||||
@ -543,10 +560,11 @@ public class VaListTest extends NativeTestHelper {
|
||||
BiFunction<Integer, VaList, Integer> sumIntsNative
|
||||
= MethodHandleProxies.asInterfaceInstance(BiFunction.class, MH_sumInts);
|
||||
return new Object[][]{
|
||||
{ winVaListScopedFactory, sumIntsJavaFact.apply(Win64.C_INT), Win64.C_INT },
|
||||
{ sysvVaListScopedFactory, sumIntsJavaFact.apply(SysV.C_INT), SysV.C_INT },
|
||||
{ aarch64VaListScopedFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ platformVaListScopedFactory, sumIntsNative, C_INT },
|
||||
{ winVaListScopedFactory, sumIntsJavaFact.apply(Win64.C_INT), Win64.C_INT },
|
||||
{ sysvVaListScopedFactory, sumIntsJavaFact.apply(SysV.C_INT), SysV.C_INT },
|
||||
{ linuxAArch64VaListScopedFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ macAArch64VaListScopedFactory, sumIntsJavaFact.apply(AArch64.C_INT), AArch64.C_INT },
|
||||
{ platformVaListScopedFactory, sumIntsNative, C_INT },
|
||||
};
|
||||
}
|
||||
|
||||
@ -591,9 +609,10 @@ public class VaListTest extends NativeTestHelper {
|
||||
@DataProvider
|
||||
public Object[][] copy() {
|
||||
return new Object[][] {
|
||||
{ winVaListFactory, Win64.C_INT },
|
||||
{ sysvVaListFactory, SysV.C_INT },
|
||||
{ aarch64VaListFactory, AArch64.C_INT },
|
||||
{ winVaListFactory, Win64.C_INT },
|
||||
{ sysvVaListFactory, SysV.C_INT },
|
||||
{ linuxAArch64VaListFactory, AArch64.C_INT },
|
||||
{ macAArch64VaListFactory, AArch64.C_INT },
|
||||
};
|
||||
}
|
||||
|
||||
@ -678,6 +697,17 @@ public class VaListTest extends NativeTestHelper {
|
||||
assertEquals((long) VH_BigPoint_x.get(struct), 8);
|
||||
assertEquals((long) VH_BigPoint_y.get(struct), 16);
|
||||
})},
|
||||
{ linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> {
|
||||
MemorySegment struct = vaList.vargAsSegment(BigPoint_LAYOUT, ResourceScope.newImplicitScope());
|
||||
assertEquals((long) VH_BigPoint_x.get(struct), 8);
|
||||
assertEquals((long) VH_BigPoint_y.get(struct), 16);
|
||||
|
||||
assertEquals(vaList.vargAsLong(C_LONG_LONG), 42);
|
||||
})},
|
||||
{ linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> {
|
||||
vaList.skip(BigPoint_LAYOUT);
|
||||
assertEquals(vaList.vargAsLong(C_LONG_LONG), 42);
|
||||
})},
|
||||
{ linkVaListCB("upcallStruct"), VaListConsumer.mh(vaList -> {
|
||||
MemorySegment struct = vaList.vargAsSegment(Point_LAYOUT, ResourceScope.newImplicitScope());
|
||||
assertEquals((int) VH_Point_x.get(struct), 5);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2021, 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
|
||||
@ -172,6 +172,13 @@ EXPORT void upcallBigStruct(CB cb) {
|
||||
passToUpcall(cb, 1, point);
|
||||
}
|
||||
|
||||
EXPORT void upcallBigStructPlusScalar(CB cb) {
|
||||
BigPoint point;
|
||||
point.x = 8;
|
||||
point.y = 16;
|
||||
passToUpcall(cb, 2, point, 42);
|
||||
}
|
||||
|
||||
EXPORT void upcallHugeStruct(CB cb) {
|
||||
HugePoint point;
|
||||
point.x = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user