8339131: Remove rarely-used accessor methods from Opcode

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-09-04 12:29:40 +00:00
parent e25a9e7fd8
commit bd8569bc6c
8 changed files with 392 additions and 280 deletions

View file

@ -262,7 +262,7 @@ public sealed interface CodeBuilder
*/
default CodeBuilder ifThen(Opcode opcode,
Consumer<BlockCodeBuilder> thenHandler) {
if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VOID) {
if (opcode.kind() != Opcode.Kind.BRANCH || BytecodeHelpers.isUnconditionalBranch(opcode)) {
throw new IllegalArgumentException("Illegal branch opcode: " + opcode);
}
@ -312,7 +312,7 @@ public sealed interface CodeBuilder
default CodeBuilder ifThenElse(Opcode opcode,
Consumer<BlockCodeBuilder> thenHandler,
Consumer<BlockCodeBuilder> elseHandler) {
if (opcode.kind() != Opcode.Kind.BRANCH || opcode.primaryTypeKind() == TypeKind.VOID) {
if (opcode.kind() != Opcode.Kind.BRANCH || BytecodeHelpers.isUnconditionalBranch(opcode)) {
throw new IllegalArgumentException("Illegal branch opcode: " + opcode);
}

View file

@ -24,8 +24,6 @@
*/
package java.lang.classfile;
import java.lang.constant.ConstantDesc;
import java.lang.constant.ConstantDescs;
import jdk.internal.javac.PreviewFeature;
/**
@ -45,55 +43,55 @@ public enum Opcode {
NOP(ClassFile.NOP, 1, Kind.NOP),
/** Push null */
ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT, TypeKind.REFERENCE, 0, ConstantDescs.NULL),
ACONST_NULL(ClassFile.ACONST_NULL, 1, Kind.CONSTANT),
/** Push int constant -1 */
ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT, TypeKind.INT, 0, -1),
ICONST_M1(ClassFile.ICONST_M1, 1, Kind.CONSTANT),
/** Push int constant 0 */
ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT, TypeKind.INT, 0, 0),
ICONST_0(ClassFile.ICONST_0, 1, Kind.CONSTANT),
/** Push int constant 1 */
ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT, TypeKind.INT, 0, 1),
ICONST_1(ClassFile.ICONST_1, 1, Kind.CONSTANT),
/** Push int constant 2 */
ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT, TypeKind.INT, 0, 2),
ICONST_2(ClassFile.ICONST_2, 1, Kind.CONSTANT),
/** Push int constant 3 */
ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT, TypeKind.INT, 0, 3),
ICONST_3(ClassFile.ICONST_3, 1, Kind.CONSTANT),
/** Push int constant 4 */
ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT, TypeKind.INT, 0, 4),
ICONST_4(ClassFile.ICONST_4, 1, Kind.CONSTANT),
/** Push int constant 5 */
ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT, TypeKind.INT, 0, 5),
ICONST_5(ClassFile.ICONST_5, 1, Kind.CONSTANT),
/** Push long constant 0 */
LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT, TypeKind.LONG, 0, 0L),
LCONST_0(ClassFile.LCONST_0, 1, Kind.CONSTANT),
/** Push long constant 1 */
LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT, TypeKind.LONG, 0, 1L),
LCONST_1(ClassFile.LCONST_1, 1, Kind.CONSTANT),
/** Push float constant 0 */
FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 0.0f),
FCONST_0(ClassFile.FCONST_0, 1, Kind.CONSTANT),
/** Push float constant 1 */
FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 1.0f),
FCONST_1(ClassFile.FCONST_1, 1, Kind.CONSTANT),
/** Push float constant 2 */
FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT, TypeKind.FLOAT, 0, 2.0f),
FCONST_2(ClassFile.FCONST_2, 1, Kind.CONSTANT),
/** Push double constant 0 */
DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT, TypeKind.DOUBLE, 0, 0.0d),
DCONST_0(ClassFile.DCONST_0, 1, Kind.CONSTANT),
/** Push double constant 1 */
DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT, TypeKind.DOUBLE, 0, 1.0d),
DCONST_1(ClassFile.DCONST_1, 1, Kind.CONSTANT),
/** Push byte */
BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT, TypeKind.BYTE),
BIPUSH(ClassFile.BIPUSH, 2, Kind.CONSTANT),
/** Push short */
SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT, TypeKind.SHORT),
SIPUSH(ClassFile.SIPUSH, 3, Kind.CONSTANT),
/** Push item from run-time constant pool */
LDC(ClassFile.LDC, 2, Kind.CONSTANT),
@ -105,202 +103,202 @@ public enum Opcode {
LDC2_W(ClassFile.LDC2_W, 3, Kind.CONSTANT),
/** Load int from local variable */
ILOAD(ClassFile.ILOAD, 2, Kind.LOAD, TypeKind.INT, -1),
ILOAD(ClassFile.ILOAD, 2, Kind.LOAD),
/** Load long from local variable */
LLOAD(ClassFile.LLOAD, 2, Kind.LOAD, TypeKind.LONG, -1),
LLOAD(ClassFile.LLOAD, 2, Kind.LOAD),
/** Load float from local variable */
FLOAD(ClassFile.FLOAD, 2, Kind.LOAD, TypeKind.FLOAT, -1),
FLOAD(ClassFile.FLOAD, 2, Kind.LOAD),
/** Load double from local variable */
DLOAD(ClassFile.DLOAD, 2, Kind.LOAD, TypeKind.DOUBLE, -1),
DLOAD(ClassFile.DLOAD, 2, Kind.LOAD),
/** Load reference from local variable */
ALOAD(ClassFile.ALOAD, 2, Kind.LOAD, TypeKind.REFERENCE, -1),
ALOAD(ClassFile.ALOAD, 2, Kind.LOAD),
/** Load int from local variable 0 */
ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD, TypeKind.INT, 0),
ILOAD_0(ClassFile.ILOAD_0, 1, Kind.LOAD),
/** Load int from local variable 1 */
ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD, TypeKind.INT, 1),
ILOAD_1(ClassFile.ILOAD_1, 1, Kind.LOAD),
/** Load int from local variable 2 */
ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD, TypeKind.INT, 2),
ILOAD_2(ClassFile.ILOAD_2, 1, Kind.LOAD),
/** Load int from local variable3 */
ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD, TypeKind.INT, 3),
ILOAD_3(ClassFile.ILOAD_3, 1, Kind.LOAD),
/** Load long from local variable 0 */
LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD, TypeKind.LONG, 0),
LLOAD_0(ClassFile.LLOAD_0, 1, Kind.LOAD),
/** Load long from local variable 1 */
LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD, TypeKind.LONG, 1),
LLOAD_1(ClassFile.LLOAD_1, 1, Kind.LOAD),
/** Load long from local variable 2 */
LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD, TypeKind.LONG, 2),
LLOAD_2(ClassFile.LLOAD_2, 1, Kind.LOAD),
/** Load long from local variable 3 */
LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD, TypeKind.LONG, 3),
LLOAD_3(ClassFile.LLOAD_3, 1, Kind.LOAD),
/** Load float from local variable 0 */
FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD, TypeKind.FLOAT, 0),
FLOAD_0(ClassFile.FLOAD_0, 1, Kind.LOAD),
/** Load float from local variable 1 */
FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD, TypeKind.FLOAT, 1),
FLOAD_1(ClassFile.FLOAD_1, 1, Kind.LOAD),
/** Load float from local variable 2 */
FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD, TypeKind.FLOAT, 2),
FLOAD_2(ClassFile.FLOAD_2, 1, Kind.LOAD),
/** Load float from local variable 3 */
FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD, TypeKind.FLOAT, 3),
FLOAD_3(ClassFile.FLOAD_3, 1, Kind.LOAD),
/** Load double from local variable 0 */
DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD, TypeKind.DOUBLE, 0),
DLOAD_0(ClassFile.DLOAD_0, 1, Kind.LOAD),
/** Load double from local variable 1 */
DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD, TypeKind.DOUBLE, 1),
DLOAD_1(ClassFile.DLOAD_1, 1, Kind.LOAD),
/** Load double from local variable 2 */
DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD, TypeKind.DOUBLE, 2),
DLOAD_2(ClassFile.DLOAD_2, 1, Kind.LOAD),
/** Load double from local variable 3 */
DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD, TypeKind.DOUBLE, 3),
DLOAD_3(ClassFile.DLOAD_3, 1, Kind.LOAD),
/** Load reference from local variable 0 */
ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD, TypeKind.REFERENCE, 0),
ALOAD_0(ClassFile.ALOAD_0, 1, Kind.LOAD),
/** Load reference from local variable 1 */
ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD, TypeKind.REFERENCE, 1),
ALOAD_1(ClassFile.ALOAD_1, 1, Kind.LOAD),
/** Load reference from local variable 2 */
ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD, TypeKind.REFERENCE, 2),
ALOAD_2(ClassFile.ALOAD_2, 1, Kind.LOAD),
/** Load reference from local variable 3 */
ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD, TypeKind.REFERENCE, 3),
ALOAD_3(ClassFile.ALOAD_3, 1, Kind.LOAD),
/** Load int from array */
IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD, TypeKind.INT),
IALOAD(ClassFile.IALOAD, 1, Kind.ARRAY_LOAD),
/** Load long from array */
LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD, TypeKind.LONG),
LALOAD(ClassFile.LALOAD, 1, Kind.ARRAY_LOAD),
/** Load float from array */
FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD, TypeKind.FLOAT),
FALOAD(ClassFile.FALOAD, 1, Kind.ARRAY_LOAD),
/** Load double from array */
DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD, TypeKind.DOUBLE),
DALOAD(ClassFile.DALOAD, 1, Kind.ARRAY_LOAD),
/** Load reference from array */
AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD, TypeKind.REFERENCE),
AALOAD(ClassFile.AALOAD, 1, Kind.ARRAY_LOAD),
/** Load byte or boolean from array */
BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD, TypeKind.BYTE),
/** Load byte from array */
BALOAD(ClassFile.BALOAD, 1, Kind.ARRAY_LOAD),
/** Load char from array */
CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD, TypeKind.CHAR),
CALOAD(ClassFile.CALOAD, 1, Kind.ARRAY_LOAD),
/** Load short from array */
SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD, TypeKind.SHORT),
SALOAD(ClassFile.SALOAD, 1, Kind.ARRAY_LOAD),
/** Store int into local variable */
ISTORE(ClassFile.ISTORE, 2, Kind.STORE, TypeKind.INT, -1),
ISTORE(ClassFile.ISTORE, 2, Kind.STORE),
/** Store long into local variable */
LSTORE(ClassFile.LSTORE, 2, Kind.STORE, TypeKind.LONG, -1),
LSTORE(ClassFile.LSTORE, 2, Kind.STORE),
/** Store float into local variable */
FSTORE(ClassFile.FSTORE, 2, Kind.STORE, TypeKind.FLOAT, -1),
FSTORE(ClassFile.FSTORE, 2, Kind.STORE),
/** Store double into local variable */
DSTORE(ClassFile.DSTORE, 2, Kind.STORE, TypeKind.DOUBLE, -1),
DSTORE(ClassFile.DSTORE, 2, Kind.STORE),
/** Store reference into local variable */
ASTORE(ClassFile.ASTORE, 2, Kind.STORE, TypeKind.REFERENCE, -1),
ASTORE(ClassFile.ASTORE, 2, Kind.STORE),
/** Store int into local variable 0 */
ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE, TypeKind.INT, 0),
ISTORE_0(ClassFile.ISTORE_0, 1, Kind.STORE),
/** Store int into local variable 1 */
ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE, TypeKind.INT, 1),
ISTORE_1(ClassFile.ISTORE_1, 1, Kind.STORE),
/** Store int into local variable 2 */
ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE, TypeKind.INT, 2),
ISTORE_2(ClassFile.ISTORE_2, 1, Kind.STORE),
/** Store int into local variable 3 */
ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE, TypeKind.INT, 3),
ISTORE_3(ClassFile.ISTORE_3, 1, Kind.STORE),
/** Store long into local variable 0 */
LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE, TypeKind.LONG, 0),
LSTORE_0(ClassFile.LSTORE_0, 1, Kind.STORE),
/** Store long into local variable 1 */
LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE, TypeKind.LONG, 1),
LSTORE_1(ClassFile.LSTORE_1, 1, Kind.STORE),
/** Store long into local variable 2 */
LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE, TypeKind.LONG, 2),
LSTORE_2(ClassFile.LSTORE_2, 1, Kind.STORE),
/** Store long into local variable 3 */
LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE, TypeKind.LONG, 3),
LSTORE_3(ClassFile.LSTORE_3, 1, Kind.STORE),
/** Store float into local variable 0 */
FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE, TypeKind.FLOAT, 0),
FSTORE_0(ClassFile.FSTORE_0, 1, Kind.STORE),
/** Store float into local variable 1 */
FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE, TypeKind.FLOAT, 1),
FSTORE_1(ClassFile.FSTORE_1, 1, Kind.STORE),
/** Store float into local variable 2 */
FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE, TypeKind.FLOAT, 2),
FSTORE_2(ClassFile.FSTORE_2, 1, Kind.STORE),
/** Store float into local variable 3 */
FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE, TypeKind.FLOAT, 3),
FSTORE_3(ClassFile.FSTORE_3, 1, Kind.STORE),
/** Store double into local variable 0 */
DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE, TypeKind.DOUBLE, 0),
DSTORE_0(ClassFile.DSTORE_0, 1, Kind.STORE),
/** Store double into local variable 1 */
DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE, TypeKind.DOUBLE, 1),
DSTORE_1(ClassFile.DSTORE_1, 1, Kind.STORE),
/** Store double into local variable 2 */
DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE, TypeKind.DOUBLE, 2),
DSTORE_2(ClassFile.DSTORE_2, 1, Kind.STORE),
/** Store double into local variable 3 */
DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE, TypeKind.DOUBLE, 3),
DSTORE_3(ClassFile.DSTORE_3, 1, Kind.STORE),
/** Store reference into local variable 0 */
ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE, TypeKind.REFERENCE, 0),
ASTORE_0(ClassFile.ASTORE_0, 1, Kind.STORE),
/** Store reference into local variable 1 */
ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE, TypeKind.REFERENCE, 1),
ASTORE_1(ClassFile.ASTORE_1, 1, Kind.STORE),
/** Store reference into local variable 2 */
ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE, TypeKind.REFERENCE, 2),
ASTORE_2(ClassFile.ASTORE_2, 1, Kind.STORE),
/** Store reference into local variable 3 */
ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE, TypeKind.REFERENCE, 3),
ASTORE_3(ClassFile.ASTORE_3, 1, Kind.STORE),
/** Store into int array */
IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE, TypeKind.INT),
IASTORE(ClassFile.IASTORE, 1, Kind.ARRAY_STORE),
/** Store into long array */
LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE, TypeKind.LONG),
LASTORE(ClassFile.LASTORE, 1, Kind.ARRAY_STORE),
/** Store into float array */
FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE, TypeKind.FLOAT),
FASTORE(ClassFile.FASTORE, 1, Kind.ARRAY_STORE),
/** Store into double array */
DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE, TypeKind.DOUBLE),
DASTORE(ClassFile.DASTORE, 1, Kind.ARRAY_STORE),
/** Store into reference array */
AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE, TypeKind.REFERENCE),
AASTORE(ClassFile.AASTORE, 1, Kind.ARRAY_STORE),
/** Store into byte or boolean array */
BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE, TypeKind.BYTE),
/** Store into byte array */
BASTORE(ClassFile.BASTORE, 1, Kind.ARRAY_STORE),
/** Store into char array */
CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE, TypeKind.CHAR),
CASTORE(ClassFile.CASTORE, 1, Kind.ARRAY_STORE),
/** Store into short array */
SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE, TypeKind.SHORT),
SASTORE(ClassFile.SASTORE, 1, Kind.ARRAY_STORE),
/** Pop the top operand stack value */
POP(ClassFile.POP, 1, Kind.STACK),
@ -330,220 +328,220 @@ public enum Opcode {
SWAP(ClassFile.SWAP, 1, Kind.STACK),
/** Add int */
IADD(ClassFile.IADD, 1, Kind.OPERATOR, TypeKind.INT),
IADD(ClassFile.IADD, 1, Kind.OPERATOR),
/** Add long */
LADD(ClassFile.LADD, 1, Kind.OPERATOR, TypeKind.LONG),
LADD(ClassFile.LADD, 1, Kind.OPERATOR),
/** Add float */
FADD(ClassFile.FADD, 1, Kind.OPERATOR, TypeKind.FLOAT),
FADD(ClassFile.FADD, 1, Kind.OPERATOR),
/** Add double */
DADD(ClassFile.DADD, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DADD(ClassFile.DADD, 1, Kind.OPERATOR),
/** Subtract int */
ISUB(ClassFile.ISUB, 1, Kind.OPERATOR, TypeKind.INT),
ISUB(ClassFile.ISUB, 1, Kind.OPERATOR),
/** Subtract long */
LSUB(ClassFile.LSUB, 1, Kind.OPERATOR, TypeKind.LONG),
LSUB(ClassFile.LSUB, 1, Kind.OPERATOR),
/** Subtract float */
FSUB(ClassFile.FSUB, 1, Kind.OPERATOR, TypeKind.FLOAT),
FSUB(ClassFile.FSUB, 1, Kind.OPERATOR),
/** Subtract double */
DSUB(ClassFile.DSUB, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DSUB(ClassFile.DSUB, 1, Kind.OPERATOR),
/** Multiply int */
IMUL(ClassFile.IMUL, 1, Kind.OPERATOR, TypeKind.INT),
IMUL(ClassFile.IMUL, 1, Kind.OPERATOR),
/** Multiply long */
LMUL(ClassFile.LMUL, 1, Kind.OPERATOR, TypeKind.LONG),
LMUL(ClassFile.LMUL, 1, Kind.OPERATOR),
/** Multiply float */
FMUL(ClassFile.FMUL, 1, Kind.OPERATOR, TypeKind.FLOAT),
FMUL(ClassFile.FMUL, 1, Kind.OPERATOR),
/** Multiply double */
DMUL(ClassFile.DMUL, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DMUL(ClassFile.DMUL, 1, Kind.OPERATOR),
/** Divide int */
IDIV(ClassFile.IDIV, 1, Kind.OPERATOR, TypeKind.INT),
IDIV(ClassFile.IDIV, 1, Kind.OPERATOR),
/** Divide long */
LDIV(ClassFile.LDIV, 1, Kind.OPERATOR, TypeKind.LONG),
LDIV(ClassFile.LDIV, 1, Kind.OPERATOR),
/** Divide float */
FDIV(ClassFile.FDIV, 1, Kind.OPERATOR, TypeKind.FLOAT),
FDIV(ClassFile.FDIV, 1, Kind.OPERATOR),
/** Divide double */
DDIV(ClassFile.DDIV, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DDIV(ClassFile.DDIV, 1, Kind.OPERATOR),
/** Remainder int */
IREM(ClassFile.IREM, 1, Kind.OPERATOR, TypeKind.INT),
IREM(ClassFile.IREM, 1, Kind.OPERATOR),
/** Remainder long */
LREM(ClassFile.LREM, 1, Kind.OPERATOR, TypeKind.LONG),
LREM(ClassFile.LREM, 1, Kind.OPERATOR),
/** Remainder float */
FREM(ClassFile.FREM, 1, Kind.OPERATOR, TypeKind.FLOAT),
FREM(ClassFile.FREM, 1, Kind.OPERATOR),
/** Remainder double */
DREM(ClassFile.DREM, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DREM(ClassFile.DREM, 1, Kind.OPERATOR),
/** Negate int */
INEG(ClassFile.INEG, 1, Kind.OPERATOR, TypeKind.INT),
INEG(ClassFile.INEG, 1, Kind.OPERATOR),
/** Negate long */
LNEG(ClassFile.LNEG, 1, Kind.OPERATOR, TypeKind.LONG),
LNEG(ClassFile.LNEG, 1, Kind.OPERATOR),
/** Negate float */
FNEG(ClassFile.FNEG, 1, Kind.OPERATOR, TypeKind.FLOAT),
FNEG(ClassFile.FNEG, 1, Kind.OPERATOR),
/** Negate double */
DNEG(ClassFile.DNEG, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DNEG(ClassFile.DNEG, 1, Kind.OPERATOR),
/** Shift left int */
ISHL(ClassFile.ISHL, 1, Kind.OPERATOR, TypeKind.INT),
ISHL(ClassFile.ISHL, 1, Kind.OPERATOR),
/** Shift left long */
LSHL(ClassFile.LSHL, 1, Kind.OPERATOR, TypeKind.LONG),
LSHL(ClassFile.LSHL, 1, Kind.OPERATOR),
/** Shift right int */
ISHR(ClassFile.ISHR, 1, Kind.OPERATOR, TypeKind.INT),
ISHR(ClassFile.ISHR, 1, Kind.OPERATOR),
/** Shift right long */
LSHR(ClassFile.LSHR, 1, Kind.OPERATOR, TypeKind.LONG),
LSHR(ClassFile.LSHR, 1, Kind.OPERATOR),
/** Logical shift right int */
IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR, TypeKind.INT),
IUSHR(ClassFile.IUSHR, 1, Kind.OPERATOR),
/** Logical shift right long */
LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR, TypeKind.LONG),
LUSHR(ClassFile.LUSHR, 1, Kind.OPERATOR),
/** Boolean AND int */
IAND(ClassFile.IAND, 1, Kind.OPERATOR, TypeKind.INT),
IAND(ClassFile.IAND, 1, Kind.OPERATOR),
/** Boolean AND long */
LAND(ClassFile.LAND, 1, Kind.OPERATOR, TypeKind.LONG),
LAND(ClassFile.LAND, 1, Kind.OPERATOR),
/** Boolean OR int */
IOR(ClassFile.IOR, 1, Kind.OPERATOR, TypeKind.INT),
IOR(ClassFile.IOR, 1, Kind.OPERATOR),
/** Boolean OR long */
LOR(ClassFile.LOR, 1, Kind.OPERATOR, TypeKind.LONG),
LOR(ClassFile.LOR, 1, Kind.OPERATOR),
/** Boolean XOR int */
IXOR(ClassFile.IXOR, 1, Kind.OPERATOR, TypeKind.INT),
IXOR(ClassFile.IXOR, 1, Kind.OPERATOR),
/** Boolean XOR long */
LXOR(ClassFile.LXOR, 1, Kind.OPERATOR, TypeKind.LONG),
LXOR(ClassFile.LXOR, 1, Kind.OPERATOR),
/** Increment local variable by constant */
IINC(ClassFile.IINC, 3, Kind.INCREMENT, TypeKind.INT, -1),
IINC(ClassFile.IINC, 3, Kind.INCREMENT),
/** Convert int to long */
I2L(ClassFile.I2L, 1, Kind.CONVERT, TypeKind.INT, TypeKind.LONG),
I2L(ClassFile.I2L, 1, Kind.CONVERT),
/** Convert int to float */
I2F(ClassFile.I2F, 1, Kind.CONVERT, TypeKind.INT, TypeKind.FLOAT),
I2F(ClassFile.I2F, 1, Kind.CONVERT),
/** Convert int to double */
I2D(ClassFile.I2D, 1, Kind.CONVERT, TypeKind.INT, TypeKind.DOUBLE),
I2D(ClassFile.I2D, 1, Kind.CONVERT),
/** Convert long to int */
L2I(ClassFile.L2I, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.INT),
L2I(ClassFile.L2I, 1, Kind.CONVERT),
/** Convert long to float */
L2F(ClassFile.L2F, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.FLOAT),
L2F(ClassFile.L2F, 1, Kind.CONVERT),
/** Convert long to double */
L2D(ClassFile.L2D, 1, Kind.CONVERT, TypeKind.LONG, TypeKind.DOUBLE),
L2D(ClassFile.L2D, 1, Kind.CONVERT),
/** Convert float to int */
F2I(ClassFile.F2I, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.INT),
F2I(ClassFile.F2I, 1, Kind.CONVERT),
/** Convert float to long */
F2L(ClassFile.F2L, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.LONG),
F2L(ClassFile.F2L, 1, Kind.CONVERT),
/** Convert float to double */
F2D(ClassFile.F2D, 1, Kind.CONVERT, TypeKind.FLOAT, TypeKind.DOUBLE),
F2D(ClassFile.F2D, 1, Kind.CONVERT),
/** Convert double to int */
D2I(ClassFile.D2I, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.INT),
D2I(ClassFile.D2I, 1, Kind.CONVERT),
/** Convert double to long */
D2L(ClassFile.D2L, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.LONG),
D2L(ClassFile.D2L, 1, Kind.CONVERT),
/** Convert double to float */
D2F(ClassFile.D2F, 1, Kind.CONVERT, TypeKind.DOUBLE, TypeKind.FLOAT),
D2F(ClassFile.D2F, 1, Kind.CONVERT),
/** Convert int to byte */
I2B(ClassFile.I2B, 1, Kind.CONVERT, TypeKind.INT, TypeKind.BYTE),
I2B(ClassFile.I2B, 1, Kind.CONVERT),
/** Convert int to char */
I2C(ClassFile.I2C, 1, Kind.CONVERT, TypeKind.INT, TypeKind.CHAR),
I2C(ClassFile.I2C, 1, Kind.CONVERT),
/** Convert int to short */
I2S(ClassFile.I2S, 1, Kind.CONVERT, TypeKind.INT, TypeKind.SHORT),
I2S(ClassFile.I2S, 1, Kind.CONVERT),
/** Compare long */
LCMP(ClassFile.LCMP, 1, Kind.OPERATOR, TypeKind.LONG),
LCMP(ClassFile.LCMP, 1, Kind.OPERATOR),
/** Compare float */
FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR, TypeKind.FLOAT),
FCMPL(ClassFile.FCMPL, 1, Kind.OPERATOR),
/** Compare float */
FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR, TypeKind.FLOAT),
FCMPG(ClassFile.FCMPG, 1, Kind.OPERATOR),
/** Compare double */
DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DCMPL(ClassFile.DCMPL, 1, Kind.OPERATOR),
/** Compare double */
DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR, TypeKind.DOUBLE),
DCMPG(ClassFile.DCMPG, 1, Kind.OPERATOR),
/** Branch if int comparison with zero succeeds */
IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH, TypeKind.INT),
IFEQ(ClassFile.IFEQ, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
IFNE(ClassFile.IFNE, 3, Kind.BRANCH, TypeKind.INT),
IFNE(ClassFile.IFNE, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
IFLT(ClassFile.IFLT, 3, Kind.BRANCH, TypeKind.INT),
IFLT(ClassFile.IFLT, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
IFGE(ClassFile.IFGE, 3, Kind.BRANCH, TypeKind.INT),
IFGE(ClassFile.IFGE, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
IFGT(ClassFile.IFGT, 3, Kind.BRANCH, TypeKind.INT),
IFGT(ClassFile.IFGT, 3, Kind.BRANCH),
/** Branch if int comparison with zero succeeds */
IFLE(ClassFile.IFLE, 3, Kind.BRANCH, TypeKind.INT),
IFLE(ClassFile.IFLE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPEQ(ClassFile.IF_ICMPEQ, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPNE(ClassFile.IF_ICMPNE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPLT(ClassFile.IF_ICMPLT, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPGE(ClassFile.IF_ICMPGE, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPGT(ClassFile.IF_ICMPGT, 3, Kind.BRANCH),
/** Branch if int comparison succeeds */
IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH, TypeKind.INT),
IF_ICMPLE(ClassFile.IF_ICMPLE, 3, Kind.BRANCH),
/** Branch if reference comparison succeeds */
IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH, TypeKind.REFERENCE),
IF_ACMPEQ(ClassFile.IF_ACMPEQ, 3, Kind.BRANCH),
/** Branch if reference comparison succeeds */
IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH, TypeKind.REFERENCE),
IF_ACMPNE(ClassFile.IF_ACMPNE, 3, Kind.BRANCH),
/** Branch always */
GOTO(ClassFile.GOTO, 3, Kind.BRANCH, TypeKind.VOID),
GOTO(ClassFile.GOTO, 3, Kind.BRANCH),
/**
* Jump subroutine is discontinued opcode
@ -564,22 +562,22 @@ public enum Opcode {
LOOKUPSWITCH(ClassFile.LOOKUPSWITCH, -1, Kind.LOOKUP_SWITCH),
/** Return int from method */
IRETURN(ClassFile.IRETURN, 1, Kind.RETURN, TypeKind.INT),
IRETURN(ClassFile.IRETURN, 1, Kind.RETURN),
/** Return long from method */
LRETURN(ClassFile.LRETURN, 1, Kind.RETURN, TypeKind.LONG),
LRETURN(ClassFile.LRETURN, 1, Kind.RETURN),
/** Return float from method */
FRETURN(ClassFile.FRETURN, 1, Kind.RETURN, TypeKind.FLOAT),
FRETURN(ClassFile.FRETURN, 1, Kind.RETURN),
/** Return double from method */
DRETURN(ClassFile.DRETURN, 1, Kind.RETURN, TypeKind.DOUBLE),
DRETURN(ClassFile.DRETURN, 1, Kind.RETURN),
/** Return reference from method */
ARETURN(ClassFile.ARETURN, 1, Kind.RETURN, TypeKind.REFERENCE),
ARETURN(ClassFile.ARETURN, 1, Kind.RETURN),
/** Return void from method */
RETURN(ClassFile.RETURN, 1, Kind.RETURN, TypeKind.VOID),
RETURN(ClassFile.RETURN, 1, Kind.RETURN),
/** Get static field from class */
GETSTATIC(ClassFile.GETSTATIC, 3, Kind.FIELD_ACCESS),
@ -621,7 +619,7 @@ public enum Opcode {
ANEWARRAY(ClassFile.ANEWARRAY, 3, Kind.NEW_REF_ARRAY),
/** Get length of array */
ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR, TypeKind.INT),
ARRAYLENGTH(ClassFile.ARRAYLENGTH, 1, Kind.OPERATOR),
/** Throw exception or error */
ATHROW(ClassFile.ATHROW, 1, Kind.THROW_EXCEPTION),
@ -642,13 +640,13 @@ public enum Opcode {
MULTIANEWARRAY(ClassFile.MULTIANEWARRAY, 4, Kind.NEW_MULTI_ARRAY),
/** Branch if reference is null */
IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH, TypeKind.REFERENCE),
IFNULL(ClassFile.IFNULL, 3, Kind.BRANCH),
/** Branch if reference not null */
IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH, TypeKind.REFERENCE),
IFNONNULL(ClassFile.IFNONNULL, 3, Kind.BRANCH),
/** Branch always (wide index) */
GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH, TypeKind.VOID),
GOTO_W(ClassFile.GOTO_W, 5, Kind.BRANCH),
/**
* Jump subroutine (wide index) is discontinued opcode
@ -657,34 +655,34 @@ public enum Opcode {
JSR_W(ClassFile.JSR_W, 5, Kind.DISCONTINUED_JSR),
/** Load int from local variable (wide index) */
ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD, TypeKind.INT, -1),
ILOAD_W((ClassFile.WIDE << 8) | ClassFile.ILOAD, 4, Kind.LOAD),
/** Load long from local variable (wide index) */
LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD, TypeKind.LONG, -1),
LLOAD_W((ClassFile.WIDE << 8) | ClassFile.LLOAD, 4, Kind.LOAD),
/** Load float from local variable (wide index) */
FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD, TypeKind.FLOAT, -1),
FLOAD_W((ClassFile.WIDE << 8) | ClassFile.FLOAD, 4, Kind.LOAD),
/** Load double from local variable (wide index) */
DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD, TypeKind.DOUBLE, -1),
DLOAD_W((ClassFile.WIDE << 8) | ClassFile.DLOAD, 4, Kind.LOAD),
/** Load reference from local variable (wide index) */
ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD, TypeKind.REFERENCE, -1),
ALOAD_W((ClassFile.WIDE << 8) | ClassFile.ALOAD, 4, Kind.LOAD),
/** Store int into local variable (wide index) */
ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE, TypeKind.INT, -1),
ISTORE_W((ClassFile.WIDE << 8) | ClassFile.ISTORE, 4, Kind.STORE),
/** Store long into local variable (wide index) */
LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE, TypeKind.LONG, -1),
LSTORE_W((ClassFile.WIDE << 8) | ClassFile.LSTORE, 4, Kind.STORE),
/** Store float into local variable (wide index) */
FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE, TypeKind.FLOAT, -1),
FSTORE_W((ClassFile.WIDE << 8) | ClassFile.FSTORE, 4, Kind.STORE),
/** Store double into local variable (wide index) */
DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE, TypeKind.DOUBLE, -1),
DSTORE_W((ClassFile.WIDE << 8) | ClassFile.DSTORE, 4, Kind.STORE),
/** Store reference into local variable (wide index) */
ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE, TypeKind.REFERENCE, -1),
ASTORE_W((ClassFile.WIDE << 8) | ClassFile.ASTORE, 4, Kind.STORE),
/**
* Return from subroutine (wide index) is discontinued opcode
@ -693,7 +691,7 @@ public enum Opcode {
RET_W((ClassFile.WIDE << 8) | ClassFile.RET, 4, Kind.DISCONTINUED_RET),
/** Increment local variable by constant (wide index) */
IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT, TypeKind.INT, -1);
IINC_W((ClassFile.WIDE << 8) | ClassFile.IINC, 6, Kind.INCREMENT);
/**
* Kinds of opcodes.
@ -1078,59 +1076,41 @@ public enum Opcode {
private final int bytecode;
private final int sizeIfFixed;
private final Kind kind;
private final TypeKind primaryTypeKind;
private final TypeKind secondaryTypeKind;
private final int slot;
private final ConstantDesc constantValue;
Opcode(int bytecode, int sizeIfFixed, Kind kind) {
this(bytecode, sizeIfFixed, kind, null, null, -1, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind) {
this(bytecode, sizeIfFixed, kind, typeKind, null, -1, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot) {
this(bytecode, sizeIfFixed, kind, typeKind, null, slot, null);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind typeKind, int slot, ConstantDesc constantValue) {
this(bytecode, sizeIfFixed, kind, typeKind, null, slot, constantValue);
}
Opcode(int bytecode, int sizeIfFixed, Kind kind, TypeKind primaryTypeKind, TypeKind secondaryTypeKind) {
this(bytecode, sizeIfFixed, kind, primaryTypeKind, secondaryTypeKind, 0, null);
}
Opcode(int bytecode,
int sizeIfFixed,
Kind kind,
TypeKind primaryTypeKind,
TypeKind secondaryTypeKind,
int slot,
ConstantDesc constantValue) {
this.bytecode = bytecode;
this.sizeIfFixed = sizeIfFixed;
this.kind = kind;
this.primaryTypeKind = primaryTypeKind;
this.secondaryTypeKind = secondaryTypeKind;
this.slot = slot;
this.constantValue = constantValue;
}
/**
* {@return bytecode}
* {@return the opcode value} For {@linkplain #isWide() wide} pseudo-opcodes, returns the
* first 2 bytes of the instruction, which are the {@code wide} opcode and the functional
* local variable opcode, as a U2 value.
*/
public int bytecode() { return bytecode; }
/**
* {@return true if the instruction has extended local variable index by additional bytes}
* {@return true if this is a pseudo-opcode modified by {@code wide}}
*
* @see #ILOAD_W
* @see #LLOAD_W
* @see #FLOAD_W
* @see #DLOAD_W
* @see #ALOAD_W
* @see #ISTORE_W
* @see #LSTORE_W
* @see #FSTORE_W
* @see #DSTORE_W
* @see #ASTORE_W
* @see #RET_W
* @see #IINC_W
*/
public boolean isWide() { return bytecode > 255; }
/**
* {@return size of the instruction if fixed, or -1 otherwise}
* {@return size of the instruction in bytes if fixed, or -1 otherwise} This size includes
* the opcode itself.
*/
public int sizeIfFixed() { return sizeIfFixed; }
@ -1138,42 +1118,4 @@ public enum Opcode {
* {@return instruction kind}
*/
public Kind kind() { return kind; }
/**
* {@return primary type kind for instructions operating with at least one type, or null otherwise}
*/
public TypeKind primaryTypeKind() {
return primaryTypeKind;
}
/**
* {@return secondary type kind for instructions operating with two types, or null otherwise}
*/
public TypeKind secondaryTypeKind() {
return secondaryTypeKind;
}
/**
* {@return local variable slot for instructions operating with local variable, or -1 otherwise}
*/
public int slot() {
return slot;
}
/**
* {@return constant value for constant instructions, or null otherwise}
*/
public ConstantDesc constantValue() {
return constantValue;
}
/**
* {@return true if the instruction represents an unconditional branch}
*/
public boolean isUnconditionalBranch() {
return switch (this) {
case GOTO, ATHROW, GOTO_W, LOOKUPSWITCH, TABLESWITCH -> true;
default -> kind() == Kind.RETURN;
};
}
}

