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;

import java.util.Objects;

/**
 * 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