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