All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.classfile.instruction.Instruction Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2020 Guardsquare NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package proguard.classfile.instruction;

import proguard.classfile.*;
import proguard.classfile.attribute.CodeAttribute;
import proguard.classfile.instruction.visitor.InstructionVisitor;

/**
 * Base class for representing instructions.
 *
 * @author Eric Lafortune
 */
public abstract class Instruction {
  public static final byte OP_NOP = 0;
  public static final byte OP_ACONST_NULL = 1;
  public static final byte OP_ICONST_M1 = 2;
  public static final byte OP_ICONST_0 = 3;
  public static final byte OP_ICONST_1 = 4;
  public static final byte OP_ICONST_2 = 5;
  public static final byte OP_ICONST_3 = 6;
  public static final byte OP_ICONST_4 = 7;
  public static final byte OP_ICONST_5 = 8;
  public static final byte OP_LCONST_0 = 9;
  public static final byte OP_LCONST_1 = 10;
  public static final byte OP_FCONST_0 = 11;
  public static final byte OP_FCONST_1 = 12;
  public static final byte OP_FCONST_2 = 13;
  public static final byte OP_DCONST_0 = 14;
  public static final byte OP_DCONST_1 = 15;
  public static final byte OP_BIPUSH = 16;
  public static final byte OP_SIPUSH = 17;
  public static final byte OP_LDC = 18;
  public static final byte OP_LDC_W = 19;
  public static final byte OP_LDC2_W = 20;
  public static final byte OP_ILOAD = 21;
  public static final byte OP_LLOAD = 22;
  public static final byte OP_FLOAD = 23;
  public static final byte OP_DLOAD = 24;
  public static final byte OP_ALOAD = 25;
  public static final byte OP_ILOAD_0 = 26;
  public static final byte OP_ILOAD_1 = 27;
  public static final byte OP_ILOAD_2 = 28;
  public static final byte OP_ILOAD_3 = 29;
  public static final byte OP_LLOAD_0 = 30;
  public static final byte OP_LLOAD_1 = 31;
  public static final byte OP_LLOAD_2 = 32;
  public static final byte OP_LLOAD_3 = 33;
  public static final byte OP_FLOAD_0 = 34;
  public static final byte OP_FLOAD_1 = 35;
  public static final byte OP_FLOAD_2 = 36;
  public static final byte OP_FLOAD_3 = 37;
  public static final byte OP_DLOAD_0 = 38;
  public static final byte OP_DLOAD_1 = 39;
  public static final byte OP_DLOAD_2 = 40;
  public static final byte OP_DLOAD_3 = 41;
  public static final byte OP_ALOAD_0 = 42;
  public static final byte OP_ALOAD_1 = 43;
  public static final byte OP_ALOAD_2 = 44;
  public static final byte OP_ALOAD_3 = 45;
  public static final byte OP_IALOAD = 46;
  public static final byte OP_LALOAD = 47;
  public static final byte OP_FALOAD = 48;
  public static final byte OP_DALOAD = 49;
  public static final byte OP_AALOAD = 50;
  public static final byte OP_BALOAD = 51;
  public static final byte OP_CALOAD = 52;
  public static final byte OP_SALOAD = 53;
  public static final byte OP_ISTORE = 54;
  public static final byte OP_LSTORE = 55;
  public static final byte OP_FSTORE = 56;
  public static final byte OP_DSTORE = 57;
  public static final byte OP_ASTORE = 58;
  public static final byte OP_ISTORE_0 = 59;
  public static final byte OP_ISTORE_1 = 60;
  public static final byte OP_ISTORE_2 = 61;
  public static final byte OP_ISTORE_3 = 62;
  public static final byte OP_LSTORE_0 = 63;
  public static final byte OP_LSTORE_1 = 64;
  public static final byte OP_LSTORE_2 = 65;
  public static final byte OP_LSTORE_3 = 66;
  public static final byte OP_FSTORE_0 = 67;
  public static final byte OP_FSTORE_1 = 68;
  public static final byte OP_FSTORE_2 = 69;
  public static final byte OP_FSTORE_3 = 70;
  public static final byte OP_DSTORE_0 = 71;
  public static final byte OP_DSTORE_1 = 72;
  public static final byte OP_DSTORE_2 = 73;
  public static final byte OP_DSTORE_3 = 74;
  public static final byte OP_ASTORE_0 = 75;
  public static final byte OP_ASTORE_1 = 76;
  public static final byte OP_ASTORE_2 = 77;
  public static final byte OP_ASTORE_3 = 78;
  public static final byte OP_IASTORE = 79;
  public static final byte OP_LASTORE = 80;
  public static final byte OP_FASTORE = 81;
  public static final byte OP_DASTORE = 82;
  public static final byte OP_AASTORE = 83;
  public static final byte OP_BASTORE = 84;
  public static final byte OP_CASTORE = 85;
  public static final byte OP_SASTORE = 86;
  public static final byte OP_POP = 87;
  public static final byte OP_POP2 = 88;
  public static final byte OP_DUP = 89;
  public static final byte OP_DUP_X1 = 90;
  public static final byte OP_DUP_X2 = 91;
  public static final byte OP_DUP2 = 92;
  public static final byte OP_DUP2_X1 = 93;
  public static final byte OP_DUP2_X2 = 94;
  public static final byte OP_SWAP = 95;
  public static final byte OP_IADD = 96;
  public static final byte OP_LADD = 97;
  public static final byte OP_FADD = 98;
  public static final byte OP_DADD = 99;
  public static final byte OP_ISUB = 100;
  public static final byte OP_LSUB = 101;
  public static final byte OP_FSUB = 102;
  public static final byte OP_DSUB = 103;
  public static final byte OP_IMUL = 104;
  public static final byte OP_LMUL = 105;
  public static final byte OP_FMUL = 106;
  public static final byte OP_DMUL = 107;
  public static final byte OP_IDIV = 108;
  public static final byte OP_LDIV = 109;
  public static final byte OP_FDIV = 110;
  public static final byte OP_DDIV = 111;
  public static final byte OP_IREM = 112;
  public static final byte OP_LREM = 113;
  public static final byte OP_FREM = 114;
  public static final byte OP_DREM = 115;
  public static final byte OP_INEG = 116;
  public static final byte OP_LNEG = 117;
  public static final byte OP_FNEG = 118;
  public static final byte OP_DNEG = 119;
  public static final byte OP_ISHL = 120;
  public static final byte OP_LSHL = 121;
  public static final byte OP_ISHR = 122;
  public static final byte OP_LSHR = 123;
  public static final byte OP_IUSHR = 124;
  public static final byte OP_LUSHR = 125;
  public static final byte OP_IAND = 126;
  public static final byte OP_LAND = 127;
  public static final byte OP_IOR = -128;
  public static final byte OP_LOR = -127;
  public static final byte OP_IXOR = -126;
  public static final byte OP_LXOR = -125;
  public static final byte OP_IINC = -124;
  public static final byte OP_I2L = -123;
  public static final byte OP_I2F = -122;
  public static final byte OP_I2D = -121;
  public static final byte OP_L2I = -120;
  public static final byte OP_L2F = -119;
  public static final byte OP_L2D = -118;
  public static final byte OP_F2I = -117;
  public static final byte OP_F2L = -116;
  public static final byte OP_F2D = -115;
  public static final byte OP_D2I = -114;
  public static final byte OP_D2L = -113;
  public static final byte OP_D2F = -112;
  public static final byte OP_I2B = -111;
  public static final byte OP_I2C = -110;
  public static final byte OP_I2S = -109;
  public static final byte OP_LCMP = -108;
  public static final byte OP_FCMPL = -107;
  public static final byte OP_FCMPG = -106;
  public static final byte OP_DCMPL = -105;
  public static final byte OP_DCMPG = -104;
  public static final byte OP_IFEQ = -103;
  public static final byte OP_IFNE = -102;
  public static final byte OP_IFLT = -101;
  public static final byte OP_IFGE = -100;
  public static final byte OP_IFGT = -99;
  public static final byte OP_IFLE = -98;
  public static final byte OP_IFICMPEQ = -97;
  public static final byte OP_IFICMPNE = -96;
  public static final byte OP_IFICMPLT = -95;
  public static final byte OP_IFICMPGE = -94;
  public static final byte OP_IFICMPGT = -93;
  public static final byte OP_IFICMPLE = -92;
  public static final byte OP_IFACMPEQ = -91;
  public static final byte OP_IFACMPNE = -90;
  public static final byte OP_GOTO = -89;
  public static final byte OP_JSR = -88;
  public static final byte OP_RET = -87;
  public static final byte OP_TABLESWITCH = -86;
  public static final byte OP_LOOKUPSWITCH = -85;
  public static final byte OP_IRETURN = -84;
  public static final byte OP_LRETURN = -83;
  public static final byte OP_FRETURN = -82;
  public static final byte OP_DRETURN = -81;
  public static final byte OP_ARETURN = -80;
  public static final byte OP_RETURN = -79;
  public static final byte OP_GETSTATIC = -78;
  public static final byte OP_PUTSTATIC = -77;
  public static final byte OP_GETFIELD = -76;
  public static final byte OP_PUTFIELD = -75;
  public static final byte OP_INVOKEVIRTUAL = -74;
  public static final byte OP_INVOKESPECIAL = -73;
  public static final byte OP_INVOKESTATIC = -72;
  public static final byte OP_INVOKEINTERFACE = -71;
  public static final byte OP_INVOKEDYNAMIC = -70;
  public static final byte OP_NEW = -69;
  public static final byte OP_NEWARRAY = -68;
  public static final byte OP_ANEWARRAY = -67;
  public static final byte OP_ARRAYLENGTH = -66;
  public static final byte OP_ATHROW = -65;
  public static final byte OP_CHECKCAST = -64;
  public static final byte OP_INSTANCEOF = -63;
  public static final byte OP_MONITORENTER = -62;
  public static final byte OP_MONITOREXIT = -61;
  public static final byte OP_WIDE = -60;
  public static final byte OP_MULTIANEWARRAY = -59;
  public static final byte OP_IFNULL = -58;
  public static final byte OP_IFNONNULL = -57;
  public static final byte OP_GOTO_W = -56;
  public static final byte OP_JSR_W = -55;

