8304283: Modernize the switch statements in jdk.internal.foreign

Reviewed-by: mcimadamore
This commit is contained in:
Per Minborg 2023-03-16 12:11:10 +00:00
parent 7277bb19f1
commit dfc7214a3e
8 changed files with 155 additions and 205 deletions

View file

@ -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
@ -197,7 +197,7 @@ import static java.lang.foreign.ValueLayout.JAVA_SHORT_UNALIGNED;
*
* --------------------
*/
public interface Binding {
public sealed interface Binding {
/**
* A binding context is used as an helper to carry out evaluation of certain bindings; for instance,
@ -292,21 +292,6 @@ public interface Binding {
};
}
enum Tag {
VM_STORE,
VM_LOAD,
BUFFER_STORE,
BUFFER_LOAD,
COPY_BUFFER,
ALLOC_BUFFER,
BOX_ADDRESS,
UNBOX_ADDRESS,
DUP,
CAST
}
Tag tag();
void verify(Deque<Class<?>> stack);
void interpret(Deque<Object> stack, BindingInterpreter.StoreFunc storeFunc,
@ -503,7 +488,7 @@ public interface Binding {
}
}
interface Move extends Binding {
sealed interface Move extends Binding {
VMStorage storage();
Class<?> type();
}
@ -514,10 +499,6 @@ public interface Binding {
* The [type] must be one of byte, short, char, int, long, float, or double
*/
record VMStore(VMStorage storage, Class<?> type) implements Move {
@Override
public Tag tag() {
return Tag.VM_STORE;
}
@Override
public void verify(Deque<Class<?>> stack) {
@ -539,10 +520,6 @@ public interface Binding {
* The [type] must be one of byte, short, char, int, long, float, or double
*/
record VMLoad(VMStorage storage, Class<?> type) implements Move {
@Override
public Tag tag() {
return Tag.VM_LOAD;
}
@Override
public void verify(Deque<Class<?>> stack) {
@ -556,7 +533,7 @@ public interface Binding {
}
}
interface Dereference extends Binding {
sealed interface Dereference extends Binding {
long offset();
Class<?> type();
}
@ -568,10 +545,6 @@ public interface Binding {
* The [type] must be one of byte, short, char, int, long, float, or double
*/
record BufferStore(long offset, Class<?> type, int byteWidth) implements Dereference {
@Override
public Tag tag() {
return Tag.BUFFER_STORE;
}
@Override
public void verify(Deque<Class<?>> stack) {
@ -629,10 +602,6 @@ public interface Binding {
* The [type] must be one of byte, short, char, int, long, float, or double
*/
record BufferLoad(long offset, Class<?> type, int byteWidth) implements Dereference {
@Override
public Tag tag() {
return Tag.BUFFER_LOAD;
}
@Override
public void verify(Deque<Class<?>> stack) {
@ -693,11 +662,6 @@ public interface Binding {
.copyFrom(operand.asSlice(0, size));
}
@Override
public Tag tag() {
return Tag.COPY_BUFFER;
}
@Override
public void verify(Deque<Class<?>> stack) {
Class<?> actualType = stack.pop();
@ -723,11 +687,6 @@ public interface Binding {
return context.allocator().allocate(size, alignment);
}
@Override
public Tag tag() {
return Tag.ALLOC_BUFFER;
}
@Override
public void verify(Deque<Class<?>> stack) {
stack.push(MemorySegment.class);
@ -748,11 +707,6 @@ public interface Binding {
record UnboxAddress() implements Binding {
static final UnboxAddress INSTANCE = new UnboxAddress();
@Override
public Tag tag() {
return Tag.UNBOX_ADDRESS;
}
@Override
public void verify(Deque<Class<?>> stack) {
Class<?> actualType = stack.pop();
@ -774,11 +728,6 @@ public interface Binding {
*/
record BoxAddress(long size, boolean needsScope) implements Binding {
@Override
public Tag tag() {
return Tag.BOX_ADDRESS;
}
@Override
public void verify(Deque<Class<?>> stack) {
Class<?> actualType = stack.pop();
@ -803,11 +752,6 @@ public interface Binding {
record Dup() implements Binding {
static final Dup INSTANCE = new Dup();
@Override
public Tag tag() {
return Tag.DUP;
}
@Override
public void verify(Deque<Class<?>> stack) {
stack.push(stack.peekLast());
@ -861,11 +805,6 @@ public interface Binding {
return toType;
}
@Override
public Tag tag() {
return Tag.CAST;
}
@Override
public void verify(Deque<Class<?>> stack) {
Class<?> actualType = stack.pop();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 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
@ -28,6 +28,16 @@ import jdk.internal.foreign.AbstractMemorySegmentImpl;
import jdk.internal.foreign.MemorySessionImpl;
import jdk.internal.foreign.NativeMemorySegmentImpl;
import jdk.internal.foreign.Utils;
import jdk.internal.foreign.abi.Binding.Allocate;
import jdk.internal.foreign.abi.Binding.BoxAddress;
import jdk.internal.foreign.abi.Binding.BufferLoad;
import jdk.internal.foreign.abi.Binding.BufferStore;
import jdk.internal.foreign.abi.Binding.Cast;
import jdk.internal.foreign.abi.Binding.Copy;
import jdk.internal.foreign.abi.Binding.Dup;
import jdk.internal.foreign.abi.Binding.UnboxAddress;
import jdk.internal.foreign.abi.Binding.VMLoad;
import jdk.internal.foreign.abi.Binding.VMStore;
import jdk.internal.misc.VM;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.ClassWriter;
@ -437,9 +447,9 @@ public class BindingSpecializer {
private boolean needsSession() {
return callingSequence.argumentBindings()
.filter(Binding.BoxAddress.class::isInstance)
.map(Binding.BoxAddress.class::cast)
.anyMatch(Binding.BoxAddress::needsScope);
.filter(BoxAddress.class::isInstance)
.map(BoxAddress.class::cast)
.anyMatch(BoxAddress::needsScope);
}
private boolean shouldAcquire(int paramIndex) {
@ -467,17 +477,17 @@ public class BindingSpecializer {
private void doBindings(List<Binding> bindings) {
for (Binding binding : bindings) {
switch (binding.tag()) {
case VM_STORE -> emitVMStore((Binding.VMStore) binding);
case VM_LOAD -> emitVMLoad((Binding.VMLoad) binding);
case BUFFER_STORE -> emitBufferStore((Binding.BufferStore) binding);
case BUFFER_LOAD -> emitBufferLoad((Binding.BufferLoad) binding);
case COPY_BUFFER -> emitCopyBuffer((Binding.Copy) binding);
case ALLOC_BUFFER -> emitAllocBuffer((Binding.Allocate) binding);
case BOX_ADDRESS -> emitBoxAddress((Binding.BoxAddress) binding);
case UNBOX_ADDRESS -> emitUnboxAddress();
case DUP -> emitDupBinding();
case CAST -> emitCast((Binding.Cast) binding);
switch (binding) {
case VMStore vmStore -> emitVMStore(vmStore);
case VMLoad vmLoad -> emitVMLoad(vmLoad);
case BufferStore bufferStore -> emitBufferStore(bufferStore);
case BufferLoad bufferLoad -> emitBufferLoad(bufferLoad);
case Copy copy -> emitCopyBuffer(copy);
case Allocate allocate -> emitAllocBuffer(allocate);
case BoxAddress boxAddress -> emitBoxAddress(boxAddress);
case UnboxAddress unused -> emitUnboxAddress();
case Dup unused -> emitDupBinding();
case Cast cast -> emitCast(cast);
}
}
}
@ -579,7 +589,7 @@ public class BindingSpecializer {
emitInvokeVirtual(Binding.Context.class, "close", CLOSE_DESC);
}
private void emitBoxAddress(Binding.BoxAddress boxAddress) {
private void emitBoxAddress(BoxAddress boxAddress) {
popType(long.class);
emitConst(boxAddress.size());
if (needsSession()) {
@ -591,7 +601,7 @@ public class BindingSpecializer {
pushType(MemorySegment.class);
}
private void emitAllocBuffer(Binding.Allocate binding) {
private void emitAllocBuffer(Allocate binding) {
if (callingSequence.forDowncall()) {
assert returnAllocatorIdx != -1;
emitLoad(Object.class, returnAllocatorIdx);
@ -602,7 +612,7 @@ public class BindingSpecializer {
pushType(MemorySegment.class);
}
private void emitBufferStore(Binding.BufferStore bufferStore) {
private void emitBufferStore(BufferStore bufferStore) {
Class<?> storeType = bufferStore.type();
long offset = bufferStore.offset();
int byteWidth = bufferStore.byteWidth();
@ -638,15 +648,15 @@ public class BindingSpecializer {
Class<?> chunkStoreType;
long mask;
switch (chunkSize) {
case 4 -> {
case Integer.BYTES -> {
chunkStoreType = int.class;
mask = 0xFFFF_FFFFL;
}
case 2 -> {
case Short.BYTES -> {
chunkStoreType = short.class;
mask = 0xFFFFL;
}
case 1 -> {
case Byte.BYTES -> {
chunkStoreType = byte.class;
mask = 0xFFL;
}
@ -684,7 +694,7 @@ public class BindingSpecializer {
}
// VM_STORE and VM_LOAD are emulated, which is different for down/upcalls
private void emitVMStore(Binding.VMStore vmStore) {
private void emitVMStore(VMStore vmStore) {
Class<?> storeType = vmStore.type();
popType(storeType);
@ -711,7 +721,7 @@ public class BindingSpecializer {
}
}
private void emitVMLoad(Binding.VMLoad vmLoad) {
private void emitVMLoad(VMLoad vmLoad) {
Class<?> loadType = vmLoad.type();
if (callingSequence.forDowncall()) {
@ -740,7 +750,7 @@ public class BindingSpecializer {
pushType(dupType);
}
private void emitCast(Binding.Cast cast) {
private void emitCast(Cast cast) {
Class<?> fromType = cast.fromType();
Class<?> toType = cast.toType();
@ -773,7 +783,7 @@ public class BindingSpecializer {
pushType(long.class);
}
private void emitBufferLoad(Binding.BufferLoad bufferLoad) {
private void emitBufferLoad(BufferLoad bufferLoad) {
Class<?> loadType = bufferLoad.type();
long offset = bufferLoad.offset();
int byteWidth = bufferLoad.byteWidth();
@ -802,17 +812,17 @@ public class BindingSpecializer {
Class<?> toULongHolder;
String toULongDescriptor;
switch (chunkSize) {
case 4 -> {
case Integer.BYTES -> {
chunkType = int.class;
toULongHolder = Integer.class;
toULongDescriptor = INTEGER_TO_UNSIGNED_LONG_DESC;
}
case 2 -> {
case Short.BYTES -> {
chunkType = short.class;
toULongHolder = Short.class;
toULongDescriptor = SHORT_TO_UNSIGNED_LONG_DESC;
}
case 1 -> {
case Byte.BYTES -> {
chunkType = byte.class;
toULongHolder = Byte.class;
toULongDescriptor = BYTE_TO_UNSIGNED_LONG_DESC;
@ -855,7 +865,7 @@ public class BindingSpecializer {
pushType(loadType);
}
private void emitCopyBuffer(Binding.Copy copy) {
private void emitCopyBuffer(Copy copy) {
long size = copy.size();
long alignment = copy.alignment();

View file

@ -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,16 @@
package jdk.internal.foreign.abi;
import jdk.internal.foreign.Utils;
import jdk.internal.foreign.abi.Binding.Allocate;
import jdk.internal.foreign.abi.Binding.BoxAddress;
import jdk.internal.foreign.abi.Binding.BufferLoad;
import jdk.internal.foreign.abi.Binding.BufferStore;
import jdk.internal.foreign.abi.Binding.Cast;
import jdk.internal.foreign.abi.Binding.Copy;
import jdk.internal.foreign.abi.Binding.Dup;
import jdk.internal.foreign.abi.Binding.UnboxAddress;
import jdk.internal.foreign.abi.Binding.VMLoad;
import jdk.internal.foreign.abi.Binding.VMStore;
import sun.security.action.GetPropertyAction;
import java.lang.foreign.FunctionDescriptor;
@ -35,12 +45,9 @@ import java.lang.invoke.MethodType;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import static java.lang.invoke.MethodType.methodType;
import static jdk.internal.foreign.abi.Binding.Tag.*;
public class CallingSequenceBuilder {
private static final boolean VERIFY_BINDINGS = Boolean.parseBoolean(
@ -92,7 +99,7 @@ public class CallingSequenceBuilder {
public CallingSequence build() {
boolean needsReturnBuffer = needsReturnBuffer();
long returnBufferSize = needsReturnBuffer ? computeReturnBuferSize() : 0;
long returnBufferSize = needsReturnBuffer ? computeReturnBufferSize() : 0;
long allocationSize = computeAllocationSize() + returnBufferSize;
MethodType callerMethodType;
MethodType calleeMethodType;
@ -128,11 +135,11 @@ public class CallingSequenceBuilder {
}
private MethodType computeCallerTypeForUpcall() {
return computeTypeHelper(Binding.VMLoad.class, Binding.VMStore.class);
return computeTypeHelper(VMLoad.class, VMStore.class);
}
private MethodType computeCalleeTypeForDowncall() {
return computeTypeHelper(Binding.VMStore.class, Binding.VMLoad.class);
return computeTypeHelper(VMStore.class, VMLoad.class);
}
private MethodType computeTypeHelper(Class<? extends Binding.Move> inputVMClass,
@ -159,10 +166,10 @@ public class CallingSequenceBuilder {
long size = 0;
for (List<Binding> bindings : inputBindings) {
for (Binding b : bindings) {
if (b instanceof Binding.Copy copy) {
if (b instanceof Copy copy) {
size = Utils.alignUp(size, copy.alignment());
size += copy.size();
} else if (b instanceof Binding.Allocate allocate) {
} else if (b instanceof Allocate allocate) {
size = Utils.alignUp(size, allocate.alignment());
size += allocate.size();
}
@ -171,7 +178,7 @@ public class CallingSequenceBuilder {
return size;
}
private long computeReturnBuferSize() {
private long computeReturnBufferSize() {
return outputBindings.stream()
.filter(Binding.Move.class::isInstance)
.map(Binding.Move.class::cast)
@ -191,25 +198,12 @@ public class CallingSequenceBuilder {
}
}
private static final Set<Binding.Tag> UNBOX_TAGS = EnumSet.of(
VM_STORE,
//VM_LOAD,
//BUFFER_STORE,
BUFFER_LOAD,
COPY_BUFFER,
//ALLOC_BUFFER,
//BOX_ADDRESS,
UNBOX_ADDRESS,
DUP,
CAST
);
private static void verifyUnboxBindings(Class<?> inType, List<Binding> bindings) {
Deque<Class<?>> stack = new ArrayDeque<>();
stack.push(inType);
for (Binding b : bindings) {
if (!UNBOX_TAGS.contains(b.tag()))
if (!isUnbox(b))
throw new IllegalArgumentException("Unexpected operator: " + b);
b.verify(stack);
}
@ -219,24 +213,27 @@ public class CallingSequenceBuilder {
}
}
private static final Set<Binding.Tag> BOX_TAGS = EnumSet.of(
//VM_STORE,
VM_LOAD,
BUFFER_STORE,
//BUFFER_LOAD,
COPY_BUFFER,
ALLOC_BUFFER,
BOX_ADDRESS,
//UNBOX_ADDRESS,
DUP,
CAST
);
static boolean isUnbox(Binding binding) {
return switch (binding) {
case VMStore unused -> true;
case BufferLoad unused -> true;
case Copy unused -> true;
case UnboxAddress unused -> true;
case Dup unused -> true;
case Cast unused -> true;
case VMLoad unused -> false;
case BufferStore unused -> false;
case Allocate unused -> false;
case BoxAddress unused -> false;
};
}
private static void verifyBoxBindings(Class<?> expectedOutType, List<Binding> bindings) {
Deque<Class<?>> stack = new ArrayDeque<>();
for (Binding b : bindings) {
if (!BOX_TAGS.contains(b.tag()))
if (!isBox(b))
throw new IllegalArgumentException("Unexpected operator: " + b);
b.verify(stack);
}
@ -248,4 +245,21 @@ public class CallingSequenceBuilder {
Class<?> actualOutType = stack.pop();
SharedUtils.checkType(actualOutType, expectedOutType);
}
static boolean isBox(Binding binding) {
return switch (binding) {
case VMLoad unused -> true;
case BufferStore unused -> true;
case Copy unused -> true;
case Allocate unused -> true;
case BoxAddress unused -> true;
case Dup unused -> true;
case Cast unused -> true;
case VMStore unused -> false;
case BufferLoad unused -> false;
case UnboxAddress unused -> false;
};
}
}

View file

@ -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, Arm Limited. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -46,13 +46,12 @@ public class AArch64Architecture implements Architecture {
@Override
public int typeSize(int cls) {
switch (cls) {
case StorageType.INTEGER: return INTEGER_REG_SIZE;
case StorageType.VECTOR: return VECTOR_REG_SIZE;
return switch (cls) {
case StorageType.INTEGER -> INTEGER_REG_SIZE;
case StorageType.VECTOR -> VECTOR_REG_SIZE;
// STACK is deliberately omitted
}
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
};
}
public interface StorageType {

View file

@ -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.
@ -48,13 +48,12 @@ public class RISCV64Architecture implements Architecture {
@Override
public int typeSize(int cls) {
switch (cls) {
case StorageType.INTEGER: return INTEGER_REG_SIZE;
case StorageType.FLOAT: return FLOAT_REG_SIZE;
return switch (cls) {
case StorageType.INTEGER -> INTEGER_REG_SIZE;
case StorageType.FLOAT -> FLOAT_REG_SIZE;
// STACK is deliberately omitted
}
throw new IllegalArgumentException("Invalid Storage Class: " + cls);
default -> throw new IllegalArgumentException("Invalid Storage Class: " + cls);
};
}
public interface StorageType {

View file

@ -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.
@ -83,30 +83,33 @@ public enum TypeClass {
static final FieldCounter SINGLE_POINTER = new FieldCounter(0, 0, 1);
static FieldCounter flatten(MemoryLayout layout) {
if (layout instanceof ValueLayout valueLayout) {
return switch (classifyValueType(valueLayout)) {
case INTEGER -> FieldCounter.SINGLE_INTEGER;
case FLOAT -> FieldCounter.SINGLE_FLOAT;
case POINTER -> FieldCounter.SINGLE_POINTER;
default -> throw new IllegalStateException("Should not reach here.");
};
} else if (layout instanceof GroupLayout groupLayout) {
FieldCounter currCounter = FieldCounter.EMPTY;
for (MemoryLayout memberLayout : groupLayout.memberLayouts()) {
if (memberLayout instanceof PaddingLayout) {
continue;
switch (layout) {
case ValueLayout valueLayout -> {
return switch (classifyValueType(valueLayout)) {
case INTEGER -> FieldCounter.SINGLE_INTEGER;
case FLOAT -> FieldCounter.SINGLE_FLOAT;
case POINTER -> FieldCounter.SINGLE_POINTER;
default -> throw new IllegalStateException("Should not reach here.");
};
}
case GroupLayout groupLayout -> {
FieldCounter currCounter = FieldCounter.EMPTY;
for (MemoryLayout memberLayout : groupLayout.memberLayouts()) {
if (memberLayout instanceof PaddingLayout) {
continue;
}
currCounter = currCounter.add(flatten(memberLayout));
}
currCounter = currCounter.add(flatten(memberLayout));
return currCounter;
}
return currCounter;
} else if (layout instanceof SequenceLayout sequenceLayout) {
long elementCount = sequenceLayout.elementCount();
if (elementCount == 0) {
return FieldCounter.EMPTY;
case SequenceLayout sequenceLayout -> {
long elementCount = sequenceLayout.elementCount();
if (elementCount == 0) {
return FieldCounter.EMPTY;
}
return flatten(sequenceLayout.elementLayout()).mul(elementCount);
}
return flatten(sequenceLayout.elementLayout()).mul(elementCount);
} else {
throw new IllegalStateException("Cannot get here: " + layout);
default -> throw new IllegalStateException("Cannot get here: " + layout);
}
}

View file

@ -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
@ -55,14 +55,13 @@ public class X86_64Architecture implements Architecture {
@Override
public int typeSize(int cls) {
switch (cls) {
case StorageType.INTEGER: return INTEGER_REG_SIZE;
case StorageType.VECTOR: return VECTOR_REG_SIZE;
case StorageType.X87: return X87_REG_SIZE;
return switch (cls) {
case StorageType.INTEGER -> INTEGER_REG_SIZE;
case StorageType.VECTOR -> VECTOR_REG_SIZE;
case StorageType.X87 -> X87_REG_SIZE;
// STACK is deliberately omitted
}
throw new IllegalArgumentException("Invalid Storage Class: " +cls);
default -> throw new IllegalArgumentException("Invalid Storage Class: " +cls);
};
}
// must keep in sync with StorageType in VM code

View file

@ -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
@ -86,9 +86,9 @@ public class CallArranger {
class CallingSequenceBuilderHelper {
final CallingSequenceBuilder csb = new CallingSequenceBuilder(CWindows, forUpcall, options);
final BindingCalculator argCalc =
forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true);
forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true);
final BindingCalculator retCalc =
forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false);
forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false);
void addArgumentBindings(Class<?> carrier, MemoryLayout layout, boolean isVararg) {
csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout, isVararg));
@ -171,7 +171,7 @@ public class CallArranger {
return (forArguments
? CWindows.inputStorage
: CWindows.outputStorage)
[type][nRegs++];
[type][nRegs++];
}
public VMStorage extraVarargsStorage() {
@ -196,39 +196,34 @@ public class CallArranger {
TypeClass argumentClass = TypeClass.typeClassFor(layout, isVararg);
Binding.Builder bindings = Binding.builder();
switch (argumentClass) {
case STRUCT_REGISTER: {
case STRUCT_REGISTER -> {
assert carrier == MemorySegment.class;
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
Class<?> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false);
bindings.bufferLoad(0, type)
.vmStore(storage, type);
break;
}
case STRUCT_REFERENCE: {
case STRUCT_REFERENCE -> {
assert carrier == MemorySegment.class;
bindings.copy(layout)
.unboxAddress();
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmStore(storage, long.class);
break;
}
case POINTER: {
case POINTER -> {
bindings.unboxAddress();
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmStore(storage, long.class);
break;
}
case INTEGER: {
case INTEGER -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmStore(storage, carrier);
break;
}
case FLOAT: {
case FLOAT -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR);
bindings.vmStore(storage, carrier);
break;
}
case VARARG_FLOAT: {
case VARARG_FLOAT -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR);
if (!INSTANCE.isStackType(storage.type())) { // need extra for register arg
VMStorage extraStorage = storageCalculator.extraVarargsStorage();
@ -237,10 +232,8 @@ public class CallArranger {
}
bindings.vmStore(storage, carrier);
break;
}
default:
throw new UnsupportedOperationException("Unhandled class " + argumentClass);
default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass);
}
return bindings.build();
}
@ -258,7 +251,7 @@ public class CallArranger {
TypeClass argumentClass = TypeClass.typeClassFor(layout, isVararg);
Binding.Builder bindings = Binding.builder();
switch (argumentClass) {
case STRUCT_REGISTER: {
case STRUCT_REGISTER -> {
assert carrier == MemorySegment.class;
bindings.allocate(layout)
.dup();
@ -266,33 +259,27 @@ public class CallArranger {
Class<?> type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false);
bindings.vmLoad(storage, type)
.bufferStore(0, type);
break;
}
case STRUCT_REFERENCE: {
case STRUCT_REFERENCE -> {
assert carrier == MemorySegment.class;
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmLoad(storage, long.class)
.boxAddress(layout);
break;
}
case POINTER: {
case POINTER -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmLoad(storage, long.class)
.boxAddressRaw(Utils.pointeeSize(layout));
break;
}
case INTEGER: {
case INTEGER -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER);
bindings.vmLoad(storage, carrier);
break;
}
case FLOAT: {
case FLOAT -> {
VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR);
bindings.vmLoad(storage, carrier);
break;
}
default:
throw new UnsupportedOperationException("Unhandled class " + argumentClass);
default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass);
}
return bindings.build();
}