View file

@ -75,7 +75,7 @@ public sealed interface ConstantInstruction extends Instruction {
*/
@Override
default TypeKind typeKind() {
return opcode().primaryTypeKind();
return BytecodeHelpers.intrinsicConstantType(opcode());
}
}
@ -98,7 +98,7 @@ public sealed interface ConstantInstruction extends Instruction {
*/
@Override
default TypeKind typeKind() {
return opcode().primaryTypeKind();
return TypeKind.INT;
}
}
@ -137,7 +137,7 @@ public sealed interface ConstantInstruction extends Instruction {
*/
static IntrinsicConstantInstruction ofIntrinsic(Opcode op) {
Util.checkKind(op, Opcode.Kind.CONSTANT);
if (op.constantValue() == null)
if (op.sizeIfFixed() != 1)
throw new IllegalArgumentException(String.format("Wrong opcode specified; found %s, expected xCONST_val", op));
return new AbstractInstruction.UnboundIntrinsicConstantInstruction(op);
}

View file

@ -145,7 +145,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.loadType(op);
}
@Override
@ -173,7 +173,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.storeType(op);
}
@Override
@ -800,7 +800,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.loadType(op);
}
@Override
@ -831,7 +831,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.storeType(op);
}
@Override
@ -993,7 +993,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.returnType(op);
}
@Override
@ -1226,7 +1226,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.arrayLoadType(op);
}
}
@ -1239,7 +1239,7 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.arrayStoreType(op);
}
}
@ -1286,12 +1286,12 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind fromType() {
return op.primaryTypeKind();
return BytecodeHelpers.convertFromType(op);
}
@Override
public TypeKind toType() {
return op.secondaryTypeKind();
return BytecodeHelpers.convertToType(op);
}
}
@ -1304,22 +1304,19 @@ public abstract sealed class AbstractInstruction
@Override
public TypeKind typeKind() {
return op.primaryTypeKind();
return BytecodeHelpers.operatorOperandType(op);
}
}
public static final class UnboundIntrinsicConstantInstruction
extends UnboundInstruction implements ConstantInstruction.IntrinsicConstantInstruction {
final ConstantDesc constant;
public UnboundIntrinsicConstantInstruction(Opcode op) {
super(op);
constant = op.constantValue();
}
@Override
public ConstantDesc constantValue() {
return constant;
return BytecodeHelpers.intrinsicConstantValue(op);
}
}

