mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8304283: Modernize the switch statements in jdk.internal.foreign
Reviewed-by: mcimadamore
This commit is contained in:
parent
7277bb19f1
commit
dfc7214a3e
8 changed files with 155 additions and 205 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue