Home | History | Annotate | Download | only in instruction
      1 /*
      2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
      3  *             of Java bytecode.
      4  *
      5  * Copyright (c) 2002-2014 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 instructions that may throw exceptions.
     35     private static final boolean[] MAY_THROW_EXCEPTIONS = 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         false, // lconst_0
     47         false, // lconst_1
     48         false, // fconst_0
     49         false, // fconst_1
     50         false, // fconst_2
     51         false, // dconst_0
     52         false, // dconst_1
     53         false, // bipush
     54         false, // sipush
     55         false, // ldc
     56         false, // ldc_w
     57         false, // ldc2_w
     58         false, // iload
     59         false, // lload
     60         false, // fload
     61         false, // dload
     62         false, // aload
     63         false, // iload_0
     64         false, // iload_1
     65         false, // iload_2
     66         false, // iload_3
     67         false, // lload_0
     68         false, // lload_1
     69         false, // lload_2
     70         false, // lload_3
     71         false, // fload_0
     72         false, // fload_1
     73         false, // fload_2
     74         false, // fload_3
     75         false, // dload_0
     76         false, // dload_1
     77         false, // dload_2
     78         false, // dload_3
     79         false, // aload_0
     80         false, // aload_1
     81         false, // aload_2
     82         false, // aload_3
     83         true,  // iaload
     84         true,  // laload
     85         true,  // faload
     86         true,  // daload
     87         true,  // aaload
     88         true,  // baload
     89         true,  // caload
     90         true,  // saload
     91         false, // istore
     92         false, // lstore
     93         false, // fstore
     94         false, // dstore
     95         false, // astore
     96         false, // istore_0
     97         false, // istore_1
     98         false, // istore_2
     99         false, // istore_3
    100         false, // lstore_0
    101         false, // lstore_1
    102         false, // lstore_2
    103         false, // lstore_3
    104         false, // fstore_0
    105         false, // fstore_1
    106         false, // fstore_2
    107         false, // fstore_3
    108         false, // dstore_0
    109         false, // dstore_1
    110         false, // dstore_2
    111         false, // dstore_3
    112         false, // astore_0
    113         false, // astore_1
    114         false, // astore_2
    115         false, // astore_3
    116         true,  // iastore
    117         true,  // lastore
    118         true,  // fastore
    119         true,  // dastore
    120         true,  // aastore
    121         true,  // bastore
    122         true,  // castore
    123         true,  // sastore
    124         false, // pop
    125         false, // pop2
    126         false, // dup
    127         false, // dup_x1
    128         false, // dup_x2
    129         false, // dup2
    130         false, // dup2_x1
    131         false, // dup2_x2
    132         false, // swap
    133         false, // iadd
    134         false, // ladd
    135         false, // fadd
    136         false, // dadd
    137         false, // isub
    138         false, // lsub
    139         false, // fsub
    140         false, // dsub
    141         false, // imul
    142         false, // lmul
    143         false, // fmul
    144         false, // dmul
    145         true,  // idiv
    146         true,  // ldiv
    147         false, // fdiv
    148         false, // ddiv
    149         true,  // irem
    150         true,  // lrem
    151         false, // frem
    152         false, // drem
    153         false, // ineg
    154         false, // lneg
    155         false, // fneg
    156         false, // dneg
    157         false, // ishl
    158         false, // lshl
    159         false, // ishr
    160         false, // lshr
    161         false, // iushr
    162         false, // lushr
    163         false, // iand
    164         false, // land
    165         false, // ior
    166         false, // lor
    167         false, // ixor
    168         false, // lxor
    169         false, // iinc
    170         false, // i2l
    171         false, // i2f
    172         false, // i2d
    173         false, // l2i
    174         false, // l2f
    175         false, // l2d
    176         false, // f2i
    177         false, // f2l
    178         false, // f2d
    179         false, // d2i
    180         false, // d2l
    181         false, // d2f
    182         false, // i2b
    183         false, // i2c
    184         false, // i2s
    185         false, // lcmp
    186         false, // fcmpl
    187         false, // fcmpg
    188         false, // dcmpl
    189         false, // 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         false, // lreturn
    211         false, // freturn
    212         false, // dreturn
    213         false, // areturn
    214         false, // return
    215         true,  // getstatic
    216         true,  // putstatic
    217         true,  // getfield
    218         true,  // putfield
    219         true,  // invokevirtual
    220         true,  // invokespecial
    221         true,  // invokestatic
    222         true,  // invokeinterface
    223         true,  // invokedynamic
    224         true,  // new
    225         true,  // newarray
    226         true,  // anewarray
    227         true,  // arraylength
    228         true,  // athrow
    229         true,  // checkcast
    230         false, // instanceof
    231         true,  // monitorenter
    232         true,  // monitorexit
    233         false, // wide
    234         true,  // multianewarray
    235         false, // ifnull
    236         false, // ifnonnull
    237         false, // goto_w
    238         false, // jsr_w
    239     };
    240 
    241 
    242     // An array for marking Category 2 instructions.
    243     private static final boolean[] IS_CATEGORY2 = new boolean[]
    244     {
    245         false, // nop
    246         false, // aconst_null
    247         false, // iconst_m1
    248         false, // iconst_0
    249         false, // iconst_1
    250         false, // iconst_2
    251         false, // iconst_3
    252         false, // iconst_4
    253         false, // iconst_5
    254         true,  // lconst_0
    255         true,  // lconst_1
    256         false, // fconst_0
    257         false, // fconst_1
    258         false, // fconst_2
    259         true,  // dconst_0
    260         true,  // dconst_1
    261         false, // bipush
    262         false, // sipush
    263         false, // ldc
    264         false, // ldc_w
    265         true,  // ldc2_w
    266         false, // iload
    267         true,  // lload
    268         false, // fload
    269         true,  // dload
    270         false, // aload
    271         false, // iload_0
    272         false, // iload_1
    273         false, // iload_2
    274         false, // iload_3
    275         true,  // lload_0
    276         true,  // lload_1
    277         true,  // lload_2
    278         true,  // lload_3
    279         false, // fload_0
    280         false, // fload_1
    281         false, // fload_2
    282         false, // fload_3
    283         true,  // dload_0
    284         true,  // dload_1
    285         true,  // dload_2
    286         true,  // dload_3
    287         false, // aload_0
    288         false, // aload_1
    289         false, // aload_2
    290         false, // aload_3
    291         false, // iaload
    292         true,  // laload
    293         false, // faload
    294         true,  // daload
    295         false, // aaload
    296         false, // baload
    297         false, // caload
    298         false, // saload
    299         false, // istore
    300         true,  // lstore
    301         false, // fstore
    302         true,  // dstore
    303         false, // astore
    304         false, // istore_0
    305         false, // istore_1
    306         false, // istore_2
    307         false, // istore_3
    308         true,  // lstore_0
    309         true,  // lstore_1
    310         true,  // lstore_2
    311         true,  // lstore_3
    312         false, // fstore_0
    313         false, // fstore_1
    314         false, // fstore_2
    315         false, // fstore_3
    316         true,  // dstore_0
    317         true,  // dstore_1
    318         true,  // dstore_2
    319         true,  // dstore_3
    320         false, // astore_0
    321         false, // astore_1
    322         false, // astore_2
    323         false, // astore_3
    324         false, // iastore
    325         true,  // lastore
    326         false, // fastore
    327         true,  // dastore
    328         false, // aastore
    329         false, // bastore
    330         false, // castore
    331         false, // sastore
    332         false, // pop
    333         true,  // pop2
    334         false, // dup
    335         false, // dup_x1
    336         false, // dup_x2
    337         true,  // dup2
    338         true,  // dup2_x1
    339         true,  // dup2_x2
    340         false, // swap
    341         false, // iadd
    342         true,  // ladd
    343         false, // fadd
    344         true,  // dadd
    345         false, // isub
    346         true,  // lsub
    347         false, // fsub
    348         true,  // dsub
    349         false, // imul
    350         true,  // lmul
    351         false, // fmul
    352         true,  // dmul
    353         false, // idiv
    354         true,  // ldiv
    355         false, // fdiv
    356         true,  // ddiv
    357         false, // irem
    358         true,  // lrem
    359         false, // frem
    360         true,  // drem
    361         false, // ineg
    362         true,  // lneg
    363         false, // fneg
    364         true,  // dneg
    365         false, // ishl
    366         true,  // lshl
    367         false, // ishr
    368         true,  // lshr
    369         false, // iushr
    370         true,  // lushr
    371         false, // iand
    372         true,  // land
    373         false, // ior
    374         true,  // lor
    375         false, // ixor
    376         true,  // lxor
    377         false, // iinc
    378         false, // i2l
    379         false, // i2f
    380         false, // i2d
    381         true,  // l2i
    382         true,  // l2f
    383         true,  // l2d
    384         false, // f2i
    385         false, // f2l
    386         false, // f2d
    387         true,  // d2i
    388         true,  // d2l
    389         true,  // d2f
    390         false, // i2b
    391         false, // i2c
    392         false, // i2s
    393         true,  // lcmp
    394         false, // fcmpl
    395         false, // fcmpg
    396         true,  // dcmpl
    397         true,  // dcmpg
    398         false, // ifeq
    399         false, // ifne
    400         false, // iflt
    401         false, // ifge
    402         false, // ifgt
    403         false, // ifle
    404         false, // ificmpeq
    405         false, // ificmpne
    406         false, // ificmplt
    407         false, // ificmpge
    408         false, // ificmpgt
    409         false, // ificmple
    410         false, // ifacmpeq
    411         false, // ifacmpne
    412         false, // goto
    413         false, // jsr
    414         false, // ret
    415         false, // tableswitch
    416         false, // lookupswitch
    417         false, // ireturn
    418         true,  // lreturn
    419         false, // freturn
    420         true,  // dreturn
    421         false, // areturn
    422         false, // return
    423         false, // getstatic
    424         false, // putstatic
    425         false, // getfield
    426         false, // putfield
    427         false, // invokevirtual
    428         false, // invokespecial
    429         false, // invokestatic
    430         false, // invokeinterface
    431         false, // invokedynamic
    432         false, // new
    433         false, // newarray
    434         false, // anewarray
    435         false, // arraylength
    436         false, // athrow
    437         false, // checkcast
    438         false, // instanceof
    439         false, // monitorenter
    440         false, // monitorexit
    441         false, // wide
    442         false, // multianewarray
    443         false, // ifnull
    444         false, // ifnonnull
    445         false, // goto_w
    446         false, // jsr_w
    447     };
    448 
    449 
    450     // An array containing the fixed number of entries popped from the stack,
    451     // for all instructions.
    452     private static final int[] STACK_POP_COUNTS = new int[]
    453     {
    454         0, // nop
    455         0, // aconst_null
    456         0, // iconst_m1
    457         0, // iconst_0
    458         0, // iconst_1
    459         0, // iconst_2
    460         0, // iconst_3
    461         0, // iconst_4
    462         0, // iconst_5
    463         0, // lconst_0
    464         0, // lconst_1
    465         0, // fconst_0
    466         0, // fconst_1
    467         0, // fconst_2
    468         0, // dconst_0
    469         0, // dconst_1
    470         0, // bipush
    471         0, // sipush
    472         0, // ldc
    473         0, // ldc_w
    474         0, // ldc2_w
    475         0, // iload
    476         0, // lload
    477         0, // fload
    478         0, // dload
    479         0, // aload
    480         0, // iload_0
    481         0, // iload_1
    482         0, // iload_2
    483         0, // iload_3
    484         0, // lload_0
    485         0, // lload_1
    486         0, // lload_2
    487         0, // lload_3
    488         0, // fload_0
    489         0, // fload_1
    490         0, // fload_2
    491         0, // fload_3
    492         0, // dload_0
    493         0, // dload_1
    494         0, // dload_2
    495         0, // dload_3
    496         0, // aload_0
    497         0, // aload_1
    498         0, // aload_2
    499         0, // aload_3
    500         2, // iaload
    501         2, // laload
    502         2, // faload
    503         2, // daload
    504         2, // aaload
    505         2, // baload
    506         2, // caload
    507         2, // saload
    508         1, // istore
    509         2, // lstore
    510         1, // fstore
    511         2, // dstore
    512         1, // astore
    513         1, // istore_0
    514         1, // istore_1
    515         1, // istore_2
    516         1, // istore_3
    517         2, // lstore_0
    518         2, // lstore_1
    519         2, // lstore_2
    520         2, // lstore_3
    521         1, // fstore_0
    522         1, // fstore_1
    523         1, // fstore_2
    524         1, // fstore_3
    525         2, // dstore_0
    526         2, // dstore_1
    527         2, // dstore_2
    528         2, // dstore_3
    529         1, // astore_0
    530         1, // astore_1
    531         1, // astore_2
    532         1, // astore_3
    533         3, // iastore
    534         4, // lastore
    535         3, // fastore
    536         4, // dastore
    537         3, // aastore
    538         3, // bastore
    539         3, // castore
    540         3, // sastore
    541         1, // pop
    542         2, // pop2
    543         1, // dup
    544         2, // dup_x1
    545         3, // dup_x2
    546         2, // dup2
    547         3, // dup2_x1
    548         4, // dup2_x2
    549         2, // swap
    550         2, // iadd
    551         4, // ladd
    552         2, // fadd
    553         4, // dadd
    554         2, // isub
    555         4, // lsub
    556         2, // fsub
    557         4, // dsub
    558         2, // imul
    559         4, // lmul
    560         2, // fmul
    561         4, // dmul
    562         2, // idiv
    563         4, // ldiv
    564         2, // fdiv
    565         4, // ddiv
    566         2, // irem
    567         4, // lrem
    568         2, // frem
    569         4, // drem
    570         1, // ineg
    571         2, // lneg
    572         1, // fneg
    573         2, // dneg
    574         2, // ishl
    575         3, // lshl
    576         2, // ishr
    577         3, // lshr
    578         2, // iushr
    579         3, // lushr
    580         2, // iand
    581         4, // land
    582         2, // ior
    583         4, // lor
    584         2, // ixor
    585         4, // lxor
    586         0, // iinc
    587         1, // i2l
    588         1, // i2f
    589         1, // i2d
    590         2, // l2i
    591         2, // l2f
    592         2, // l2d
    593         1, // f2i
    594         1, // f2l
    595         1, // f2d
    596         2, // d2i
    597         2, // d2l
    598         2, // d2f
    599         1, // i2b
    600         1, // i2c
    601         1, // i2s
    602         4, // lcmp
    603         2, // fcmpl
    604         2, // fcmpg
    605         4, // dcmpl
    606         4, // dcmpg
    607         1, // ifeq
    608         1, // ifne
    609         1, // iflt
    610         1, // ifge
    611         1, // ifgt
    612         1, // ifle
    613         2, // ificmpeq
    614         2, // ificmpne
    615         2, // ificmplt
    616         2, // ificmpge
    617         2, // ificmpgt
    618         2, // ificmple
    619         2, // ifacmpeq
    620         2, // ifacmpne
    621         0, // goto
    622         0, // jsr
    623         0, // ret
    624         1, // tableswitch
    625         1, // lookupswitch
    626         1, // ireturn
    627         2, // lreturn
    628         1, // freturn
    629         2, // dreturn
    630         1, // areturn
    631         0, // return
    632         0, // getstatic
    633         0, // putstatic
    634         1, // getfield
    635         1, // putfield
    636         1, // invokevirtual
    637         1, // invokespecial
    638         0, // invokestatic
    639         1, // invokeinterface
    640         0, // invokedynamic
    641         0, // new
    642         1, // newarray
    643         1, // anewarray
    644         1, // arraylength
    645         1, // athrow
    646         1, // checkcast
    647         1, // instanceof
    648         1, // monitorenter
    649         1, // monitorexit
    650         0, // wide
    651         0, // multianewarray
    652         1, // ifnull
    653         1, // ifnonnull
    654         0, // goto_w
    655         0, // jsr_w
    656     };
    657 
    658 
    659     // An array containing the fixed number of entries pushed onto the stack,
    660     // for all instructions.
    661     private static final int[] STACK_PUSH_COUNTS = new int[]
    662     {
    663         0, // nop
    664         1, // aconst_null
    665         1, // iconst_m1
    666         1, // iconst_0
    667         1, // iconst_1
    668         1, // iconst_2
    669         1, // iconst_3
    670         1, // iconst_4
    671         1, // iconst_5
    672         2, // lconst_0
    673         2, // lconst_1
    674         1, // fconst_0
    675         1, // fconst_1
    676         1, // fconst_2
    677         2, // dconst_0
    678         2, // dconst_1
    679         1, // bipush
    680         1, // sipush
    681         1, // ldc
    682         1, // ldc_w
    683         2, // ldc2_w
    684         1, // iload
    685         2, // lload
    686         1, // fload
    687         2, // dload
    688         1, // aload
    689         1, // iload_0
    690         1, // iload_1
    691         1, // iload_2
    692         1, // iload_3
    693         2, // lload_0
    694         2, // lload_1
    695         2, // lload_2
    696         2, // lload_3
    697         1, // fload_0
    698         1, // fload_1
    699         1, // fload_2
    700         1, // fload_3
    701         2, // dload_0
    702         2, // dload_1
    703         2, // dload_2
    704         2, // dload_3
    705         1, // aload_0
    706         1, // aload_1
    707         1, // aload_2
    708         1, // aload_3
    709         1, // iaload
    710         2, // laload
    711         1, // faload
    712         2, // daload
    713         1, // aaload
    714         1, // baload
    715         1, // caload
    716         1, // saload
    717         0, // istore
    718         0, // lstore
    719         0, // fstore
    720         0, // dstore
    721         0, // astore
    722         0, // istore_0
    723         0, // istore_1
    724         0, // istore_2
    725         0, // istore_3
    726         0, // lstore_0
    727         0, // lstore_1
    728         0, // lstore_2
    729         0, // lstore_3
    730         0, // fstore_0
    731         0, // fstore_1
    732         0, // fstore_2
    733         0, // fstore_3
    734         0, // dstore_0
    735         0, // dstore_1
    736         0, // dstore_2
    737         0, // dstore_3
    738         0, // astore_0
    739         0, // astore_1
    740         0, // astore_2
    741         0, // astore_3
    742         0, // iastore
    743         0, // lastore
    744         0, // fastore
    745         0, // dastore
    746         0, // aastore
    747         0, // bastore
    748         0, // castore
    749         0, // sastore
    750         0, // pop
    751         0, // pop2
    752         2, // dup
    753         3, // dup_x1
    754         4, // dup_x2
    755         4, // dup2
    756         5, // dup2_x1
    757         6, // dup2_x2
    758         2, // swap
    759         1, // iadd
    760         2, // ladd
    761         1, // fadd
    762         2, // dadd
    763         1, // isub
    764         2, // lsub
    765         1, // fsub
    766         2, // dsub
    767         1, // imul
    768         2, // lmul
    769         1, // fmul
    770         2, // dmul
    771         1, // idiv
    772         2, // ldiv
    773         1, // fdiv
    774         2, // ddiv
    775         1, // irem
    776         2, // lrem
    777         1, // frem
    778         2, // drem
    779         1, // ineg
    780         2, // lneg
    781         1, // fneg
    782         2, // dneg
    783         1, // ishl
    784         2, // lshl
    785         1, // ishr
    786         2, // lshr
    787         1, // iushr
    788         2, // lushr
    789         1, // iand
    790         2, // land
    791         1, // ior
    792         2, // lor
    793         1, // ixor
    794         2, // lxor
    795         0, // iinc
    796         2, // i2l
    797         1, // i2f
    798         2, // i2d
    799         1, // l2i
    800         1, // l2f
    801         2, // l2d
    802         1, // f2i
    803         2, // f2l
    804         2, // f2d
    805         1, // d2i
    806         2, // d2l
    807         1, // d2f
    808         1, // i2b
    809         1, // i2c
    810         1, // i2s
    811         1, // lcmp
    812         1, // fcmpl
    813         1, // fcmpg
    814         1, // dcmpl
    815         1, // dcmpg
    816         0, // ifeq
    817         0, // ifne
    818         0, // iflt
    819         0, // ifge
    820         0, // ifgt
    821         0, // ifle
    822         0, // ificmpeq
    823         0, // ificmpne
    824         0, // ificmplt
    825         0, // ificmpge
    826         0, // ificmpgt
    827         0, // ificmple
    828         0, // ifacmpeq
    829         0, // ifacmpne
    830         0, // goto
    831         1, // jsr
    832         0, // ret
    833         0, // tableswitch
    834         0, // lookupswitch
    835         0, // ireturn
    836         0, // lreturn
    837         0, // freturn
    838         0, // dreturn
    839         0, // areturn
    840         0, // return
    841         0, // getstatic
    842         0, // putstatic
    843         0, // getfield
    844         0, // putfield
    845         0, // invokevirtual
    846         0, // invokespecial
    847         0, // invokestatic
    848         0, // invokeinterface
    849         0, // invokedynamic
    850         1, // new
    851         1, // newarray
    852         1, // anewarray
    853         1, // arraylength
    854         0, // athrow
    855         1, // checkcast
    856         1, // instanceof
    857         0, // monitorenter
    858         0, // monitorexit
    859         0, // wide
    860         1, // multianewarray
    861         0, // ifnull
    862         0, // ifnonnull
    863         0, // goto_w
    864         1, // jsr_w
    865     };
    866 
    867 
    868     public byte opcode;
    869 
    870 
    871     /**
    872      * Returns the canonical opcode of this instruction, i.e. typically the
    873      * opcode whose extension has been removed.
    874      */
    875     public byte canonicalOpcode()
    876     {
    877         return opcode;
    878     }
    879 
    880 
    881     /**
    882      * Shrinks this instruction to its shortest possible form.
    883      * @return this instruction.
    884      */
    885     public abstract Instruction shrink();
    886 
    887 
    888 
    889     /**
    890      * Writes the Instruction at the given offset in the given code attribute.
    891      */
    892     public final void write(CodeAttribute codeAttribute, int offset)
    893     {
    894         write(codeAttribute.code, offset);
    895     }
    896 
    897 
    898     /**
    899      * Writes the Instruction at the given offset in the given code array.
    900      */
    901     public void write(byte[] code, int offset)
    902     {
    903         // Write the wide opcode, if necessary.
    904         if (isWide())
    905         {
    906             code[offset++] = InstructionConstants.OP_WIDE;
    907         }
    908 
    909         // Write the opcode.
    910         code[offset++] = opcode;
    911 
    912         // Write any additional arguments.
    913         writeInfo(code, offset);
    914     }
    915 
    916 
    917     /**
    918      * Returns whether the instruction is wide, i.e. preceded by a wide opcode.
    919      * With the current specifications, only variable instructions can be wide.
    920      */
    921     protected boolean isWide()
    922     {
    923         return false;
    924     }
    925 
    926 
    927     /**
    928      * Reads the data following the instruction opcode.
    929      */
    930     protected abstract void readInfo(byte[] code, int offset);
    931 
    932 
    933     /**
    934      * Writes data following the instruction opcode.
    935      */
    936     protected abstract void writeInfo(byte[] code, int offset);
    937 
    938 
    939     /**
    940      * Returns the length in bytes of the instruction.
    941      */
    942     public abstract int length(int offset);
    943 
    944 
    945     /**
    946      * Accepts the given visitor.
    947      */
    948     public abstract void accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor);
    949 
    950 
    951     /**
    952      * Returns a description of the instruction, at the given offset.
    953      */
    954     public String toString(int offset)
    955     {
    956         return "["+offset+"] "+ this.toString();
    957     }
    958 
    959 
    960     /**
    961      * Returns the name of the instruction.
    962      */
    963     public String getName()
    964     {
    965         return InstructionConstants.NAMES[opcode & 0xff];
    966     }
    967 
    968 
    969     /**
    970      * Returns whether the instruction may throw exceptions.
    971      */
    972     public boolean mayThrowExceptions()
    973     {
    974         return MAY_THROW_EXCEPTIONS[opcode & 0xff];
    975     }
    976 
    977 
    978     /**
    979      * Returns whether the instruction is a Category 2 instruction. This means
    980      * that it operates on long or double arguments.
    981      */
    982     public boolean isCategory2()
    983     {
    984         return IS_CATEGORY2[opcode & 0xff];
    985     }
    986 
    987 
    988     /**
    989      * Returns the number of entries popped from the stack during the execution
    990      * of the instruction.
    991      */
    992     public int stackPopCount(Clazz clazz)
    993     {
    994         return STACK_POP_COUNTS[opcode & 0xff];
    995     }
    996 
    997 
    998     /**
    999      * Returns the number of entries pushed onto the stack during the execution
   1000      * of the instruction.
   1001      */
   1002     public int stackPushCount(Clazz clazz)
   1003     {
   1004         return STACK_PUSH_COUNTS[opcode & 0xff];
   1005     }
   1006 
   1007 
   1008     // Small utility methods.
   1009 
   1010     protected static int readByte(byte[] code, int offset)
   1011     {
   1012         return code[offset] & 0xff;
   1013     }
   1014 
   1015     protected static int readShort(byte[] code, int offset)
   1016     {
   1017         return ((code[offset++] & 0xff) << 8) |
   1018                ( code[offset  ] & 0xff      );
   1019     }
   1020 
   1021     protected static int readInt(byte[] code, int offset)
   1022     {
   1023         return ( code[offset++]         << 24) |
   1024                ((code[offset++] & 0xff) << 16) |
   1025                ((code[offset++] & 0xff) <<  8) |
   1026                ( code[offset  ] & 0xff       );
   1027     }
   1028 
   1029     protected static int readValue(byte[] code, int offset, int valueSize)
   1030     {
   1031         switch (valueSize)
   1032         {
   1033             case 0: return 0;
   1034             case 1: return readByte( code, offset);
   1035             case 2: return readShort(code, offset);
   1036             case 4: return readInt(  code, offset);
   1037             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
   1038         }
   1039     }
   1040 
   1041     protected static int readSignedByte(byte[] code, int offset)
   1042     {
   1043         return code[offset];
   1044     }
   1045 
   1046     protected static int readSignedShort(byte[] code, int offset)
   1047     {
   1048         return (code[offset++] <<   8) |
   1049                (code[offset  ] & 0xff);
   1050     }
   1051 
   1052     protected static int readSignedValue(byte[] code, int offset, int valueSize)
   1053     {
   1054         switch (valueSize)
   1055         {
   1056             case 0: return 0;
   1057             case 1: return readSignedByte( code, offset);
   1058             case 2: return readSignedShort(code, offset);
   1059             case 4: return readInt(        code, offset);
   1060             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
   1061         }
   1062     }
   1063 
   1064     protected static void writeByte(byte[] code, int offset, int value)
   1065     {
   1066         if (value > 0xff)
   1067         {
   1068             throw new IllegalArgumentException("Unsigned byte value larger than 0xff ["+value+"]");
   1069         }
   1070 
   1071         code[offset] = (byte)value;
   1072     }
   1073 
   1074     protected static void writeShort(byte[] code, int offset, int value)
   1075     {
   1076         if (value > 0xffff)
   1077         {
   1078             throw new IllegalArgumentException("Unsigned short value larger than 0xffff ["+value+"]");
   1079         }
   1080 
   1081         code[offset++] = (byte)(value >> 8);
   1082         code[offset  ] = (byte)(value     );
   1083     }
   1084 
   1085     protected static void writeInt(byte[] code, int offset, int value)
   1086     {
   1087         code[offset++] = (byte)(value >> 24);
   1088         code[offset++] = (byte)(value >> 16);
   1089         code[offset++] = (byte)(value >>  8);
   1090         code[offset  ] = (byte)(value      );
   1091     }
   1092 
   1093     protected static void writeValue(byte[] code, int offset, int value, int valueSize)
   1094     {
   1095         switch (valueSize)
   1096         {
   1097             case 0:                                  break;
   1098             case 1: writeByte( code, offset, value); break;
   1099             case 2: writeShort(code, offset, value); break;
   1100             case 4: writeInt(  code, offset, value); break;
   1101             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
   1102         }
   1103     }
   1104 
   1105     protected static void writeSignedByte(byte[] code, int offset, int value)
   1106     {
   1107         if ((byte)value != value)
   1108         {
   1109             throw new IllegalArgumentException("Signed byte value out of range ["+value+"]");
   1110         }
   1111 
   1112         code[offset] = (byte)value;
   1113     }
   1114 
   1115     protected static void writeSignedShort(byte[] code, int offset, int value)
   1116     {
   1117         if ((short)value != value)
   1118         {
   1119             throw new IllegalArgumentException("Signed short value out of range ["+value+"]");
   1120         }
   1121 
   1122         code[offset++] = (byte)(value >> 8);
   1123         code[offset  ] = (byte)(value     );
   1124     }
   1125 
   1126     protected static void writeSignedValue(byte[] code, int offset, int value, int valueSize)
   1127     {
   1128         switch (valueSize)
   1129         {
   1130             case 0:                                        break;
   1131             case 1: writeSignedByte( code, offset, value); break;
   1132             case 2: writeSignedShort(code, offset, value); break;
   1133             case 4: writeInt(        code, offset, value); break;
   1134             default: throw new IllegalArgumentException("Unsupported value size ["+valueSize+"]");
   1135         }
   1136     }
   1137 }
   1138