1 package serp.bytecode;
2
3 import java.io.*;
4 import java.util.*;
5
6 import serp.bytecode.lowlevel.*;
7 import serp.bytecode.visitor.*;
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public class Code extends Attribute {
33 private final CodeEntry _head;
34 private final CodeEntry _tail;
35 private CodeIterator _ci;
36 private int _maxStack = 0;
37 private int _maxLocals = 0;
38 private int _size = 0;
39 private Collection _handlers = new LinkedList();
40 private Collection _attrs = new LinkedList();
41 private boolean _byteIndexesValid;
42
43 Code(int nameIndex, Attributes owner) {
44 super(nameIndex, owner);
45 _head = new CodeEntry();
46 _tail = new CodeEntry();
47 _head.next = _tail;
48 _tail.prev = _head;
49 _ci = new CodeIterator(_head, -1);
50 }
51
52
53
54
55
56
57 public Code() {
58 this(0, new Project().loadClass("", null).declareMethod("", void.class,
59 null));
60 }
61
62
63
64
65 public BCMethod getMethod() {
66 return (BCMethod) getOwner();
67 }
68
69 Collection getAttributesHolder() {
70 return _attrs;
71 }
72
73
74
75
76
77
78
79
80 public int getMaxStack() {
81 return _maxStack;
82 }
83
84
85
86
87 public void setMaxStack(int max) {
88 _maxStack = max;
89 }
90
91
92
93
94
95 public int getMaxLocals() {
96 return _maxLocals;
97 }
98
99
100
101
102
103 public void setMaxLocals(int max) {
104 _maxLocals = max;
105 }
106
107
108
109
110
111
112
113
114 public int getLocalsIndex(int paramIndex) {
115 if (paramIndex < 0)
116 return -1;
117
118 int pos = 0;
119 if (!getMethod().isStatic())
120 pos = 1;
121 String[] params = getMethod().getParamNames();
122 for (int i = 0; i < paramIndex; i++, pos++) {
123 if (i == params.length)
124 return -1;
125 if (params[i].equals(long.class.getName())
126 || params[i].equals(double.class.getName()))
127 pos++;
128 }
129 return pos;
130 }
131
132
133
134
135
136
137
138 public int getParamsIndex(int localIndex) {
139 int pos = 0;
140 if (!getMethod().isStatic())
141 pos = 1;
142 String[] params = getMethod().getParamNames();
143 for (int i = 0; i < params.length; i++, pos++) {
144 if (localIndex == pos)
145 return i;
146 if (params[i].equals(long.class.getName())
147 || params[i].equals(double.class.getName()))
148 pos++;
149 }
150 return -1;
151 }
152
153
154
155
156 public int getNextLocalsIndex() {
157 calculateMaxLocals();
158 return getMaxLocals();
159 }
160
161
162
163
164
165
166
167
168 public void calculateMaxLocals() {
169
170
171 String[] params = getMethod().getParamNames();
172 int max = 0;
173 if ((params.length == 0) && !getMethod().isStatic())
174 max = 1;
175 else if (params.length > 0) {
176 max = getLocalsIndex(params.length - 1) + 1;
177 if (params[params.length - 1].equals(long.class.getName())
178 || params[params.length - 1].equals(double.class.getName()))
179 max++;
180 }
181
182
183
184 StoreInstruction store;
185 int current;
186 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
187 current = 0;
188 if (entry instanceof StoreInstruction) {
189 store = (StoreInstruction) entry;
190 current = store.getLocal() + 1;
191 if (store.getType().equals(long.class)
192 || store.getType().equals(double.class))
193 current++;
194 if (current > max)
195 max = current;
196 }
197 }
198 setMaxLocals(max);
199 }
200
201
202
203
204
205
206
207 public void calculateMaxStack() {
208 int stack = 0;
209 int max = 0;
210 ExceptionHandler[] handlers = getExceptionHandlers();
211 Instruction ins;
212 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
213 ins = (Instruction) entry;
214 stack += ins.getStackChange();
215
216
217
218 for (int j = 0; j < handlers.length; j++)
219 if (handlers[j].getTryStart() == ins)
220 stack++;
221 if (stack > max)
222 max = stack;
223 }
224 setMaxStack(max);
225 }
226
227
228
229
230
231
232
233
234
235 public ExceptionHandler[] getExceptionHandlers() {
236 return (ExceptionHandler[]) _handlers.toArray
237 (new ExceptionHandler[_handlers.size()]);
238 }
239
240
241
242
243
244
245 public ExceptionHandler getExceptionHandler(String catchType) {
246 catchType = getProject().getNameCache().getExternalForm(catchType,
247 false);
248 String type;
249 ExceptionHandler[] handlers = getExceptionHandlers();
250 for (int i = 0; i < handlers.length; i++) {
251 type = handlers[i].getCatchName();
252 if ((type == null && catchType == null)
253 || (type != null && type.equals(catchType)))
254 return handlers[i];
255 }
256 return null;
257 }
258
259
260
261
262
263
264 public ExceptionHandler getExceptionHandler(Class catchType) {
265 if (catchType == null)
266 return getExceptionHandler((String) null);
267 return getExceptionHandler(catchType.getName());
268 }
269
270
271
272
273
274
275 public ExceptionHandler getExceptionHandler(BCClass catchType) {
276 if (catchType == null)
277 return getExceptionHandler((String) null);
278 return getExceptionHandler(catchType.getName());
279 }
280
281
282
283
284
285 public ExceptionHandler[] getExceptionHandlers(String catchType) {
286 catchType = getProject().getNameCache().getExternalForm(catchType,
287 false);
288 List matches = new LinkedList();
289 String type;
290 ExceptionHandler[] handlers = getExceptionHandlers();
291 for (int i = 0; i < handlers.length; i++) {
292 type = handlers[i].getCatchName();
293 if ((type == null && catchType == null)
294 || (type != null && type.equals(catchType)))
295 matches.add(handlers[i]);
296 }
297 return (ExceptionHandler[]) matches.toArray
298 (new ExceptionHandler[matches.size()]);
299 }
300
301
302
303
304
305 public ExceptionHandler[] getExceptionHandlers(Class catchType) {
306 if (catchType == null)
307 return getExceptionHandlers((String) null);
308 return getExceptionHandlers(catchType.getName());
309 }
310
311
312
313
314
315 public ExceptionHandler[] getExceptionHandlers(BCClass catchType) {
316 if (catchType == null)
317 return getExceptionHandlers((String) null);
318 return getExceptionHandlers(catchType.getName());
319 }
320
321
322
323
324
325
326 public void setExceptionHandlers(ExceptionHandler[] handlers) {
327 clearExceptionHandlers();
328 if (handlers != null)
329 for (int i = 0; i < handlers.length; i++)
330 addExceptionHandler(handlers[i]);
331 }
332
333
334
335
336 public ExceptionHandler addExceptionHandler(ExceptionHandler handler) {
337 ExceptionHandler newHandler = addExceptionHandler();
338 newHandler.read(handler);
339 return newHandler;
340 }
341
342
343
344
345 public ExceptionHandler addExceptionHandler() {
346 ExceptionHandler handler = new ExceptionHandler(this);
347 _handlers.add(handler);
348 return handler;
349 }
350
351
352
353
354
355
356
357
358
359 public ExceptionHandler addExceptionHandler(Instruction tryStart,
360 Instruction tryEnd, Instruction handlerStart, String catchType) {
361 ExceptionHandler handler = addExceptionHandler();
362 handler.setTryStart(tryStart);
363 handler.setTryEnd(tryEnd);
364 handler.setHandlerStart(handlerStart);
365 handler.setCatch(catchType);
366 return handler;
367 }
368
369
370
371
372
373
374
375
376
377 public ExceptionHandler addExceptionHandler(Instruction tryStart,
378 Instruction tryEnd, Instruction handlerStart, Class catchType) {
379 String catchName = null;
380 if (catchType != null)
381 catchName = catchType.getName();
382 return addExceptionHandler(tryStart, tryEnd, handlerStart, catchName);
383 }
384
385
386
387
388
389
390
391
392
393 public ExceptionHandler addExceptionHandler(Instruction tryStart,
394 Instruction tryEnd, Instruction handlerStart, BCClass catchType) {
395 String catchName = null;
396 if (catchType != null)
397 catchName = catchType.getName();
398 return addExceptionHandler(tryStart, tryEnd, handlerStart, catchName);
399 }
400
401
402
403
404 public void clearExceptionHandlers() {
405 ExceptionHandler handler;
406 for (Iterator itr = _handlers.iterator(); itr.hasNext();) {
407 handler = (ExceptionHandler) itr.next();
408 itr.remove();
409 handler.invalidate();
410 }
411 }
412
413
414
415
416 public boolean removeExceptionHandler(String catchType) {
417 return removeExceptionHandler(getExceptionHandler(catchType));
418 }
419
420
421
422
423
424
425 public boolean removeExceptionHandler(Class catchType) {
426 if (catchType == null)
427 return removeExceptionHandler((String) null);
428 return removeExceptionHandler(catchType.getName());
429 }
430
431
432
433
434
435
436 public boolean removeExceptionHandler(BCClass catchType) {
437 if (catchType == null)
438 return removeExceptionHandler((String) null);
439 return removeExceptionHandler(catchType.getName());
440 }
441
442
443
444
445
446 public boolean removeExceptionHandler(ExceptionHandler handler) {
447 if ((handler == null) || !_handlers.remove(handler))
448 return false;
449 handler.invalidate();
450 return true;
451 }
452
453
454
455
456
457
458
459
460 public int size() {
461 return _size;
462 }
463
464
465
466
467 public void beforeFirst() {
468 _ci = new CodeIterator(_head, -1);
469 }
470
471
472
473
474 public void afterLast() {
475 if (_size == 0)
476 _ci = new CodeIterator(_head, -1);
477 else
478 _ci = new CodeIterator(_tail.prev, _size - 1);
479 }
480
481
482
483
484
485 public void before(Instruction ins) {
486 if (ins.getCode() != this)
487 throw new IllegalArgumentException("ins.code != this");
488 _ci = new CodeIterator(ins.prev, CodeIterator.UNSET);
489 }
490
491
492
493
494
495 public void after(Instruction ins) {
496 before(ins);
497 next();
498 }
499
500
501
502
503
504 public boolean hasNext() {
505 return _ci.hasNext();
506 }
507
508
509
510
511
512 public boolean hasPrevious() {
513 return _ci.hasPrevious();
514 }
515
516
517
518
519 public Instruction next() {
520 return (Instruction) _ci.next();
521 }
522
523
524
525
526 public int nextIndex() {
527 return _ci.nextIndex();
528 }
529
530
531
532
533 public Instruction previous() {
534 return (Instruction) _ci.previous();
535 }
536
537
538
539
540 public int previousIndex() {
541 return _ci.previousIndex();
542 }
543
544
545
546
547 public void before(int index) {
548 if (index < 0 || index >= _size)
549 throw new IndexOutOfBoundsException(String.valueOf(index));
550
551 CodeEntry entry = _head;
552 for (int i = 0; i < index; entry = entry.next, i++);
553 _ci = new CodeIterator(entry, index - 1);
554 }
555
556
557
558
559 public void after(int index) {
560 before(index);
561 next();
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576 public boolean searchForward(Instruction template) {
577 if (template == null)
578 return false;
579
580 while (hasNext())
581 if (template.equalsInstruction(next()))
582 return true;
583 return false;
584 }
585
586
587
588
589
590
591
592
593
594
595
596
597
598 public boolean searchBackward(Instruction template) {
599 if (template == null)
600 return false;
601
602 while (hasPrevious())
603 if (template.equalsInstruction(previous()))
604 return true;
605 return false;
606 }
607
608
609
610
611
612
613 public Instruction add(Instruction ins) {
614 Instruction newIns = createInstruction(ins.getOpcode());
615 newIns.read(ins);
616 _ci.add(newIns);
617 return newIns;
618 }
619
620
621
622
623
624
625
626
627
628 public Instruction set(Instruction ins) {
629 Instruction newIns = createInstruction(ins.getOpcode());
630 newIns.read(ins);
631 _ci.set(newIns);
632 return newIns;
633 }
634
635
636
637
638
639
640
641
642 public int replace(Instruction template, Instruction with) {
643 beforeFirst();
644 int count;
645 for (count = 0; searchForward(template); count++)
646 set(with);
647 return count;
648 }
649
650
651
652
653
654 public int replace(Instruction[] templates, Instruction[] with) {
655 if (templates == null || with == null)
656 return 0;
657
658 int count = 0;
659 for (int i = 0; i < templates.length; i++) {
660 if (with == null)
661 count += replace(templates[i], null);
662 else
663 count += replace(templates[i], with[i]);
664 }
665 return count;
666 }
667
668
669
670
671
672
673 public void remove() {
674 _ci.remove();
675 }
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690 public ClassConstantInstruction classconstant() {
691 return new ClassConstantInstruction(getMethod().getDeclarer(), this,
692 nop());
693 }
694
695
696
697
698 public Instruction nop() {
699 return addInstruction(Constants.NOP);
700 }
701
702
703
704
705
706
707
708
709 public ConstantInstruction constant() {
710 return (ConstantInstruction) addInstruction(new ConstantInstruction
711 (this));
712 }
713
714
715
716
717
718 public LoadInstruction xload() {
719 return (LoadInstruction) addInstruction(new LoadInstruction(this));
720 }
721
722
723
724
725
726 public LoadInstruction iload() {
727 return (LoadInstruction) addInstruction(new LoadInstruction(this).
728 setType(int.class));
729 }
730
731
732
733
734
735 public LoadInstruction lload() {
736 return (LoadInstruction) addInstruction(new LoadInstruction(this).
737 setType(long.class));
738 }
739
740
741
742
743
744 public LoadInstruction fload() {
745 return (LoadInstruction) addInstruction(new LoadInstruction(this).
746 setType(float.class));
747 }
748
749
750
751
752
753 public LoadInstruction dload() {
754 return (LoadInstruction) addInstruction(new LoadInstruction(this).
755 setType(double.class));
756 }
757
758
759
760
761
762 public LoadInstruction aload() {
763 return (LoadInstruction) addInstruction(new LoadInstruction(this).
764 setType(Object.class));
765 }
766
767
768
769
770
771 public StoreInstruction xstore() {
772 return (StoreInstruction) addInstruction(new StoreInstruction(this));
773 }
774
775
776
777
778
779
780 public StoreInstruction istore() {
781 return (StoreInstruction) addInstruction(new StoreInstruction(this).
782 setType(int.class));
783 }
784
785
786
787
788
789
790 public StoreInstruction lstore() {
791 return (StoreInstruction) addInstruction(new StoreInstruction(this).
792 setType(long.class));
793 }
794
795
796
797
798
799
800 public StoreInstruction fstore() {
801 return (StoreInstruction) addInstruction(new StoreInstruction(this).
802 setType(float.class));
803 }
804
805
806
807
808
809
810 public StoreInstruction dstore() {
811 return (StoreInstruction) addInstruction(new StoreInstruction(this).
812 setType(double.class));
813 }
814
815
816
817
818
819
820 public StoreInstruction astore() {
821 return (StoreInstruction) addInstruction(new StoreInstruction(this).
822 setType(Object.class));
823 }
824
825
826
827
828
829 public RetInstruction ret() {
830 return (RetInstruction) addInstruction(Constants.RET);
831 }
832
833
834
835
836 public IIncInstruction iinc() {
837 return (IIncInstruction) addInstruction(Constants.IINC);
838 }
839
840
841
842
843 public WideInstruction wide() {
844 return (WideInstruction) addInstruction(Constants.WIDE);
845 }
846
847
848
849
850
851 public ArrayLoadInstruction xaload() {
852 return (ArrayLoadInstruction) addInstruction(new ArrayLoadInstruction(
853 this));
854 }
855
856
857
858
859 public ArrayLoadInstruction iaload() {
860 return (ArrayLoadInstruction) addInstruction(Constants.IALOAD);
861 }
862
863
864
865
866 public ArrayLoadInstruction laload() {
867 return (ArrayLoadInstruction) addInstruction(Constants.LALOAD);
868 }
869
870
871
872
873 public ArrayLoadInstruction faload() {
874 return (ArrayLoadInstruction) addInstruction(Constants.FALOAD);
875 }
876
877
878
879
880 public ArrayLoadInstruction daload() {
881 return (ArrayLoadInstruction) addInstruction(Constants.DALOAD);
882 }
883
884
885
886
887
888 public ArrayLoadInstruction aaload() {
889 return (ArrayLoadInstruction) addInstruction(Constants.AALOAD);
890 }
891
892
893
894
895 public ArrayLoadInstruction baload() {
896 return (ArrayLoadInstruction) addInstruction(Constants.BALOAD);
897 }
898
899
900
901
902 public ArrayLoadInstruction caload() {
903 return (ArrayLoadInstruction) addInstruction(Constants.CALOAD);
904 }
905
906
907
908
909 public ArrayLoadInstruction saload() {
910 return (ArrayLoadInstruction) addInstruction(Constants.SALOAD);
911 }
912
913
914
915
916
917 public ArrayStoreInstruction xastore() {
918 return (ArrayStoreInstruction) addInstruction(new ArrayStoreInstruction(
919 this));
920 }
921
922
923
924
925
926 public ArrayStoreInstruction iastore() {
927 return (ArrayStoreInstruction) addInstruction(Constants.IASTORE);
928 }
929
930
931
932
933
934 public ArrayStoreInstruction lastore() {
935 return (ArrayStoreInstruction) addInstruction(Constants.LASTORE);
936 }
937
938
939
940
941
942 public ArrayStoreInstruction fastore() {
943 return (ArrayStoreInstruction) addInstruction(Constants.FASTORE);
944 }
945
946
947
948
949
950 public ArrayStoreInstruction dastore() {
951 return (ArrayStoreInstruction) addInstruction(Constants.DASTORE);
952 }
953
954
955
956
957
958 public ArrayStoreInstruction aastore() {
959 return (ArrayStoreInstruction) addInstruction(Constants.AASTORE);
960 }
961
962
963
964
965
966 public ArrayStoreInstruction bastore() {
967 return (ArrayStoreInstruction) addInstruction(Constants.BASTORE);
968 }
969
970
971
972
973
974 public ArrayStoreInstruction castore() {
975 return (ArrayStoreInstruction) addInstruction(Constants.CASTORE);
976 }
977
978
979
980
981
982 public ArrayStoreInstruction sastore() {
983 return (ArrayStoreInstruction) addInstruction(Constants.SASTORE);
984 }
985
986
987
988
989 public StackInstruction pop() {
990 return (StackInstruction) addInstruction(Constants.POP);
991 }
992
993
994
995
996 public StackInstruction pop2() {
997 return (StackInstruction) addInstruction(Constants.POP2);
998 }
999
1000
1001
1002
1003 public StackInstruction dup() {
1004 return (StackInstruction) addInstruction(Constants.DUP);
1005 }
1006
1007
1008
1009
1010 public StackInstruction dupx1() {
1011 return (StackInstruction) addInstruction(Constants.DUPX1);
1012 }
1013
1014
1015
1016
1017 public StackInstruction dupx2() {
1018 return (StackInstruction) addInstruction(Constants.DUPX2);
1019 }
1020
1021
1022
1023
1024 public StackInstruction dup2() {
1025 return (StackInstruction) addInstruction(Constants.DUP2);
1026 }
1027
1028
1029
1030
1031 public StackInstruction dup2x1() {
1032 return (StackInstruction) addInstruction(Constants.DUP2X1);
1033 }
1034
1035
1036
1037
1038 public StackInstruction dup2x2() {
1039 return (StackInstruction) addInstruction(Constants.DUP2X2);
1040 }
1041
1042
1043
1044
1045 public StackInstruction swap() {
1046 return (StackInstruction) addInstruction(Constants.SWAP);
1047 }
1048
1049
1050
1051
1052
1053 public MathInstruction math() {
1054 return (MathInstruction) addInstruction(new MathInstruction(this));
1055 }
1056
1057
1058
1059
1060
1061 public MathInstruction xadd() {
1062 MathInstruction mi = math();
1063
1064 return mi.setOperation(Constants.MATH_ADD);
1065 }
1066
1067
1068
1069
1070 public MathInstruction iadd() {
1071 return (MathInstruction) addInstruction(Constants.IADD);
1072 }
1073
1074
1075
1076
1077 public MathInstruction ladd() {
1078 return (MathInstruction) addInstruction(Constants.LADD);
1079 }
1080
1081
1082
1083
1084 public MathInstruction fadd() {
1085 return (MathInstruction) addInstruction(Constants.FADD);
1086 }
1087
1088
1089
1090
1091 public MathInstruction dadd() {
1092 return (MathInstruction) addInstruction(Constants.DADD);
1093 }
1094
1095
1096
1097
1098
1099 public MathInstruction xsub() {
1100 MathInstruction mi = math();
1101 return mi.setOperation(Constants.MATH_SUB);
1102 }
1103
1104
1105
1106
1107 public MathInstruction isub() {
1108 return (MathInstruction) addInstruction(Constants.ISUB);
1109 }
1110
1111
1112
1113
1114 public MathInstruction lsub() {
1115 return (MathInstruction) addInstruction(Constants.LSUB);
1116 }
1117
1118
1119
1120
1121 public MathInstruction fsub() {
1122 return (MathInstruction) addInstruction(Constants.FSUB);
1123 }
1124
1125
1126
1127
1128 public MathInstruction dsub() {
1129 return (MathInstruction) addInstruction(Constants.DSUB);
1130 }
1131
1132
1133
1134
1135
1136 public MathInstruction xmul() {
1137 MathInstruction mi = math();
1138 return mi.setOperation(Constants.MATH_MUL);
1139 }
1140
1141
1142
1143
1144 public MathInstruction imul() {
1145 return (MathInstruction) addInstruction(Constants.IMUL);
1146 }
1147
1148
1149
1150
1151 public MathInstruction lmul() {
1152 return (MathInstruction) addInstruction(Constants.LMUL);
1153 }
1154
1155
1156
1157
1158 public MathInstruction fmul() {
1159 return (MathInstruction) addInstruction(Constants.FMUL);
1160 }
1161
1162
1163
1164
1165 public MathInstruction dmul() {
1166 return (MathInstruction) addInstruction(Constants.DMUL);
1167 }
1168
1169
1170
1171
1172
1173 public MathInstruction xdiv() {
1174 MathInstruction mi = math();
1175 return mi.setOperation(Constants.MATH_DIV);
1176 }
1177
1178
1179
1180
1181 public MathInstruction idiv() {
1182 return (MathInstruction) addInstruction(Constants.IDIV);
1183 }
1184
1185
1186
1187
1188 public MathInstruction ldiv() {
1189 return (MathInstruction) addInstruction(Constants.LDIV);
1190 }
1191
1192
1193
1194
1195 public MathInstruction fdiv() {
1196 return (MathInstruction) addInstruction(Constants.FDIV);
1197 }
1198
1199
1200
1201
1202 public MathInstruction ddiv() {
1203 return (MathInstruction) addInstruction(Constants.DDIV);
1204 }
1205
1206
1207
1208
1209
1210 public MathInstruction xrem() {
1211 MathInstruction mi = math();
1212 return mi.setOperation(Constants.MATH_REM);
1213 }
1214
1215
1216
1217
1218
1219 public MathInstruction irem() {
1220 return (MathInstruction) addInstruction(Constants.IREM);
1221 }
1222
1223
1224
1225
1226
1227 public MathInstruction lrem() {
1228 return (MathInstruction) addInstruction(Constants.LREM);
1229 }
1230
1231
1232
1233
1234
1235 public MathInstruction frem() {
1236 return (MathInstruction) addInstruction(Constants.FREM);
1237 }
1238
1239
1240
1241
1242
1243 public MathInstruction drem() {
1244 return (MathInstruction) addInstruction(Constants.DREM);
1245 }
1246
1247
1248
1249
1250
1251 public MathInstruction xneg() {
1252 MathInstruction mi = math();
1253 return mi.setOperation(Constants.MATH_NEG);
1254 }
1255
1256
1257
1258
1259 public MathInstruction ineg() {
1260 return (MathInstruction) addInstruction(Constants.INEG);
1261 }
1262
1263
1264
1265
1266 public MathInstruction lneg() {
1267 return (MathInstruction) addInstruction(Constants.LNEG);
1268 }
1269
1270
1271
1272
1273 public MathInstruction fneg() {
1274 return (MathInstruction) addInstruction(Constants.FNEG);
1275 }
1276
1277
1278
1279
1280 public MathInstruction dneg() {
1281 return (MathInstruction) addInstruction(Constants.DNEG);
1282 }
1283
1284
1285
1286
1287
1288 public MathInstruction xshl() {
1289 MathInstruction mi = math();
1290 return mi.setOperation(Constants.MATH_SHL);
1291 }
1292
1293
1294
1295
1296 public MathInstruction ishl() {
1297 return (MathInstruction) addInstruction(Constants.ISHL);
1298 }
1299
1300
1301
1302
1303 public MathInstruction lshl() {
1304 return (MathInstruction) addInstruction(Constants.LSHL);
1305 }
1306
1307
1308
1309
1310
1311 public MathInstruction xshr() {
1312 MathInstruction mi = math();
1313 return mi.setOperation(Constants.MATH_SHR);
1314 }
1315
1316
1317
1318
1319 public MathInstruction ishr() {
1320 return (MathInstruction) addInstruction(Constants.ISHR);
1321 }
1322
1323
1324
1325
1326 public MathInstruction lshr() {
1327 return (MathInstruction) addInstruction(Constants.LSHR);
1328 }
1329
1330
1331
1332
1333
1334 public MathInstruction xushr() {
1335 MathInstruction mi = math();
1336 return mi.setOperation(Constants.MATH_USHR);
1337 }
1338
1339
1340
1341
1342 public MathInstruction iushr() {
1343 return (MathInstruction) addInstruction(Constants.IUSHR);
1344 }
1345
1346
1347
1348
1349 public MathInstruction lushr() {
1350 return (MathInstruction) addInstruction(Constants.LUSHR);
1351 }
1352
1353
1354
1355
1356
1357 public MathInstruction xand() {
1358 MathInstruction mi = math();
1359 return mi.setOperation(Constants.MATH_AND);
1360 }
1361
1362
1363
1364
1365
1366 public MathInstruction iand() {
1367 return (MathInstruction) addInstruction(Constants.IAND);
1368 }
1369
1370
1371
1372
1373
1374 public MathInstruction land() {
1375 return (MathInstruction) addInstruction(Constants.LAND);
1376 }
1377
1378
1379
1380
1381
1382 public MathInstruction xor() {
1383 MathInstruction mi = math();
1384 return mi.setOperation(Constants.MATH_OR);
1385 }
1386
1387
1388
1389
1390
1391 public MathInstruction ior() {
1392 return (MathInstruction) addInstruction(Constants.IOR);
1393 }
1394
1395
1396
1397
1398
1399 public MathInstruction lor() {
1400 return (MathInstruction) addInstruction(Constants.LOR);
1401 }
1402
1403
1404
1405
1406
1407 public MathInstruction xxor() {
1408 MathInstruction mi = math();
1409 return mi.setOperation(Constants.MATH_XOR);
1410 }
1411
1412
1413
1414
1415
1416 public MathInstruction ixor() {
1417 return (MathInstruction) addInstruction(Constants.IXOR);
1418 }
1419
1420
1421
1422
1423
1424 public MathInstruction lxor() {
1425 return (MathInstruction) addInstruction(Constants.LXOR);
1426 }
1427
1428
1429
1430
1431
1432
1433 public ConvertInstruction convert() {
1434 return (ConvertInstruction)addInstruction(new ConvertInstruction(this));
1435 }
1436
1437
1438
1439
1440
1441 public CmpInstruction xcmp() {
1442 return (CmpInstruction) addInstruction(new CmpInstruction(this));
1443 }
1444
1445
1446
1447
1448 public CmpInstruction lcmp() {
1449 return (CmpInstruction) addInstruction(Constants.LCMP);
1450 }
1451
1452
1453
1454
1455 public CmpInstruction fcmpl() {
1456 return (CmpInstruction) addInstruction(Constants.FCMPL);
1457 }
1458
1459
1460
1461
1462 public CmpInstruction fcmpg() {
1463 return (CmpInstruction) addInstruction(Constants.FCMPG);
1464 }
1465
1466
1467
1468
1469 public CmpInstruction dcmpl() {
1470 return (CmpInstruction) addInstruction(Constants.DCMPL);
1471 }
1472
1473
1474
1475
1476 public CmpInstruction dcmpg() {
1477 return (CmpInstruction) addInstruction(Constants.DCMPG);
1478 }
1479
1480
1481
1482
1483 public IfInstruction ifeq() {
1484 return (IfInstruction) addInstruction(Constants.IFEQ);
1485 }
1486
1487
1488
1489
1490 public IfInstruction ifne() {
1491 return (IfInstruction) addInstruction(Constants.IFNE);
1492 }
1493
1494
1495
1496
1497 public IfInstruction iflt() {
1498 return (IfInstruction) addInstruction(Constants.IFLT);
1499 }
1500
1501
1502
1503
1504 public IfInstruction ifge() {
1505 return (IfInstruction) addInstruction(Constants.IFGE);
1506 }
1507
1508
1509
1510
1511 public IfInstruction ifgt() {
1512 return (IfInstruction) addInstruction(Constants.IFGT);
1513 }
1514
1515
1516
1517
1518 public IfInstruction ifle() {
1519 return (IfInstruction) addInstruction(Constants.IFLE);
1520 }
1521
1522
1523
1524
1525 public IfInstruction ificmpeq() {
1526 return (IfInstruction) addInstruction(Constants.IFICMPEQ);
1527 }
1528
1529
1530
1531
1532 public IfInstruction ificmpne() {
1533 return (IfInstruction) addInstruction(Constants.IFICMPNE);
1534 }
1535
1536
1537
1538
1539 public IfInstruction ificmplt() {
1540 return (IfInstruction) addInstruction(Constants.IFICMPLT);
1541 }
1542
1543
1544
1545
1546 public IfInstruction ificmpge() {
1547 return (IfInstruction) addInstruction(Constants.IFICMPGE);
1548 }
1549
1550
1551
1552
1553 public IfInstruction ificmpgt() {
1554 return (IfInstruction) addInstruction(Constants.IFICMPGT);
1555 }
1556
1557
1558
1559
1560 public IfInstruction ificmple() {
1561 return (IfInstruction) addInstruction(Constants.IFICMPLE);
1562 }
1563
1564
1565
1566
1567 public IfInstruction ifacmpeq() {
1568 return (IfInstruction) addInstruction(Constants.IFACMPEQ);
1569 }
1570
1571
1572
1573
1574 public IfInstruction ifacmpne() {
1575 return (IfInstruction) addInstruction(Constants.IFACMPNE);
1576 }
1577
1578
1579
1580
1581 public IfInstruction ifnull() {
1582 return (IfInstruction) addInstruction(Constants.IFNULL);
1583 }
1584
1585
1586
1587
1588 public IfInstruction ifnonnull() {
1589 return (IfInstruction) addInstruction(Constants.IFNONNULL);
1590 }
1591
1592
1593
1594
1595 public JumpInstruction go2() {
1596 return (JumpInstruction) addInstruction(Constants.GOTO);
1597 }
1598
1599
1600
1601
1602
1603 public JumpInstruction jsr() {
1604 return (JumpInstruction) addInstruction(Constants.JSR);
1605 }
1606
1607
1608
1609
1610 public TableSwitchInstruction tableswitch() {
1611 return (TableSwitchInstruction) addInstruction(Constants.TABLESWITCH);
1612 }
1613
1614
1615
1616
1617 public LookupSwitchInstruction lookupswitch() {
1618 return (LookupSwitchInstruction) addInstruction(Constants.LOOKUPSWITCH);
1619 }
1620
1621
1622
1623
1624
1625 public ReturnInstruction xreturn() {
1626 return (ReturnInstruction) addInstruction(new ReturnInstruction(this));
1627 }
1628
1629
1630
1631
1632 public ReturnInstruction vreturn() {
1633 return (ReturnInstruction) addInstruction(Constants.RETURN);
1634 }
1635
1636
1637
1638
1639 public ReturnInstruction ireturn() {
1640 return (ReturnInstruction) addInstruction(Constants.IRETURN);
1641 }
1642
1643
1644
1645
1646 public ReturnInstruction lreturn() {
1647 return (ReturnInstruction) addInstruction(Constants.LRETURN);
1648 }
1649
1650
1651
1652
1653 public ReturnInstruction freturn() {
1654 return (ReturnInstruction) addInstruction(Constants.FRETURN);
1655 }
1656
1657
1658
1659
1660 public ReturnInstruction dreturn() {
1661 return (ReturnInstruction) addInstruction(Constants.DRETURN);
1662 }
1663
1664
1665
1666
1667 public ReturnInstruction areturn() {
1668 return (ReturnInstruction) addInstruction(Constants.ARETURN);
1669 }
1670
1671
1672
1673
1674
1675 public GetFieldInstruction getfield() {
1676 return (GetFieldInstruction) addInstruction(Constants.GETFIELD);
1677 }
1678
1679
1680
1681
1682
1683 public GetFieldInstruction getstatic() {
1684 return (GetFieldInstruction) addInstruction(Constants.GETSTATIC);
1685 }
1686
1687
1688
1689
1690
1691 public PutFieldInstruction putfield() {
1692 return (PutFieldInstruction) addInstruction(Constants.PUTFIELD);
1693 }
1694
1695
1696
1697
1698
1699 public PutFieldInstruction putstatic() {
1700 return (PutFieldInstruction) addInstruction(Constants.PUTSTATIC);
1701 }
1702
1703
1704
1705
1706 public MethodInstruction invokevirtual() {
1707 return (MethodInstruction) addInstruction(Constants.INVOKEVIRTUAL);
1708 }
1709
1710
1711
1712
1713
1714 public MethodInstruction invokespecial() {
1715 return (MethodInstruction) addInstruction(Constants.INVOKESPECIAL);
1716 }
1717
1718
1719
1720
1721 public MethodInstruction invokeinterface() {
1722 return (MethodInstruction) addInstruction(Constants.INVOKEINTERFACE);
1723 }
1724
1725
1726
1727
1728 public MethodInstruction invokestatic() {
1729 return (MethodInstruction) addInstruction(Constants.INVOKESTATIC);
1730 }
1731
1732
1733
1734
1735 public ClassInstruction anew() {
1736 return (ClassInstruction) addInstruction(Constants.NEW);
1737 }
1738
1739
1740
1741
1742 public ClassInstruction anewarray() {
1743 return (ClassInstruction) addInstruction(Constants.ANEWARRAY);
1744 }
1745
1746
1747
1748
1749
1750 public ClassInstruction checkcast() {
1751 return (ClassInstruction) addInstruction(Constants.CHECKCAST);
1752 }
1753
1754
1755
1756
1757
1758 public ClassInstruction isinstance() {
1759 return (ClassInstruction) addInstruction(Constants.INSTANCEOF);
1760 }
1761
1762
1763
1764
1765
1766 public MultiANewArrayInstruction multianewarray() {
1767 return (MultiANewArrayInstruction) addInstruction
1768 (Constants.MULTIANEWARRAY);
1769 }
1770
1771
1772
1773
1774 public NewArrayInstruction newarray() {
1775 return (NewArrayInstruction) addInstruction(Constants.NEWARRAY);
1776 }
1777
1778
1779
1780
1781
1782 public Instruction arraylength() {
1783 return addInstruction(Constants.ARRAYLENGTH);
1784 }
1785
1786
1787
1788
1789 public Instruction athrow() {
1790 return addInstruction(Constants.ATHROW);
1791 }
1792
1793
1794
1795
1796 public MonitorEnterInstruction monitorenter() {
1797 return (MonitorEnterInstruction) addInstruction(Constants.MONITORENTER);
1798 }
1799
1800
1801
1802
1803 public MonitorExitInstruction monitorexit() {
1804 return (MonitorExitInstruction) addInstruction(Constants.MONITOREXIT);
1805 }
1806
1807
1808
1809
1810
1811
1812
1813
1814 public Instruction[] getInstructions() {
1815 Instruction[] arr = new Instruction[_size];
1816 int i = 0;
1817 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next)
1818 arr[i++] = (Instruction) entry;
1819 return arr;
1820 }
1821
1822 int getLength() {
1823
1824
1825 int length = 12;
1826
1827
1828 Instruction last = getLastInstruction();
1829 if (last != null)
1830 length += last.getByteIndex() + last.getLength();
1831
1832
1833 length += (8 * _handlers.size());
1834
1835
1836 Attribute[] attrs = getAttributes();
1837 for (int i = 0; i < attrs.length; i++)
1838 length += (attrs[i].getLength() + 6);
1839 return length;
1840 }
1841
1842 public void acceptVisit(BCVisitor visit) {
1843 visit.enterCode(this);
1844 Instruction ins;
1845 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
1846 ins = (Instruction) entry;
1847 visit.enterInstruction(ins);
1848 ins.acceptVisit(visit);
1849 visit.exitInstruction(ins);
1850 }
1851 for (Iterator i = _handlers.iterator(); i.hasNext();)
1852 ((ExceptionHandler) i.next()).acceptVisit(visit);
1853 visitAttributes(visit);
1854 visit.exitCode(this);
1855 }
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870 public LineNumberTable getLineNumberTable(boolean add) {
1871 LineNumberTable attr = (LineNumberTable) getAttribute
1872 (Constants.ATTR_LINENUMBERS);
1873
1874 if (!add || (attr != null))
1875 return attr;
1876 return (LineNumberTable) addAttribute(Constants.ATTR_LINENUMBERS);
1877 }
1878
1879
1880
1881
1882
1883
1884
1885 public boolean removeLineNumberTable() {
1886 return removeAttribute(Constants.ATTR_LINENUMBERS);
1887 }
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898 public LocalVariableTable getLocalVariableTable(boolean add) {
1899 LocalVariableTable attr = (LocalVariableTable) getAttribute
1900 (Constants.ATTR_LOCALS);
1901 if (!add || (attr != null))
1902 return attr;
1903 return (LocalVariableTable) addAttribute(Constants.ATTR_LOCALS);
1904 }
1905
1906
1907
1908
1909
1910
1911
1912 public boolean removeLocalVariableTables() {
1913 return removeAttribute(Constants.ATTR_LOCALS);
1914 }
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925 public LocalVariableTypeTable getLocalVariableTypeTable(boolean add) {
1926 LocalVariableTypeTable attr = (LocalVariableTypeTable) getAttribute
1927 (Constants.ATTR_LOCAL_TYPES);
1928 if (!add || (attr != null))
1929 return attr;
1930 return (LocalVariableTypeTable)addAttribute(Constants.ATTR_LOCAL_TYPES);
1931 }
1932
1933
1934
1935
1936
1937
1938
1939 public boolean removeLocalVariableTypeTables() {
1940 return removeAttribute(Constants.ATTR_LOCAL_TYPES);
1941 }
1942
1943
1944
1945
1946
1947 void read(Attribute attr) {
1948 Code orig = (Code) attr;
1949 _maxStack = orig.getMaxStack();
1950 _maxLocals = orig.getMaxLocals();
1951
1952
1953 _head.next = _tail;
1954 _tail.prev = _head;
1955 _size = 0;
1956 _byteIndexesValid = false;
1957 beforeFirst();
1958 _handlers.clear();
1959
1960
1961
1962
1963 Instruction ins;
1964 Instruction origIns;
1965 for (CodeEntry entry = orig._head.next; entry != orig._tail;
1966 entry = entry.next) {
1967 origIns = (Instruction) entry;
1968 ins = createInstruction(origIns.getOpcode());
1969 _ci.addInternal(ins);
1970 if (!(ins instanceof ConstantInstruction))
1971 ins.read(origIns);
1972 }
1973
1974
1975 ExceptionHandler[] origHandlers = orig.getExceptionHandlers();
1976 ExceptionHandler handler;
1977 for (int i = 0; i < origHandlers.length; i++) {
1978 handler = addExceptionHandler();
1979 handler.read(origHandlers[i]);
1980 handler.updateTargets();
1981 }
1982
1983
1984 updateInstructionPointers();
1985 setAttributes(orig.getAttributes());
1986
1987
1988 LocalVariableTable locals = getLocalVariableTable(false);
1989 if (locals != null)
1990 locals.updateTargets();
1991
1992
1993 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false);
1994 if (localTypes != null)
1995 localTypes.updateTargets();
1996
1997
1998 LineNumberTable lines = getLineNumberTable(false);
1999 if (lines != null)
2000 lines.updateTargets();
2001
2002
2003 CodeEntry copy = _head.next;
2004 for (CodeEntry entry = orig._head.next; entry != orig._tail;
2005 entry = entry.next, copy = copy.next) {
2006 if (entry instanceof ConstantInstruction)
2007 ((ConstantInstruction) copy).read((Instruction) entry);
2008 }
2009 beforeFirst();
2010 }
2011
2012 void read(DataInput in, int length) throws IOException {
2013 _maxStack = in.readUnsignedShort();
2014 _maxLocals = in.readUnsignedShort();
2015 readCode(in, in.readInt());
2016
2017 _handlers.clear();
2018 int exceptionCount = in.readUnsignedShort();
2019 ExceptionHandler excep;
2020 for (int i = 0; i < exceptionCount; i++) {
2021 excep = addExceptionHandler();
2022 excep.read(in);
2023 excep.updateTargets();
2024 }
2025
2026 readAttributes(in);
2027
2028
2029 LocalVariableTable locals = getLocalVariableTable(false);
2030 if (locals != null)
2031 locals.updateTargets();
2032
2033
2034 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false);
2035 if (localTypes != null)
2036 localTypes.updateTargets();
2037
2038
2039 LineNumberTable lines = getLineNumberTable(false);
2040 if (lines != null)
2041 lines.updateTargets();
2042 }
2043
2044 void write(DataOutput out, int length) throws IOException {
2045 out.writeShort(_maxStack);
2046 out.writeShort(_maxLocals);
2047
2048 byte[] code = toByteArray();
2049 out.writeInt(code.length);
2050 out.write(code);
2051
2052 out.writeShort(_handlers.size());
2053 for (Iterator itr = _handlers.iterator(); itr.hasNext();)
2054 ((ExceptionHandler) itr.next()).write(out);
2055 writeAttributes(out);
2056 }
2057
2058 private void readCode(DataInput in, int len) throws IOException {
2059 _head.next = _tail;
2060 _tail.prev = _head;
2061 _size = 0;
2062 _byteIndexesValid = true;
2063
2064 beforeFirst();
2065 Instruction ins;
2066 for (int byteIndex = 0; byteIndex < len;) {
2067 ins = createInstruction(in.readUnsignedByte());
2068 _ci.addInternal(ins);
2069 ins.byteIndex = byteIndex;
2070 ins.read(in);
2071 byteIndex += ins.getLength();
2072 }
2073 updateInstructionPointers();
2074 beforeFirst();
2075
2076
2077 if (!_byteIndexesValid)
2078 throw new IllegalStateException();
2079 }
2080
2081
2082
2083
2084 private void updateInstructionPointers() {
2085 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next)
2086 if (entry instanceof InstructionPtr)
2087 ((InstructionPtr) entry).updateTargets();
2088 }
2089
2090
2091
2092
2093 int getByteIndex(Instruction ins) {
2094 if (_byteIndexesValid && ins.byteIndex != -1)
2095 return ins.byteIndex;
2096
2097 int byteIndex = 0;
2098 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
2099 if (entry == ins)
2100 return byteIndex;
2101 byteIndex += ((Instruction) entry).getLength();
2102 }
2103 throw new IllegalArgumentException("ins.owner != this");
2104 }
2105
2106
2107
2108
2109 void invalidateByteIndexes() {
2110 _byteIndexesValid = false;
2111 }
2112
2113
2114
2115
2116 Instruction getInstruction(int byteIndex) {
2117 if (byteIndex < 0)
2118 return null;
2119
2120 int curIndex = 0;
2121 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
2122 if (byteIndex == curIndex)
2123 return (Instruction) entry;
2124 curIndex += ((Instruction) entry).getLength();
2125 }
2126
2127
2128
2129 if (byteIndex == curIndex)
2130 return null;
2131 throw new IllegalArgumentException(String.valueOf(byteIndex));
2132 }
2133
2134
2135
2136
2137 Instruction getFirstInstruction() {
2138 return (Instruction) _head.next;
2139 }
2140
2141
2142
2143
2144 Instruction getLastInstruction() {
2145 return (Instruction) _tail.prev;
2146 }
2147
2148
2149
2150
2151
2152
2153
2154
2155 private int indexOf(Instruction ins) {
2156 int i = 0;
2157 for (CodeEntry entry = _head.next; entry != _tail;
2158 entry = entry.next, i++)
2159 if (entry == ins)
2160 return i;
2161 throw new IllegalArgumentException("ins.code != this");
2162 }
2163
2164 private void writeCode(DataOutput out) throws IOException {
2165 Instruction ins;
2166 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) {
2167 ins = (Instruction) entry;
2168 out.writeByte(ins.getOpcode());
2169 ins.write(out);
2170 }
2171 }
2172
2173 private byte[] toByteArray() throws IOException {
2174 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
2175 DataOutputStream stream = new DataOutputStream(byteStream);
2176 try {
2177 writeCode(stream);
2178 return byteStream.toByteArray();
2179 } finally {
2180 try { stream.close(); } catch (Exception e) {}
2181 }
2182 }
2183
2184 private void fromByteArray(byte[] code) throws IOException {
2185 if (code == null) {
2186 _head.next = _tail;
2187 _tail.prev = _head;
2188 _size = 0;
2189 } else {
2190 DataInputStream stream = new DataInputStream
2191 (new ByteArrayInputStream(code));
2192 try {
2193 readCode(stream, code.length);
2194 } finally {
2195 try { stream.close(); } catch (Exception e) {}
2196 }
2197 }
2198 }
2199
2200 private Instruction addInstruction(Instruction ins) {
2201 _ci.add(ins);
2202 return ins;
2203 }
2204
2205 private Instruction addInstruction(int opcode) {
2206 return addInstruction(createInstruction(opcode));
2207 }
2208
2209
2210
2211
2212
2213 private Instruction createInstruction(int opcode) {
2214 switch (opcode) {
2215 case Constants.NOP:
2216 case Constants.ARRAYLENGTH:
2217 case Constants.ATHROW:
2218 return new Instruction(this, opcode);
2219 case Constants.ACONSTNULL:
2220 case Constants.ICONSTM1:
2221 case Constants.ICONST0:
2222 case Constants.ICONST1:
2223 case Constants.ICONST2:
2224 case Constants.ICONST3:
2225 case Constants.ICONST4:
2226 case Constants.ICONST5:
2227 case Constants.LCONST0:
2228 case Constants.LCONST1:
2229 case Constants.FCONST0:
2230 case Constants.FCONST1:
2231 case Constants.FCONST2:
2232 case Constants.DCONST0:
2233 case Constants.DCONST1:
2234 case Constants.BIPUSH:
2235 case Constants.SIPUSH:
2236 case Constants.LDC:
2237 case Constants.LDCW:
2238 case Constants.LDC2W:
2239 return new ConstantInstruction(this, opcode);
2240 case Constants.ILOAD:
2241 case Constants.LLOAD:
2242 case Constants.FLOAD:
2243 case Constants.DLOAD:
2244 case Constants.ALOAD:
2245 case Constants.ILOAD0:
2246 case Constants.ILOAD1:
2247 case Constants.ILOAD2:
2248 case Constants.ILOAD3:
2249 case Constants.LLOAD0:
2250 case Constants.LLOAD1:
2251 case Constants.LLOAD2:
2252 case Constants.LLOAD3:
2253 case Constants.FLOAD0:
2254 case Constants.FLOAD1:
2255 case Constants.FLOAD2:
2256 case Constants.FLOAD3:
2257 case Constants.DLOAD0:
2258 case Constants.DLOAD1:
2259 case Constants.DLOAD2:
2260 case Constants.DLOAD3:
2261 case Constants.ALOAD0:
2262 case Constants.ALOAD1:
2263 case Constants.ALOAD2:
2264 case Constants.ALOAD3:
2265 return new LoadInstruction(this, opcode);
2266 case Constants.IALOAD:
2267 case Constants.LALOAD:
2268 case Constants.FALOAD:
2269 case Constants.DALOAD:
2270 case Constants.AALOAD:
2271 case Constants.BALOAD:
2272 case Constants.CALOAD:
2273 case Constants.SALOAD:
2274 return new ArrayLoadInstruction(this, opcode);
2275 case Constants.ISTORE:
2276 case Constants.LSTORE:
2277 case Constants.FSTORE:
2278 case Constants.DSTORE:
2279 case Constants.ASTORE:
2280 case Constants.ISTORE0:
2281 case Constants.ISTORE1:
2282 case Constants.ISTORE2:
2283 case Constants.ISTORE3:
2284 case Constants.LSTORE0:
2285 case Constants.LSTORE1:
2286 case Constants.LSTORE2:
2287 case Constants.LSTORE3:
2288 case Constants.FSTORE0:
2289 case Constants.FSTORE1:
2290 case Constants.FSTORE2:
2291 case Constants.FSTORE3:
2292 case Constants.DSTORE0:
2293 case Constants.DSTORE1:
2294 case Constants.DSTORE2:
2295 case Constants.DSTORE3:
2296 case Constants.ASTORE0:
2297 case Constants.ASTORE1:
2298 case Constants.ASTORE2:
2299 case Constants.ASTORE3:
2300 return new StoreInstruction(this, opcode);
2301 case Constants.IASTORE:
2302 case Constants.LASTORE:
2303 case Constants.FASTORE:
2304 case Constants.DASTORE:
2305 case Constants.AASTORE:
2306 case Constants.BASTORE:
2307 case Constants.CASTORE:
2308 case Constants.SASTORE:
2309 return new ArrayStoreInstruction(this, opcode);
2310 case Constants.POP:
2311 case Constants.POP2:
2312 case Constants.DUP:
2313 case Constants.DUPX1:
2314 case Constants.DUPX2:
2315 case Constants.DUP2:
2316 case Constants.DUP2X1:
2317 case Constants.DUP2X2:
2318 case Constants.SWAP:
2319 return new StackInstruction(this, opcode);
2320 case Constants.IADD:
2321 case Constants.LADD:
2322 case Constants.FADD:
2323 case Constants.DADD:
2324 case Constants.ISUB:
2325 case Constants.LSUB:
2326 case Constants.FSUB:
2327 case Constants.DSUB:
2328 case Constants.IMUL:
2329 case Constants.LMUL:
2330 case Constants.FMUL:
2331 case Constants.DMUL:
2332 case Constants.IDIV:
2333 case Constants.LDIV:
2334 case Constants.FDIV:
2335 case Constants.DDIV:
2336 case Constants.IREM:
2337 case Constants.LREM:
2338 case Constants.FREM:
2339 case Constants.DREM:
2340 case Constants.INEG:
2341 case Constants.LNEG:
2342 case Constants.FNEG:
2343 case Constants.DNEG:
2344 case Constants.ISHL:
2345 case Constants.LSHL:
2346 case Constants.ISHR:
2347 case Constants.LSHR:
2348 case Constants.IUSHR:
2349 case Constants.LUSHR:
2350 case Constants.IAND:
2351 case Constants.LAND:
2352 case Constants.IOR:
2353 case Constants.LOR:
2354 case Constants.IXOR:
2355 case Constants.LXOR:
2356 return new MathInstruction(this, opcode);
2357 case Constants.IINC:
2358 return new IIncInstruction(this);
2359 case Constants.I2L:
2360 case Constants.I2F:
2361 case Constants.I2D:
2362 case Constants.L2I:
2363 case Constants.L2F:
2364 case Constants.L2D:
2365 case Constants.F2I:
2366 case Constants.F2L:
2367 case Constants.F2D:
2368 case Constants.D2I:
2369 case Constants.D2L:
2370 case Constants.D2F:
2371 case Constants.I2B:
2372 case Constants.I2C:
2373 case Constants.I2S:
2374 return new ConvertInstruction(this, opcode);
2375 case Constants.LCMP:
2376 case Constants.FCMPL:
2377 case Constants.FCMPG:
2378 case Constants.DCMPL:
2379 case Constants.DCMPG:
2380 return new CmpInstruction(this, opcode);
2381 case Constants.IFEQ:
2382 case Constants.IFNE:
2383 case Constants.IFLT:
2384 case Constants.IFGE:
2385 case Constants.IFGT:
2386 case Constants.IFLE:
2387 case Constants.IFICMPEQ:
2388 case Constants.IFICMPNE:
2389 case Constants.IFICMPLT:
2390 case Constants.IFICMPGE:
2391 case Constants.IFICMPGT:
2392 case Constants.IFICMPLE:
2393 case Constants.IFACMPEQ:
2394 case Constants.IFACMPNE:
2395 case Constants.IFNULL:
2396 case Constants.IFNONNULL:
2397 return new IfInstruction(this, opcode);
2398 case Constants.GOTO:
2399 case Constants.JSR:
2400 case Constants.GOTOW:
2401 case Constants.JSRW:
2402 return new GotoInstruction(this, opcode);
2403 case Constants.RET:
2404 return new RetInstruction(this);
2405 case Constants.TABLESWITCH:
2406 return new TableSwitchInstruction(this);
2407 case Constants.LOOKUPSWITCH:
2408 return new LookupSwitchInstruction(this);
2409 case Constants.IRETURN:
2410 case Constants.LRETURN:
2411 case Constants.FRETURN:
2412 case Constants.DRETURN:
2413 case Constants.ARETURN:
2414 case Constants.RETURN:
2415 return new ReturnInstruction(this, opcode);
2416 case Constants.GETSTATIC:
2417 case Constants.GETFIELD:
2418 return new GetFieldInstruction(this, opcode);
2419 case Constants.PUTSTATIC:
2420 case Constants.PUTFIELD:
2421 return new PutFieldInstruction(this, opcode);
2422 case Constants.INVOKEVIRTUAL:
2423 case Constants.INVOKESPECIAL:
2424 case Constants.INVOKESTATIC:
2425 case Constants.INVOKEINTERFACE:
2426 return new MethodInstruction(this, opcode);
2427 case Constants.NEW:
2428 case Constants.ANEWARRAY:
2429 case Constants.CHECKCAST:
2430 case Constants.INSTANCEOF:
2431 return new ClassInstruction(this, opcode);
2432 case Constants.NEWARRAY:
2433 return new NewArrayInstruction(this);
2434 case Constants.MONITORENTER:
2435 return new MonitorEnterInstruction(this);
2436 case Constants.MONITOREXIT:
2437 return new MonitorExitInstruction(this);
2438 case Constants.WIDE:
2439 return new WideInstruction(this);
2440 case Constants.MULTIANEWARRAY:
2441 return new MultiANewArrayInstruction(this);
2442 default:
2443 throw new IllegalArgumentException("Illegal opcode: " + opcode);
2444 }
2445 }
2446
2447
2448
2449
2450
2451
2452
2453 public ListIterator listIterator() {
2454 return new CodeIterator(_head, -1);
2455 }
2456
2457
2458
2459
2460
2461 private class CodeIterator implements ListIterator {
2462 public static final int UNSET = -99;
2463 private CodeEntry _bn = null;
2464 private Instruction _last = null;
2465 private int _index = UNSET;
2466
2467 public CodeIterator(CodeEntry entry, int index) {
2468 _bn = entry;
2469 _index = index;
2470 }
2471
2472 public boolean hasNext() {
2473 return _bn.next != _tail;
2474 }
2475
2476 public boolean hasPrevious() {
2477 return _bn != _head;
2478 }
2479
2480 public Object next() {
2481 if (!hasNext())
2482 throw new NoSuchElementException();
2483
2484 _bn = _bn.next;
2485 _last = (Instruction) _bn;
2486 if (_index != UNSET)
2487 _index++;
2488 return _last;
2489 }
2490
2491 public int nextIndex() {
2492 return initIndex() + 1;
2493 }
2494
2495 public Object previous() {
2496 if (!hasPrevious())
2497 throw new NoSuchElementException();
2498
2499 _last = (Instruction) _bn;
2500 _bn = _bn.prev;
2501 if (_index != UNSET)
2502 _index--;
2503 return _last;
2504 }
2505
2506 public int previousIndex() {
2507 return initIndex();
2508 }
2509
2510 private int initIndex() {
2511 if (_index == UNSET) {
2512 if (_bn == _head)
2513 _index = -1;
2514 else
2515 _index = indexOf((Instruction) _bn);
2516 }
2517 return _index;
2518 }
2519
2520 public void add(Object obj) {
2521 addInternal(obj);
2522 invalidateByteIndexes();
2523 }
2524
2525 private void addInternal(Object obj) {
2526 if (obj == null)
2527 throw new NullPointerException("obj = null");
2528
2529 Instruction ins = (Instruction) obj;
2530 if (_size == 0) {
2531 _head.next = ins;
2532 _tail.prev = ins;
2533 ins.prev = _head;
2534 ins.next = _tail;
2535 _index = 0;
2536 } else {
2537 CodeEntry next = _bn.next;
2538 _bn.next = ins;
2539 next.prev = ins;
2540 ins.prev = _bn;
2541 ins.next = next;
2542 if (_index != UNSET)
2543 _index++;
2544 }
2545
2546 _bn = ins;
2547 _last = ins;
2548 _size++;
2549 }
2550
2551 public void set(Object obj) {
2552 if (obj == null)
2553 throw new NullPointerException("obj = null");
2554 if (_last == null)
2555 throw new IllegalStateException();
2556
2557 Instruction ins = (Instruction) obj;
2558 ins.prev = _last.prev;
2559 ins.next = _last.next;
2560 ins.prev.next = ins;
2561 ins.next.prev = ins;
2562
2563 replaceTarget(_last, ins);
2564 _last.invalidate();
2565 if (_bn == _last)
2566 _bn = ins;
2567 _last = ins;
2568 invalidateByteIndexes();
2569 }
2570
2571 public void remove() {
2572 if (_last == null)
2573 throw new IllegalStateException();
2574
2575 if (_bn == _last)
2576 _bn = _last.prev;
2577 _index--;
2578 _last.prev.next = _last.next;
2579 _last.next.prev = _last.prev;
2580 _size--;
2581
2582 Instruction orig = _last;
2583 Instruction replace = null;
2584 if (orig.next != _tail)
2585 replace = (Instruction) orig.next;
2586 else
2587 replace = nop();
2588 replaceTarget(orig, replace);
2589 orig.invalidate();
2590 _last = null;
2591 invalidateByteIndexes();
2592 }
2593
2594 private void replaceTarget(Instruction orig, Instruction replace) {
2595 for (CodeEntry entry = _head.next; entry != _tail;
2596 entry = entry.next) {
2597 if (entry instanceof InstructionPtr)
2598 ((InstructionPtr) entry).replaceTarget(orig, replace);
2599 }
2600
2601
2602 ExceptionHandler[] handlers = getExceptionHandlers();
2603 for (int i = 0; i < handlers.length; i++)
2604 handlers[i].replaceTarget(orig, replace);
2605
2606
2607 LineNumberTable lineNumbers = getLineNumberTable(false);
2608 if (lineNumbers != null)
2609 lineNumbers.replaceTarget(orig, replace);
2610
2611
2612 LocalVariableTable variables = getLocalVariableTable(false);
2613 if (variables != null)
2614 variables.replaceTarget(orig, replace);
2615
2616
2617 LocalVariableTypeTable types = getLocalVariableTypeTable(false);
2618 if (types != null)
2619 types.replaceTarget(orig, replace);
2620 }
2621 }
2622 }