  public static final String[] NAMES = {
    "nop",
    "aconst_null",
    "iconst_m1",
    "iconst_0",
    "iconst_1",
    "iconst_2",
    "iconst_3",
    "iconst_4",
    "iconst_5",
    "lconst_0",
    "lconst_1",
    "fconst_0",
    "fconst_1",
    "fconst_2",
    "dconst_0",
    "dconst_1",
    "bipush",
    "sipush",
    "ldc",
    "ldc_w",
    "ldc2_w",
    "iload",
    "lload",
    "fload",
    "dload",
    "aload",
    "iload_0",
    "iload_1",
    "iload_2",
    "iload_3",
    "lload_0",
    "lload_1",
    "lload_2",
    "lload_3",
    "fload_0",
    "fload_1",
    "fload_2",
    "fload_3",
    "dload_0",
    "dload_1",
    "dload_2",
    "dload_3",
    "aload_0",
    "aload_1",
    "aload_2",
    "aload_3",
    "iaload",
    "laload",
    "faload",
    "daload",
    "aaload",
    "baload",
    "caload",
    "saload",
    "istore",
    "lstore",
    "fstore",
    "dstore",
    "astore",
    "istore_0",
    "istore_1",
    "istore_2",
    "istore_3",
    "lstore_0",
    "lstore_1",
    "lstore_2",
    "lstore_3",
    "fstore_0",
    "fstore_1",
    "fstore_2",
    "fstore_3",
    "dstore_0",
    "dstore_1",
    "dstore_2",
    "dstore_3",
    "astore_0",
    "astore_1",
    "astore_2",
    "astore_3",
    "iastore",
    "lastore",
    "fastore",
    "dastore",
    "aastore",
    "bastore",
    "castore",
    "sastore",
    "pop",
    "pop2",
    "dup",
    "dup_x1",
    "dup_x2",
    "dup2",
    "dup2_x1",
    "dup2_x2",
    "swap",
    "iadd",
    "ladd",
    "fadd",
    "dadd",
    "isub",
    "lsub",
    "fsub",
    "dsub",
    "imul",
    "lmul",
    "fmul",
    "dmul",
    "idiv",
    "ldiv",
    "fdiv",
    "ddiv",
    "irem",
    "lrem",
    "frem",
    "drem",
    "ineg",
    "lneg",
    "fneg",
    "dneg",
    "ishl",
    "lshl",
    "ishr",
    "lshr",
    "iushr",
    "lushr",
    "iand",
    "land",
    "ior",
    "lor",
    "ixor",
    "lxor",
    "iinc",
    "i2l",
    "i2f",
    "i2d",
    "l2i",
    "l2f",
    "l2d",
    "f2i",
    "f2l",
    "f2d",
    "d2i",
    "d2l",
    "d2f",
    "i2b",
    "i2c",
    "i2s",
    "lcmp",
    "fcmpl",
    "fcmpg",
    "dcmpl",
    "dcmpg",
    "ifeq",
    "ifne",
    "iflt",
    "ifge",
    "ifgt",
    "ifle",
    "if_icmpeq",
    "if_icmpne",
    "if_icmplt",
    "if_icmpge",
    "if_icmpgt",
    "if_icmple",
    "if_acmpeq",
    "if_acmpne",
    "goto",
    "jsr",
    "ret",
    "tableswitch",
    "lookupswitch",
    "ireturn",
    "lreturn",
    "freturn",
    "dreturn",
    "areturn",
    "return",
    "getstatic",
    "putstatic",
    "getfield",
    "putfield",
    "invokevirtual",
    "invokespecial",
    "invokestatic",
    "invokeinterface",
    "invokedynamic",
    "new",
    "newarray",
    "anewarray",
    "arraylength",
    "athrow",
    "checkcast",
    "instanceof",
    "monitorenter",
    "monitorexit",
    "wide",
    "multianewarray",
    "ifnull",
    "ifnonnull",
    "goto_w",
    "jsr_w",
  };

