8297733: Refactor Cast binding to enum

Reviewed-by: mcimadamore
This commit is contained in:
Jorn Vernee 2022-12-05 15:28:51 +00:00
parent 19d849884b
commit a38c63da56
2 changed files with 68 additions and 26 deletions
src/java.base/share/classes/jdk/internal/foreign/abi

@ -25,6 +25,7 @@
package jdk.internal.foreign.abi;
import jdk.internal.foreign.NativeMemorySegmentImpl;
import jdk.internal.foreign.Utils;
import java.lang.foreign.Arena;
import java.lang.foreign.MemoryLayout;
@ -367,7 +368,28 @@ public interface Binding {
}
static Binding cast(Class<?> fromType, Class<?> toType) {
return new Cast(fromType, toType);
if (fromType == int.class) {
if (toType == boolean.class) {
return Cast.INT_TO_BOOLEAN;
} else if (toType == byte.class) {
return Cast.INT_TO_BYTE;
} else if (toType == short.class) {
return Cast.INT_TO_SHORT;
} else if (toType == char.class) {
return Cast.INT_TO_CHAR;
}
} else if (toType == int.class) {
if (fromType == boolean.class) {
return Cast.BOOLEAN_TO_INT;
} else if (fromType == byte.class) {
return Cast.BYTE_TO_INT;
} else if (fromType == short.class) {
return Cast.SHORT_TO_INT;
} else if (fromType == char.class) {
return Cast.CHAR_TO_INT;
}
}
throw new IllegalArgumentException("Unknown conversion: " + fromType + " -> " + toType);
}
@ -713,7 +735,40 @@ public interface Binding {
* value onto the stack.
*
*/
record Cast(Class<?> fromType, Class<?> toType) implements Binding {
enum Cast implements Binding {
INT_TO_BOOLEAN(int.class, boolean.class) {
@Override
public void interpret(Deque<Object> stack, BindingInterpreter.StoreFunc storeFunc,
BindingInterpreter.LoadFunc loadFunc, Context context) {
// implement least significant byte non-zero test
int arg = (int) stack.pop();
boolean result = Utils.byteToBoolean((byte) arg);
stack.push(result);
}
},
INT_TO_BYTE(int.class, byte.class),
INT_TO_CHAR(int.class, char.class),
INT_TO_SHORT(int.class, short.class),
BOOLEAN_TO_INT(boolean.class, int.class),
BYTE_TO_INT(byte.class, int.class),
CHAR_TO_INT(char.class, int.class),
SHORT_TO_INT(short.class, int.class);
private final Class<?> fromType;
private final Class<?> toType;
Cast(Class<?> fromType, Class<?> toType) {
this.fromType = fromType;
this.toType = toType;
}
public Class<?> fromType() {
return fromType;
}
public Class<?> toType() {
return toType;
}
@Override
public Tag tag() {

@ -676,10 +676,9 @@ public class BindingSpecializer {
Class<?> fromType = cast.fromType();
Class<?> toType = cast.toType();
if (fromType == int.class) {
popType(int.class);
if (toType == boolean.class) {
popType(fromType);
switch (cast) {
case INT_TO_BOOLEAN -> {
// implement least significant byte non-zero test
// select first byte
@ -688,28 +687,16 @@ public class BindingSpecializer {
// convert to boolean
emitInvokeStatic(Utils.class, "byteToBoolean", "(B)Z");
} else if (toType == byte.class) {
mv.visitInsn(I2B);
} else if (toType == short.class) {
mv.visitInsn(I2S);
} else {
assert toType == char.class;
mv.visitInsn(I2C);
}
pushType(toType);
} else {
popType(fromType);
assert fromType == boolean.class
|| fromType == byte.class
|| fromType == short.class
|| fromType == char.class;
// no-op in bytecode
assert toType == int.class;
pushType(int.class);
case INT_TO_BYTE -> mv.visitInsn(I2B);
case INT_TO_CHAR -> mv.visitInsn(I2C);
case INT_TO_SHORT -> mv.visitInsn(I2S);
case BOOLEAN_TO_INT, BYTE_TO_INT, CHAR_TO_INT, SHORT_TO_INT -> {
// no-op in bytecode
}
default -> throw new IllegalStateException("Unknown cast: " + cast);
}
pushType(toType);
}
private void emitUnboxAddress() {