Home | History | Annotate | Download | only in bytecode
      1 /*
      2  * Javassist, a Java-bytecode translator toolkit.
      3  * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
      4  *
      5  * The contents of this file are subject to the Mozilla Public License Version
      6  * 1.1 (the "License"); you may not use this file except in compliance with
      7  * the License.  Alternatively, the contents of this file may be used under
      8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
      9  *
     10  * Software distributed under the License is distributed on an "AS IS" basis,
     11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
     12  * for the specific language governing rights and limitations under the
     13  * License.
     14  */
     15 
     16 package javassist.bytecode;
     17 
     18 import java.util.ArrayList;
     19 
     20 /**
     21  * An iterator for editing a code attribute.
     22  *
     23  * <p>If there are multiple <code>CodeIterator</code>s referring to the
     24  * same <code>Code_attribute</code>, then inserting a gap by one
     25  * <code>CodeIterator</code> will break the other
     26  * <code>CodeIterator</code>.
     27  *
     28  * <p>This iterator does not provide <code>remove()</code>.
     29  * If a piece of code in a <code>Code_attribute</code> is unnecessary,
     30  * it should be overwritten with <code>NOP</code>.
     31  *
     32  * @see CodeAttribute#iterator()
     33  */
     34 public class CodeIterator implements Opcode {
     35     protected CodeAttribute codeAttr;
     36     protected byte[] bytecode;
     37     protected int endPos;
     38     protected int currentPos;
     39     protected int mark;
     40 
     41     protected CodeIterator(CodeAttribute ca) {
     42         codeAttr = ca;
     43         bytecode = ca.getCode();
     44         begin();
     45     }
     46 
     47     /**
     48      * Moves to the first instruction.
     49      */
     50     public void begin() {
     51         currentPos = mark = 0;
     52         endPos = getCodeLength();
     53     }
     54 
     55     /**
     56      * Moves to the given index.
     57      *
     58      * <p>The index of the next instruction is set to the given index.
     59      * The successive call to <code>next()</code>
     60      * returns the index that has been given to <code>move()</code>.
     61      *
     62      * <p>Note that the index is into the byte array returned by
     63      * <code>get().getCode()</code>.
     64      *
     65      * @see CodeAttribute#getCode()
     66      */
     67     public void move(int index) {
     68         currentPos = index;
     69     }
     70 
     71     /**
     72      * Sets a mark to the bytecode at the given index.
     73      * The mark can be used to track the position of that bytecode
     74      * when code blocks are inserted.
     75      * If a code block is inclusively inserted at the position of the
     76      * bytecode, the mark is set to the inserted code block.
     77      *
     78      * @see #getMark()
     79      * @since 3.11
     80      */
     81     public void setMark(int index) {
     82         mark = index;
     83     }
     84 
     85     /**
     86      * Gets the index of the position of the mark set by
     87      * <code>setMark</code>.
     88      *
     89      * @return the index of the position.
     90      * @see #setMark(int)
     91      * @since 3.11
     92      */
     93     public int getMark() { return mark; }
     94 
     95     /**
     96      * Returns a Code attribute read with this iterator.
     97      */
     98     public CodeAttribute get() {
     99         return codeAttr;
    100     }
    101 
    102     /**
    103      * Returns <code>code_length</code> of <code>Code_attribute</code>.
    104      */
    105     public int getCodeLength() {
    106         return bytecode.length;
    107     }
    108 
    109     /**
    110      * Returns the unsigned 8bit value at the given index.
    111      */
    112     public int byteAt(int index) { return bytecode[index] & 0xff; }
    113 
    114     /**
    115      * Writes an 8bit value at the given index.
    116      */
    117     public void writeByte(int value, int index) {
    118         bytecode[index] = (byte)value;
    119     }
    120 
    121     /**
    122      * Returns the unsigned 16bit value at the given index.
    123      */
    124     public int u16bitAt(int index) {
    125         return ByteArray.readU16bit(bytecode, index);
    126     }
    127 
    128     /**
    129      * Returns the signed 16bit value at the given index.
    130      */
    131     public int s16bitAt(int index) {
    132         return ByteArray.readS16bit(bytecode, index);
    133     }
    134 
    135     /**
    136      * Writes a 16 bit integer at the index.
    137      */
    138     public void write16bit(int value, int index) {
    139         ByteArray.write16bit(value, bytecode, index);
    140     }
    141 
    142     /**
    143      * Returns the signed 32bit value at the given index.
    144      */
    145     public int s32bitAt(int index) {
    146         return ByteArray.read32bit(bytecode, index);
    147     }
    148 
    149     /**
    150      * Writes a 32bit integer at the index.
    151      */
    152     public void write32bit(int value, int index) {
    153         ByteArray.write32bit(value, bytecode, index);
    154     }
    155 
    156     /**
    157      * Writes a byte array at the index.
    158      *
    159      * @param code	may be a zero-length array.
    160      */
    161     public void write(byte[] code, int index) {
    162         int len = code.length;
    163         for (int j = 0; j < len; ++j)
    164             bytecode[index++] = code[j];
    165     }
    166 
    167     /**
    168      * Returns true if there is more instructions.
    169      */
    170     public boolean hasNext() { return currentPos < endPos; }
    171 
    172     /**
    173      * Returns the index of the next instruction
    174      * (not the operand following the current opcode).
    175      *
    176      * <p>Note that the index is into the byte array returned by
    177      * <code>get().getCode()</code>.
    178      *
    179      * @see CodeAttribute#getCode()
    180      * @see CodeIterator#byteAt(int)
    181      */
    182     public int next() throws BadBytecode {
    183         int pos = currentPos;
    184         currentPos = nextOpcode(bytecode, pos);
    185         return pos;
    186     }
    187 
    188     /**
    189      * Obtains the value that the next call
    190      * to <code>next()</code> will return.
    191      *
    192      * <p>This method is side-effects free.
    193      * Successive calls to <code>lookAhead()</code> return the
    194      * same value until <code>next()</code> is called.
    195      */
    196     public int lookAhead() {
    197         return currentPos;
    198     }
    199 
    200     /**
    201      * Moves to the instruction for
    202      * either <code>super()</code> or <code>this()</code>.
    203      *
    204      * <p>This method skips all the instructions for computing arguments
    205      * to <code>super()</code> or <code>this()</code>, which should be
    206      * placed at the beginning of a constructor body.
    207      *
    208      * <p>This method returns the index of INVOKESPECIAL instruction
    209      * executing <code>super()</code> or <code>this()</code>.
    210      * A successive call to <code>next()</code> returns the
    211      * index of the next instruction following that INVOKESPECIAL.
    212      *
    213      * <p>This method works only for a constructor.
    214      *
    215      * @return  the index of the INVOKESPECIAL instruction, or -1
    216      *          if a constructor invocation is not found.
    217      */
    218     public int skipConstructor() throws BadBytecode {
    219         return skipSuperConstructor0(-1);
    220     }
    221 
    222     /**
    223      * Moves to the instruction for <code>super()</code>.
    224      *
    225      * <p>This method skips all the instructions for computing arguments to
    226      * <code>super()</code>, which should be
    227      * placed at the beginning of a constructor body.
    228      *
    229      * <p>This method returns the index of INVOKESPECIAL instruction
    230      * executing <code>super()</code>.
    231      * A successive call to <code>next()</code> returns the
    232      * index of the next instruction following that INVOKESPECIAL.
    233      *
    234      * <p>This method works only for a constructor.
    235      *
    236      * @return  the index of the INVOKESPECIAL instruction, or -1
    237      *          if a super constructor invocation is not found
    238      *          but <code>this()</code> is found.
    239      */
    240     public int skipSuperConstructor() throws BadBytecode {
    241         return skipSuperConstructor0(0);
    242     }
    243 
    244     /**
    245      * Moves to the instruction for <code>this()</code>.
    246      *
    247      * <p>This method skips all the instructions for computing arguments to
    248      * <code>this()</code>, which should be
    249      * placed at the beginning of a constructor body.
    250      *
    251      * <p>This method returns the index of INVOKESPECIAL instruction
    252      * executing <code>this()</code>.
    253      * A successive call to <code>next()</code> returns the
    254      * index of the next instruction following that INVOKESPECIAL.
    255      *
    256      * <p>This method works only for a constructor.
    257      *
    258      * @return  the index of the INVOKESPECIAL instruction, or -1
    259      *          if a explicit constructor invocation is not found
    260      *          but <code>super()</code> is found.
    261      */
    262     public int skipThisConstructor() throws BadBytecode {
    263         return skipSuperConstructor0(1);
    264     }
    265 
    266     /* skipSuper        1: this(), 0: super(), -1: both.
    267      */
    268     private int skipSuperConstructor0(int skipThis) throws BadBytecode {
    269         begin();
    270         ConstPool cp = codeAttr.getConstPool();
    271         String thisClassName = codeAttr.getDeclaringClass();
    272         int nested = 0;
    273         while (hasNext()) {
    274             int index = next();
    275             int c = byteAt(index);
    276             if (c == NEW)
    277                 ++nested;
    278             else if (c == INVOKESPECIAL) {
    279                 int mref = ByteArray.readU16bit(bytecode, index + 1);
    280                 if (cp.getMethodrefName(mref).equals(MethodInfo.nameInit))
    281                     if (--nested < 0) {
    282                         if (skipThis < 0)
    283                             return index;
    284 
    285                         String cname = cp.getMethodrefClassName(mref);
    286                         if (cname.equals(thisClassName) == (skipThis > 0))
    287                             return index;
    288                         else
    289                             break;
    290                     }
    291             }
    292         }
    293 
    294         begin();
    295         return -1;
    296     }
    297 
    298     /**
    299      * Inserts the given bytecode sequence
    300      * before the next instruction that would be returned by
    301      * <code>next()</code> (not before the instruction returned
    302      * by the last call to <code>next()</code>).
    303      * Branch offsets and the exception table are also updated.
    304      *
    305      * <p>If the next instruction is at the beginning of a block statement,
    306      * then the bytecode is inserted within that block.
    307      *
    308      * <p>An extra gap may be inserted at the end of the inserted
    309      * bytecode sequence for adjusting alignment if the code attribute
    310      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    311      *
    312      * @param code      inserted bytecode sequence.
    313      * @return          the index indicating the first byte of the
    314      *                  inserted byte sequence.
    315      */
    316     public int insert(byte[] code)
    317         throws BadBytecode
    318     {
    319         return insert0(currentPos, code, false);
    320     }
    321 
    322     /**
    323      * Inserts the given bytecode sequence
    324      * before the instruction at the given index <code>pos</code>.
    325      * Branch offsets and the exception table are also updated.
    326      *
    327      * <p>If the instruction at the given index is at the beginning
    328      * of a block statement,
    329      * then the bytecode is inserted within that block.
    330      *
    331      * <p>An extra gap may be inserted at the end of the inserted
    332      * bytecode sequence for adjusting alignment if the code attribute
    333      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    334      *
    335      * <p>The index at which the byte sequence is actually inserted
    336      * might be different from pos since some other bytes might be
    337      * inserted at other positions (e.g. to change <code>GOTO</code>
    338      * to <code>GOTO_W</code>).
    339      *
    340      * @param pos       the index at which a byte sequence is inserted.
    341      * @param code      inserted bytecode sequence.
    342      */
    343     public void insert(int pos, byte[] code) throws BadBytecode {
    344         insert0(pos, code, false);
    345     }
    346 
    347     /**
    348      * Inserts the given bytecode sequence
    349      * before the instruction at the given index <code>pos</code>.
    350      * Branch offsets and the exception table are also updated.
    351      *
    352      * <p>If the instruction at the given index is at the beginning
    353      * of a block statement,
    354      * then the bytecode is inserted within that block.
    355      *
    356      * <p>An extra gap may be inserted at the end of the inserted
    357      * bytecode sequence for adjusting alignment if the code attribute
    358      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    359      *
    360      * @param pos       the index at which a byte sequence is inserted.
    361      * @param code      inserted bytecode sequence.
    362      * @return          the index indicating the first byte of the
    363      *                  inserted byte sequence, which might be
    364      *                  different from pos.
    365      * @since 3.11
    366      */
    367     public int insertAt(int pos, byte[] code) throws BadBytecode {
    368         return insert0(pos, code, false);
    369     }
    370 
    371     /**
    372      * Inserts the given bytecode sequence exclusively
    373      * before the next instruction that would be returned by
    374      * <code>next()</code> (not before the instruction returned
    375      * by tha last call to <code>next()</code>).
    376      * Branch offsets and the exception table are also updated.
    377      *
    378      * <p>If the next instruction is at the beginning of a block statement,
    379      * then the bytecode is excluded from that block.
    380      *
    381      * <p>An extra gap may be inserted at the end of the inserted
    382      * bytecode sequence for adjusting alignment if the code attribute
    383      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    384      *
    385      * @param code      inserted bytecode sequence.
    386      * @return          the index indicating the first byte of the
    387      *                  inserted byte sequence.
    388      */
    389     public int insertEx(byte[] code)
    390         throws BadBytecode
    391     {
    392         return insert0(currentPos, code, true);
    393     }
    394 
    395     /**
    396      * Inserts the given bytecode sequence exclusively
    397      * before the instruction at the given index <code>pos</code>.
    398      * Branch offsets and the exception table are also updated.
    399      *
    400      * <p>If the instruction at the given index is at the beginning
    401      * of a block statement,
    402      * then the bytecode is excluded from that block.
    403      *
    404      * <p>An extra gap may be inserted at the end of the inserted
    405      * bytecode sequence for adjusting alignment if the code attribute
    406      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    407      *
    408      * <p>The index at which the byte sequence is actually inserted
    409      * might be different from pos since some other bytes might be
    410      * inserted at other positions (e.g. to change <code>GOTO</code>
    411      * to <code>GOTO_W</code>).
    412      *
    413      * @param pos       the index at which a byte sequence is inserted.
    414      * @param code      inserted bytecode sequence.
    415      */
    416     public void insertEx(int pos, byte[] code) throws BadBytecode {
    417         insert0(pos, code, true);
    418     }
    419 
    420     /**
    421      * Inserts the given bytecode sequence exclusively
    422      * before the instruction at the given index <code>pos</code>.
    423      * Branch offsets and the exception table are also updated.
    424      *
    425      * <p>If the instruction at the given index is at the beginning
    426      * of a block statement,
    427      * then the bytecode is excluded from that block.
    428      *
    429      * <p>An extra gap may be inserted at the end of the inserted
    430      * bytecode sequence for adjusting alignment if the code attribute
    431      * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>.
    432      *
    433      * @param pos       the index at which a byte sequence is inserted.
    434      * @param code      inserted bytecode sequence.
    435      * @return          the index indicating the first byte of the
    436      *                  inserted byte sequence, which might be
    437      *                  different from pos.
    438      * @since 3.11
    439      */
    440     public int insertExAt(int pos, byte[] code) throws BadBytecode {
    441         return insert0(pos, code, true);
    442     }
    443 
    444     /**
    445      * @return          the index indicating the first byte of the
    446      *                  inserted byte sequence.
    447      */
    448     private int insert0(int pos, byte[] code, boolean exclusive)
    449         throws BadBytecode
    450     {
    451         int len = code.length;
    452         if (len <= 0)
    453             return pos;
    454 
    455         // currentPos will change.
    456         pos = insertGapAt(pos, len, exclusive).position;
    457 
    458         int p = pos;
    459         for (int j = 0; j < len; ++j)
    460             bytecode[p++] = code[j];
    461 
    462         return pos;
    463     }
    464 
    465     /**
    466      * Inserts a gap
    467      * before the next instruction that would be returned by
    468      * <code>next()</code> (not before the instruction returned
    469      * by the last call to <code>next()</code>).
    470      * Branch offsets and the exception table are also updated.
    471      * The inserted gap is filled with NOP.  The gap length may be
    472      * extended to a multiple of 4.
    473      *
    474      * <p>If the next instruction is at the beginning of a block statement,
    475      * then the gap is inserted within that block.
    476      *
    477      * @param length            gap length
    478      * @return  the index indicating the first byte of the inserted gap.
    479      */
    480     public int insertGap(int length) throws BadBytecode {
    481         return insertGapAt(currentPos, length, false).position;
    482     }
    483 
    484     /**
    485      * Inserts a gap in front of the instruction at the given
    486      * index <code>pos</code>.
    487      * Branch offsets and the exception table are also updated.
    488      * The inserted gap is filled with NOP.  The gap length may be
    489      * extended to a multiple of 4.
    490      *
    491      * <p>If the instruction at the given index is at the beginning
    492      * of a block statement,
    493      * then the gap is inserted within that block.
    494      *
    495      * @param pos               the index at which a gap is inserted.
    496      * @param length            gap length.
    497      * @return the length of the inserted gap.
    498      *          It might be bigger than <code>length</code>.
    499      */
    500     public int insertGap(int pos, int length) throws BadBytecode {
    501         return insertGapAt(pos, length, false).length;
    502     }
    503 
    504     /**
    505      * Inserts an exclusive gap
    506      * before the next instruction that would be returned by
    507      * <code>next()</code> (not before the instruction returned
    508      * by the last call to <code>next()</code>).
    509      * Branch offsets and the exception table are also updated.
    510      * The inserted gap is filled with NOP.  The gap length may be
    511      * extended to a multiple of 4.
    512      *
    513      * <p>If the next instruction is at the beginning of a block statement,
    514      * then the gap is excluded from that block.
    515      *
    516      * @param length            gap length
    517      * @return  the index indicating the first byte of the inserted gap.
    518      */
    519     public int insertExGap(int length) throws BadBytecode {
    520         return insertGapAt(currentPos, length, true).position;
    521     }
    522 
    523     /**
    524      * Inserts an exclusive gap in front of the instruction at the given
    525      * index <code>pos</code>.
    526      * Branch offsets and the exception table are also updated.
    527      * The inserted gap is filled with NOP.  The gap length may be
    528      * extended to a multiple of 4.
    529      *
    530      * <p>If the instruction at the given index is at the beginning
    531      * of a block statement,
    532      * then the gap is excluded from that block.
    533      *
    534      * @param pos               the index at which a gap is inserted.
    535      * @param length            gap length.
    536      * @return the length of the inserted gap.
    537      *          It might be bigger than <code>length</code>.
    538      */
    539     public int insertExGap(int pos, int length) throws BadBytecode {
    540         return insertGapAt(pos, length, true).length;
    541     }
    542 
    543     /**
    544      * An inserted gap.
    545      *
    546      * @since 3.11
    547      */
    548     public static class Gap {
    549         /**
    550          * The position of the gap.
    551          */
    552         public int position;
    553 
    554         /**
    555          * The length of the gap.
    556          */
    557         public int length;
    558     }
    559 
    560     /**
    561      * Inserts an inclusive or exclusive gap in front of the instruction
    562      * at the given index <code>pos</code>.
    563      * Branch offsets and the exception table in the method body
    564      * are also updated.  The inserted gap is filled with NOP.
    565      * The gap length may be extended to a multiple of 4.
    566      *
    567      * <p>Suppose that the instruction at the given index is at the
    568      * beginning of a block statement.  If the gap is inclusive,
    569      * then it is included within that block.  If the gap is exclusive,
    570      * then it is excluded from that block.
    571      *
    572      * <p>The index at which the gap is actually inserted
    573      * might be different from pos since some other bytes might be
    574      * inserted at other positions (e.g. to change <code>GOTO</code>
    575      * to <code>GOTO_W</code>).  The index is available from the <code>Gap</code>
    576      * object returned by this method.
    577      *
    578      * <p>Suppose that the gap is inserted at the position of
    579      * the next instruction that would be returned by
    580      * <code>next()</code> (not the last instruction returned
    581      * by the last call to <code>next()</code>).  The next
    582      * instruction returned by <code>next()</code> after the gap is
    583      * inserted is still the same instruction.  It is not <code>NOP</code>
    584      * at the first byte of the inserted gap.
    585      *
    586      * @param pos               the index at which a gap is inserted.
    587      * @param length            gap length.
    588      * @param exclusive         true if exclusive, otherwise false.
    589      * @return the position and the length of the inserted gap.
    590      * @since 3.11
    591      */
    592     public Gap insertGapAt(int pos, int length, boolean exclusive)
    593         throws BadBytecode
    594     {
    595         /**
    596          * cursorPos indicates the next bytecode whichever exclusive is
    597          * true or false.
    598          */
    599         Gap gap = new Gap();
    600         if (length <= 0) {
    601             gap.position = pos;
    602             gap.length = 0;
    603             return gap;
    604         }
    605 
    606         byte[] c;
    607         int length2;
    608         if (bytecode.length + length > Short.MAX_VALUE) {
    609             // currentPos might change after calling insertGapCore0w().
    610             c = insertGapCore0w(bytecode, pos, length, exclusive,
    611                                 get().getExceptionTable(), codeAttr, gap);
    612             pos = gap.position;
    613             length2 = length; // == gap.length
    614         }
    615         else {
    616             int cur = currentPos;
    617             c = insertGapCore0(bytecode, pos, length, exclusive,
    618                                       get().getExceptionTable(), codeAttr);
    619             // insertGapCore0() never changes pos.
    620             length2 = c.length - bytecode.length;
    621             gap.position = pos;
    622             gap.length = length2;
    623             if (cur >= pos)
    624                 currentPos = cur + length2;
    625 
    626             if (mark > pos || (mark == pos && exclusive))
    627                 mark += length2;
    628         }
    629 
    630         codeAttr.setCode(c);
    631         bytecode = c;
    632         endPos = getCodeLength();
    633         updateCursors(pos, length2);
    634         return gap;
    635     }
    636 
    637     /**
    638      * Is called when a gap is inserted.  The default implementation is empty.
    639      * A subclass can override this method so that cursors will be updated.
    640      *
    641      * @param pos           the position where a gap is inserted.
    642      * @param length        the length of the gap.
    643      */
    644     protected void updateCursors(int pos, int length) {
    645         // empty
    646     }
    647 
    648     /**
    649      * Copies and inserts the entries in the given exception table
    650      * at the beginning of the exception table in the code attribute
    651      * edited by this object.
    652      *
    653      * @param offset    the value added to the code positions included
    654      *                          in the entries.
    655      */
    656     public void insert(ExceptionTable et, int offset) {
    657         codeAttr.getExceptionTable().add(0, et, offset);
    658     }
    659 
    660     /**
    661      * Appends the given bytecode sequence at the end.
    662      *
    663      * @param code      the bytecode appended.
    664      * @return  the position of the first byte of the appended bytecode.
    665      */
    666     public int append(byte[] code) {
    667         int size = getCodeLength();
    668         int len = code.length;
    669         if (len <= 0)
    670             return size;
    671 
    672         appendGap(len);
    673         byte[] dest = bytecode;
    674         for (int i = 0; i < len; ++i)
    675             dest[i + size] = code[i];
    676 
    677         return size;
    678     }
    679 
    680     /**
    681      * Appends a gap at the end of the bytecode sequence.
    682      *
    683      * @param gapLength            gap length
    684      */
    685     public void appendGap(int gapLength) {
    686         byte[] code = bytecode;
    687         int codeLength = code.length;
    688         byte[] newcode = new byte[codeLength + gapLength];
    689 
    690         int i;
    691         for (i = 0; i < codeLength; ++i)
    692             newcode[i] = code[i];
    693 
    694         for (i = codeLength; i < codeLength + gapLength; ++i)
    695             newcode[i] = NOP;
    696 
    697         codeAttr.setCode(newcode);
    698         bytecode = newcode;
    699         endPos = getCodeLength();
    700     }
    701 
    702     /**
    703      * Copies and appends the entries in the given exception table
    704      * at the end of the exception table in the code attribute
    705      * edited by this object.
    706      *
    707      * @param offset    the value added to the code positions included
    708      *                          in the entries.
    709      */
    710     public void append(ExceptionTable et, int offset) {
    711         ExceptionTable table = codeAttr.getExceptionTable();
    712         table.add(table.size(), et, offset);
    713     }
    714 
    715     /* opcodeLegth is used for implementing nextOpcode().
    716      */
    717     private static final int opcodeLength[] = {
    718         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3,
    719         3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    720         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1,
    721         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    722         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    723         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    724         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1,
    725         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3,
    726         3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3,
    727         3, 3, 3, 3, 3, 5, 0, 3, 2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3,
    728         5, 5
    729     };
    730     // 0 .. UNUSED (186), LOOKUPSWITCH, TABLESWITCH, WIDE
    731 
    732     /**
    733      * Calculates the index of the next opcode.
    734      */
    735     static int nextOpcode(byte[] code, int index)
    736         throws BadBytecode
    737     {
    738         int opcode;
    739         try {
    740             opcode = code[index] & 0xff;
    741         }
    742         catch (IndexOutOfBoundsException e) {
    743             throw new BadBytecode("invalid opcode address");
    744         }
    745 
    746         try {
    747             int len = opcodeLength[opcode];
    748             if (len > 0)
    749                 return index + len;
    750             else if (opcode == WIDE)
    751                 if (code[index + 1] == (byte)IINC)      // WIDE IINC
    752                     return index + 6;
    753                 else
    754                     return index + 4;           // WIDE ...
    755             else {
    756                 int index2 = (index & ~3) + 8;
    757                 if (opcode == LOOKUPSWITCH) {
    758                     int npairs = ByteArray.read32bit(code, index2);
    759                     return index2 + npairs * 8 + 4;
    760                 }
    761                 else if (opcode == TABLESWITCH) {
    762                     int low = ByteArray.read32bit(code, index2);
    763                     int high = ByteArray.read32bit(code, index2 + 4);
    764                     return index2 + (high - low + 1) * 4 + 8;
    765                 }
    766                 // else
    767                 //     throw new BadBytecode(opcode);
    768             }
    769         }
    770         catch (IndexOutOfBoundsException e) {
    771         }
    772 
    773         // opcode is UNUSED or an IndexOutOfBoundsException was thrown.
    774         throw new BadBytecode(opcode);
    775     }
    776 
    777     // methods for implementing insertGap().
    778 
    779     static class AlignmentException extends Exception {}
    780 
    781     /**
    782      * insertGapCore0() inserts a gap (some NOPs).
    783      * It cannot handle a long code sequence more than 32K.  All branch offsets must be
    784      * signed 16bits.
    785      *
    786      * If "where" is the beginning of a block statement and exclusive is false,
    787      * then the inserted gap is also included in the block statement.
    788      * "where" must indicate the first byte of an opcode.
    789      * The inserted gap is filled with NOP.  gapLength may be extended to
    790      * a multiple of 4.
    791      *
    792      * This method was also called from CodeAttribute.LdcEntry.doit().
    793      *
    794      * @param where       It must indicate the first byte of an opcode.
    795      */
    796     static byte[] insertGapCore0(byte[] code, int where, int gapLength,
    797                                  boolean exclusive, ExceptionTable etable, CodeAttribute ca)
    798         throws BadBytecode
    799     {
    800         if (gapLength <= 0)
    801             return code;
    802 
    803         try {
    804             return insertGapCore1(code, where, gapLength, exclusive, etable, ca);
    805         }
    806         catch (AlignmentException e) {
    807             try {
    808                 return insertGapCore1(code, where, (gapLength + 3) & ~3,
    809                                   exclusive, etable, ca);
    810             }
    811             catch (AlignmentException e2) {
    812                 throw new RuntimeException("fatal error?");
    813             }
    814         }
    815     }
    816 
    817     private static byte[] insertGapCore1(byte[] code, int where, int gapLength,
    818                                          boolean exclusive, ExceptionTable etable,
    819                                          CodeAttribute ca)
    820         throws BadBytecode, AlignmentException
    821     {
    822         int codeLength = code.length;
    823         byte[] newcode = new byte[codeLength + gapLength];
    824         insertGap2(code, where, gapLength, codeLength, newcode, exclusive);
    825         etable.shiftPc(where, gapLength, exclusive);
    826         LineNumberAttribute na
    827             = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
    828         if (na != null)
    829             na.shiftPc(where, gapLength, exclusive);
    830 
    831         LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute(
    832                                                 LocalVariableAttribute.tag);
    833         if (va != null)
    834             va.shiftPc(where, gapLength, exclusive);
    835 
    836         LocalVariableAttribute vta
    837             = (LocalVariableAttribute)ca.getAttribute(
    838                                               LocalVariableAttribute.typeTag);
    839         if (vta != null)
    840             vta.shiftPc(where, gapLength, exclusive);
    841 
    842         StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag);
    843         if (smt != null)
    844             smt.shiftPc(where, gapLength, exclusive);
    845 
    846         StackMap sm = (StackMap)ca.getAttribute(StackMap.tag);
    847         if (sm != null)
    848             sm.shiftPc(where, gapLength, exclusive);
    849 
    850         return newcode;
    851     }
    852 
    853     private static void insertGap2(byte[] code, int where, int gapLength,
    854                         int endPos, byte[] newcode, boolean exclusive)
    855         throws BadBytecode, AlignmentException
    856     {
    857         int nextPos;
    858         int i = 0;
    859         int j = 0;
    860         for (; i < endPos; i = nextPos) {
    861             if (i == where) {
    862                 int j2 = j + gapLength;
    863                 while (j < j2)
    864                     newcode[j++] = NOP;
    865             }
    866 
    867             nextPos = nextOpcode(code, i);
    868             int inst = code[i] & 0xff;
    869             // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr
    870             if ((153 <= inst && inst <= 168)
    871                 || inst == IFNULL || inst == IFNONNULL) {
    872                 /* 2bytes *signed* offset */
    873                 int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff);
    874                 offset = newOffset(i, offset, where, gapLength, exclusive);
    875                 newcode[j] = code[i];
    876                 ByteArray.write16bit(offset, newcode, j + 1);
    877                 j += 3;
    878             }
    879             else if (inst == GOTO_W || inst == JSR_W) {
    880                 /* 4bytes offset */
    881                 int offset = ByteArray.read32bit(code, i + 1);
    882                 offset = newOffset(i, offset, where, gapLength, exclusive);
    883                 newcode[j++] = code[i];
    884                 ByteArray.write32bit(offset, newcode, j);
    885                 j += 4;
    886             }
    887             else if (inst == TABLESWITCH) {
    888                 if (i != j && (gapLength & 3) != 0)
    889                     throw new AlignmentException();
    890 
    891                 int i2 = (i & ~3) + 4;  // 0-3 byte padding
    892                 // IBM JVM 1.4.2 cannot run the following code:
    893                 // int i0 = i;
    894                 // while (i0 < i2)
    895                 //    newcode[j++] = code[i0++];
    896                 // So extracting this code into an external method.
    897                 // see JIRA JASSIST-74.
    898                 j = copyGapBytes(newcode, j, code, i, i2);
    899 
    900                 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2),
    901                                             where, gapLength, exclusive);
    902                 ByteArray.write32bit(defaultbyte, newcode, j);
    903                 int lowbyte = ByteArray.read32bit(code, i2 + 4);
    904                 ByteArray.write32bit(lowbyte, newcode, j + 4);
    905                 int highbyte = ByteArray.read32bit(code, i2 + 8);
    906                 ByteArray.write32bit(highbyte, newcode, j + 8);
    907                 j += 12;
    908                 int i0 = i2 + 12;
    909                 i2 = i0 + (highbyte - lowbyte + 1) * 4;
    910                 while (i0 < i2) {
    911                     int offset = newOffset(i, ByteArray.read32bit(code, i0),
    912                                            where, gapLength, exclusive);
    913                     ByteArray.write32bit(offset, newcode, j);
    914                     j += 4;
    915                     i0 += 4;
    916                 }
    917             }
    918             else if (inst == LOOKUPSWITCH) {
    919                 if (i != j && (gapLength & 3) != 0)
    920                     throw new AlignmentException();
    921 
    922                 int i2 = (i & ~3) + 4;  // 0-3 byte padding
    923 
    924                 // IBM JVM 1.4.2 cannot run the following code:
    925                 // int i0 = i;
    926                 // while (i0 < i2)
    927                 //    newcode[j++] = code[i0++];
    928                 // So extracting this code into an external method.
    929                 // see JIRA JASSIST-74.
    930                 j = copyGapBytes(newcode, j, code, i, i2);
    931 
    932                 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2),
    933                                             where, gapLength, exclusive);
    934                 ByteArray.write32bit(defaultbyte, newcode, j);
    935                 int npairs = ByteArray.read32bit(code, i2 + 4);
    936                 ByteArray.write32bit(npairs, newcode, j + 4);
    937                 j += 8;
    938                 int i0 = i2 + 8;
    939                 i2 = i0 + npairs * 8;
    940                 while (i0 < i2) {
    941                     ByteArray.copy32bit(code, i0, newcode, j);
    942                     int offset = newOffset(i,
    943                                         ByteArray.read32bit(code, i0 + 4),
    944                                         where, gapLength, exclusive);
    945                     ByteArray.write32bit(offset, newcode, j + 4);
    946                     j += 8;
    947                     i0 += 8;
    948                 }
    949             }
    950             else
    951                 while (i < nextPos)
    952                     newcode[j++] = code[i++];
    953             }
    954     }
    955 
    956 
    957     private static int copyGapBytes(byte[] newcode, int j, byte[] code, int i, int iEnd) {
    958         switch (iEnd - i) {
    959         case 4:
    960             newcode[j++] = code[i++];
    961         case 3:
    962             newcode[j++] = code[i++];
    963         case 2:
    964             newcode[j++] = code[i++];
    965         case 1:
    966             newcode[j++] = code[i++];
    967         default:
    968         }
    969 
    970         return j;
    971     }
    972 
    973     private static int newOffset(int i, int offset, int where,
    974                                  int gapLength, boolean exclusive) {
    975         int target = i + offset;
    976         if (i < where) {
    977             if (where < target || (exclusive && where == target))
    978                 offset += gapLength;
    979         }
    980         else if (i == where) {
    981             // This code is different from the code in Branch#shiftOffset().
    982             // see JASSIST-124.
    983             if (target < where)
    984                 offset -= gapLength;
    985         }
    986         else
    987             if (target < where || (!exclusive && where == target))
    988                 offset -= gapLength;
    989 
    990         return offset;
    991     }
    992 
    993     static class Pointers {
    994         int cursor;
    995         int mark0, mark;
    996         ExceptionTable etable;
    997         LineNumberAttribute line;
    998         LocalVariableAttribute vars, types;
    999         StackMapTable stack;
   1000         StackMap stack2;
   1001 
   1002         Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca) {
   1003             cursor = cur;
   1004             mark = m;
   1005             mark0 = m0;
   1006             etable = et;    // non null
   1007             line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag);
   1008             vars = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.tag);
   1009             types = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.typeTag);
   1010             stack = (StackMapTable)ca.getAttribute(StackMapTable.tag);
   1011             stack2 = (StackMap)ca.getAttribute(StackMap.tag);
   1012         }
   1013 
   1014         void shiftPc(int where, int gapLength, boolean exclusive) throws BadBytecode {
   1015             if (where < cursor || (where == cursor && exclusive))
   1016                 cursor += gapLength;
   1017 
   1018             if (where < mark || (where == mark && exclusive))
   1019                 mark += gapLength;
   1020 
   1021             if (where < mark0 || (where == mark0 && exclusive))
   1022                 mark0 += gapLength;
   1023 
   1024             etable.shiftPc(where, gapLength, exclusive);
   1025             if (line != null)
   1026                 line.shiftPc(where, gapLength, exclusive);
   1027 
   1028             if (vars != null)
   1029                 vars.shiftPc(where, gapLength, exclusive);
   1030 
   1031             if (types != null)
   1032                 types.shiftPc(where, gapLength, exclusive);
   1033 
   1034             if (stack != null)
   1035                 stack.shiftPc(where, gapLength, exclusive);
   1036 
   1037             if (stack2 != null)
   1038                 stack2.shiftPc(where, gapLength, exclusive);
   1039         }
   1040     }
   1041 
   1042     /*
   1043      * This method is called from CodeAttribute.LdcEntry.doit().
   1044      */
   1045     static byte[] changeLdcToLdcW(byte[] code, ExceptionTable etable,
   1046                                   CodeAttribute ca, CodeAttribute.LdcEntry ldcs)
   1047         throws BadBytecode
   1048     {
   1049         ArrayList jumps = makeJumpList(code, code.length);
   1050         while (ldcs != null) {
   1051             addLdcW(ldcs, jumps);
   1052             ldcs = ldcs.next;
   1053         }
   1054 
   1055         Pointers pointers = new Pointers(0, 0, 0, etable, ca);
   1056         byte[] r = insertGap2w(code, 0, 0, false, jumps, pointers);
   1057         return r;
   1058     }
   1059 
   1060     private static void addLdcW(CodeAttribute.LdcEntry ldcs, ArrayList jumps) {
   1061         int where = ldcs.where;
   1062         LdcW ldcw = new LdcW(where, ldcs.index);
   1063         int s = jumps.size();
   1064         for (int i = 0; i < s; i++)
   1065             if (where < ((Branch)jumps.get(i)).orgPos) {
   1066                 jumps.add(i, ldcw);
   1067                 return;
   1068             }
   1069 
   1070         jumps.add(ldcw);
   1071     }
   1072 
   1073     /*
   1074      * insertGapCore0w() can handle a long code sequence more than 32K.
   1075      * It guarantees that the length of the inserted gap (NOPs) is equal to
   1076      * gapLength.  No other NOPs except some NOPs following TABLESWITCH or
   1077      * LOOKUPSWITCH will not be inserted.
   1078      *
   1079      * Note: currentPos might be moved.
   1080      *
   1081      * @param where       It must indicate the first byte of an opcode.
   1082      * @param newWhere    It contains the updated index of the position where a gap
   1083      *                    is inserted and the length of the gap.
   1084      *                    It must not be null.
   1085      */
   1086     private byte[] insertGapCore0w(byte[] code, int where, int gapLength, boolean exclusive,
   1087                                    ExceptionTable etable, CodeAttribute ca, Gap newWhere)
   1088         throws BadBytecode
   1089     {
   1090         if (gapLength <= 0)
   1091             return code;
   1092 
   1093         ArrayList jumps = makeJumpList(code, code.length);
   1094         Pointers pointers = new Pointers(currentPos, mark, where, etable, ca);
   1095         byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers);
   1096         currentPos = pointers.cursor;
   1097         mark = pointers.mark;
   1098         int where2 = pointers.mark0;
   1099         if (where2 == currentPos && !exclusive)
   1100             currentPos += gapLength;
   1101 
   1102         if (exclusive)
   1103             where2 -= gapLength;
   1104 
   1105         newWhere.position = where2;
   1106         newWhere.length = gapLength;
   1107         return r;
   1108     }
   1109 
   1110     private static byte[] insertGap2w(byte[] code, int where, int gapLength,
   1111                                       boolean exclusive, ArrayList jumps, Pointers ptrs)
   1112         throws BadBytecode
   1113     {
   1114         int n = jumps.size();
   1115         if (gapLength > 0) {
   1116             ptrs.shiftPc(where, gapLength, exclusive);
   1117             for (int i = 0; i < n; i++)
   1118                 ((Branch)jumps.get(i)).shift(where, gapLength, exclusive);
   1119         }
   1120 
   1121         boolean unstable = true;
   1122         do {
   1123             while (unstable) {
   1124                 unstable = false;
   1125                 for (int i = 0; i < n; i++) {
   1126                     Branch b = (Branch)jumps.get(i);
   1127                     if (b.expanded()) {
   1128                         unstable = true;
   1129                         int p = b.pos;
   1130                         int delta = b.deltaSize();
   1131                         ptrs.shiftPc(p, delta, false);
   1132                         for (int j = 0; j < n; j++)
   1133                             ((Branch)jumps.get(j)).shift(p, delta, false);
   1134                     }
   1135                 }
   1136             }
   1137 
   1138             for (int i = 0; i < n; i++) {
   1139                 Branch b = (Branch)jumps.get(i);
   1140                 int diff = b.gapChanged();
   1141                 if (diff > 0) {
   1142                     unstable = true;
   1143                     int p = b.pos;
   1144                     ptrs.shiftPc(p, diff, false);
   1145                     for (int j = 0; j < n; j++)
   1146                         ((Branch)jumps.get(j)).shift(p, diff, false);
   1147                 }
   1148             }
   1149         } while (unstable);
   1150 
   1151         return makeExapndedCode(code, jumps, where, gapLength);
   1152     }
   1153 
   1154     private static ArrayList makeJumpList(byte[] code, int endPos)
   1155         throws BadBytecode
   1156     {
   1157         ArrayList jumps = new ArrayList();
   1158         int nextPos;
   1159         for (int i = 0; i < endPos; i = nextPos) {
   1160             nextPos = nextOpcode(code, i);
   1161             int inst = code[i] & 0xff;
   1162             // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr
   1163             if ((153 <= inst && inst <= 168)
   1164                     || inst == IFNULL || inst == IFNONNULL) {
   1165                 /* 2bytes *signed* offset */
   1166                 int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff);
   1167                 Branch b;
   1168                 if (inst == GOTO || inst == JSR)
   1169                     b = new Jump16(i, offset);
   1170                 else
   1171                     b = new If16(i, offset);
   1172 
   1173                 jumps.add(b);
   1174             }
   1175             else if (inst == GOTO_W || inst == JSR_W) {
   1176                 /* 4bytes offset */
   1177                 int offset = ByteArray.read32bit(code, i + 1);
   1178                 jumps.add(new Jump32(i, offset));
   1179             }
   1180             else if (inst == TABLESWITCH) {
   1181                 int i2 = (i & ~3) + 4;  // 0-3 byte padding
   1182                 int defaultbyte = ByteArray.read32bit(code, i2);
   1183                 int lowbyte = ByteArray.read32bit(code, i2 + 4);
   1184                 int highbyte = ByteArray.read32bit(code, i2 + 8);
   1185                 int i0 = i2 + 12;
   1186                 int size = highbyte - lowbyte + 1;
   1187                 int[] offsets = new int[size];
   1188                 for (int j = 0; j < size; j++) {
   1189                     offsets[j] = ByteArray.read32bit(code, i0);
   1190                     i0 += 4;
   1191                 }
   1192 
   1193                 jumps.add(new Table(i, defaultbyte, lowbyte, highbyte, offsets));
   1194             }
   1195             else if (inst == LOOKUPSWITCH) {
   1196                 int i2 = (i & ~3) + 4;  // 0-3 byte padding
   1197                 int defaultbyte = ByteArray.read32bit(code, i2);
   1198                 int npairs = ByteArray.read32bit(code, i2 + 4);
   1199                 int i0 = i2 + 8;
   1200                 int[] matches = new int[npairs];
   1201                 int[] offsets = new int[npairs];
   1202                 for (int j = 0; j < npairs; j++) {
   1203                     matches[j] = ByteArray.read32bit(code, i0);
   1204                     offsets[j] = ByteArray.read32bit(code, i0 + 4);
   1205                     i0 += 8;
   1206                 }
   1207 
   1208                 jumps.add(new Lookup(i, defaultbyte, matches, offsets));
   1209             }
   1210         }
   1211 
   1212         return jumps;
   1213     }
   1214 
   1215     private static byte[] makeExapndedCode(byte[] code, ArrayList jumps,
   1216                                            int where, int gapLength)
   1217         throws BadBytecode
   1218     {
   1219         int n = jumps.size();
   1220         int size = code.length + gapLength;
   1221         for (int i = 0; i < n; i++) {
   1222             Branch b = (Branch)jumps.get(i);
   1223             size += b.deltaSize();
   1224         }
   1225 
   1226         byte[] newcode = new byte[size];
   1227         int src = 0, dest = 0, bindex = 0;
   1228         int len = code.length;
   1229         Branch b;
   1230         int bpos;
   1231         if (0 < n) {
   1232             b = (Branch)jumps.get(0);
   1233             bpos = b.orgPos;
   1234         }
   1235         else {
   1236             b = null;
   1237             bpos = len;  // src will be never equal to bpos
   1238         }
   1239 
   1240         while (src < len) {
   1241             if (src == where) {
   1242                 int pos2 = dest + gapLength;
   1243                 while (dest < pos2)
   1244                     newcode[dest++] = NOP;
   1245             }
   1246 
   1247             if (src != bpos)
   1248                 newcode[dest++] = code[src++];
   1249             else {
   1250                 int s = b.write(src, code, dest, newcode);
   1251                 src += s;
   1252                 dest += s + b.deltaSize();
   1253                 if (++bindex < n) {
   1254                     b = (Branch)jumps.get(bindex);
   1255                     bpos = b.orgPos;
   1256                 }
   1257                 else  {
   1258                     b = null;
   1259                     bpos = len;
   1260                 }
   1261             }
   1262         }
   1263 
   1264         return newcode;
   1265     }
   1266 
   1267     static abstract class Branch {
   1268         int pos, orgPos;
   1269         Branch(int p) { pos = orgPos = p; }
   1270         void shift(int where, int gapLength, boolean exclusive) {
   1271             if (where < pos || (where == pos && exclusive))
   1272                 pos += gapLength;
   1273         }
   1274 
   1275         static int shiftOffset(int i, int offset, int where,
   1276                                int gapLength, boolean exclusive) {
   1277             int target = i + offset;
   1278             if (i < where) {
   1279                 if (where < target || (exclusive && where == target))
   1280                     offset += gapLength;
   1281             }
   1282             else if (i == where) {
   1283                 // This code is different from the code in CodeIterator#newOffset().
   1284                 // see JASSIST-124.
   1285                 if (target < where && exclusive)
   1286                     offset -= gapLength;
   1287                 else if (where < target && !exclusive)
   1288                     offset += gapLength;
   1289             }
   1290             else
   1291                 if (target < where || (!exclusive && where == target))
   1292                     offset -= gapLength;
   1293 
   1294             return offset;
   1295         }
   1296 
   1297         boolean expanded() { return false; }
   1298         int gapChanged() { return 0; }
   1299         int deltaSize() { return 0; }   // newSize - oldSize
   1300 
   1301         // This returns the original instruction size.
   1302         abstract int write(int srcPos, byte[] code, int destPos, byte[] newcode);
   1303     }
   1304 
   1305     /* used by changeLdcToLdcW() and CodeAttribute.LdcEntry.
   1306      */
   1307     static class LdcW extends Branch {
   1308         int index;
   1309         boolean state;
   1310         LdcW(int p, int i) {
   1311             super(p);
   1312             index = i;
   1313             state = true;
   1314         }
   1315 
   1316         boolean expanded() {
   1317             if (state) {
   1318                 state = false;
   1319                 return true;
   1320             }
   1321             else
   1322                 return false;
   1323         }
   1324 
   1325         int deltaSize() { return 1; }
   1326 
   1327         int write(int srcPos, byte[] code, int destPos, byte[] newcode) {
   1328             newcode[destPos] = LDC_W;
   1329             ByteArray.write16bit(index, newcode, destPos + 1);
   1330             return 2;
   1331         }
   1332     }
   1333 
   1334     static abstract class Branch16 extends Branch {
   1335         int offset;
   1336         int state;
   1337         static final int BIT16 = 0;
   1338         static final int EXPAND = 1;
   1339         static final int BIT32 = 2;
   1340 
   1341         Branch16(int p, int off) {
   1342             super(p);
   1343             offset = off;
   1344             state = BIT16;
   1345         }
   1346 
   1347         void shift(int where, int gapLength, boolean exclusive) {
   1348             offset = shiftOffset(pos, offset, where, gapLength, exclusive);
   1349             super.shift(where, gapLength, exclusive);
   1350             if (state == BIT16)
   1351                 if (offset < Short.MIN_VALUE || Short.MAX_VALUE < offset)
   1352                     state = EXPAND;
   1353         }
   1354 
   1355         boolean expanded() {
   1356             if (state == EXPAND) {
   1357                 state = BIT32;
   1358                 return true;
   1359             }
   1360             else
   1361                 return false;
   1362         }
   1363 
   1364         abstract int deltaSize();
   1365         abstract void write32(int src, byte[] code, int dest, byte[] newcode);
   1366 
   1367         int write(int src, byte[] code, int dest, byte[] newcode) {
   1368             if (state == BIT32)
   1369                 write32(src, code, dest, newcode);
   1370             else {
   1371                 newcode[dest] = code[src];
   1372                 ByteArray.write16bit(offset, newcode, dest + 1);
   1373             }
   1374 
   1375             return 3;
   1376         }
   1377     }
   1378 
   1379     // GOTO or JSR
   1380     static class Jump16 extends Branch16 {
   1381         Jump16(int p, int off) {
   1382             super(p, off);
   1383         }
   1384 
   1385         int deltaSize() {
   1386             return state == BIT32 ? 2 : 0;
   1387         }
   1388 
   1389         void write32(int src, byte[] code, int dest, byte[] newcode) {
   1390             newcode[dest] = (byte)(((code[src] & 0xff) == GOTO) ? GOTO_W : JSR_W);
   1391             ByteArray.write32bit(offset, newcode, dest + 1);
   1392         }
   1393     }
   1394 
   1395     // if<cond>, if_icmp<cond>, or if_acmp<cond>
   1396     static class If16 extends Branch16 {
   1397         If16(int p, int off) {
   1398             super(p, off);
   1399         }
   1400 
   1401         int deltaSize() {
   1402             return state == BIT32 ? 5 : 0;
   1403         }
   1404 
   1405         void write32(int src, byte[] code, int dest, byte[] newcode) {
   1406             newcode[dest] = (byte)opcode(code[src] & 0xff);
   1407             newcode[dest + 1] = 0;
   1408             newcode[dest + 2] = 8;  // branch_offset = 8
   1409             newcode[dest + 3] = (byte)GOTO_W;
   1410             ByteArray.write32bit(offset - 3, newcode, dest + 4);
   1411         }
   1412 
   1413         int opcode(int op) {
   1414             if (op == IFNULL)
   1415                 return IFNONNULL;
   1416             else if (op == IFNONNULL)
   1417                 return IFNULL;
   1418             else {
   1419                 if (((op - IFEQ) & 1) == 0)
   1420                     return op + 1;
   1421                 else
   1422                     return op - 1;
   1423             }
   1424         }
   1425     }
   1426 
   1427     static class Jump32 extends Branch {
   1428         int offset;
   1429 
   1430         Jump32(int p, int off) {
   1431             super(p);
   1432             offset = off;
   1433         }
   1434 
   1435         void shift(int where, int gapLength, boolean exclusive) {
   1436             offset = shiftOffset(pos, offset, where, gapLength, exclusive);
   1437             super.shift(where, gapLength, exclusive);
   1438         }
   1439 
   1440         int write(int src, byte[] code, int dest, byte[] newcode) {
   1441             newcode[dest] = code[src];
   1442             ByteArray.write32bit(offset, newcode, dest + 1);
   1443             return 5;
   1444         }
   1445     }
   1446 
   1447     static abstract class Switcher extends Branch {
   1448         int gap, defaultByte;
   1449         int[] offsets;
   1450 
   1451         Switcher(int pos, int defaultByte, int[] offsets) {
   1452             super(pos);
   1453             this.gap = 3 - (pos & 3);
   1454             this.defaultByte = defaultByte;
   1455             this.offsets = offsets;
   1456         }
   1457 
   1458         void shift(int where, int gapLength, boolean exclusive) {
   1459             int p = pos;
   1460             defaultByte = shiftOffset(p, defaultByte, where, gapLength, exclusive);
   1461             int num = offsets.length;
   1462             for (int i = 0; i < num; i++)
   1463                 offsets[i] = shiftOffset(p, offsets[i], where, gapLength, exclusive);
   1464 
   1465             super.shift(where, gapLength, exclusive);
   1466         }
   1467 
   1468         int gapChanged() {
   1469             int newGap = 3 - (pos & 3);
   1470             if (newGap > gap) {
   1471                 int diff = newGap - gap;
   1472                 gap = newGap;
   1473                 return diff;
   1474             }
   1475 
   1476             return 0;
   1477         }
   1478 
   1479         int deltaSize() {
   1480             return gap - (3 - (orgPos & 3));
   1481         }
   1482 
   1483         int write(int src, byte[] code, int dest, byte[] newcode) {
   1484             int padding = 3 - (pos & 3);
   1485             int nops = gap - padding;
   1486             int bytecodeSize = 5 + (3 - (orgPos & 3)) + tableSize();
   1487             adjustOffsets(bytecodeSize, nops);
   1488             newcode[dest++] = code[src];
   1489             while (padding-- > 0)
   1490                 newcode[dest++] = 0;
   1491 
   1492             ByteArray.write32bit(defaultByte, newcode, dest);
   1493             int size = write2(dest + 4, newcode);
   1494             dest += size + 4;
   1495             while (nops-- > 0)
   1496                 newcode[dest++] = NOP;
   1497 
   1498             return 5 + (3 - (orgPos & 3)) + size;
   1499         }
   1500 
   1501         abstract int write2(int dest, byte[] newcode);
   1502         abstract int tableSize();
   1503 
   1504         /* If the new bytecode size is shorter than the original, some NOPs
   1505          * are appended after this branch instruction (tableswitch or
   1506          * lookupswitch) to fill the gap.
   1507          * This method changes a branch offset to point to the first NOP
   1508          * if the offset originally points to the bytecode next to this
   1509          * branch instruction.  Otherwise, the bytecode would contain
   1510          * dead code.  It complicates the generation of StackMap and
   1511          * StackMapTable.
   1512          */
   1513         void adjustOffsets(int size, int nops) {
   1514             if (defaultByte == size)
   1515                 defaultByte -= nops;
   1516 
   1517             for (int i = 0; i < offsets.length; i++)
   1518                 if (offsets[i] == size)
   1519                     offsets[i] -= nops;
   1520         }
   1521     }
   1522 
   1523     static class Table extends Switcher {
   1524         int low, high;
   1525 
   1526         Table(int pos, int defaultByte, int low, int high, int[] offsets) {
   1527             super(pos, defaultByte, offsets);
   1528             this.low = low;
   1529             this.high = high;
   1530         }
   1531 
   1532         int write2(int dest, byte[] newcode) {
   1533             ByteArray.write32bit(low, newcode, dest);
   1534             ByteArray.write32bit(high, newcode, dest + 4);
   1535             int n = offsets.length;
   1536             dest += 8;
   1537             for (int i = 0; i < n; i++) {
   1538                 ByteArray.write32bit(offsets[i], newcode, dest);
   1539                 dest += 4;
   1540             }
   1541 
   1542             return 8 + 4 * n;
   1543         }
   1544 
   1545         int tableSize() { return 8 + 4 * offsets.length; }
   1546     }
   1547 
   1548     static class Lookup extends Switcher {
   1549         int[] matches;
   1550 
   1551         Lookup(int pos, int defaultByte, int[] matches, int[] offsets) {
   1552             super(pos, defaultByte, offsets);
   1553             this.matches = matches;
   1554         }
   1555 
   1556         int write2(int dest, byte[] newcode) {
   1557             int n = matches.length;
   1558             ByteArray.write32bit(n, newcode, dest);
   1559             dest += 4;
   1560             for (int i = 0; i < n; i++) {
   1561                 ByteArray.write32bit(matches[i], newcode, dest);
   1562                 ByteArray.write32bit(offsets[i], newcode, dest + 4);
   1563                 dest += 8;
   1564             }
   1565 
   1566             return 4 + 8 * n;
   1567         }
   1568 
   1569         int tableSize() { return 4 + 8 * matches.length; }
   1570     }
   1571 }
   1572