KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > proguard > classfile > instruction > Instruction


1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  * of Java bytecode.
4  *
5  * Copyright (c) 2002-2007 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.instruction.visitor.InstructionVisitor;
25 import proguard.classfile.attribute.*;
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, // unused
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, // unused
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, // unused
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 final 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, index.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 JavaDoc toString(int offset)
747     {
748         return "["+offset+"] "+ this.toString();
749     }
750
751
752     /**
753      * Returns the name of the instruction.
754      */

755     public String JavaDoc 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 JavaDoc("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 JavaDoc("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 JavaDoc("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 JavaDoc("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 JavaDoc("Unsupported value size ["+valueSize+"]");
885         }
886     }
887
888     protected static void writeSignedByte(byte[] code, int offset, int value)
889     {
890         if (value << 24 >> 24 != value)
891         {
892             throw new IllegalArgumentException JavaDoc("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 (value << 16 >> 16 != value)
901         {
902             throw new IllegalArgumentException JavaDoc("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 JavaDoc("Unsupported value size ["+valueSize+"]");
918         }
919     }
920 }
921
Popular Tags