Home | History | Annotate | Download | only in instruction
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2013 Eric Lafortune (eric (at) graphics.cornell.edu)
      6  *
      7  * This program is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU General Public License as published by the Free
      9  * Software Foundation; either version 2 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with this program; if not, write to the Free Software Foundation, Inc.,
     19  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  */
     21 package proguard.classfile.instruction;
     22 
     23 import proguard.classfile.*;
     24 import proguard.classfile.attribute.CodeAttribute;
     25 import proguard.classfile.instruction.visitor.InstructionVisitor;
     26 
     27 /**
     28  * Base class for representing instructions.
     29  *
     30  * @author Eric Lafortune
     31  */
     32 public abstract class Instruction
     33 {
     34     // An array for marking Category 2 instructions.
     35     private static final boolean[] IS_CATEGORY2 = new boolean[]
     36     {
     37         false, // nop
     38         false, // aconst_null
     39         false, // iconst_m1
     40         false, // iconst_0
     41         false, // iconst_1
     42         false, // iconst_2
     43         false, // iconst_3
     44         false, // iconst_4
     45         false, // iconst_5
     46         true,  // lconst_0
     47         true,  // lconst_1
     48         false, // fconst_0
     49         false, // fconst_1
     50         false, // fconst_2
     51         true,  // dconst_0
     52         true,  // dconst_1
     53         false, // bipush
     54         false, // sipush
     55         false, // ldc
     56         false, // ldc_w
     57         true,  // ldc2_w
     58         false, // iload
     59         true,  // lload
     60         false, // fload
     61         true,  // dload
     62         false, // aload
     63         false, // iload_0
     64         false, // iload_1
     65         false, // iload_2
     66         false, // iload_3
     67         true,  // lload_0
     68         true,  // lload_1
     69         true,  // lload_2
     70         true,  // lload_3
     71         false, // fload_0
     72         false, // fload_1
     73         false, // fload_2
     74         false, // fload_3
     75         true,  // dload_0
     76         true,  // dload_1
     77         true,  // dload_2
     78         true,  // dload_3
     79         false, // aload_0
     80         false, // aload_1
     81         false, // aload_2
     82         false, // aload_3
     83         false, // iaload
     84         true,  // laload
     85         false, // faload
     86         true,  // daload
     87         false, // aaload
     88         false, // baload
     89         false, // caload
     90         false, // saload
     91         false, // istore
     92         true,  // lstore
     93         false, // fstore
     94         true,  // dstore
     95         false, // astore
     96         false, // istore_0
     97         false, // istore_1
     98         false, // istore_2
     99         false, // istore_3
    100         true,  // lstore_0
    101         true,  // lstore_1
    102         true,  // lstore_2
    103         true,  // lstore_3
    104         false, // fstore_0
    105         false, // fstore_1
    106         false, // fstore_2
    107         false, // fstore_3
    108         true,  // dstore_0
    109         true,  // dstore_1
    110         true,  // dstore_2
    111         true,  // dstore_3
    112         false, // astore_0
    113         false, // astore_1
    114         false, // astore_2
    115         false, // astore_3
    116         false, // iastore
    117         true,  // lastore
    118         false, // fastore
    119         true,  // dastore
    120         false, // aastore
    121         false, // bastore
    122         false, // castore
    123         false, // sastore
    124         false, // pop
    125         true,  // pop2
    126         false, // dup
    127         false, // dup_x1
    128         false, // dup_x2
    129         true,  // dup2
    130         true,  // dup2_x1
    131         true,  // dup2_x2
    132         false, // swap
    133         false, // iadd
    134         true,  // ladd
    135         false, // fadd
    136         true,  // dadd
    137         false, // isub
    138         true,  // lsub
    139         false, // fsub
    140         true,  // dsub
    141         false, // imul
    142         true,  // lmul
    143         false, // fmul
    144         true,  // dmul
    145         false, // idiv
    146         true,  // ldiv
    147         false, // fdiv
    148         true,  // ddiv
    149         false, // irem
    150         true,  // lrem
    151         false, // frem
    152         true,  // drem
    153         false, // ineg
    154         true,  // lneg
    155         false, // fneg
    156         true,  // dneg
    157         false, // ishl
    158         true,  // lshl
    159         false, // ishr
    160         true,  // lshr
    161         false, // iushr
    162         true,  // lushr
    163         false, // iand
    164         true,  // land
    165         false, // ior
    166         true,  // lor
    167         false, // ixor
    168         true,  // lxor
    169         false, // iinc
    170         false, // i2l
    171         false, // i2f
    172         false, // i2d
    173         true,  // l2i
    174         true,  // l2f
    175         true,  // l2d
    176         false, // f2i
    177         false, // f2l
    178         false, // f2d
    179         true,  // d2i
    180         true,  // d2l
    181         true,  // d2f
    182         false, // i2b
    183         false, // i2c
    184         false, // i2s
    185         true,  // lcmp
    186         false, // fcmpl
    187         false, // fcmpg
    188         true,  // dcmpl
    189         true,  // dcmpg
    190         false, // ifeq
    191         false, // ifne
    192         false, // iflt
    193         false, // ifge
    194         false, // ifgt
    195         false, // ifle
    196         false, // ificmpeq
    197         false, // ificmpne
    198         false, // ificmplt
    199         false, // ificmpge
    200         false, // ificmpgt
    201         false, // ificmple
    202         false, // ifacmpeq
    203         false, // ifacmpne
    204         false, // goto
    205         false, // jsr
    206         false, // ret
    207         false, // tableswitch
    208         false, // lookupswitch
    209         false, // ireturn
    210         true,  // lreturn
    211         false, // freturn
    212         true,  // dreturn
    213         false, // areturn
    214         false, // return
    215         false, // getstatic
    216         false, // putstatic
    217         false, // getfield
    218         false, // putfield
    219         false, // invokevirtual
    220         false, // invokespecial
    221         false, // invokestatic
    222         false, // invokeinterface
    223         false, // invokedynamic
    224         false, // new
    225         false, // newarray
    226         false, // anewarray
    227         false, // arraylength
    228         false, // athrow
    229         false, // checkcast
    230         false, // instanceof
    231         false, // monitorenter
    232         false, // monitorexit
    233         false, // wide
    234         false, // multianewarray
    235         false, // ifnull
    236         false, // ifnonnull
    237         false, // goto_w
    238         false, // jsr_w
    239     };
    240 
    241 
    242     // An array containing the fixed number of entries popped from the stack,
    243     // for all instructions.
    244     private static final int[] STACK_POP_COUNTS = new int[]
    245     {
    246         0, // nop
    247         0, // aconst_null
    248         0, // iconst_m1
    249         0, // iconst_0
    250         0, // iconst_1
    251         0, // iconst_2
    252         0, // iconst_3
    253         0, // iconst_4
    254         0, // iconst_5
    255         0, // lconst_0
    256         0, // lconst_1
    257         0, // fconst_0
    258         0, // fconst_1
    259         0, // fconst_2
    260         0, // dconst_0
    261         0, // dconst_1
    262         0, // bipush
    263         0, // sipush
    264         0, // ldc
    265         0, // ldc_w
    266         0, // ldc2_w
    267         0, // iload
    268         0, // lload
    269         0, // fload
    270         0, // dload
    271         0, // aload
    272         0, // iload_0
    273         0, // iload_1
    274         0, // iload_2
    275         0, // iload_3
    276         0, // lload_0
    277         0, // lload_1
    278         0, // lload_2
    279         0, // lload_3
    280         0, // fload_0
    281         0, // fload_1
    282         0, // fload_2
    283         0, // fload_3
    284         0, // dload_0
    285         0, // dload_1
    286         0, // dload_2
    287         0, // dload_3
    288         0, // aload_0
    289         0, // aload_1
    290         0, // aload_2
    291         0, // aload_3
    292         2, // iaload
    293         2, // laload
    294         2, // faload
    295         2, // daload
    296         2, // aaload
    297         2, // baload
    298         2, // caload
    299         2, // saload
    300         1, // istore
    301         2, // lstore
    302         1, // fstore
    303         2, // dstore
    304         1, // astore
    305         1, // istore_0
    306         1, // istore_1
    307         1, // istore_2
    308         1, // istore_3
    309         2, // lstore_0
    310         2, // lstore_1
    311         2, // lstore_2
    312         2, // lstore_3
    313         1, // fstore_0
    314         1, // fstore_1
    315         1, // fstore_2
    316         1, // fstore_3
    317         2, // dstore_0
    318         2, // dstore_1
    319         2, // dstore_2
    320         2, // dstore_3
    321         1, // astore_0
    322         1, // astore_1
    323         1, // astore_2
    324         1, // astore_3
    325         3, // iastore
    326         4, // lastore
    327         3, // fastore
    328         4, // dastore
    329         3, // aastore
    330         3, // bastore
    331         3, // castore
    332         3, // sastore
    333         1, // pop
    334         2, // pop2
    335         1, // dup
    336         2, // dup_x1
    337         3, // dup_x2
    338         2, // dup2
    339         3, // dup2_x1
    340         4, // dup2_x2
    341         2, // swap
    342         2, // iadd
    343         4, // ladd
    344         2, // fadd
    345         4, // dadd
    346         2, // isub
    347         4, // lsub
    348         2, // fsub
    349         4, // dsub
    350         2, // imul
    351         4, // lmul
    352         2, // fmul
    353         4, // dmul
    354         2, // idiv
    355         4, // ldiv
    356         2, // fdiv
    357         4, // ddiv
    358         2, // irem
    359         4, // lrem
    360         2, // frem
    361         4, // drem
    362         1, // ineg
    363         2, // lneg
    364         1, // fneg
    365         2, // dneg
    366         2, // ishl
    367         3, // lshl
    368         2, // ishr
    369         3, // lshr
    370         2, // iushr
    371         3, // lushr
    372         2, // iand
    373         4, // land
    374         2, // ior
    375         4, // lor
    376         2, // ixor
    377         4, // lxor
    378         0, // iinc
    379         1, // i2l
    380         1, // i2f
    381         1, // i2d
    382         2, // l2i
    383         2, // l2f
    384         2, // l2d
    385         1, // f2i
    386         1, // f2l
    387         1, // f2d
    388         2, // d2i
    389         2, // d2l
    390         2, // d2f
    391         1, // i2b
    392         1, // i2c
    393         1, // i2s
    394         4, // lcmp
    395         2, // fcmpl
    396         2, // fcmpg
    397         4, // dcmpl
    398         4, // dcmpg
    399         1, // ifeq
    400         1, // ifne
    401         1, // iflt
    402         1, // ifge
    403         1, // ifgt
    404         1, // ifle
    405         2, // ificmpeq
    406         2, // ificmpne
    407         2, // ificmplt
    408         2, // ificmpge
    409         2, // ificmpgt
    410         2, // ificmple
    411         2, // ifacmpeq
    412         2, // ifacmpne
    413         0, // goto
    414         0, // jsr
    415         0, // ret
    416         1, // tableswitch
    417         1, // lookupswitch
    418         1, // ireturn
    419         2, // lreturn
    420         1, // freturn
    421         2, // dreturn
    422         1, // areturn
    423         0, // return
    424         0, // getstatic
    425         0, // putstatic
    426         1, // getfield
    427         1, // putfield
    428         1, // invokevirtual
    429         1, // invokespecial
    430         0, // invokestatic
    431         1, // invokeinterface
    432         0, // invokedynamic
    433         0, // new
    434         1, // newarray
    435         1, // anewarray
    436         1, // arraylength
    437         1, // athrow
    438         1, // checkcast
    439         1, // instanceof
    440         1, // monitorenter
    441         1, // monitorexit
    442         0, // wide
    443         0, // multianewarray
    444         1, // ifnull
    445         1, // ifnonnull
    446         0, // goto_w
    447         0, // jsr_w
    448     };
    449 
    450 
    451     // An array containing the fixed number of entries pushed onto the stack,
    452     // for all instructions.
    453     private static final int[] STACK_PUSH_COUNTS = new int[]
    454     {
    455         0, // nop
    456         1, // aconst_null
    457         1, // iconst_m1
    458         1, // iconst_0
    459         1, // iconst_1
    460         1, // iconst_2
    461         1, // iconst_3
    462         1, // iconst_4
    463         1, // iconst_5
    464         2, // lconst_0
    465         2, // lconst_1
    466         1, // fconst_0
    467         1, // fconst_1
    468         1, // fconst_2
    469         2, // dconst_0
    470         2, // dconst_1
    471         1, // bipush
    472         1, // sipush
    473         1, // ldc
    474         1, // ldc_w
    475         2, // ldc2_w
    476         1, // iload
    477         2, // lload
    478         1, // fload
    479         2, // dload
    480         1, // aload
    481         1, // iload_0
    482         1, // iload_1
    483         1, // iload_2
    484         1, // iload_3
    485         2, // lload_0
    486         2, // lload_1
    487         2, // lload_2
    488         2, // lload_3
    489         1, // fload_0
    490         1, // fload_1
    491         1, // fload_2
    492         1, // fload_3
    493         2, // dload_0
    494         2, // dload_1
    495         2, // dload_2
    496         2, // dload_3
    497         1, // aload_0
    498         1, // aload_1
    499         1, // aload_2
    500         1, // aload_3
    501         1, // iaload
    502         2, // laload
    503         1, // faload
    504         2, // daload
    505         1, // aaload
    506         1, // baload
    507         1, // caload
    508         1, // saload
    509         0, // istore
    510         0, // lstore
    511         0, // fstore
    512         0, // dstore
    513         0, // astore
    514         0, // istore_0
    515         0, // istore_1
    516         0, // istore_2
    517         0, // istore_3
    518         0, // lstore_0
    519         0, // lstore_1
    520         0, // lstore_2
    521         0, // lstore_3
    522         0, // fstore_0
    523         0, // fstore_1
    524         0, // fstore_2
    525         0, // fstore_3
    526         0, // dstore_0
    527         0, // dstore_1
    528         0, // dstore_2
    529         0, // dstore_3
    530         0, // astore_0
    531         0, // astore_1
    532         0, // astore_2
    533         0, // astore_3
    534         0, // iastore
    535         0, // lastore
    536         0, // fastore
    537         0, // dastore
    538         0, // aastore
    539         0, // bastore
    540         0, // castore
    541         0, // sastore
    542         0, // pop
    543         0, // pop2
    544         2, // dup
    545         3, // dup_x1
    546         4, // dup_x2
    547         4, // dup2
    548         5, // dup2_x1
    549         6, // dup2_x2
    550         2, // swap
    551         1, // iadd
    552         2, // ladd
    553         1, // fadd
    554         2, // dadd
    555         1, // isub
    556         2, // lsub
    557         1, // fsub
    558         2, // dsub
    559         1, // imul
    560         2, // lmul
    561         1, // fmul
    562         2, // dmul
    563         1, // idiv
    564         2, // ldiv
    565         1, // fdiv
    566         2, // ddiv
    567         1, // irem
    568         2, // lrem
    569         1, // frem
    570         2, // drem
    571         1, // ineg
    572         2, // lneg
    573         1, // fneg
    574         2, // dneg
    575         1, // ishl
    576         2, // lshl
    577         1, // ishr
    578         2, // lshr
    579         1, // iushr
    580         2, // lushr
    581         1, // iand
    582         2, // land
    583         1, // ior
    584         2, // lor
    585         1, // ixor
    586         2, // lxor
    587         0, // iinc
    588         2, // i2l
    589         1, // i2f
    590         2, // i2d
    591         1, // l2i
    592         1, // l2f
    593         2, // l2d
    594         1, // f2i
    595         2, // f2l
    596         2, // f2d
    597         1, // d2i
    598         2, // d2l
    599         1, // d2f
    600         1, // i2b
    601         1, // i2c
    602         1, // i2s
    603         1, // lcmp
    604         1, // fcmpl
    605         1, // fcmpg
    606         1, // dcmpl
    607         1, // dcmpg
    608         0, // ifeq
    609         0, // ifne
    610         0, // iflt
    611         0, // ifge
    612         0, // ifgt
    613         0, // ifle
    614         0, // ificmpeq
    615         0, // ificmpne
    616         0, // ificmplt
    617         0, // ificmpge
    618         0, // ificmpgt
    619         0, // ificmple
    620         0, // ifacmpeq
    621         0, // ifacmpne
    622         0, // goto
    623         1, // jsr
    624         0, // ret
    625         0, // tableswitch
    626         0, // lookupswitch
    627         0, // ireturn
    628         0, // lreturn
    629         0, // freturn
    630         0, // dreturn
    631         0, // areturn
    632         0, // return
    633         0, // getstatic
    634         0, // putstatic
    635         0, // getfield
    636         0, // putfield
    637         0, // invokevirtual
    638         0, // invokespecial
    639         0, // invokestatic
    640         0, // invokeinterface
    641         0, // invokedynamic
    642         1, // new
    643         1, // newarray
    644         1, // anewarray
    645         1, // arraylength
    646         0, // athrow
    647         1, // checkcast
    648         1, // instanceof
    649         0, // monitorenter
    650         0, // monitorexit
    651         0, // wide
    652         1, // multianewarray
    653         0, // ifnull
    654         0, // ifnonnull
    655         0, // goto_w
    656         1, // jsr_w
    657     };
    658 
    659 
    660     public byte opcode;
    661 
    662 
    663     /**
    664      * Returns the canonical opcode of this instruction, i.e. typically the
    665      * opcode whose extension has been removed.
    666      */
    667     public byte canonicalOpcode()
    668     {
    669         return opcode;
    670     }
    671 
    672 
    673     /**
    674      * Shrinks this instruction to its shortest possible form.
    675      * @return this instruction.
    676      */
    677     public abstract Instruction shrink();
    678 
    679 
    680 
    681     /**
    682      * Writes the Instruction at the given offset in the given code attribute.
    683      */
    684     public final void write(CodeAttribute codeAttribute, int offset)
    685     {
    686         write(codeAttribute.code, offset);
    687     }
    688 
    689 
    690     /**
    691      * Writes the Instruction at the given offset in the given code array.
    692      */
    693     public void write(byte[] code, int offset)
    694     {
    695         // Write the wide opcode, if necessary.
    696         if (isWide())
    697         {
    698             code[offset++] = InstructionConstants.OP_WIDE;
    699         }
    700 
    701         // Write the opcode.
    702         code[offset++] = opcode;
    703 
    704         // Write any additional arguments.
    705         writeInfo(code, offset);
    706     }
    707 
    708 
    709     /**
    710      * Returns whether the instruction is wide, i.e. preceded by a wide opcode.
    711      * With the current specifications, only variable instructions can be wide.
    712      */
    713     protected boolean isWide()
    714     {
    715         return false;
    716     }
    717 
    718 
    719     /**
    720      * Reads the data following the instruction opcode.
    721      */
    722     protected abstract void readInfo(byte[] code, int offset);
    723 
    724 
    725     /**
    726      * Writes data following the instruction opcode.
    727      */
    728     protected abstract void writeInfo(byte[] code, int offset);
    729 
    730 
    731     /**
    732      * Returns the length in bytes of the instruction.
    733      */
    734     public abstract int length(int offset);
    735 
    736 
    737     /**
    738      * Accepts the given visitor.
    739      */
    740     public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor);
    741 
    742 
    743     /**
    744      * Returns a description of the instruction, at the given offset.
    745      */
    746     public String toString(int offset)
    747     {
    748         return "["+offset+"] "+ this.toString();
    749     }
    750 
    751 
    752     /**
    753      * Returns the name of the instruction.
    754      */
    755     public String getName()
    756     {
    757         return InstructionConstants.NAMES[opcode & 0xff];
    758     }
    759 
    760 
    761     /**
    762      * Returns whether the instruction is a Category 2 instruction. This means
    763      * that it operates on long or double arguments.
    764      */
    765     public boolean isCategory2()
    766     {
    767         return IS_CATEGORY2[opcode & 0xff];
    768     }
    769 
    770 
    771     /**
    772      * Returns the number of entries popped from the stack during the execution
    773      * of the instruction.
    774      */
    775     public int stackPopCount(Clazz clazz)
    776     {
    777         return STACK_POP_COUNTS[opcode & 0xff];
    778     }
    779 
    780 
    781     /**
    782      * Returns the number of entries pushed onto the stack during the execution
    783      * of the instruction.
    784      */
    785     public int stackPushCount(Clazz clazz)
    786     {
    787         return STACK_PUSH_COUNTS[opcode & 0xff];
    788     }
    789 
    790 
    791     // Small utility methods.
    792 
    793     protected static int readByte(byte[] code, int offset)
    794     {
    795         return code[offset] & 0xff;
    796     }
    797 
    798     protected static int readShort(byte[] code, int offset)
    799     {
    800         return ((code[offset++] & 0xff) << 8) |
    801                ( code[offset  ] & 0xff      );
    802     }
    803 
    804     protected static int readInt(byte[] code, int offset)
    805     {
    806         return ( code[offset++]         << 24) |
    807                ((code[offset++] & 0xff) << 16) |
    808                ((code[offset++] & 0xff) <<  8) |
    809                ( code[offset  ] & 0xff       );
    810     }
    811 
    812     protected static int readValue(byte[] code, int offset, int valueSize)
    813     {
    814         switch (valueSize)
    815         {
    816             case 0: return 0;
    817             case 1: return readByte( code, offset);
    818             case 2: return readShort(code, offset);
    819             case 4: return readInt(  code, offset);
    820             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
    821         }
    822     }
    823 
    824     protected static int readSignedByte(byte[] code, int offset)
    825     {
    826         return code[offset];
    827     }
    828 
    829     protected static int readSignedShort(byte[] code, int offset)
    830     {
    831         return (code[offset++] <<   8) |
    832                (code[offset  ] & 0xff);
    833     }
    834 
    835     protected static int readSignedValue(byte[] code, int offset, int valueSize)
    836     {
    837         switch (valueSize)
    838         {
    839             case 0: return 0;
    840             case 1: return readSignedByte( code, offset);
    841             case 2: return readSignedShort(code, offset);
    842             case 4: return readInt(        code, offset);
    843             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
    844         }
    845     }
    846 
    847     protected static void writeByte(byte[] code, int offset, int value)
    848     {
    849         if (value > 0xff)
    850         {
    851             throw new IllegalArgumentException("Unsigned byte value larger than 0xff ["+value+"]");
    852         }
    853 
    854         code[offset] = (byte)value;
    855     }
    856 
    857     protected static void writeShort(byte[] code, int offset, int value)
    858     {
    859         if (value > 0xffff)
    860         {
    861             throw new IllegalArgumentException("Unsigned short value larger than 0xffff ["+value+"]");
    862         }
    863 
    864         code[offset++] = (byte)(value >> 8);
    865         code[offset  ] = (byte)(value     );
    866     }
    867 
    868     protected static void writeInt(byte[] code, int offset, int value)
    869     {
    870         code[offset++] = (byte)(value >> 24);
    871         code[offset++] = (byte)(value >> 16);
    872         code[offset++] = (byte)(value >>  8);
    873         code[offset  ] = (byte)(value      );
    874     }
    875 
    876     protected static void writeValue(byte[] code, int offset, int value, int valueSize)
    877     {
    878         switch (valueSize)
    879         {
    880             case 0:                                  break;
    881             case 1: writeByte( code, offset, value); break;
    882             case 2: writeShort(code, offset, value); break;
    883             case 4: writeInt(  code, offset, value); break;
    884             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
    885         }
    886     }
    887 
    888     protected static void writeSignedByte(byte[] code, int offset, int value)
    889     {
    890         if ((byte)value != value)
    891         {
    892             throw new IllegalArgumentException("Signed byte value out of range ["+value+"]");
    893         }
    894 
    895         code[offset] = (byte)value;
    896     }
    897 
    898     protected static void writeSignedShort(byte[] code, int offset, int value)
    899     {
    900         if ((short)value != value)
    901         {
    902             throw new IllegalArgumentException("Signed short value out of range ["+value+"]");
    903         }
    904 
    905         code[offset++] = (byte)(value >> 8);
    906         code[offset  ] = (byte)(value     );
    907     }
    908 
    909     protected static void writeSignedValue(byte[] code, int offset, int value, int valueSize)
    910     {
    911         switch (valueSize)
    912         {
    913             case 0:                                        break;
    914             case 1: writeSignedByte( code, offset, value); break;
    915             case 2: writeSignedShort(code, offset, value); break;
    916             case 4: writeInt(        code, offset, value); break;
    917             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
    918         }
    919     }
    920 }
    921