  public static final byte ARRAY_T_BOOLEAN = 4;
  public static final byte ARRAY_T_CHAR = 5;
  public static final byte ARRAY_T_FLOAT = 6;
  public static final byte ARRAY_T_DOUBLE = 7;
  public static final byte ARRAY_T_BYTE = 8;
  public static final byte ARRAY_T_SHORT = 9;
  public static final byte ARRAY_T_INT = 10;
  public static final byte ARRAY_T_LONG = 11;

  // An array for marking instructions that may throw exceptions.
  private static final boolean[] MAY_THROW_EXCEPTIONS =
      new boolean[] {
        false, // nop
        false, // aconst_null
        false, // iconst_m1
        false, // iconst_0
        false, // iconst_1
        false, // iconst_2
        false, // iconst_3
        false, // iconst_4
        false, // iconst_5
        false, // lconst_0
        false, // lconst_1
        false, // fconst_0
        false, // fconst_1
        false, // fconst_2
        false, // dconst_0
        false, // dconst_1
        false, // bipush
        false, // sipush

        // Conservatively mark ldc as throwing even though only ldc with class, method type or
        // method handler constants
        // operands may throw, we cannot know the operand type at this point.
        // ClassConstant.mayInstanceThrowExceptions(Clazz) has access to the context necessary to
        // determine this.
        true, // ldc
        true, // ldc_w
        false, // ldc2_w
        false, // iload
        false, // lload
        false, // fload
        false, // dload
        false, // aload
        false, // iload_0
        false, // iload_1
        false, // iload_2
        false, // iload_3
        false, // lload_0
        false, // lload_1
        false, // lload_2
        false, // lload_3
        false, // fload_0
        false, // fload_1
        false, // fload_2
        false, // fload_3
        false, // dload_0
        false, // dload_1
        false, // dload_2
        false, // dload_3
        false, // aload_0
        false, // aload_1
        false, // aload_2
        false, // aload_3
        true, // iaload
        true, // laload
        true, // faload
        true, // daload
        true, // aaload
        true, // baload
        true, // caload
        true, // saload
        false, // istore
        false, // lstore
        false, // fstore
        false, // dstore
        false, // astore
        false, // istore_0
        false, // istore_1
        false, // istore_2
        false, // istore_3
        false, // lstore_0
        false, // lstore_1
        false, // lstore_2
        false, // lstore_3
        false, // fstore_0
        false, // fstore_1
        false, // fstore_2
        false, // fstore_3
        false, // dstore_0
        false, // dstore_1
        false, // dstore_2
        false, // dstore_3
        false, // astore_0
        false, // astore_1
        false, // astore_2
        false, // astore_3
        true, // iastore
        true, // lastore
        true, // fastore
        true, // dastore
        true, // aastore
        true, // bastore
        true, // castore
        true, // sastore
        false, // pop
        false, // pop2
        false, // dup
        false, // dup_x1
        false, // dup_x2
        false, // dup2
        false, // dup2_x1
        false, // dup2_x2
        false, // swap
        false, // iadd
        false, // ladd
        false, // fadd
        false, // dadd
        false, // isub
        false, // lsub
        false, // fsub
        false, // dsub
        false, // imul
        false, // lmul
        false, // fmul
        false, // dmul
        true, // idiv
        true, // ldiv
        false, // fdiv
        false, // ddiv
        true, // irem
        true, // lrem
        false, // frem
        false, // drem
        false, // ineg
        false, // lneg
        false, // fneg
        false, // dneg
        false, // ishl
        false, // lshl
        false, // ishr
        false, // lshr
        false, // iushr
        false, // lushr
        false, // iand
        false, // land
        false, // ior
        false, // lor
        false, // ixor
        false, // lxor
        false, // iinc
        false, // i2l
        false, // i2f
        false, // i2d
        false, // l2i
        false, // l2f
        false, // l2d
        false, // f2i
        false, // f2l
        false, // f2d
        false, // d2i
        false, // d2l
        false, // d2f
        false, // i2b
        false, // i2c
        false, // i2s
        false, // lcmp
        false, // fcmpl
        false, // fcmpg
        false, // dcmpl
        false, // dcmpg
        false, // ifeq
        false, // ifne
        false, // iflt
        false, // ifge
        false, // ifgt
        false, // ifle
        false, // ificmpeq
        false, // ificmpne
        false, // ificmplt
        false, // ificmpge
        false, // ificmpgt
        false, // ificmple
        false, // ifacmpeq
        false, // ifacmpne
        false, // goto
        false, // jsr
        false, // ret
        false, // tableswitch
        false, // lookupswitch
        false, // ireturn
        false, // lreturn
        false, // freturn
        false, // dreturn
        false, // areturn
        false, // return
        true, // getstatic
        true, // putstatic
        true, // getfield
        true, // putfield
        true, // invokevirtual
        true, // invokespecial
        true, // invokestatic
        true, // invokeinterface
        true, // invokedynamic
        true, // new
        true, // newarray
        true, // anewarray
        true, // arraylength
        true, // athrow
        true, // checkcast
        false, // instanceof
        true, // monitorenter
        false, // monitorexit
        false, // wide
        true, // multianewarray
        false, // ifnull
        false, // ifnonnull
        false, // goto_w
        false, // jsr_w
      };