View file

@ -85,7 +85,7 @@ public final class BlockCodeBuilderImpl
hasInstructions |= element instanceof Instruction;
if (reachable) {
if (element instanceof Instruction i && i.opcode().isUnconditionalBranch())
if (element instanceof Instruction i && BytecodeHelpers.isUnconditionalBranch(i.opcode()))
reachable = false;
}
else if (element instanceof LabelTarget) {

View file

@ -46,6 +46,11 @@ import java.lang.classfile.constantpool.MemberRefEntry;
import java.lang.classfile.constantpool.MethodHandleEntry;
import java.lang.classfile.constantpool.NameAndTypeEntry;
import static java.lang.classfile.ClassFile.*;
/**
* Note: This class switches on opcode.bytecode for code size
*/
public class BytecodeHelpers {
private BytecodeHelpers() {
@ -236,7 +241,7 @@ public class BytecodeHelpers {
case IF_ACMPNE -> Opcode.IF_ACMPEQ;
case IFNULL -> Opcode.IFNONNULL;
case IFNONNULL -> Opcode.IFNULL;
default -> throw new IllegalArgumentException("Unknown branch instruction: " + op);
default -> throw Util.badOpcodeKindException(op, Opcode.Kind.BRANCH);
};
}
@ -277,6 +282,29 @@ public class BytecodeHelpers {
};
}
public static TypeKind convertFromType(Opcode opcode) {
return switch (opcode) {
case I2D, I2F, I2L, I2B, I2C, I2S -> TypeKind.INT;
case L2D, L2F, L2I -> TypeKind.LONG;
case F2D, F2I, F2L -> TypeKind.FLOAT;
case D2F, D2I, D2L -> TypeKind.DOUBLE;
default -> throw Util.badOpcodeKindException(opcode, Opcode.Kind.CONVERT);
};
}
public static TypeKind convertToType(Opcode opcode) {
return switch (opcode) {
case I2B -> TypeKind.BYTE;
case I2C -> TypeKind.CHAR;
case I2S -> TypeKind.SHORT;
case L2I, F2I, D2I -> TypeKind.INT;
case I2L, F2L, D2L -> TypeKind.LONG;
case I2F, L2F, D2F -> TypeKind.FLOAT;
case I2D, L2D, F2D -> TypeKind.DOUBLE;
default -> throw Util.badOpcodeKindException(opcode, Opcode.Kind.CONVERT);
};
}
public static void validateSipush(int value) {
if (value != (short) value)
throw new IllegalArgumentException(
@ -358,4 +386,145 @@ public class BytecodeHelpers {
}
throw new UnsupportedOperationException("not yet: " + constantValue);
}
public static ConstantDesc intrinsicConstantValue(Opcode opcode) {
return switch (opcode) {
case ACONST_NULL -> ConstantDescs.NULL;
case ICONST_M1 -> -1;
case ICONST_0 -> 0;
case ICONST_1 -> 1;
case ICONST_2 -> 2;
case ICONST_3 -> 3;
case ICONST_4 -> 4;
case ICONST_5 -> 5;
case LCONST_0 -> 0L;
case LCONST_1 -> 1L;
case FCONST_0 -> 0F;
case FCONST_1 -> 1F;
case FCONST_2 -> 2F;
case DCONST_0 -> 0D;
case DCONST_1 -> 1D;
default -> throw Util.badOpcodeKindException(opcode, Opcode.Kind.CONSTANT);
};
}
public static TypeKind intrinsicConstantType(Opcode opcode) {
return switch (opcode) {
case ACONST_NULL -> TypeKind.REFERENCE;
case ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 -> TypeKind.INT;
case LCONST_0, LCONST_1 -> TypeKind.LONG;
case FCONST_0, FCONST_1, FCONST_2 -> TypeKind.FLOAT;
case DCONST_0, DCONST_1 -> TypeKind.DOUBLE;
default -> throw Util.badOpcodeKindException(opcode, Opcode.Kind.CONSTANT);
};
}
public static boolean isUnconditionalBranch(Opcode opcode) {
return switch (opcode) {
case GOTO, ATHROW, GOTO_W, LOOKUPSWITCH, TABLESWITCH -> true;
default -> opcode.kind() == Opcode.Kind.RETURN;
};
}
// Must check Opcode.sizeIfFixed() == 1 before call!
public static int intrinsicLoadSlot(Opcode loadOpcode) {
return switch (loadOpcode) {
case ILOAD_0, LLOAD_0, FLOAD_0, DLOAD_0, ALOAD_0 -> 0;
case ILOAD_1, LLOAD_1, FLOAD_1, DLOAD_1, ALOAD_1 -> 1;
case ILOAD_2, LLOAD_2, FLOAD_2, DLOAD_2, ALOAD_2 -> 2;
case ILOAD_3, LLOAD_3, FLOAD_3, DLOAD_3, ALOAD_3 -> 3;
default -> throw Util.badOpcodeKindException(loadOpcode, Opcode.Kind.LOAD);
};
}
// Must check Opcode.sizeIfFixed() == 1 before call!
public static int intrinsicStoreSlot(Opcode storeOpcode) {
return switch (storeOpcode) {
case ISTORE_0, LSTORE_0, FSTORE_0, DSTORE_0, ASTORE_0 -> 0;
case ISTORE_1, LSTORE_1, FSTORE_1, DSTORE_1, ASTORE_1 -> 1;
case ISTORE_2, LSTORE_2, FSTORE_2, DSTORE_2, ASTORE_2 -> 2;
case ISTORE_3, LSTORE_3, FSTORE_3, DSTORE_3, ASTORE_3 -> 3;
default -> throw Util.badOpcodeKindException(storeOpcode, Opcode.Kind.STORE);
};
}
public static TypeKind loadType(Opcode loadOpcode) {
// Note: 0xFF handles wide pseudo-opcodes
return switch (loadOpcode.bytecode() & 0xFF) {
case ILOAD, ILOAD_0, ILOAD_1, ILOAD_2, ILOAD_3 -> TypeKind.INT;
case LLOAD, LLOAD_0, LLOAD_1, LLOAD_2, LLOAD_3 -> TypeKind.LONG;
case FLOAD, FLOAD_0, FLOAD_1, FLOAD_2, FLOAD_3 -> TypeKind.FLOAT;
case DLOAD, DLOAD_0, DLOAD_1, DLOAD_2, DLOAD_3 -> TypeKind.DOUBLE;
case ALOAD, ALOAD_0, ALOAD_1, ALOAD_2, ALOAD_3 -> TypeKind.REFERENCE;
default -> throw Util.badOpcodeKindException(loadOpcode, Opcode.Kind.LOAD);
};
}
public static TypeKind storeType(Opcode storeOpcode) {
// Note: 0xFF handles wide pseudo-opcodes
return switch (storeOpcode.bytecode() & 0xFF) {
case ISTORE, ISTORE_0, ISTORE_1, ISTORE_2, ISTORE_3 -> TypeKind.INT;
case LSTORE, LSTORE_0, LSTORE_1, LSTORE_2, LSTORE_3 -> TypeKind.LONG;
case FSTORE, FSTORE_0, FSTORE_1, FSTORE_2, FSTORE_3 -> TypeKind.FLOAT;
case DSTORE, DSTORE_0, DSTORE_1, DSTORE_2, DSTORE_3 -> TypeKind.DOUBLE;
case ASTORE, ASTORE_0, ASTORE_1, ASTORE_2, ASTORE_3 -> TypeKind.REFERENCE;
default -> throw Util.badOpcodeKindException(storeOpcode, Opcode.Kind.STORE);
};
}
public static TypeKind arrayLoadType(Opcode arrayLoadOpcode) {
return switch (arrayLoadOpcode) {
case IALOAD -> TypeKind.INT;
case LALOAD -> TypeKind.LONG;
case FALOAD -> TypeKind.FLOAT;
case DALOAD -> TypeKind.DOUBLE;
case AALOAD -> TypeKind.REFERENCE;
case BALOAD -> TypeKind.BYTE;
case CALOAD -> TypeKind.CHAR;
case SALOAD -> TypeKind.SHORT;
default -> throw Util.badOpcodeKindException(arrayLoadOpcode, Opcode.Kind.ARRAY_LOAD);
};
}
public static TypeKind arrayStoreType(Opcode arrayStoreOpcode) {
return switch (arrayStoreOpcode) {
case IASTORE -> TypeKind.INT;
case LASTORE -> TypeKind.LONG;
case FASTORE -> TypeKind.FLOAT;
case DASTORE -> TypeKind.DOUBLE;
case AASTORE -> TypeKind.REFERENCE;
case BASTORE -> TypeKind.BYTE;
case CASTORE -> TypeKind.CHAR;
case SASTORE -> TypeKind.SHORT;
default -> throw Util.badOpcodeKindException(arrayStoreOpcode, Opcode.Kind.ARRAY_STORE);
};
}
public static TypeKind returnType(Opcode returnOpcode) {
return switch (returnOpcode) {
case IRETURN -> TypeKind.INT;
case LRETURN -> TypeKind.LONG;
case FRETURN -> TypeKind.FLOAT;
case DRETURN -> TypeKind.DOUBLE;
case ARETURN -> TypeKind.REFERENCE;
case RETURN -> TypeKind.VOID;
default -> throw Util.badOpcodeKindException(returnOpcode, Opcode.Kind.RETURN);
};
}
public static TypeKind operatorOperandType(Opcode operationOpcode) {
return switch (operationOpcode) {
case IADD, ISUB, IMUL, IDIV, IREM, INEG,
ISHL, ISHR, IUSHR, IAND, IOR, IXOR,
ARRAYLENGTH -> TypeKind.INT;
case LADD, LSUB, LMUL, LDIV, LREM, LNEG,
LSHL, LSHR, LUSHR, LAND, LOR, LXOR,
LCMP -> TypeKind.LONG;
case FADD, FSUB, FMUL, FDIV, FREM, FNEG,
FCMPL, FCMPG -> TypeKind.FLOAT;
case DADD, DSUB, DMUL, DDIV, DREM, DNEG,
DCMPL, DCMPG -> TypeKind.DOUBLE;
default -> throw Util.badOpcodeKindException(operationOpcode, Opcode.Kind.OPERATOR);
};
}
}

View file

@ -55,13 +55,13 @@ public final class CodeImpl
case ARRAY_STORE -> ArrayStoreInstruction.of(o);
case CONSTANT -> ConstantInstruction.ofIntrinsic(o);
case CONVERT -> ConvertInstruction.of(o);
case LOAD -> LoadInstruction.of(o, o.slot());
case LOAD -> LoadInstruction.of(o, BytecodeHelpers.intrinsicLoadSlot(o));
case MONITOR -> MonitorInstruction.of(o);
case NOP -> NopInstruction.of();
case OPERATOR -> OperatorInstruction.of(o);
case RETURN -> ReturnInstruction.of(o);
case STACK -> StackInstruction.of(o);
case STORE -> StoreInstruction.of(o, o.slot());
case STORE -> StoreInstruction.of(o, BytecodeHelpers.intrinsicStoreSlot(o));
case THROW_EXCEPTION -> ThrowInstruction.of();
default -> throw new AssertionError("invalid opcode: " + o);
};

View file

@ -185,7 +185,11 @@ public class Util {
public static void checkKind(Opcode op, Opcode.Kind k) {
if (op.kind() != k)
throw new IllegalArgumentException(
throw badOpcodeKindException(op, k);
}
public static IllegalArgumentException badOpcodeKindException(Opcode op, Opcode.Kind k) {
return new IllegalArgumentException(
String.format("Wrong opcode kind specified; found %s(%s), expected %s", op, op.kind(), k));
}