1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.bcel.generic;
19
20 import java.util.ArrayList;
21 import java.util.Hashtable;
22 import java.util.List;
23 import java.util.Stack;
24 import org.apache.bcel.Constants;
25 import org.apache.bcel.classfile.AnnotationEntry;
26 import org.apache.bcel.classfile.Annotations;
27 import org.apache.bcel.classfile.Attribute;
28 import org.apache.bcel.classfile.Code;
29 import org.apache.bcel.classfile.CodeException;
30 import org.apache.bcel.classfile.ExceptionTable;
31 import org.apache.bcel.classfile.LineNumber;
32 import org.apache.bcel.classfile.LineNumberTable;
33 import org.apache.bcel.classfile.LocalVariable;
34 import org.apache.bcel.classfile.LocalVariableTable;
35 import org.apache.bcel.classfile.LocalVariableTypeTable;
36 import org.apache.bcel.classfile.Method;
37 import org.apache.bcel.classfile.ParameterAnnotationEntry;
38 import org.apache.bcel.classfile.ParameterAnnotations;
39 import org.apache.bcel.classfile.RuntimeVisibleParameterAnnotations;
40 import org.apache.bcel.classfile.Utility;
41 import org.apache.bcel.util.BCELComparator;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class MethodGen extends FieldGenOrMethodGen {
60
61 private static final long serialVersionUID = -3924667713338957720L;
62 private String class_name;
63 private Type[] arg_types;
64 private String[] arg_names;
65 private int max_locals;
66 private int max_stack;
67 private InstructionList il;
68 private boolean strip_attributes;
69 private List<LocalVariableGen> variable_vec = new ArrayList<LocalVariableGen>();
70 private List<LineNumberGen> line_number_vec = new ArrayList<LineNumberGen>();
71 private List<CodeExceptionGen> exception_vec = new ArrayList<CodeExceptionGen>();
72 private List<String> throws_vec = new ArrayList<String>();
73 private List<Attribute> code_attrs_vec = new ArrayList<Attribute>();
74
75 private List<AnnotationEntryGen>[] param_annotations;
76 private boolean hasParameterAnnotations = false;
77 private boolean haveUnpackedParameterAnnotations = false;
78
79 private static BCELComparator _cmp = new BCELComparator() {
80
81 public boolean equals( Object o1, Object o2 ) {
82 MethodGen THIS = (MethodGen) o1;
83 MethodGen THAT = (MethodGen) o2;
84 return THIS.getName().equals(THAT.getName())
85 && THIS.getSignature().equals(THAT.getSignature());
86 }
87
88
89 public int hashCode( Object o ) {
90 MethodGen THIS = (MethodGen) o;
91 return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
92 }
93 };
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public MethodGen(int access_flags, Type return_type, Type[] arg_types, String[] arg_names,
119 String method_name, String class_name, InstructionList il, ConstantPoolGen cp) {
120 setAccessFlags(access_flags);
121 setType(return_type);
122 setArgumentTypes(arg_types);
123 setArgumentNames(arg_names);
124 setName(method_name);
125 setClassName(class_name);
126 setInstructionList(il);
127 setConstantPool(cp);
128 boolean abstract_ = isAbstract() || isNative();
129 InstructionHandle start = null;
130 InstructionHandle end = null;
131 if (!abstract_) {
132 start = il.getStart();
133 end = il.getEnd();
134
135
136 if (!isStatic() && (class_name != null)) {
137 addLocalVariable("this", new ObjectType(class_name), start, end);
138 }
139 }
140 if (arg_types != null) {
141 int size = arg_types.length;
142 for (int i = 0; i < size; i++) {
143 if (Type.VOID == arg_types[i]) {
144 throw new ClassGenException("'void' is an illegal argument type for a method");
145 }
146 }
147 if (arg_names != null) {
148 if (size != arg_names.length) {
149 throw new ClassGenException("Mismatch in argument array lengths: " + size
150 + " vs. " + arg_names.length);
151 }
152 } else {
153 arg_names = new String[size];
154 for (int i = 0; i < size; i++) {
155 arg_names[i] = "arg" + i;
156 }
157 setArgumentNames(arg_names);
158 }
159 if (!abstract_) {
160 for (int i = 0; i < size; i++) {
161 addLocalVariable(arg_names[i], arg_types[i], start, end);
162 }
163 }
164 }
165 }
166
167
168
169
170
171
172
173
174
175 public MethodGen(Method m, String class_name, ConstantPoolGen cp) {
176 this(m.getAccessFlags(), Type.getReturnType(m.getSignature()), Type.getArgumentTypes(m
177 .getSignature()), null
178 , m.getName(), class_name,
179 ((m.getAccessFlags() & (Constants.ACC_ABSTRACT | Constants.ACC_NATIVE)) == 0)
180 ? new InstructionList(m.getCode().getCode())
181 : null, cp);
182 Attribute[] attributes = m.getAttributes();
183 for (int i = 0; i < attributes.length; i++) {
184 Attribute a = attributes[i];
185 if (a instanceof Code) {
186 Code c = (Code) a;
187 setMaxStack(c.getMaxStack());
188 setMaxLocals(c.getMaxLocals());
189 CodeException[] ces = c.getExceptionTable();
190 if (ces != null) {
191 for (int j = 0; j < ces.length; j++) {
192 CodeException ce = ces[j];
193 int type = ce.getCatchType();
194 ObjectType c_type = null;
195 if (type > 0) {
196 String cen = m.getConstantPool().getConstantString(type,
197 Constants.CONSTANT_Class);
198 c_type = new ObjectType(cen);
199 }
200 int end_pc = ce.getEndPC();
201 int length = m.getCode().getCode().length;
202 InstructionHandle end;
203 if (length == end_pc) {
204 end = il.getEnd();
205 } else {
206 end = il.findHandle(end_pc);
207 end = end.getPrev();
208 }
209 addExceptionHandler(il.findHandle(ce.getStartPC()), end, il.findHandle(ce
210 .getHandlerPC()), c_type);
211 }
212 }
213 Attribute[] c_attributes = c.getAttributes();
214 for (int j = 0; j < c_attributes.length; j++) {
215 a = c_attributes[j];
216 if (a instanceof LineNumberTable) {
217 LineNumber[] ln = ((LineNumberTable) a).getLineNumberTable();
218 for (int k = 0; k < ln.length; k++) {
219 LineNumber l = ln[k];
220 InstructionHandle ih = il.findHandle(l.getStartPC());
221 if (ih != null) {
222 addLineNumber(ih, l.getLineNumber());
223 }
224 }
225 } else if (a instanceof LocalVariableTable) {
226 LocalVariable[] lv = ((LocalVariableTable) a).getLocalVariableTable();
227 removeLocalVariables();
228 for (int k = 0; k < lv.length; k++) {
229 LocalVariable l = lv[k];
230 InstructionHandle start = il.findHandle(l.getStartPC());
231 InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
232
233 if (null == start) {
234 start = il.getStart();
235 }
236 if (null == end) {
237 end = il.getEnd();
238 }
239 addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
240 .getIndex(), start, end);
241 }
242 } else if (a instanceof LocalVariableTypeTable) {
243 LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
244 removeLocalVariables();
245 for (int k = 0; k < lv.length; k++) {
246 LocalVariable l = lv[k];
247 InstructionHandle start = il.findHandle(l.getStartPC());
248 InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
249
250 if (null == start) {
251 start = il.getStart();
252 }
253 if (null == end) {
254 end = il.getEnd();
255 }
256 addLocalVariable(l.getName(), Type.getType(l.getSignature()), l
257 .getIndex(), start, end);
258 }
259 } else {
260 addCodeAttribute(a);
261 }
262 }
263 } else if (a instanceof ExceptionTable) {
264 String[] names = ((ExceptionTable) a).getExceptionNames();
265 for (int j = 0; j < names.length; j++) {
266 addException(names[j]);
267 }
268 } else if (a instanceof Annotations) {
269 Annotations runtimeAnnotations = (Annotations) a;
270 AnnotationEntry[] aes = runtimeAnnotations.getAnnotationEntries();
271 for (int k = 0; k < aes.length; k++) {
272 AnnotationEntry element = aes[k];
273 addAnnotationEntry(new AnnotationEntryGen(element, cp, false));
274 }
275 } else {
276 addAttribute(a);
277 }
278 }
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294 public LocalVariableGen addLocalVariable( String name, Type type, int slot,
295 InstructionHandle start, InstructionHandle end ) {
296 byte t = type.getType();
297 if (t != Constants.T_ADDRESS) {
298 int add = type.getSize();
299 if (slot + add > max_locals) {
300 max_locals = slot + add;
301 }
302 LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end);
303 int i;
304 if ((i = variable_vec.indexOf(l)) >= 0) {
305 variable_vec.set(i, l);
306 } else {
307 variable_vec.add(l);
308 }
309 return l;
310 } else {
311 throw new IllegalArgumentException("Can not use " + type
312 + " as type for local variable");
313 }
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329 public LocalVariableGen addLocalVariable( String name, Type type, InstructionHandle start,
330 InstructionHandle end ) {
331 return addLocalVariable(name, type, max_locals, start, end);
332 }
333
334
335
336
337
338
339 public void removeLocalVariable( LocalVariableGen l ) {
340 variable_vec.remove(l);
341 }
342
343
344
345
346
347 public void removeLocalVariables() {
348 variable_vec.clear();
349 }
350
351
352
353
354
355 private static final void sort( LocalVariableGen[] vars, int l, int r ) {
356 int i = l, j = r;
357 int m = vars[(l + r) / 2].getIndex();
358 LocalVariableGen h;
359 do {
360 while (vars[i].getIndex() < m) {
361 i++;
362 }
363 while (m < vars[j].getIndex()) {
364 j--;
365 }
366 if (i <= j) {
367 h = vars[i];
368 vars[i] = vars[j];
369 vars[j] = h;
370 i++;
371 j--;
372 }
373 } while (i <= j);
374 if (l < j) {
375 sort(vars, l, j);
376 }
377 if (i < r) {
378 sort(vars, i, r);
379 }
380 }
381
382
383
384
385
386
387
388
389 public LocalVariableGen[] getLocalVariables() {
390 int size = variable_vec.size();
391 LocalVariableGen[] lg = new LocalVariableGen[size];
392 variable_vec.toArray(lg);
393 for (int i = 0; i < size; i++) {
394 if (lg[i].getStart() == null) {
395 lg[i].setStart(il.getStart());
396 }
397 if (lg[i].getEnd() == null) {
398 lg[i].setEnd(il.getEnd());
399 }
400 }
401 if (size > 1) {
402 sort(lg, 0, size - 1);
403 }
404 return lg;
405 }
406
407
408
409
410
411 public LocalVariableTable getLocalVariableTable( ConstantPoolGen cp ) {
412 LocalVariableGen[] lg = getLocalVariables();
413 int size = lg.length;
414 LocalVariable[] lv = new LocalVariable[size];
415 for (int i = 0; i < size; i++) {
416 lv[i] = lg[i].getLocalVariable(cp);
417 }
418 return new LocalVariableTable(cp.addUtf8("LocalVariableTable"), 2 + lv.length * 10, lv, cp
419 .getConstantPool());
420 }
421
422
423
424
425
426
427
428
429
430 public LineNumberGen addLineNumber( InstructionHandle ih, int src_line ) {
431 LineNumberGen l = new LineNumberGen(ih, src_line);
432 line_number_vec.add(l);
433 return l;
434 }
435
436
437
438
439
440 public void removeLineNumber( LineNumberGen l ) {
441 line_number_vec.remove(l);
442 }
443
444
445
446
447
448 public void removeLineNumbers() {
449 line_number_vec.clear();
450 }
451
452
453
454
455
456 public LineNumberGen[] getLineNumbers() {
457 LineNumberGen[] lg = new LineNumberGen[line_number_vec.size()];
458 line_number_vec.toArray(lg);
459 return lg;
460 }
461
462
463
464
465
466 public LineNumberTable getLineNumberTable( ConstantPoolGen cp ) {
467 int size = line_number_vec.size();
468 LineNumber[] ln = new LineNumber[size];
469 try {
470 for (int i = 0; i < size; i++) {
471 ln[i] = line_number_vec.get(i).getLineNumber();
472 }
473 } catch (ArrayIndexOutOfBoundsException e) {
474 }
475 return new LineNumberTable(cp.addUtf8("LineNumberTable"), 2 + ln.length * 4, ln, cp
476 .getConstantPool());
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
491 public CodeExceptionGen addExceptionHandler( InstructionHandle start_pc,
492 InstructionHandle end_pc, InstructionHandle handler_pc, ObjectType catch_type ) {
493 if ((start_pc == null) || (end_pc == null) || (handler_pc == null)) {
494 throw new ClassGenException("Exception handler target is null instruction");
495 }
496 CodeExceptionGen c = new CodeExceptionGen(start_pc, end_pc, handler_pc, catch_type);
497 exception_vec.add(c);
498 return c;
499 }
500
501
502
503
504
505 public void removeExceptionHandler( CodeExceptionGen c ) {
506 exception_vec.remove(c);
507 }
508
509
510
511
512
513 public void removeExceptionHandlers() {
514 exception_vec.clear();
515 }
516
517
518
519
520
521 public CodeExceptionGen[] getExceptionHandlers() {
522 CodeExceptionGen[] cg = new CodeExceptionGen[exception_vec.size()];
523 exception_vec.toArray(cg);
524 return cg;
525 }
526
527
528
529
530
531 private CodeException[] getCodeExceptions() {
532 int size = exception_vec.size();
533 CodeException[] c_exc = new CodeException[size];
534 try {
535 for (int i = 0; i < size; i++) {
536 CodeExceptionGen c = exception_vec.get(i);
537 c_exc[i] = c.getCodeException(cp);
538 }
539 } catch (ArrayIndexOutOfBoundsException e) {
540 }
541 return c_exc;
542 }
543
544
545
546
547
548
549
550 public void addException( String class_name ) {
551 throws_vec.add(class_name);
552 }
553
554
555
556
557
558 public void removeException( String c ) {
559 throws_vec.remove(c);
560 }
561
562
563
564
565
566 public void removeExceptions() {
567 throws_vec.clear();
568 }
569
570
571
572
573
574 public String[] getExceptions() {
575 String[] e = new String[throws_vec.size()];
576 throws_vec.toArray(e);
577 return e;
578 }
579
580
581
582
583
584 private ExceptionTable getExceptionTable( ConstantPoolGen cp ) {
585 int size = throws_vec.size();
586 int[] ex = new int[size];
587 try {
588 for (int i = 0; i < size; i++) {
589 ex[i] = cp.addClass(throws_vec.get(i));
590 }
591 } catch (ArrayIndexOutOfBoundsException e) {
592 }
593 return new ExceptionTable(cp.addUtf8("Exceptions"), 2 + 2 * size, ex, cp.getConstantPool());
594 }
595
596
597
598
599
600
601
602
603
604
605
606 public void addCodeAttribute( Attribute a ) {
607 code_attrs_vec.add(a);
608 }
609
610
611
612
613
614 public void removeCodeAttribute( Attribute a ) {
615 code_attrs_vec.remove(a);
616 }
617
618
619
620
621
622 public void removeCodeAttributes() {
623 code_attrs_vec.clear();
624 }
625
626
627
628
629
630 public Attribute[] getCodeAttributes() {
631 Attribute[] attributes = new Attribute[code_attrs_vec.size()];
632 code_attrs_vec.toArray(attributes);
633 return attributes;
634 }
635
636 public void addAnnotationsAsAttribute(ConstantPoolGen cp) {
637 Attribute[] attrs = Utility.getAnnotationAttributes(cp,annotation_vec);
638 for (int i = 0; i < attrs.length; i++) {
639 addAttribute(attrs[i]);
640 }
641 }
642
643 public void addParameterAnnotationsAsAttribute(ConstantPoolGen cp) {
644 if (!hasParameterAnnotations) return;
645 Attribute[] attrs = Utility.getParameterAnnotationAttributes(cp,param_annotations);
646 if (attrs!=null) {
647 for (int i = 0; i < attrs.length; i++) {
648 addAttribute(attrs[i]);
649 }
650 }
651 }
652
653
654
655
656
657
658
659
660 public Method getMethod() {
661 String signature = getSignature();
662 int name_index = cp.addUtf8(name);
663 int signature_index = cp.addUtf8(signature);
664
665
666 byte[] byte_code = null;
667 if (il != null) {
668 byte_code = il.getByteCode();
669 }
670 LineNumberTable lnt = null;
671 LocalVariableTable lvt = null;
672
673
674 if ((variable_vec.size() > 0) && !strip_attributes) {
675 addCodeAttribute(lvt = getLocalVariableTable(cp));
676 }
677 if ((line_number_vec.size() > 0) && !strip_attributes) {
678 addCodeAttribute(lnt = getLineNumberTable(cp));
679 }
680 Attribute[] code_attrs = getCodeAttributes();
681
682
683 int attrs_len = 0;
684 for (int i = 0; i < code_attrs.length; i++) {
685 attrs_len += (code_attrs[i].getLength() + 6);
686 }
687 CodeException[] c_exc = getCodeExceptions();
688 int exc_len = c_exc.length * 8;
689 Code code = null;
690 if ((il != null) && !isAbstract() && !isNative()) {
691
692 Attribute[] attributes = getAttributes();
693 for (int i = 0; i < attributes.length; i++) {
694 Attribute a = attributes[i];
695 if (a instanceof Code) {
696 removeAttribute(a);
697 }
698 }
699 code = new Code(cp.addUtf8("Code"), 8 + byte_code.length +
700 2 + exc_len +
701 2 + attrs_len,
702 max_stack, max_locals, byte_code, c_exc, code_attrs, cp.getConstantPool());
703 addAttribute(code);
704 }
705 addAnnotationsAsAttribute(cp);
706 addParameterAnnotationsAsAttribute(cp);
707 ExceptionTable et = null;
708 if (throws_vec.size() > 0) {
709 addAttribute(et = getExceptionTable(cp));
710
711 }
712 Method m = new Method(access_flags, name_index, signature_index, getAttributes(), cp
713 .getConstantPool());
714
715 if (lvt != null) {
716 removeCodeAttribute(lvt);
717 }
718 if (lnt != null) {
719 removeCodeAttribute(lnt);
720 }
721 if (code != null) {
722 removeAttribute(code);
723 }
724 if (et != null) {
725 removeAttribute(et);
726 }
727 return m;
728 }
729
730
731
732
733
734
735
736 public void removeNOPs() {
737 if (il != null) {
738 InstructionHandle next;
739
740
741 for (InstructionHandle ih = il.getStart(); ih != null; ih = next) {
742 next = ih.next;
743 if ((next != null) && (ih.getInstruction() instanceof NOP)) {
744 try {
745 il.delete(ih);
746 } catch (TargetLostException e) {
747 InstructionHandle[] targets = e.getTargets();
748 for (int i = 0; i < targets.length; i++) {
749 InstructionTargeter[] targeters = targets[i].getTargeters();
750 for (int j = 0; j < targeters.length; j++) {
751 targeters[j].updateTarget(targets[i], next);
752 }
753 }
754 }
755 }
756 }
757 }
758 }
759
760
761
762
763
764 public void setMaxLocals( int m ) {
765 max_locals = m;
766 }
767
768
769 public int getMaxLocals() {
770 return max_locals;
771 }
772
773
774
775
776
777 public void setMaxStack( int m ) {
778 max_stack = m;
779 }
780
781
782 public int getMaxStack() {
783 return max_stack;
784 }
785
786
787
788
789 public String getClassName() {
790 return class_name;
791 }
792
793
794 public void setClassName( String class_name ) {
795 this.class_name = class_name;
796 }
797
798
799 public void setReturnType( Type return_type ) {
800 setType(return_type);
801 }
802
803
804 public Type getReturnType() {
805 return getType();
806 }
807
808
809 public void setArgumentTypes( Type[] arg_types ) {
810 this.arg_types = arg_types;
811 }
812
813
814 public Type[] getArgumentTypes() {
815 return arg_types.clone();
816 }
817
818
819 public void setArgumentType( int i, Type type ) {
820 arg_types[i] = type;
821 }
822
823
824 public Type getArgumentType( int i ) {
825 return arg_types[i];
826 }
827
828
829 public void setArgumentNames( String[] arg_names ) {
830 this.arg_names = arg_names;
831 }
832
833
834 public String[] getArgumentNames() {
835 return arg_names.clone();
836 }
837
838
839 public void setArgumentName( int i, String name ) {
840 arg_names[i] = name;
841 }
842
843
844 public String getArgumentName( int i ) {
845 return arg_names[i];
846 }
847
848
849 public InstructionList getInstructionList() {
850 return il;
851 }
852
853
854 public void setInstructionList( InstructionList il ) {
855 this.il = il;
856 }
857
858
859 @Override
860 public String getSignature() {
861 return Type.getMethodSignature(type, arg_types);
862 }
863
864
865
866
867
868 public void setMaxStack() {
869 if (il != null) {
870 max_stack = getMaxStack(cp, il, getExceptionHandlers());
871 } else {
872 max_stack = 0;
873 }
874 }
875
876
877
878
879
880 public void setMaxLocals() {
881 if (il != null) {
882 int max = isStatic() ? 0 : 1;
883 if (arg_types != null) {
884 for (int i = 0; i < arg_types.length; i++) {
885 max += arg_types[i].getSize();
886 }
887 }
888 for (InstructionHandle ih = il.getStart(); ih != null; ih = ih.getNext()) {
889 Instruction ins = ih.getInstruction();
890 if ((ins instanceof LocalVariableInstruction) || (ins instanceof RET)
891 || (ins instanceof IINC)) {
892 int index = ((IndexedInstruction) ins).getIndex()
893 + ((TypedInstruction) ins).getType(cp).getSize();
894 if (index > max) {
895 max = index;
896 }
897 }
898 }
899 max_locals = max;
900 } else {
901 max_locals = 0;
902 }
903 }
904
905
906
907
908
909 public void stripAttributes( boolean flag ) {
910 strip_attributes = flag;
911 }
912
913 static final class BranchTarget {
914
915 InstructionHandle target;
916 int stackDepth;
917
918
919 BranchTarget(InstructionHandle target, int stackDepth) {
920 this.target = target;
921 this.stackDepth = stackDepth;
922 }
923 }
924
925 static final class BranchStack {
926
927 Stack<BranchTarget> branchTargets = new Stack<BranchTarget>();
928 Hashtable<InstructionHandle, BranchTarget> visitedTargets = new Hashtable<InstructionHandle, BranchTarget>();
929
930
931 public void push( InstructionHandle target, int stackDepth ) {
932 if (visited(target)) {
933 return;
934 }
935 branchTargets.push(visit(target, stackDepth));
936 }
937
938
939 public BranchTarget pop() {
940 if (!branchTargets.empty()) {
941 BranchTarget bt = branchTargets.pop();
942 return bt;
943 }
944 return null;
945 }
946
947
948 private final BranchTarget visit( InstructionHandle target, int stackDepth ) {
949 BranchTarget bt = new BranchTarget(target, stackDepth);
950 visitedTargets.put(target, bt);
951 return bt;
952 }
953
954
955 private final boolean visited( InstructionHandle target ) {
956 return (visitedTargets.get(target) != null);
957 }
958 }
959
960
961
962
963
964
965
966 public static int getMaxStack( ConstantPoolGen cp, InstructionList il, CodeExceptionGen[] et ) {
967 BranchStack branchTargets = new BranchStack();
968
969
970
971
972
973 for (int i = 0; i < et.length; i++) {
974 InstructionHandle handler_pc = et[i].getHandlerPC();
975 if (handler_pc != null) {
976 branchTargets.push(handler_pc, 1);
977 }
978 }
979 int stackDepth = 0, maxStackDepth = 0;
980 InstructionHandle ih = il.getStart();
981 while (ih != null) {
982 Instruction instruction = ih.getInstruction();
983 short opcode = instruction.getOpcode();
984 int delta = instruction.produceStack(cp) - instruction.consumeStack(cp);
985 stackDepth += delta;
986 if (stackDepth > maxStackDepth) {
987 maxStackDepth = stackDepth;
988 }
989
990 if (instruction instanceof BranchInstruction) {
991 BranchInstruction branch = (BranchInstruction) instruction;
992 if (instruction instanceof Select) {
993
994 Select select = (Select) branch;
995 InstructionHandle[] targets = select.getTargets();
996 for (int i = 0; i < targets.length; i++) {
997 branchTargets.push(targets[i], stackDepth);
998 }
999
1000 ih = null;
1001 } else if (!(branch instanceof IfInstruction)) {
1002
1003
1004 if (opcode == Constants.JSR || opcode == Constants.JSR_W) {
1005 branchTargets.push(ih.getNext(), stackDepth - 1);
1006 }
1007 ih = null;
1008 }
1009
1010
1011
1012 branchTargets.push(branch.getTarget(), stackDepth);
1013 } else {
1014
1015 if (opcode == Constants.ATHROW || opcode == Constants.RET
1016 || (opcode >= Constants.IRETURN && opcode <= Constants.RETURN)) {
1017 ih = null;
1018 }
1019 }
1020
1021 if (ih != null) {
1022 ih = ih.getNext();
1023 }
1024
1025 if (ih == null) {
1026 BranchTarget bt = branchTargets.pop();
1027 if (bt != null) {
1028 ih = bt.target;
1029 stackDepth = bt.stackDepth;
1030 }
1031 }
1032 }
1033 return maxStackDepth;
1034 }
1035
1036 private List<MethodObserver> observers;
1037
1038
1039
1040
1041 public void addObserver( MethodObserver o ) {
1042 if (observers == null) {
1043 observers = new ArrayList<MethodObserver>();
1044 }
1045 observers.add(o);
1046 }
1047
1048
1049
1050
1051 public void removeObserver( MethodObserver o ) {
1052 if (observers != null) {
1053 observers.remove(o);
1054 }
1055 }
1056
1057
1058
1059
1060
1061
1062 public void update() {
1063 if (observers != null) {
1064 for (MethodObserver observer : observers) {
1065 observer.notify(this);
1066 }
1067 }
1068 }
1069
1070
1071
1072
1073
1074
1075
1076
1077 @Override
1078 public final String toString() {
1079 String access = Utility.accessToString(access_flags);
1080 String signature = Type.getMethodSignature(type, arg_types);
1081 signature = Utility.methodSignatureToString(signature, name, access, true,
1082 getLocalVariableTable(cp));
1083 StringBuilder buf = new StringBuilder(signature);
1084 for (int i = 0; i < getAttributes().length; i++) {
1085 Attribute a = getAttributes()[i];
1086 if (!((a instanceof Code) || (a instanceof ExceptionTable))) {
1087 buf.append(" [").append(a.toString()).append("]");
1088 }
1089 }
1090
1091 if (throws_vec.size() > 0) {
1092 for (String throwsDescriptor : throws_vec) {
1093 buf.append("\n\t\tthrows ").append(throwsDescriptor);
1094 }
1095 }
1096 return buf.toString();
1097 }
1098
1099
1100
1101
1102 public MethodGen copy( String class_name, ConstantPoolGen cp ) {
1103 Method m = ((MethodGen) clone()).getMethod();
1104 MethodGen mg = new MethodGen(m, class_name, this.cp);
1105 if (this.cp != cp) {
1106 mg.setConstantPool(cp);
1107 mg.getInstructionList().replaceConstantPool(this.cp, cp);
1108 }
1109 return mg;
1110 }
1111
1112
1113
1114
1115
1116
1117 public List<AnnotationEntryGen> getAnnotationsOnParameter(int i) {
1118 ensureExistingParameterAnnotationsUnpacked();
1119 if (!hasParameterAnnotations || i>arg_types.length) return null;
1120 return param_annotations[i];
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 private void ensureExistingParameterAnnotationsUnpacked()
1132 {
1133 if (haveUnpackedParameterAnnotations)
1134 return;
1135
1136 Attribute[] attrs = getAttributes();
1137 ParameterAnnotations paramAnnVisAttr = null;
1138 ParameterAnnotations paramAnnInvisAttr = null;
1139 for (int i = 0; i < attrs.length; i++)
1140 {
1141 Attribute attribute = attrs[i];
1142 if (attribute instanceof ParameterAnnotations)
1143 {
1144
1145 if (!hasParameterAnnotations)
1146 {
1147 param_annotations = new List[arg_types.length];
1148 for (int j = 0; j < arg_types.length; j++)
1149 param_annotations[j] = new ArrayList<AnnotationEntryGen>();
1150 }
1151 hasParameterAnnotations = true;
1152 ParameterAnnotations rpa = (ParameterAnnotations) attribute;
1153 if (rpa instanceof RuntimeVisibleParameterAnnotations)
1154 paramAnnVisAttr = rpa;
1155 else
1156 paramAnnInvisAttr = rpa;
1157 for (int j = 0; j < arg_types.length; j++)
1158 {
1159
1160 ParameterAnnotationEntry immutableArray = rpa
1161 .getParameterAnnotationEntries()[j];
1162
1163 List<AnnotationEntryGen> mutable = makeMutableVersion(immutableArray.getAnnotationEntries());
1164
1165 param_annotations[j].addAll(mutable);
1166 }
1167 }
1168 }
1169 if (paramAnnVisAttr != null)
1170 removeAttribute(paramAnnVisAttr);
1171 if (paramAnnInvisAttr != null)
1172 removeAttribute(paramAnnInvisAttr);
1173 haveUnpackedParameterAnnotations = true;
1174 }
1175
1176 private List<AnnotationEntryGen> makeMutableVersion(AnnotationEntry[] mutableArray)
1177 {
1178 List<AnnotationEntryGen> result = new ArrayList<AnnotationEntryGen>();
1179 for (int i = 0; i < mutableArray.length; i++)
1180 {
1181 result.add(new AnnotationEntryGen(mutableArray[i], getConstantPool(),
1182 false));
1183 }
1184 return result;
1185 }
1186
1187 public void addParameterAnnotation(int parameterIndex,
1188 AnnotationEntryGen annotation)
1189 {
1190 ensureExistingParameterAnnotationsUnpacked();
1191 if (!hasParameterAnnotations)
1192 {
1193 param_annotations = new List[arg_types.length];
1194 hasParameterAnnotations = true;
1195 }
1196 List<AnnotationEntryGen> existingAnnotations = param_annotations[parameterIndex];
1197 if (existingAnnotations != null)
1198 {
1199 existingAnnotations.add(annotation);
1200 }
1201 else
1202 {
1203 List<AnnotationEntryGen> l = new ArrayList<AnnotationEntryGen>();
1204 l.add(annotation);
1205 param_annotations[parameterIndex] = l;
1206 }
1207 }
1208
1209
1210
1211
1212
1213
1214
1215 public static BCELComparator getComparator() {
1216 return _cmp;
1217 }
1218
1219
1220
1221
1222
1223 public static void setComparator( BCELComparator comparator ) {
1224 _cmp = comparator;
1225 }
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235 @Override
1236 public boolean equals( Object obj ) {
1237 return _cmp.equals(this, obj);
1238 }
1239
1240
1241
1242
1243
1244
1245
1246
1247 @Override
1248 public int hashCode() {
1249 return _cmp.hashCode(this);
1250 }
1251 }