  // An array for marking Category 2 instructions.
  private static final boolean[] IS_CATEGORY2 =
      new boolean[] {
        false, // nop
        false, // aconst_null
        false, // iconst_m1
        false, // iconst_0
        false, // iconst_1
        false, // iconst_2
        false, // iconst_3
        false, // iconst_4
        false, // iconst_5
        true, // lconst_0
        true, // lconst_1
        false, // fconst_0
        false, // fconst_1
        false, // fconst_2
        true, // dconst_0
        true, // dconst_1
        false, // bipush
        false, // sipush
        false, // ldc
        false, // ldc_w
        true, // ldc2_w
        false, // iload
        true, // lload
        false, // fload
        true, // dload
        false, // aload
        false, // iload_0
        false, // iload_1
        false, // iload_2
        false, // iload_3
        true, // lload_0
        true, // lload_1
        true, // lload_2
        true, // lload_3
        false, // fload_0
        false, // fload_1
        false, // fload_2
        false, // fload_3
        true, // dload_0
        true, // dload_1
        true, // dload_2
        true, // dload_3
        false, // aload_0
        false, // aload_1
        false, // aload_2
        false, // aload_3
        false, // iaload
        true, // laload
        false, // faload
        true, // daload
        false, // aaload
        false, // baload
        false, // caload
        false, // saload
        false, // istore
        true, // lstore
        false, // fstore
        true, // dstore
        false, // astore
        false, // istore_0
        false, // istore_1
        false, // istore_2
        false, // istore_3
        true, // lstore_0
        true, // lstore_1
        true, // lstore_2
        true, // lstore_3
        false, // fstore_0
        false, // fstore_1
        false, // fstore_2
        false, // fstore_3
        true, // dstore_0
        true, // dstore_1
        true, // dstore_2
        true, // dstore_3
        false, // astore_0
        false, // astore_1
        false, // astore_2
        false, // astore_3
        false, // iastore
        true, // lastore
        false, // fastore
        true, // dastore
        false, // aastore
        false, // bastore
        false, // castore
        false, // sastore
        false, // pop
        true, // pop2
        false, // dup
        false, // dup_x1
        false, // dup_x2
        true, // dup2
        true, // dup2_x1
        true, // dup2_x2
        false, // swap
        false, // iadd
        true, // ladd
        false, // fadd
        true, // dadd
        false, // isub
        true, // lsub
        false, // fsub
        true, // dsub
        false, // imul
        true, // lmul
        false, // fmul
        true, // dmul
        false, // idiv
        true, // ldiv
        false, // fdiv
        true, // ddiv
        false, // irem
        true, // lrem
        false, // frem
        true, // drem
        false, // ineg
        true, // lneg
        false, // fneg
        true, // dneg
        false, // ishl
        true, // lshl
        false, // ishr
        true, // lshr
        false, // iushr
        true, // lushr
        false, // iand
        true, // land
        false, // ior
        true, // lor
        false, // ixor
        true, // lxor
        false, // iinc
        false, // i2l
        false, // i2f
        false, // i2d
        true, // l2i
        true, // l2f
        true, // l2d
        false, // f2i
        false, // f2l
        false, // f2d
        true, // d2i
        true, // d2l
        true, // d2f
        false, // i2b
        false, // i2c
        false, // i2s
        true, // lcmp
        false, // fcmpl
        false, // fcmpg
        true, // dcmpl
        true, // dcmpg
        false, // ifeq
        false, // ifne
        false, // iflt
        false, // ifge
        false, // ifgt
        false, // ifle
        false, // ificmpeq
        false, // ificmpne
        false, // ificmplt
        false, // ificmpge
        false, // ificmpgt
        false, // ificmple
        false, // ifacmpeq
        false, // ifacmpne
        false, // goto
        false, // jsr
        false, // ret
        false, // tableswitch
        false, // lookupswitch
        false, // ireturn
        true, // lreturn
        false, // freturn
        true, // dreturn
        false, // areturn
        false, // return
        false, // getstatic
        false, // putstatic
        false, // getfield
        false, // putfield
        false, // invokevirtual
        false, // invokespecial
        false, // invokestatic
        false, // invokeinterface
        false, // invokedynamic
        false, // new
        false, // newarray
        false, // anewarray
        false, // arraylength
        false, // athrow
        false, // checkcast
        false, // instanceof
        false, // monitorenter
        false, // monitorexit
        false, // wide
        false, // multianewarray
        false, // ifnull
        false, // ifnonnull
        false, // goto_w
        false, // jsr_w
      };

