• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@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      */
canonicalOpcode()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      */
shrink()885     public abstract Instruction shrink();
886 
887 
888 
889     /**
890      * Writes the Instruction at the given offset in the given code attribute.
891      */
write(CodeAttribute codeAttribute, int offset)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      */
write(byte[] code, int offset)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      */
isWide()921     protected boolean isWide()
922     {
923         return false;
924     }
925 
926 
927     /**
928      * Reads the data following the instruction opcode.
929      */
readInfo(byte[] code, int offset)930     protected abstract void readInfo(byte[] code, int offset);
931 
932 
933     /**
934      * Writes data following the instruction opcode.
935      */
writeInfo(byte[] code, int offset)936     protected abstract void writeInfo(byte[] code, int offset);
937 
938 
939     /**
940      * Returns the length in bytes of the instruction.
941      */
length(int offset)942     public abstract int length(int offset);
943 
944 
945     /**
946      * Accepts the given visitor.
947      */
accept(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, InstructionVisitor instructionVisitor)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      */
toString(int offset)954     public String toString(int offset)
955     {
956         return "["+offset+"] "+ this.toString();
957     }
958 
959 
960     /**
961      * Returns the name of the instruction.
962      */
getName()963     public String getName()
964     {
965         return InstructionConstants.NAMES[opcode & 0xff];
966     }
967 
968 
969     /**
970      * Returns whether the instruction may throw exceptions.
971      */
mayThrowExceptions()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      */
isCategory2()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      */
stackPopCount(Clazz clazz)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      */
stackPushCount(Clazz clazz)1002     public int stackPushCount(Clazz clazz)
1003     {
1004         return STACK_PUSH_COUNTS[opcode & 0xff];
1005     }
1006 
1007 
1008     // Small utility methods.
1009 
readByte(byte[] code, int offset)1010     protected static int readByte(byte[] code, int offset)
1011     {
1012         return code[offset] & 0xff;
1013     }
1014 
readShort(byte[] code, int offset)1015     protected static int readShort(byte[] code, int offset)
1016     {
1017         return ((code[offset++] & 0xff) << 8) |
1018                ( code[offset  ] & 0xff      );
1019     }
1020 
readInt(byte[] code, int offset)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 
readValue(byte[] code, int offset, int valueSize)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 
readSignedByte(byte[] code, int offset)1041     protected static int readSignedByte(byte[] code, int offset)
1042     {
1043         return code[offset];
1044     }
1045 
readSignedShort(byte[] code, int offset)1046     protected static int readSignedShort(byte[] code, int offset)
1047     {
1048         return (code[offset++] <<   8) |
1049                (code[offset  ] & 0xff);
1050     }
1051 
readSignedValue(byte[] code, int offset, int valueSize)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 
writeByte(byte[] code, int offset, int value)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 
writeShort(byte[] code, int offset, int value)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 
writeInt(byte[] code, int offset, int value)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 
writeValue(byte[] code, int offset, int value, int valueSize)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 
writeSignedByte(byte[] code, int offset, int value)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 
writeSignedShort(byte[] code, int offset, int value)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 
writeSignedValue(byte[] code, int offset, int value, int valueSize)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