Home | History | Annotate | Download | only in code
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.cf.code;
     18 
     19 import com.android.dx.rop.cst.Constant;
     20 import com.android.dx.rop.cst.ConstantPool;
     21 import com.android.dx.rop.cst.CstDouble;
     22 import com.android.dx.rop.cst.CstFloat;
     23 import com.android.dx.rop.cst.CstInteger;
     24 import com.android.dx.rop.cst.CstKnownNull;
     25 import com.android.dx.rop.cst.CstLiteralBits;
     26 import com.android.dx.rop.cst.CstLong;
     27 import com.android.dx.rop.cst.CstType;
     28 import com.android.dx.rop.type.Type;
     29 import com.android.dx.util.Bits;
     30 import com.android.dx.util.ByteArray;
     31 import com.android.dx.util.Hex;
     32 import java.util.ArrayList;
     33 
     34 /**
     35  * Bytecode array, which is part of a standard {@code Code} attribute.
     36  */
     37 public final class BytecodeArray {
     38     /** convenient no-op implementation of {@link Visitor} */
     39     public static final Visitor EMPTY_VISITOR = new BaseVisitor();
     40 
     41     /** {@code non-null;} underlying bytes */
     42     private final ByteArray bytes;
     43 
     44     /**
     45      * {@code non-null;} constant pool to use when resolving constant
     46      * pool indices
     47      */
     48     private final ConstantPool pool;
     49 
     50     /**
     51      * Constructs an instance.
     52      *
     53      * @param bytes {@code non-null;} underlying bytes
     54      * @param pool {@code non-null;} constant pool to use when
     55      * resolving constant pool indices
     56      */
     57     public BytecodeArray(ByteArray bytes, ConstantPool pool) {
     58         if (bytes == null) {
     59             throw new NullPointerException("bytes == null");
     60         }
     61 
     62         if (pool == null) {
     63             throw new NullPointerException("pool == null");
     64         }
     65 
     66         this.bytes = bytes;
     67         this.pool = pool;
     68     }
     69 
     70     /**
     71      * Gets the underlying byte array.
     72      *
     73      * @return {@code non-null;} the byte array
     74      */
     75     public ByteArray getBytes() {
     76         return bytes;
     77     }
     78 
     79     /**
     80      * Gets the size of the bytecode array, per se.
     81      *
     82      * @return {@code >= 0;} the length of the bytecode array
     83      */
     84     public int size() {
     85         return bytes.size();
     86     }
     87 
     88     /**
     89      * Gets the total length of this structure in bytes, when included in
     90      * a {@code Code} attribute. The returned value includes the
     91      * array size plus four bytes for {@code code_length}.
     92      *
     93      * @return {@code >= 4;} the total length, in bytes
     94      */
     95     public int byteLength() {
     96         return 4 + bytes.size();
     97     }
     98 
     99     /**
    100      * Parses each instruction in the array, in order.
    101      *
    102      * @param visitor {@code null-ok;} visitor to call back to for
    103      * each instruction
    104      */
    105     public void forEach(Visitor visitor) {
    106         int sz = bytes.size();
    107         int at = 0;
    108 
    109         while (at < sz) {
    110             /*
    111              * Don't record the previous offset here, so that we get to see the
    112              * raw code that initializes the array
    113              */
    114             at += parseInstruction(at, visitor);
    115         }
    116     }
    117 
    118     /**
    119      * Finds the offset to each instruction in the bytecode array. The
    120      * result is a bit set with the offset of each opcode-per-se flipped on.
    121      *
    122      * @see Bits
    123      * @return {@code non-null;} appropriately constructed bit set
    124      */
    125     public int[] getInstructionOffsets() {
    126         int sz = bytes.size();
    127         int[] result = Bits.makeBitSet(sz);
    128         int at = 0;
    129 
    130         while (at < sz) {
    131             Bits.set(result, at, true);
    132             int length = parseInstruction(at, null);
    133             at += length;
    134         }
    135 
    136         return result;
    137     }
    138 
    139     /**
    140      * Processes the given "work set" by repeatedly finding the lowest bit
    141      * in the set, clearing it, and parsing and visiting the instruction at
    142      * the indicated offset (that is, the bit index), repeating until the
    143      * work set is empty. It is expected that the visitor will regularly
    144      * set new bits in the work set during the process.
    145      *
    146      * @param workSet {@code non-null;} the work set to process
    147      * @param visitor {@code non-null;} visitor to call back to for
    148      * each instruction
    149      */
    150     public void processWorkSet(int[] workSet, Visitor visitor) {
    151         if (visitor == null) {
    152             throw new NullPointerException("visitor == null");
    153         }
    154 
    155         for (;;) {
    156             int offset = Bits.findFirst(workSet, 0);
    157             if (offset < 0) {
    158                 break;
    159             }
    160             Bits.clear(workSet, offset);
    161             parseInstruction(offset, visitor);
    162             visitor.setPreviousOffset(offset);
    163         }
    164     }
    165 
    166     /**
    167      * Parses the instruction at the indicated offset. Indicate the
    168      * result by calling the visitor if supplied and by returning the
    169      * number of bytes consumed by the instruction.
    170      *
    171      * <p>In order to simplify further processing, the opcodes passed
    172      * to the visitor are canonicalized, altering the opcode to a more
    173      * universal one and making formerly implicit arguments
    174      * explicit. In particular:</p>
    175      *
    176      * <ul>
    177      * <li>The opcodes to push literal constants of primitive types all become
    178      *   {@code ldc}.
    179      *   E.g., {@code fconst_0}, {@code sipush}, and
    180      *   {@code lconst_0} qualify for this treatment.</li>
    181      * <li>{@code aconst_null} becomes {@code ldc} of a
    182      *   "known null."</li>
    183      * <li>Shorthand local variable accessors become the corresponding
    184      *   longhand. E.g. {@code aload_2} becomes {@code aload}.</li>
    185      * <li>{@code goto_w} and {@code jsr_w} become {@code goto}
    186      *   and {@code jsr} (respectively).</li>
    187      * <li>{@code ldc_w} becomes {@code ldc}.</li>
    188      * <li>{@code tableswitch} becomes {@code lookupswitch}.
    189      * <li>Arithmetic, array, and value-returning ops are collapsed
    190      *   to the {@code int} variant opcode, with the {@code type}
    191      *   argument set to indicate the actual type. E.g.,
    192      *   {@code fadd} becomes {@code iadd}, but
    193      *   {@code type} is passed as {@code Type.FLOAT} in that
    194      *   case. Similarly, {@code areturn} becomes
    195      *   {@code ireturn}. (However, {@code return} remains
    196      *   unchanged.</li>
    197      * <li>Local variable access ops are collapsed to the {@code int}
    198      *   variant opcode, with the {@code type} argument set to indicate
    199      *   the actual type. E.g., {@code aload} becomes {@code iload},
    200      *   but {@code type} is passed as {@code Type.OBJECT} in
    201      *   that case.</li>
    202      * <li>Numeric conversion ops ({@code i2l}, etc.) are left alone
    203      *   to avoid too much confustion, but their {@code type} is
    204      *   the pushed type. E.g., {@code i2b} gets type
    205      *   {@code Type.INT}, and {@code f2d} gets type
    206      *   {@code Type.DOUBLE}. Other unaltered opcodes also get
    207      *   their pushed type. E.g., {@code arraylength} gets type
    208      *   {@code Type.INT}.</li>
    209      * </ul>
    210      *
    211      * @param offset {@code >= 0, < bytes.size();} offset to the start of the
    212      * instruction
    213      * @param visitor {@code null-ok;} visitor to call back to
    214      * @return the length of the instruction, in bytes
    215      */
    216     public int parseInstruction(int offset, Visitor visitor) {
    217         if (visitor == null) {
    218             visitor = EMPTY_VISITOR;
    219         }
    220 
    221         try {
    222             int opcode = bytes.getUnsignedByte(offset);
    223             int info = ByteOps.opInfo(opcode);
    224             int fmt = info & ByteOps.FMT_MASK;
    225 
    226             switch (opcode) {
    227                 case ByteOps.NOP: {
    228                     visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
    229                     return 1;
    230                 }
    231                 case ByteOps.ACONST_NULL: {
    232                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    233                                           CstKnownNull.THE_ONE, 0);
    234                     return 1;
    235                 }
    236                 case ByteOps.ICONST_M1: {
    237                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    238                                           CstInteger.VALUE_M1, -1);
    239                     return 1;
    240                 }
    241                 case ByteOps.ICONST_0: {
    242                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    243                                           CstInteger.VALUE_0, 0);
    244                     return 1;
    245                 }
    246                 case ByteOps.ICONST_1: {
    247                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    248                                           CstInteger.VALUE_1, 1);
    249                     return 1;
    250                 }
    251                 case ByteOps.ICONST_2: {
    252                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    253                                           CstInteger.VALUE_2, 2);
    254                     return 1;
    255                 }
    256                 case ByteOps.ICONST_3: {
    257                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    258                                           CstInteger.VALUE_3, 3);
    259                     return 1;
    260                 }
    261                 case ByteOps.ICONST_4: {
    262                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    263                                           CstInteger.VALUE_4, 4);
    264                     return 1;
    265                 }
    266                 case ByteOps.ICONST_5:  {
    267                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    268                                           CstInteger.VALUE_5, 5);
    269                     return 1;
    270                 }
    271                 case ByteOps.LCONST_0: {
    272                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    273                                           CstLong.VALUE_0, 0);
    274                     return 1;
    275                 }
    276                 case ByteOps.LCONST_1: {
    277                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    278                                           CstLong.VALUE_1, 0);
    279                     return 1;
    280                 }
    281                 case ByteOps.FCONST_0: {
    282                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    283                                           CstFloat.VALUE_0, 0);
    284                     return 1;
    285                 }
    286                 case ByteOps.FCONST_1: {
    287                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    288                                           CstFloat.VALUE_1, 0);
    289                     return 1;
    290                 }
    291                 case ByteOps.FCONST_2:  {
    292                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    293                                           CstFloat.VALUE_2, 0);
    294                     return 1;
    295                 }
    296                 case ByteOps.DCONST_0: {
    297                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    298                                           CstDouble.VALUE_0, 0);
    299                     return 1;
    300                 }
    301                 case ByteOps.DCONST_1: {
    302                     visitor.visitConstant(ByteOps.LDC, offset, 1,
    303                                           CstDouble.VALUE_1, 0);
    304                     return 1;
    305                 }
    306                 case ByteOps.BIPUSH: {
    307                     int value = bytes.getByte(offset + 1);
    308                     visitor.visitConstant(ByteOps.LDC, offset, 2,
    309                                           CstInteger.make(value), value);
    310                     return 2;
    311                 }
    312                 case ByteOps.SIPUSH: {
    313                     int value = bytes.getShort(offset + 1);
    314                     visitor.visitConstant(ByteOps.LDC, offset, 3,
    315                                           CstInteger.make(value), value);
    316                     return 3;
    317                 }
    318                 case ByteOps.LDC: {
    319                     int idx = bytes.getUnsignedByte(offset + 1);
    320                     Constant cst = pool.get(idx);
    321                     int value = (cst instanceof CstInteger) ?
    322                         ((CstInteger) cst).getValue() : 0;
    323                     visitor.visitConstant(ByteOps.LDC, offset, 2, cst, value);
    324                     return 2;
    325                 }
    326                 case ByteOps.LDC_W: {
    327                     int idx = bytes.getUnsignedShort(offset + 1);
    328                     Constant cst = pool.get(idx);
    329                     int value = (cst instanceof CstInteger) ?
    330                         ((CstInteger) cst).getValue() : 0;
    331                     visitor.visitConstant(ByteOps.LDC, offset, 3, cst, value);
    332                     return 3;
    333                 }
    334                 case ByteOps.LDC2_W: {
    335                     int idx = bytes.getUnsignedShort(offset + 1);
    336                     Constant cst = pool.get(idx);
    337                     visitor.visitConstant(ByteOps.LDC2_W, offset, 3, cst, 0);
    338                     return 3;
    339                 }
    340                 case ByteOps.ILOAD: {
    341                     int idx = bytes.getUnsignedByte(offset + 1);
    342                     visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
    343                                        Type.INT, 0);
    344                     return 2;
    345                 }
    346                 case ByteOps.LLOAD: {
    347                     int idx = bytes.getUnsignedByte(offset + 1);
    348                     visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
    349                                        Type.LONG, 0);
    350                     return 2;
    351                 }
    352                 case ByteOps.FLOAD: {
    353                     int idx = bytes.getUnsignedByte(offset + 1);
    354                     visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
    355                                        Type.FLOAT, 0);
    356                     return 2;
    357                 }
    358                 case ByteOps.DLOAD: {
    359                     int idx = bytes.getUnsignedByte(offset + 1);
    360                     visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
    361                                        Type.DOUBLE, 0);
    362                     return 2;
    363                 }
    364                 case ByteOps.ALOAD: {
    365                     int idx = bytes.getUnsignedByte(offset + 1);
    366                     visitor.visitLocal(ByteOps.ILOAD, offset, 2, idx,
    367                                        Type.OBJECT, 0);
    368                     return 2;
    369                 }
    370                 case ByteOps.ILOAD_0:
    371                 case ByteOps.ILOAD_1:
    372                 case ByteOps.ILOAD_2:
    373                 case ByteOps.ILOAD_3: {
    374                     int idx = opcode - ByteOps.ILOAD_0;
    375                     visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
    376                                        Type.INT, 0);
    377                     return 1;
    378                 }
    379                 case ByteOps.LLOAD_0:
    380                 case ByteOps.LLOAD_1:
    381                 case ByteOps.LLOAD_2:
    382                 case ByteOps.LLOAD_3: {
    383                     int idx = opcode - ByteOps.LLOAD_0;
    384                     visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
    385                                        Type.LONG, 0);
    386                     return 1;
    387                 }
    388                 case ByteOps.FLOAD_0:
    389                 case ByteOps.FLOAD_1:
    390                 case ByteOps.FLOAD_2:
    391                 case ByteOps.FLOAD_3: {
    392                     int idx = opcode - ByteOps.FLOAD_0;
    393                     visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
    394                                        Type.FLOAT, 0);
    395                     return 1;
    396                 }
    397                 case ByteOps.DLOAD_0:
    398                 case ByteOps.DLOAD_1:
    399                 case ByteOps.DLOAD_2:
    400                 case ByteOps.DLOAD_3: {
    401                     int idx = opcode - ByteOps.DLOAD_0;
    402                     visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
    403                                        Type.DOUBLE, 0);
    404                     return 1;
    405                 }
    406                 case ByteOps.ALOAD_0:
    407                 case ByteOps.ALOAD_1:
    408                 case ByteOps.ALOAD_2:
    409                 case ByteOps.ALOAD_3: {
    410                     int idx = opcode - ByteOps.ALOAD_0;
    411                     visitor.visitLocal(ByteOps.ILOAD, offset, 1, idx,
    412                                        Type.OBJECT, 0);
    413                     return 1;
    414                 }
    415                 case ByteOps.IALOAD: {
    416                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.INT);
    417                     return 1;
    418                 }
    419                 case ByteOps.LALOAD: {
    420                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.LONG);
    421                     return 1;
    422                 }
    423                 case ByteOps.FALOAD: {
    424                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
    425                                         Type.FLOAT);
    426                     return 1;
    427                 }
    428                 case ByteOps.DALOAD: {
    429                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
    430                                         Type.DOUBLE);
    431                     return 1;
    432                 }
    433                 case ByteOps.AALOAD: {
    434                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
    435                                         Type.OBJECT);
    436                     return 1;
    437                 }
    438                 case ByteOps.BALOAD: {
    439                     /*
    440                      * Note: This is a load from either a byte[] or a
    441                      * boolean[].
    442                      */
    443                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.BYTE);
    444                     return 1;
    445                 }
    446                 case ByteOps.CALOAD: {
    447                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1, Type.CHAR);
    448                     return 1;
    449                 }
    450                 case ByteOps.SALOAD: {
    451                     visitor.visitNoArgs(ByteOps.IALOAD, offset, 1,
    452                                         Type.SHORT);
    453                     return 1;
    454                 }
    455                 case ByteOps.ISTORE: {
    456                     int idx = bytes.getUnsignedByte(offset + 1);
    457                     visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
    458                                        Type.INT, 0);
    459                     return 2;
    460                 }
    461                 case ByteOps.LSTORE: {
    462                     int idx = bytes.getUnsignedByte(offset + 1);
    463                     visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
    464                                        Type.LONG, 0);
    465                     return 2;
    466                 }
    467                 case ByteOps.FSTORE: {
    468                     int idx = bytes.getUnsignedByte(offset + 1);
    469                     visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
    470                                        Type.FLOAT, 0);
    471                     return 2;
    472                 }
    473                 case ByteOps.DSTORE: {
    474                     int idx = bytes.getUnsignedByte(offset + 1);
    475                     visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
    476                                        Type.DOUBLE, 0);
    477                     return 2;
    478                 }
    479                 case ByteOps.ASTORE: {
    480                     int idx = bytes.getUnsignedByte(offset + 1);
    481                     visitor.visitLocal(ByteOps.ISTORE, offset, 2, idx,
    482                                        Type.OBJECT, 0);
    483                     return 2;
    484                 }
    485                 case ByteOps.ISTORE_0:
    486                 case ByteOps.ISTORE_1:
    487                 case ByteOps.ISTORE_2:
    488                 case ByteOps.ISTORE_3: {
    489                     int idx = opcode - ByteOps.ISTORE_0;
    490                     visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
    491                                        Type.INT, 0);
    492                     return 1;
    493                 }
    494                 case ByteOps.LSTORE_0:
    495                 case ByteOps.LSTORE_1:
    496                 case ByteOps.LSTORE_2:
    497                 case ByteOps.LSTORE_3: {
    498                     int idx = opcode - ByteOps.LSTORE_0;
    499                     visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
    500                                        Type.LONG, 0);
    501                     return 1;
    502                 }
    503                 case ByteOps.FSTORE_0:
    504                 case ByteOps.FSTORE_1:
    505                 case ByteOps.FSTORE_2:
    506                 case ByteOps.FSTORE_3: {
    507                     int idx = opcode - ByteOps.FSTORE_0;
    508                     visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
    509                                        Type.FLOAT, 0);
    510                     return 1;
    511                 }
    512                 case ByteOps.DSTORE_0:
    513                 case ByteOps.DSTORE_1:
    514                 case ByteOps.DSTORE_2:
    515                 case ByteOps.DSTORE_3: {
    516                     int idx = opcode - ByteOps.DSTORE_0;
    517                     visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
    518                                        Type.DOUBLE, 0);
    519                     return 1;
    520                 }
    521                 case ByteOps.ASTORE_0:
    522                 case ByteOps.ASTORE_1:
    523                 case ByteOps.ASTORE_2:
    524                 case ByteOps.ASTORE_3: {
    525                     int idx = opcode - ByteOps.ASTORE_0;
    526                     visitor.visitLocal(ByteOps.ISTORE, offset, 1, idx,
    527                                        Type.OBJECT, 0);
    528                     return 1;
    529                 }
    530                 case ByteOps.IASTORE: {
    531                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1, Type.INT);
    532                     return 1;
    533                 }
    534                 case ByteOps.LASTORE: {
    535                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    536                                         Type.LONG);
    537                     return 1;
    538                 }
    539                 case ByteOps.FASTORE: {
    540                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    541                                         Type.FLOAT);
    542                     return 1;
    543                 }
    544                 case ByteOps.DASTORE: {
    545                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    546                                         Type.DOUBLE);
    547                     return 1;
    548                 }
    549                 case ByteOps.AASTORE: {
    550                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    551                                         Type.OBJECT);
    552                     return 1;
    553                 }
    554                 case ByteOps.BASTORE: {
    555                     /*
    556                      * Note: This is a load from either a byte[] or a
    557                      * boolean[].
    558                      */
    559                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    560                                         Type.BYTE);
    561                     return 1;
    562                 }
    563                 case ByteOps.CASTORE: {
    564                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    565                                         Type.CHAR);
    566                     return 1;
    567                 }
    568                 case ByteOps.SASTORE: {
    569                     visitor.visitNoArgs(ByteOps.IASTORE, offset, 1,
    570                                         Type.SHORT);
    571                     return 1;
    572                 }
    573                 case ByteOps.POP:
    574                 case ByteOps.POP2:
    575                 case ByteOps.DUP:
    576                 case ByteOps.DUP_X1:
    577                 case ByteOps.DUP_X2:
    578                 case ByteOps.DUP2:
    579                 case ByteOps.DUP2_X1:
    580                 case ByteOps.DUP2_X2:
    581                 case ByteOps.SWAP: {
    582                     visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
    583                     return 1;
    584                 }
    585                 case ByteOps.IADD:
    586                 case ByteOps.ISUB:
    587                 case ByteOps.IMUL:
    588                 case ByteOps.IDIV:
    589                 case ByteOps.IREM:
    590                 case ByteOps.INEG:
    591                 case ByteOps.ISHL:
    592                 case ByteOps.ISHR:
    593                 case ByteOps.IUSHR:
    594                 case ByteOps.IAND:
    595                 case ByteOps.IOR:
    596                 case ByteOps.IXOR: {
    597                     visitor.visitNoArgs(opcode, offset, 1, Type.INT);
    598                     return 1;
    599                 }
    600                 case ByteOps.LADD:
    601                 case ByteOps.LSUB:
    602                 case ByteOps.LMUL:
    603                 case ByteOps.LDIV:
    604                 case ByteOps.LREM:
    605                 case ByteOps.LNEG:
    606                 case ByteOps.LSHL:
    607                 case ByteOps.LSHR:
    608                 case ByteOps.LUSHR:
    609                 case ByteOps.LAND:
    610                 case ByteOps.LOR:
    611                 case ByteOps.LXOR: {
    612                     /*
    613                      * It's "opcode - 1" because, conveniently enough, all
    614                      * these long ops are one past the int variants.
    615                      */
    616                     visitor.visitNoArgs(opcode - 1, offset, 1, Type.LONG);
    617                     return 1;
    618                 }
    619                 case ByteOps.FADD:
    620                 case ByteOps.FSUB:
    621                 case ByteOps.FMUL:
    622                 case ByteOps.FDIV:
    623                 case ByteOps.FREM:
    624                 case ByteOps.FNEG: {
    625                     /*
    626                      * It's "opcode - 2" because, conveniently enough, all
    627                      * these float ops are two past the int variants.
    628                      */
    629                     visitor.visitNoArgs(opcode - 2, offset, 1, Type.FLOAT);
    630                     return 1;
    631                 }
    632                 case ByteOps.DADD:
    633                 case ByteOps.DSUB:
    634                 case ByteOps.DMUL:
    635                 case ByteOps.DDIV:
    636                 case ByteOps.DREM:
    637                 case ByteOps.DNEG: {
    638                     /*
    639                      * It's "opcode - 3" because, conveniently enough, all
    640                      * these double ops are three past the int variants.
    641                      */
    642                     visitor.visitNoArgs(opcode - 3, offset, 1, Type.DOUBLE);
    643                     return 1;
    644                 }
    645                 case ByteOps.IINC: {
    646                     int idx = bytes.getUnsignedByte(offset + 1);
    647                     int value = bytes.getByte(offset + 2);
    648                     visitor.visitLocal(opcode, offset, 3, idx,
    649                                        Type.INT, value);
    650                     return 3;
    651                 }
    652                 case ByteOps.I2L:
    653                 case ByteOps.F2L:
    654                 case ByteOps.D2L: {
    655                     visitor.visitNoArgs(opcode, offset, 1, Type.LONG);
    656                     return 1;
    657                 }
    658                 case ByteOps.I2F:
    659                 case ByteOps.L2F:
    660                 case ByteOps.D2F: {
    661                     visitor.visitNoArgs(opcode, offset, 1, Type.FLOAT);
    662                     return 1;
    663                 }
    664                 case ByteOps.I2D:
    665                 case ByteOps.L2D:
    666                 case ByteOps.F2D: {
    667                     visitor.visitNoArgs(opcode, offset, 1, Type.DOUBLE);
    668                     return 1;
    669                 }
    670                 case ByteOps.L2I:
    671                 case ByteOps.F2I:
    672                 case ByteOps.D2I:
    673                 case ByteOps.I2B:
    674                 case ByteOps.I2C:
    675                 case ByteOps.I2S:
    676                 case ByteOps.LCMP:
    677                 case ByteOps.FCMPL:
    678                 case ByteOps.FCMPG:
    679                 case ByteOps.DCMPL:
    680                 case ByteOps.DCMPG:
    681                 case ByteOps.ARRAYLENGTH: {
    682                     visitor.visitNoArgs(opcode, offset, 1, Type.INT);
    683                     return 1;
    684                 }
    685                 case ByteOps.IFEQ:
    686                 case ByteOps.IFNE:
    687                 case ByteOps.IFLT:
    688                 case ByteOps.IFGE:
    689                 case ByteOps.IFGT:
    690                 case ByteOps.IFLE:
    691                 case ByteOps.IF_ICMPEQ:
    692                 case ByteOps.IF_ICMPNE:
    693                 case ByteOps.IF_ICMPLT:
    694                 case ByteOps.IF_ICMPGE:
    695                 case ByteOps.IF_ICMPGT:
    696                 case ByteOps.IF_ICMPLE:
    697                 case ByteOps.IF_ACMPEQ:
    698                 case ByteOps.IF_ACMPNE:
    699                 case ByteOps.GOTO:
    700                 case ByteOps.JSR:
    701                 case ByteOps.IFNULL:
    702                 case ByteOps.IFNONNULL: {
    703                     int target = offset + bytes.getShort(offset + 1);
    704                     visitor.visitBranch(opcode, offset, 3, target);
    705                     return 3;
    706                 }
    707                 case ByteOps.RET: {
    708                     int idx = bytes.getUnsignedByte(offset + 1);
    709                     visitor.visitLocal(opcode, offset, 2, idx,
    710                                        Type.RETURN_ADDRESS, 0);
    711                     return 2;
    712                 }
    713                 case ByteOps.TABLESWITCH: {
    714                     return parseTableswitch(offset, visitor);
    715                 }
    716                 case ByteOps.LOOKUPSWITCH: {
    717                     return parseLookupswitch(offset, visitor);
    718                 }
    719                 case ByteOps.IRETURN: {
    720                     visitor.visitNoArgs(ByteOps.IRETURN, offset, 1, Type.INT);
    721                     return 1;
    722                 }
    723                 case ByteOps.LRETURN: {
    724                     visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
    725                                         Type.LONG);
    726                     return 1;
    727                 }
    728                 case ByteOps.FRETURN: {
    729                     visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
    730                                         Type.FLOAT);
    731                     return 1;
    732                 }
    733                 case ByteOps.DRETURN: {
    734                     visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
    735                                         Type.DOUBLE);
    736                     return 1;
    737                 }
    738                 case ByteOps.ARETURN: {
    739                     visitor.visitNoArgs(ByteOps.IRETURN, offset, 1,
    740                                         Type.OBJECT);
    741                     return 1;
    742                 }
    743                 case ByteOps.RETURN:
    744                 case ByteOps.ATHROW:
    745                 case ByteOps.MONITORENTER:
    746                 case ByteOps.MONITOREXIT: {
    747                     visitor.visitNoArgs(opcode, offset, 1, Type.VOID);
    748                     return 1;
    749                 }
    750                 case ByteOps.GETSTATIC:
    751                 case ByteOps.PUTSTATIC:
    752                 case ByteOps.GETFIELD:
    753                 case ByteOps.PUTFIELD:
    754                 case ByteOps.INVOKEVIRTUAL:
    755                 case ByteOps.INVOKESPECIAL:
    756                 case ByteOps.INVOKESTATIC:
    757                 case ByteOps.NEW:
    758                 case ByteOps.ANEWARRAY:
    759                 case ByteOps.CHECKCAST:
    760                 case ByteOps.INSTANCEOF: {
    761                     int idx = bytes.getUnsignedShort(offset + 1);
    762                     Constant cst = pool.get(idx);
    763                     visitor.visitConstant(opcode, offset, 3, cst, 0);
    764                     return 3;
    765                 }
    766                 case ByteOps.INVOKEINTERFACE: {
    767                     int idx = bytes.getUnsignedShort(offset + 1);
    768                     int count = bytes.getUnsignedByte(offset + 3);
    769                     int expectZero = bytes.getUnsignedByte(offset + 4);
    770                     Constant cst = pool.get(idx);
    771                     visitor.visitConstant(opcode, offset, 5, cst,
    772                                           count | (expectZero << 8));
    773                     return 5;
    774                 }
    775                 case ByteOps.NEWARRAY: {
    776                     return parseNewarray(offset, visitor);
    777                 }
    778                 case ByteOps.WIDE: {
    779                     return parseWide(offset, visitor);
    780                 }
    781                 case ByteOps.MULTIANEWARRAY: {
    782                     int idx = bytes.getUnsignedShort(offset + 1);
    783                     int dimensions = bytes.getUnsignedByte(offset + 3);
    784                     Constant cst = pool.get(idx);
    785                     visitor.visitConstant(opcode, offset, 4, cst, dimensions);
    786                     return 4;
    787                 }
    788                 case ByteOps.GOTO_W:
    789                 case ByteOps.JSR_W: {
    790                     int target = offset + bytes.getInt(offset + 1);
    791                     int newop =
    792                         (opcode == ByteOps.GOTO_W) ? ByteOps.GOTO :
    793                         ByteOps.JSR;
    794                     visitor.visitBranch(newop, offset, 5, target);
    795                     return 5;
    796                 }
    797                 default: {
    798                     visitor.visitInvalid(opcode, offset, 1);
    799                     return 1;
    800                 }
    801             }
    802         } catch (SimException ex) {
    803             ex.addContext("...at bytecode offset " + Hex.u4(offset));
    804             throw ex;
    805         } catch (RuntimeException ex) {
    806             SimException se = new SimException(ex);
    807             se.addContext("...at bytecode offset " + Hex.u4(offset));
    808             throw se;
    809         }
    810     }
    811 
    812     /**
    813      * Helper to deal with {@code tableswitch}.
    814      *
    815      * @param offset the offset to the {@code tableswitch} opcode itself
    816      * @param visitor {@code non-null;} visitor to use
    817      * @return instruction length, in bytes
    818      */
    819     private int parseTableswitch(int offset, Visitor visitor) {
    820         int at = (offset + 4) & ~3; // "at" skips the padding.
    821 
    822         // Collect the padding.
    823         int padding = 0;
    824         for (int i = offset + 1; i < at; i++) {
    825             padding = (padding << 8) | bytes.getUnsignedByte(i);
    826         }
    827 
    828         int defaultTarget = offset + bytes.getInt(at);
    829         int low = bytes.getInt(at + 4);
    830         int high = bytes.getInt(at + 8);
    831         int count = high - low + 1;
    832         at += 12;
    833 
    834         if (low > high) {
    835             throw new SimException("low / high inversion");
    836         }
    837 
    838         SwitchList cases = new SwitchList(count);
    839         for (int i = 0; i < count; i++) {
    840             int target = offset + bytes.getInt(at);
    841             at += 4;
    842             cases.add(low + i, target);
    843         }
    844         cases.setDefaultTarget(defaultTarget);
    845         cases.removeSuperfluousDefaults();
    846         cases.setImmutable();
    847 
    848         int length = at - offset;
    849         visitor.visitSwitch(ByteOps.LOOKUPSWITCH, offset, length, cases,
    850                             padding);
    851 
    852         return length;
    853     }
    854 
    855     /**
    856      * Helper to deal with {@code lookupswitch}.
    857      *
    858      * @param offset the offset to the {@code lookupswitch} opcode itself
    859      * @param visitor {@code non-null;} visitor to use
    860      * @return instruction length, in bytes
    861      */
    862     private int parseLookupswitch(int offset, Visitor visitor) {
    863         int at = (offset + 4) & ~3; // "at" skips the padding.
    864 
    865         // Collect the padding.
    866         int padding = 0;
    867         for (int i = offset + 1; i < at; i++) {
    868             padding = (padding << 8) | bytes.getUnsignedByte(i);
    869         }
    870 
    871         int defaultTarget = offset + bytes.getInt(at);
    872         int npairs = bytes.getInt(at + 4);
    873         at += 8;
    874 
    875         SwitchList cases = new SwitchList(npairs);
    876         for (int i = 0; i < npairs; i++) {
    877             int match = bytes.getInt(at);
    878             int target = offset + bytes.getInt(at + 4);
    879             at += 8;
    880             cases.add(match, target);
    881         }
    882         cases.setDefaultTarget(defaultTarget);
    883         cases.removeSuperfluousDefaults();
    884         cases.setImmutable();
    885 
    886         int length = at - offset;
    887         visitor.visitSwitch(ByteOps.LOOKUPSWITCH, offset, length, cases,
    888                             padding);
    889 
    890         return length;
    891     }
    892 
    893     /**
    894      * Helper to deal with {@code newarray}.
    895      *
    896      * @param offset the offset to the {@code newarray} opcode itself
    897      * @param visitor {@code non-null;} visitor to use
    898      * @return instruction length, in bytes
    899      */
    900     private int parseNewarray(int offset, Visitor visitor) {
    901         int value = bytes.getUnsignedByte(offset + 1);
    902         CstType type;
    903         switch (value) {
    904             case ByteOps.NEWARRAY_BOOLEAN: {
    905                 type = CstType.BOOLEAN_ARRAY;
    906                 break;
    907             }
    908             case ByteOps.NEWARRAY_CHAR: {
    909                 type = CstType.CHAR_ARRAY;
    910                 break;
    911             }
    912             case ByteOps.NEWARRAY_DOUBLE: {
    913                 type = CstType.DOUBLE_ARRAY;
    914                 break;
    915             }
    916             case ByteOps.NEWARRAY_FLOAT: {
    917                 type = CstType.FLOAT_ARRAY;
    918                 break;
    919             }
    920             case ByteOps.NEWARRAY_BYTE: {
    921                 type = CstType.BYTE_ARRAY;
    922                 break;
    923             }
    924             case ByteOps.NEWARRAY_SHORT: {
    925                 type = CstType.SHORT_ARRAY;
    926                 break;
    927             }
    928             case ByteOps.NEWARRAY_INT: {
    929                 type = CstType.INT_ARRAY;
    930                 break;
    931             }
    932             case ByteOps.NEWARRAY_LONG: {
    933                 type = CstType.LONG_ARRAY;
    934                 break;
    935             }
    936             default: {
    937                 throw new SimException("bad newarray code " +
    938                         Hex.u1(value));
    939             }
    940         }
    941 
    942         // Revisit the previous bytecode to find out the length of the array
    943         int previousOffset = visitor.getPreviousOffset();
    944         ConstantParserVisitor constantVisitor = new ConstantParserVisitor();
    945         int arrayLength = 0;
    946 
    947         /*
    948          * For visitors that don't record the previous offset, -1 will be
    949          * seen here
    950          */
    951         if (previousOffset >= 0) {
    952             parseInstruction(previousOffset, constantVisitor);
    953             if (constantVisitor.cst instanceof CstInteger &&
    954                     constantVisitor.length + previousOffset == offset) {
    955                 arrayLength = constantVisitor.value;
    956 
    957             }
    958         }
    959 
    960         /*
    961          * Try to match the array initialization idiom. For example, if the
    962          * subsequent code is initializing an int array, we are expecting the
    963          * following pattern repeatedly:
    964          *  dup
    965          *  push index
    966          *  push value
    967          *  *astore
    968          *
    969          * where the index value will be incrimented sequentially from 0 up.
    970          */
    971         int nInit = 0;
    972         int curOffset = offset+2;
    973         int lastOffset = curOffset;
    974         ArrayList<Constant> initVals = new ArrayList<Constant>();
    975 
    976         if (arrayLength != 0) {
    977             while (true) {
    978                 boolean punt = false;
    979 
    980                 // First, check if the next bytecode is dup.
    981                 int nextByte = bytes.getUnsignedByte(curOffset++);
    982                 if (nextByte != ByteOps.DUP)
    983                     break;
    984 
    985                 /*
    986                  * Next, check if the expected array index is pushed to
    987                  * the stack.
    988                  */
    989                 parseInstruction(curOffset, constantVisitor);
    990                 if (constantVisitor.length == 0 ||
    991                         !(constantVisitor.cst instanceof CstInteger) ||
    992                         constantVisitor.value != nInit)
    993                     break;
    994 
    995                 // Next, fetch the init value and record it.
    996                 curOffset += constantVisitor.length;
    997 
    998                 /*
    999                  * Next, find out what kind of constant is pushed onto
   1000                  * the stack.
   1001                  */
   1002                 parseInstruction(curOffset, constantVisitor);
   1003                 if (constantVisitor.length == 0 ||
   1004                         !(constantVisitor.cst instanceof CstLiteralBits))
   1005                     break;
   1006 
   1007                 curOffset += constantVisitor.length;
   1008                 initVals.add(constantVisitor.cst);
   1009 
   1010                 nextByte = bytes.getUnsignedByte(curOffset++);
   1011                 // Now, check if the value is stored to the array properly.
   1012                 switch (value) {
   1013                     case ByteOps.NEWARRAY_BYTE:
   1014                     case ByteOps.NEWARRAY_BOOLEAN: {
   1015                         if (nextByte != ByteOps.BASTORE) {
   1016                             punt = true;
   1017                         }
   1018                         break;
   1019                     }
   1020                     case ByteOps.NEWARRAY_CHAR: {
   1021                         if (nextByte != ByteOps.CASTORE) {
   1022                             punt = true;
   1023                         }
   1024                         break;
   1025                     }
   1026                     case ByteOps.NEWARRAY_DOUBLE: {
   1027                         if (nextByte != ByteOps.DASTORE) {
   1028                             punt = true;
   1029                         }
   1030                         break;
   1031                     }
   1032                     case ByteOps.NEWARRAY_FLOAT: {
   1033                         if (nextByte != ByteOps.FASTORE) {
   1034                             punt = true;
   1035                         }
   1036                         break;
   1037                     }
   1038                     case ByteOps.NEWARRAY_SHORT: {
   1039                         if (nextByte != ByteOps.SASTORE) {
   1040                             punt = true;
   1041                         }
   1042                         break;
   1043                     }
   1044                     case ByteOps.NEWARRAY_INT: {
   1045                         if (nextByte != ByteOps.IASTORE) {
   1046                             punt = true;
   1047                         }
   1048                         break;
   1049                     }
   1050                     case ByteOps.NEWARRAY_LONG: {
   1051                         if (nextByte != ByteOps.LASTORE) {
   1052                             punt = true;
   1053                         }
   1054                         break;
   1055                     }
   1056                     default:
   1057                         punt = true;
   1058                         break;
   1059                 }
   1060                 if (punt) {
   1061                     break;
   1062                 }
   1063                 lastOffset = curOffset;
   1064                 nInit++;
   1065             }
   1066         }
   1067 
   1068         /*
   1069          * For singleton arrays it is still more economical to
   1070          * generate the aput.
   1071          */
   1072         if (nInit < 2 || nInit != arrayLength) {
   1073             visitor.visitNewarray(offset, 2, type, null);
   1074             return 2;
   1075         } else {
   1076             visitor.visitNewarray(offset, lastOffset - offset, type, initVals);
   1077             return lastOffset - offset;
   1078         }
   1079      }
   1080 
   1081 
   1082     /**
   1083      * Helper to deal with {@code wide}.
   1084      *
   1085      * @param offset the offset to the {@code wide} opcode itself
   1086      * @param visitor {@code non-null;} visitor to use
   1087      * @return instruction length, in bytes
   1088      */
   1089     private int parseWide(int offset, Visitor visitor) {
   1090         int opcode = bytes.getUnsignedByte(offset + 1);
   1091         int idx = bytes.getUnsignedShort(offset + 2);
   1092         switch (opcode) {
   1093             case ByteOps.ILOAD: {
   1094                 visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
   1095                                    Type.INT, 0);
   1096                 return 4;
   1097             }
   1098             case ByteOps.LLOAD: {
   1099                 visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
   1100                                    Type.LONG, 0);
   1101                 return 4;
   1102             }
   1103             case ByteOps.FLOAD: {
   1104                 visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
   1105                                    Type.FLOAT, 0);
   1106                 return 4;
   1107             }
   1108             case ByteOps.DLOAD: {
   1109                 visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
   1110                                    Type.DOUBLE, 0);
   1111                 return 4;
   1112             }
   1113             case ByteOps.ALOAD: {
   1114                 visitor.visitLocal(ByteOps.ILOAD, offset, 4, idx,
   1115                                    Type.OBJECT, 0);
   1116                 return 4;
   1117             }
   1118             case ByteOps.ISTORE: {
   1119                 visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
   1120                                    Type.INT, 0);
   1121                 return 4;
   1122             }
   1123             case ByteOps.LSTORE: {
   1124                 visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
   1125                                    Type.LONG, 0);
   1126                 return 4;
   1127             }
   1128             case ByteOps.FSTORE: {
   1129                 visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
   1130                                    Type.FLOAT, 0);
   1131                 return 4;
   1132             }
   1133             case ByteOps.DSTORE: {
   1134                 visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
   1135                                    Type.DOUBLE, 0);
   1136                 return 4;
   1137             }
   1138             case ByteOps.ASTORE: {
   1139                 visitor.visitLocal(ByteOps.ISTORE, offset, 4, idx,
   1140                                    Type.OBJECT, 0);
   1141                 return 4;
   1142             }
   1143             case ByteOps.RET: {
   1144                 visitor.visitLocal(opcode, offset, 4, idx,
   1145                                    Type.RETURN_ADDRESS, 0);
   1146                 return 4;
   1147             }
   1148             case ByteOps.IINC: {
   1149                 int value = bytes.getShort(offset + 4);
   1150                 visitor.visitLocal(opcode, offset, 6, idx,
   1151                                    Type.INT, value);
   1152                 return 6;
   1153             }
   1154             default: {
   1155                 visitor.visitInvalid(ByteOps.WIDE, offset, 1);
   1156                 return 1;
   1157             }
   1158         }
   1159     }
   1160 
   1161     /**
   1162      * Instruction visitor interface.
   1163      */
   1164     public interface Visitor {
   1165         /**
   1166          * Visits an invalid instruction.
   1167          *
   1168          * @param opcode the opcode
   1169          * @param offset offset to the instruction
   1170          * @param length length of the instruction, in bytes
   1171          */
   1172         public void visitInvalid(int opcode, int offset, int length);
   1173 
   1174         /**
   1175          * Visits an instruction which has no inline arguments
   1176          * (implicit or explicit).
   1177          *
   1178          * @param opcode the opcode
   1179          * @param offset offset to the instruction
   1180          * @param length length of the instruction, in bytes
   1181          * @param type {@code non-null;} type the instruction operates on
   1182          */
   1183         public void visitNoArgs(int opcode, int offset, int length,
   1184                 Type type);
   1185 
   1186         /**
   1187          * Visits an instruction which has a local variable index argument.
   1188          *
   1189          * @param opcode the opcode
   1190          * @param offset offset to the instruction
   1191          * @param length length of the instruction, in bytes
   1192          * @param idx the local variable index
   1193          * @param type {@code non-null;} the type of the accessed value
   1194          * @param value additional literal integer argument, if salient (i.e.,
   1195          * for {@code iinc})
   1196          */
   1197         public void visitLocal(int opcode, int offset, int length,
   1198                 int idx, Type type, int value);
   1199 
   1200         /**
   1201          * Visits an instruction which has a (possibly synthetic)
   1202          * constant argument, and possibly also an
   1203          * additional literal integer argument. In the case of
   1204          * {@code multianewarray}, the argument is the count of
   1205          * dimensions. In the case of {@code invokeinterface},
   1206          * the argument is the parameter count or'ed with the
   1207          * should-be-zero value left-shifted by 8. In the case of entries
   1208          * of type {@code int}, the {@code value} field always
   1209          * holds the raw value (for convenience of clients).
   1210          *
   1211          * <p><b>Note:</b> In order to avoid giving it a barely-useful
   1212          * visitor all its own, {@code newarray} also uses this
   1213          * form, passing {@code value} as the array type code and
   1214          * {@code cst} as a {@link CstType} instance
   1215          * corresponding to the array type.</p>
   1216          *
   1217          * @param opcode the opcode
   1218          * @param offset offset to the instruction
   1219          * @param length length of the instruction, in bytes
   1220          * @param cst {@code non-null;} the constant
   1221          * @param value additional literal integer argument, if salient
   1222          * (ignore if not)
   1223          */
   1224         public void visitConstant(int opcode, int offset, int length,
   1225                 Constant cst, int value);
   1226 
   1227         /**
   1228          * Visits an instruction which has a branch target argument.
   1229          *
   1230          * @param opcode the opcode
   1231          * @param offset offset to the instruction
   1232          * @param length length of the instruction, in bytes
   1233          * @param target the absolute (not relative) branch target
   1234          */
   1235         public void visitBranch(int opcode, int offset, int length,
   1236                 int target);
   1237 
   1238         /**
   1239          * Visits a switch instruction.
   1240          *
   1241          * @param opcode the opcode
   1242          * @param offset offset to the instruction
   1243          * @param length length of the instruction, in bytes
   1244          * @param cases {@code non-null;} list of (value, target)
   1245          * pairs, plus the default target
   1246          * @param padding the bytes found in the padding area (if any),
   1247          * packed
   1248          */
   1249         public void visitSwitch(int opcode, int offset, int length,
   1250                 SwitchList cases, int padding);
   1251 
   1252         /**
   1253          * Visits a newarray instruction.
   1254          *
   1255          * @param offset   offset to the instruction
   1256          * @param length   length of the instruction, in bytes
   1257          * @param type {@code non-null;} the type of the array
   1258          * @param initVals {@code non-null;} list of bytecode offsets
   1259          * for init values
   1260          */
   1261         public void visitNewarray(int offset, int length, CstType type,
   1262                 ArrayList<Constant> initVals);
   1263 
   1264         /**
   1265          * Set previous bytecode offset
   1266          * @param offset    offset of the previous fully parsed bytecode
   1267          */
   1268         public void setPreviousOffset(int offset);
   1269 
   1270         /**
   1271          * Get previous bytecode offset
   1272          * @return return the recored offset of the previous bytecode
   1273          */
   1274         public int getPreviousOffset();
   1275     }
   1276 
   1277     /**
   1278      * Base implementation of {@link Visitor}, which has empty method
   1279      * bodies for all methods.
   1280      */
   1281     public static class BaseVisitor implements Visitor {
   1282 
   1283         /** offset of the previously parsed bytecode */
   1284         private int previousOffset;
   1285 
   1286         BaseVisitor() {
   1287             previousOffset = -1;
   1288         }
   1289 
   1290         /** {@inheritDoc} */
   1291         public void visitInvalid(int opcode, int offset, int length) {
   1292             // This space intentionally left blank.
   1293         }
   1294 
   1295         /** {@inheritDoc} */
   1296         public void visitNoArgs(int opcode, int offset, int length,
   1297                 Type type) {
   1298             // This space intentionally left blank.
   1299         }
   1300 
   1301         /** {@inheritDoc} */
   1302         public void visitLocal(int opcode, int offset, int length,
   1303                 int idx, Type type, int value) {
   1304             // This space intentionally left blank.
   1305         }
   1306 
   1307         /** {@inheritDoc} */
   1308         public void visitConstant(int opcode, int offset, int length,
   1309                 Constant cst, int value) {
   1310             // This space intentionally left blank.
   1311         }
   1312 
   1313         /** {@inheritDoc} */
   1314         public void visitBranch(int opcode, int offset, int length,
   1315                 int target) {
   1316             // This space intentionally left blank.
   1317         }
   1318 
   1319         /** {@inheritDoc} */
   1320         public void visitSwitch(int opcode, int offset, int length,
   1321                 SwitchList cases, int padding) {
   1322             // This space intentionally left blank.
   1323         }
   1324 
   1325         /** {@inheritDoc} */
   1326         public void visitNewarray(int offset, int length, CstType type,
   1327                 ArrayList<Constant> initValues) {
   1328             // This space intentionally left blank.
   1329         }
   1330 
   1331         /** {@inheritDoc} */
   1332         public void setPreviousOffset(int offset) {
   1333             previousOffset = offset;
   1334         }
   1335 
   1336         /** {@inheritDoc} */
   1337         public int getPreviousOffset() {
   1338             return previousOffset;
   1339         }
   1340     }
   1341 
   1342     /**
   1343      * Implementation of {@link Visitor}, which just pays attention
   1344      * to constant values.
   1345      */
   1346     class ConstantParserVisitor extends BaseVisitor {
   1347         Constant cst;
   1348         int length;
   1349         int value;
   1350 
   1351         /** Empty constructor */
   1352         ConstantParserVisitor() {
   1353         }
   1354 
   1355         private void clear() {
   1356             length = 0;
   1357         }
   1358 
   1359         /** {@inheritDoc} */
   1360         @Override
   1361         public void visitInvalid(int opcode, int offset, int length) {
   1362             clear();
   1363         }
   1364 
   1365         /** {@inheritDoc} */
   1366         @Override
   1367         public void visitNoArgs(int opcode, int offset, int length,
   1368                 Type type) {
   1369             clear();
   1370         }
   1371 
   1372         /** {@inheritDoc} */
   1373         @Override
   1374         public void visitLocal(int opcode, int offset, int length,
   1375                 int idx, Type type, int value) {
   1376             clear();
   1377         }
   1378 
   1379         /** {@inheritDoc} */
   1380         @Override
   1381         public void visitConstant(int opcode, int offset, int length,
   1382                 Constant cst, int value) {
   1383             this.cst = cst;
   1384             this.length = length;
   1385             this.value = value;
   1386         }
   1387 
   1388         /** {@inheritDoc} */
   1389         @Override
   1390         public void visitBranch(int opcode, int offset, int length,
   1391                 int target) {
   1392             clear();
   1393         }
   1394 
   1395         /** {@inheritDoc} */
   1396         @Override
   1397         public void visitSwitch(int opcode, int offset, int length,
   1398                 SwitchList cases, int padding) {
   1399             clear();
   1400         }
   1401 
   1402         /** {@inheritDoc} */
   1403         @Override
   1404         public void visitNewarray(int offset, int length, CstType type,
   1405                 ArrayList<Constant> initVals) {
   1406             clear();
   1407         }
   1408 
   1409         /** {@inheritDoc} */
   1410         @Override
   1411         public void setPreviousOffset(int offset) {
   1412             // Intentionally left empty
   1413         }
   1414 
   1415         /** {@inheritDoc} */
   1416         @Override
   1417         public int getPreviousOffset() {
   1418             // Intentionally left empty
   1419             return -1;
   1420         }
   1421     }
   1422 }
   1423