  // An array containing the fixed number of entries popped from the stack,
  // for all instructions.
  private static final int[] STACK_POP_COUNTS =
      new int[] {
        0, // nop
        0, // aconst_null
        0, // iconst_m1
        0, // iconst_0
        0, // iconst_1
        0, // iconst_2
        0, // iconst_3
        0, // iconst_4
        0, // iconst_5
        0, // lconst_0
        0, // lconst_1
        0, // fconst_0
        0, // fconst_1
        0, // fconst_2
        0, // dconst_0
        0, // dconst_1
        0, // bipush
        0, // sipush
        0, // ldc
        0, // ldc_w
        0, // ldc2_w
        0, // iload
        0, // lload
        0, // fload
        0, // dload
        0, // aload
        0, // iload_0
        0, // iload_1
        0, // iload_2
        0, // iload_3
        0, // lload_0
        0, // lload_1
        0, // lload_2
        0, // lload_3
        0, // fload_0
        0, // fload_1
        0, // fload_2
        0, // fload_3
        0, // dload_0
        0, // dload_1
        0, // dload_2
        0, // dload_3
        0, // aload_0
        0, // aload_1
        0, // aload_2
        0, // aload_3
        2, // iaload
        2, // laload
        2, // faload
        2, // daload
        2, // aaload
        2, // baload
        2, // caload
        2, // saload
        1, // istore
        2, // lstore
        1, // fstore
        2, // dstore
        1, // astore
        1, // istore_0
        1, // istore_1
        1, // istore_2
        1, // istore_3
        2, // lstore_0
        2, // lstore_1
        2, // lstore_2
        2, // lstore_3
        1, // fstore_0
        1, // fstore_1
        1, // fstore_2
        1, // fstore_3
        2, // dstore_0
        2, // dstore_1
        2, // dstore_2
        2, // dstore_3
        1, // astore_0
        1, // astore_1
        1, // astore_2
        1, // astore_3
        3, // iastore
        4, // lastore
        3, // fastore
        4, // dastore
        3, // aastore
        3, // bastore
        3, // castore
        3, // sastore
        1, // pop
        2, // pop2
        1, // dup
        2, // dup_x1
        3, // dup_x2
        2, // dup2
        3, // dup2_x1
        4, // dup2_x2
        2, // swap
        2, // iadd
        4, // ladd
        2, // fadd
        4, // dadd
        2, // isub
        4, // lsub
        2, // fsub
        4, // dsub
        2, // imul
        4, // lmul
        2, // fmul
        4, // dmul
        2, // idiv
        4, // ldiv
        2, // fdiv
        4, // ddiv
        2, // irem
        4, // lrem
        2, // frem
        4, // drem
        1, // ineg
        2, // lneg
        1, // fneg
        2, // dneg
        2, // ishl
        3, // lshl
        2, // ishr
        3, // lshr
        2, // iushr
        3, // lushr
        2, // iand
        4, // land
        2, // ior
        4, // lor
        2, // ixor
        4, // lxor
        0, // iinc
        1, // i2l
        1, // i2f
        1, // i2d
        2, // l2i
        2, // l2f
        2, // l2d
        1, // f2i
        1, // f2l
        1, // f2d
        2, // d2i
        2, // d2l
        2, // d2f
        1, // i2b
        1, // i2c
        1, // i2s
        4, // lcmp
        2, // fcmpl
        2, // fcmpg
        4, // dcmpl
        4, // dcmpg
        1, // ifeq
        1, // ifne
        1, // iflt
        1, // ifge
        1, // ifgt
        1, // ifle
        2, // ificmpeq
        2, // ificmpne
        2, // ificmplt
        2, // ificmpge
        2, // ificmpgt
        2, // ificmple
        2, // ifacmpeq
        2, // ifacmpne
        0, // goto
        0, // jsr
        0, // ret
        1, // tableswitch
        1, // lookupswitch
        1, // ireturn
        2, // lreturn
        1, // freturn
        2, // dreturn
        1, // areturn
        0, // return
        0, // getstatic
        0, // putstatic
        1, // getfield
        1, // putfield
        1, // invokevirtual
        1, // invokespecial
        0, // invokestatic
        1, // invokeinterface
        0, // invokedynamic
        0, // new
        1, // newarray
        1, // anewarray
        1, // arraylength
        1, // athrow
        1, // checkcast
        1, // instanceof
        1, // monitorenter
        1, // monitorexit
        0, // wide
        0, // multianewarray
        1, // ifnull
        1, // ifnonnull
        0, // goto_w
        0, // jsr_w
      };

  // An array containing the fixed number of entries pushed onto the stack,
  // for all instructions.
  private static final int[] STACK_PUSH_COUNTS =
      new int[] {
        0, // nop
        1, // aconst_null
        1, // iconst_m1
        1, // iconst_0
        1, // iconst_1
        1, // iconst_2
        1, // iconst_3
        1, // iconst_4
        1, // iconst_5
        2, // lconst_0
        2, // lconst_1
        1, // fconst_0
        1, // fconst_1
        1, // fconst_2
        2, // dconst_0
        2, // dconst_1
        1, // bipush
        1, // sipush
        1, // ldc
        1, // ldc_w
        2, // ldc2_w
        1, // iload
        2, // lload
        1, // fload
        2, // dload
        1, // aload
        1, // iload_0
        1, // iload_1
        1, // iload_2
        1, // iload_3
        2, // lload_0
        2, // lload_1
        2, // lload_2
        2, // lload_3
        1, // fload_0
        1, // fload_1
        1, // fload_2
        1, // fload_3
        2, // dload_0
        2, // dload_1
        2, // dload_2
        2, // dload_3
        1, // aload_0
        1, // aload_1
        1, // aload_2
        1, // aload_3
        1, // iaload
        2, // laload
        1, // faload
        2, // daload
        1, // aaload
        1, // baload
        1, // caload
        1, // saload
        0, // istore
        0, // lstore
        0, // fstore
        0, // dstore
        0, // astore
        0, // istore_0
        0, // istore_1
        0, // istore_2
        0, // istore_3
        0, // lstore_0
        0, // lstore_1
        0, // lstore_2
        0, // lstore_3
        0, // fstore_0
        0, // fstore_1
        0, // fstore_2
        0, // fstore_3
        0, // dstore_0
        0, // dstore_1
        0, // dstore_2
        0, // dstore_3
        0, // astore_0
        0, // astore_1
        0, // astore_2
        0, // astore_3
        0, // iastore
        0, // lastore
        0, // fastore
        0, // dastore
        0, // aastore
        0, // bastore
        0, // castore
        0, // sastore
        0, // pop
        0, // pop2
        2, // dup
        3, // dup_x1
        4, // dup_x2
        4, // dup2
        5, // dup2_x1
        6, // dup2_x2
        2, // swap
        1, // iadd
        2, // ladd
        1, // fadd
        2, // dadd
        1, // isub
        2, // lsub
        1, // fsub
        2, // dsub
        1, // imul
        2, // lmul
        1, // fmul
        2, // dmul
        1, // idiv
        2, // ldiv
        1, // fdiv
        2, // ddiv
        1, // irem
        2, // lrem
        1, // frem
        2, // drem
        1, // ineg
        2, // lneg
        1, // fneg
        2, // dneg
        1, // ishl
        2, // lshl
        1, // ishr
        2, // lshr
        1, // iushr
        2, // lushr
        1, // iand
        2, // land
        1, // ior
        2, // lor
        1, // ixor
        2, // lxor
        0, // iinc
        2, // i2l
        1, // i2f
        2, // i2d
        1, // l2i
        1, // l2f
        2, // l2d
        1, // f2i
        2, // f2l
        2, // f2d
        1, // d2i
        2, // d2l
        1, // d2f
        1, // i2b
        1, // i2c
        1, // i2s
        1, // lcmp
        1, // fcmpl
        1, // fcmpg
        1, // dcmpl
        1, // dcmpg
        0, // ifeq
        0, // ifne
        0, // iflt
        0, // ifge
        0, // ifgt
        0, // ifle
        0, // ificmpeq
        0, // ificmpne
        0, // ificmplt
        0, // ificmpge
        0, // ificmpgt
        0, // ificmple
        0, // ifacmpeq
        0, // ifacmpne
        0, // goto
        1, // jsr
        0, // ret
        0, // tableswitch
        0, // lookupswitch
        0, // ireturn
        0, // lreturn
        0, // freturn
        0, // dreturn
        0, // areturn
        0, // return
        0, // getstatic
        0, // putstatic
        0, // getfield
        0, // putfield
        0, // invokevirtual
        0, // invokespecial
        0, // invokestatic
        0, // invokeinterface
        0, // invokedynamic
        1, // new
        1, // newarray
        1, // anewarray
        1, // arraylength
        0, // athrow
        1, // checkcast
        1, // instanceof
        0, // monitorenter
        0, // monitorexit
        0, // wide
        1, // multianewarray
        0, // ifnull
        0, // ifnonnull
        0, // goto_w
        1, // jsr_w
      };

  public byte opcode;

  @Override
  public abstract boolean equals(Object o);

  @Override
  public abstract int hashCode();

  /**
   * Returns the canonical opcode of this instruction, i.e. typically the opcode whose extension has
   * been removed.
   */
  public byte canonicalOpcode() {
    return opcode;
  }

  /**
   * Returns the actual opcode of this instruction, i.e. the opcode that is stored in the bytecode.
   */
  public byte actualOpcode() {
    return opcode;
  }

  /**
   * Shrinks this instruction to its shortest possible form.
   *
   * @return this instruction.
   */
  public abstract Instruction shrink();

  /** Writes the Instruction at the given offset in the given code attribute. */
  public final void write(CodeAttribute codeAttribute, int offset) {
    write(codeAttribute.code, offset);
  }

  /** Writes the Instruction at the given offset in the given code array. */
  public void write(byte[] code, int offset) {
    // Write the wide opcode, if necessary.
    if (isWide()) {
      code[offset++] = OP_WIDE;
    }

    // Write the opcode.
    code[offset++] = actualOpcode();

    // Write any additional arguments.
    writeInfo(code, offset);
  }

  /**
   * Returns whether the instruction is wide, i.e. preceded by a wide opcode. With the current
   * specifications, only variable instructions can be wide.
   */
  protected boolean isWide() {
    return false;
  }

  /** Reads the data following the instruction opcode. */
  protected abstract void readInfo(byte[] code, int offset);

  /** Writes data following the instruction opcode. */
  protected abstract void writeInfo(byte[] code, int offset);

  /** Returns the length in bytes of the instruction. */
  public abstract int length(int offset);

  /** Accepts the given visitor. */
  public abstract void accept(
      Clazz clazz,
      Method method,
      CodeAttribute codeAttribute,
      int offset,
      InstructionVisitor instructionVisitor);

  /** Returns a description of the instruction, at the given offset. */
  public String toString(Clazz clazz, int offset) {
    return this.toString(offset);
  }

  /** Returns a description of the instruction, at the given offset. */
  public String toString(int offset) {
    return "[" + offset + "] " + this.toString();
  }

  /** Returns the name of the instruction. */
  public String getName() {
    return NAMES[opcode & 0xff];
  }

  /** Returns whether the instruction may conservatively throw exceptions. */
  public boolean mayThrowExceptions() {
    return MAY_THROW_EXCEPTIONS[opcode & 0xff];
  }

  /** Returns whether a particular instance of an instruction may throw exceptions. */
  public boolean mayInstanceThrowExceptions(Clazz clazz) {
    return this.mayThrowExceptions();
  }

  /**
   * Returns whether the instruction is a Category 2 instruction. This means that it operates on
   * long or double arguments.
   */
  public boolean isCategory2() {
    return IS_CATEGORY2[opcode & 0xff];
  }

  /**
   * Returns the number of entries popped from the stack during the execution of the instruction.
   */
  public int stackPopCount(Clazz clazz) {
    return STACK_POP_COUNTS[opcode & 0xff];
  }

  /**
   * Returns the number of entries pushed onto the stack during the execution of the instruction.
   */
  public int stackPushCount(Clazz clazz) {
    return STACK_PUSH_COUNTS[opcode & 0xff];
  }

  /**
   * Returns the stack entry index from which the specified stack entry is copied by a
   * dup/swap/checkcast instruction, or -1 otherwise. Stack entry indices are counted from the top
   * of the stack.
   *
   * 
    *
  • checkcast: after: 0 (before: 0 ) -- not anymore *
  • dup: after: 0 0 (before: 0 ) *
  • dup_x1: after: 0 1 0 (before: 1 0 ) *
  • dup_x2: after: 0 2 1 0 (before: 2 1 0 ) *
  • dup2: after: 1 0 1 0 (before: 1 0 ) *
  • dup2_x1: after: 1 0 2 1 0 (before: 2 1 0 ) *
  • dup2_x2: after: 1 0 3 2 1 0 (before: 3 2 1 0) *
*/ public int stackEntryIndexBefore(Clazz clazz, int stackEntryIndexAfter) { return -1; } // Small utility methods. protected static int readByte(byte[] code, int offset) { return code[offset] & 0xff; } protected static int readShort(byte[] code, int offset) { return ((code[offset++] & 0xff) << 8) | (code[offset] & 0xff); } protected static int readInt(byte[] code, int offset) { return (code[offset++] << 24) | ((code[offset++] & 0xff) << 16) | ((code[offset++] & 0xff) << 8) | (code[offset] & 0xff); } protected static int readValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readByte(code, offset); case 2: return readShort(code, offset); case 4: return readInt(code, offset); default: throw new IllegalArgumentException("Unsupported value size [" + valueSize + "]"); } } protected static int readSignedByte(byte[] code, int offset) { return code[offset]; } protected static int readSignedShort(byte[] code, int offset) { return (code[offset++] << 8) | (code[offset] & 0xff); } protected static int readSignedValue(byte[] code, int offset, int valueSize) { switch (valueSize) { case 0: return 0; case 1: return readSignedByte(code, offset); case 2: return readSignedShort(code, offset); case 4: return readInt(code, offset); default: throw new IllegalArgumentException("Unsupported value size [" + valueSize + "]"); } } protected static void writeByte(byte[] code, int offset, int value) { if (value > 0xff) { throw new IllegalArgumentException("Unsigned byte value larger than 0xff [" + value + "]"); } code[offset] = (byte) value; } protected static void writeShort(byte[] code, int offset, int value) { if (value > 0xffff) { throw new IllegalArgumentException("Unsigned short value larger than 0xffff [" + value + "]"); } code[offset++] = (byte) (value >> 8); code[offset] = (byte) (value); } protected static void writeInt(byte[] code, int offset, int value) { code[offset++] = (byte) (value >> 24); code[offset++] = (byte) (value >> 16); code[offset++] = (byte) (value >> 8); code[offset] = (byte) (value); } protected static void writeValue(byte[] code, int offset, int value, int valueSize) { switch (valueSize) { case 0: break; case 1: writeByte(code, offset, value); break; case 2: writeShort(code, offset, value); break; case 4: writeInt(code, offset, value); break; default: throw new IllegalArgumentException("Unsupported value size [" + valueSize + "]"); } } protected static void writeSignedByte(byte[] code, int offset, int value) { if ((byte) value != value) { throw new IllegalArgumentException("Signed byte value out of range [" + value + "]"); } code[offset] = (byte) value; } protected static void writeSignedShort(byte[] code, int offset, int value) { if ((short) value != value) { throw new IllegalArgumentException("Signed short value out of range [" + value + "]"); } code[offset++] = (byte) (value >> 8); code[offset] = (byte) (value); } protected static void writeSignedValue(byte[] code, int offset, int value, int valueSize) { switch (valueSize) { case 0: break; case 1: writeSignedByte(code, offset, value); break; case 2: writeSignedShort(code, offset, value); break; case 4: writeInt(code, offset, value); break; default: throw new IllegalArgumentException("Unsupported value size [" + valueSize + "]"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy