1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.generic;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.DataOutputStream;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.NoSuchElementException;
29
30 import org.apache.bcel.Const;
31 import org.apache.bcel.classfile.Constant;
32 import org.apache.bcel.util.ByteSequence;
33 import org.apache.commons.lang3.ArrayUtils;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class InstructionList implements Iterable<InstructionHandle> {
49
50
51
52
53
54
55
56
57
58
59 public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) {
60 int l = 0;
61 int r = count - 1;
62
63
64
65 do {
66 final int i = l + r >>> 1;
67 final int j = pos[i];
68 if (j == target) {
69 return ihs[i];
70 }
71 if (target < j) {
72 r = i - 1;
73 } else {
74 l = i + 1;
75 }
76 } while (l <= r);
77 return null;
78 }
79
80 private InstructionHandle start;
81 private InstructionHandle end;
82 private int length;
83
84 private int[] bytePositions;
85
86 private List<InstructionListObserver> observers;
87
88
89
90
91 public InstructionList() {
92 }
93
94
95
96
97
98
99 public InstructionList(final BranchInstruction i) {
100 append(i);
101 }
102
103
104
105
106
107
108 public InstructionList(final byte[] code) {
109 int count = 0;
110 int[] pos;
111 InstructionHandle[] ihs;
112 try (ByteSequence bytes = new ByteSequence(code)) {
113 ihs = new InstructionHandle[code.length];
114 pos = new int[code.length];
115
116
117
118 while (bytes.available() > 0) {
119
120 final int off = bytes.getIndex();
121 pos[count] = off;
122
123
124
125 final Instruction i = Instruction.readInstruction(bytes);
126 InstructionHandle ih;
127 if (i instanceof BranchInstruction) {
128 ih = append((BranchInstruction) i);
129 } else {
130 ih = append(i);
131 }
132 ih.setPosition(off);
133 ihs[count] = ih;
134 count++;
135 }
136 } catch (final IOException e) {
137 throw new ClassGenException(e.toString(), e);
138 }
139 bytePositions = Arrays.copyOf(pos, count);
140
141
142
143 for (int i = 0; i < count; i++) {
144 if (ihs[i] instanceof BranchHandle) {
145 final BranchInstruction bi = (BranchInstruction) ihs[i].getInstruction();
146 int target = bi.getPosition() + bi.getIndex();
147
148
149
150 InstructionHandle ih = findHandle(ihs, pos, count, target);
151 if (ih == null) {
152 throw new ClassGenException("Couldn't find target for branch: " + bi);
153 }
154 bi.setTarget(ih);
155
156 if (bi instanceof Select) {
157 final Select s = (Select) bi;
158 final int[] indices = s.getIndices();
159 for (int j = 0; j < indices.length; j++) {
160 target = bi.getPosition() + indices[j];
161 ih = findHandle(ihs, pos, count, target);
162 if (ih == null) {
163 throw new ClassGenException("Couldn't find target for switch: " + bi);
164 }
165 s.setTarget(j, ih);
166 }
167 }
168 }
169 }
170 }
171
172
173
174
175
176
177 public InstructionList(final CompoundInstruction c) {
178 append(c.getInstructionList());
179 }
180
181
182
183
184
185
186 public InstructionList(final Instruction i) {
187 append(i);
188 }
189
190
191
192
193 public void addObserver(final InstructionListObserver o) {
194 if (observers == null) {
195 observers = new ArrayList<>();
196 }
197 observers.add(o);
198 }
199
200
201
202
203
204
205
206 public BranchHandle append(final BranchInstruction i) {
207 final BranchHandle ih = BranchHandle.getBranchHandle(i);
208 append(ih);
209 return ih;
210 }
211
212
213
214
215
216
217
218 public InstructionHandle append(final CompoundInstruction c) {
219 return append(c.getInstructionList());
220 }
221
222
223
224
225
226
227
228 public InstructionHandle append(final Instruction i) {
229 final InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
230 append(ih);
231 return ih;
232 }
233
234
235
236
237
238
239
240
241 public InstructionHandle append(final Instruction i, final CompoundInstruction c) {
242 return append(i, c.getInstructionList());
243 }
244
245
246
247
248
249
250
251
252 public InstructionHandle append(final Instruction i, final Instruction j) {
253 return append(i, new InstructionList(j));
254 }
255
256
257
258
259
260
261
262
263 public InstructionHandle append(final Instruction i, final InstructionList il) {
264 InstructionHandle ih;
265 if ((ih = findInstruction2(i)) == null) {
266 throw new ClassGenException("Instruction " + i + " is not contained in this list.");
267 }
268 return append(ih, il);
269 }
270
271
272
273
274
275
276 private void append(final InstructionHandle ih) {
277 if (isEmpty()) {
278 start = end = ih;
279 ih.setNext(ih.setPrev(null));
280 } else {
281 end.setNext(ih);
282 ih.setPrev(end);
283 ih.setNext(null);
284 end = ih;
285 }
286 length++;
287 }
288
289
290
291
292
293
294
295
296 public BranchHandle append(final InstructionHandle ih, final BranchInstruction i) {
297 final BranchHandle bh = BranchHandle.getBranchHandle(i);
298 final InstructionList il = new InstructionList();
299 il.append(bh);
300 append(ih, il);
301 return bh;
302 }
303
304
305
306
307
308
309
310
311 public InstructionHandle append(final InstructionHandle ih, final CompoundInstruction c) {
312 return append(ih, c.getInstructionList());
313 }
314
315
316
317
318
319
320
321
322 public InstructionHandle append(final InstructionHandle ih, final Instruction i) {
323 return append(ih, new InstructionList(i));
324 }
325
326
327
328
329
330
331
332
333
334 public InstructionHandle append(final InstructionHandle ih, final InstructionList il) {
335 if (il == null) {
336 throw new ClassGenException("Appending null InstructionList");
337 }
338 if (il.isEmpty()) {
339 return ih;
340 }
341 final InstructionHandle next = ih.getNext();
342 final InstructionHandle ret = il.start;
343 ih.setNext(il.start);
344 il.start.setPrev(ih);
345 il.end.setNext(next);
346 if (next != null) {
347 next.setPrev(il.end);
348 } else {
349 end = il.end;
350 }
351 length += il.length;
352 il.clear();
353 return ret;
354 }
355
356
357
358
359
360
361
362 public InstructionHandle append(final InstructionList il) {
363 if (il == null) {
364 throw new ClassGenException("Appending null InstructionList");
365 }
366 if (il.isEmpty()) {
367 return null;
368 }
369 if (isEmpty()) {
370 start = il.start;
371 end = il.end;
372 length = il.length;
373 il.clear();
374 return start;
375 }
376 return append(end, il);
377 }
378
379 private void clear() {
380 start = end = null;
381 length = 0;
382 }
383
384 public boolean contains(final Instruction i) {
385 return findInstruction1(i) != null;
386 }
387
388 public boolean contains(final InstructionHandle i) {
389 if (i == null) {
390 return false;
391 }
392 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
393 if (ih == i) {
394 return true;
395 }
396 }
397 return false;
398 }
399
400
401
402
403 public InstructionList copy() {
404 final Map<InstructionHandle, InstructionHandle> map = new HashMap<>();
405 final InstructionList il = new InstructionList();
406
407
408
409
410 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
411 final Instruction i = ih.getInstruction();
412 final Instruction c = i.copy();
413 if (c instanceof BranchInstruction) {
414 map.put(ih, il.append((BranchInstruction) c));
415 } else {
416 map.put(ih, il.append(c));
417 }
418 }
419
420
421
422 InstructionHandle ih = start;
423 InstructionHandle ch = il.start;
424 while (ih != null) {
425 final Instruction i = ih.getInstruction();
426 final Instruction c = ch.getInstruction();
427 if (i instanceof BranchInstruction) {
428 final BranchInstruction bi = (BranchInstruction) i;
429 final BranchInstruction bc = (BranchInstruction) c;
430 final InstructionHandle itarget = bi.getTarget();
431
432 bc.setTarget(map.get(itarget));
433 if (bi instanceof Select) {
434 final InstructionHandle[] itargets = ((Select) bi).getTargets();
435 final InstructionHandle[] ctargets = ((Select) bc).getTargets();
436 for (int j = 0; j < itargets.length; j++) {
437 ctargets[j] = map.get(itargets[j]);
438 }
439 }
440 }
441 ih = ih.getNext();
442 ch = ch.getNext();
443 }
444 return il;
445 }
446
447
448
449
450
451
452 public void delete(final Instruction i) throws TargetLostException {
453 InstructionHandle ih;
454 if ((ih = findInstruction1(i)) == null) {
455 throw new ClassGenException("Instruction " + i + " is not contained in this list.");
456 }
457 delete(ih);
458 }
459
460
461
462
463
464
465
466
467 public void delete(final Instruction from, final Instruction to) throws TargetLostException {
468 InstructionHandle fromIh;
469 InstructionHandle toIh;
470 if ((fromIh = findInstruction1(from)) == null) {
471 throw new ClassGenException("Instruction " + from + " is not contained in this list.");
472 }
473 if ((toIh = findInstruction2(to)) == null) {
474 throw new ClassGenException("Instruction " + to + " is not contained in this list.");
475 }
476 delete(fromIh, toIh);
477 }
478
479
480
481
482
483
484 public void delete(final InstructionHandle ih) throws TargetLostException {
485 remove(ih.getPrev(), ih.getNext());
486 }
487
488
489
490
491
492
493
494
495 public void delete(final InstructionHandle from, final InstructionHandle to) throws TargetLostException {
496 remove(from.getPrev(), to.getNext());
497 }
498
499
500
501
502
503 public void dispose() {
504
505 for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) {
506
507 ih.dispose();
508 }
509 clear();
510 }
511
512
513
514
515
516
517
518
519 public InstructionHandle findHandle(final int pos) {
520 final int[] positions = bytePositions;
521 InstructionHandle ih = start;
522 for (int i = 0; i < length; i++) {
523 if (positions[i] == pos) {
524 return ih;
525 }
526 ih = ih.getNext();
527 }
528 return null;
529 }
530
531
532
533
534
535
536
537 private InstructionHandle findInstruction1(final Instruction i) {
538 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
539 if (ih.getInstruction() == i) {
540 return ih;
541 }
542 }
543 return null;
544 }
545
546
547
548
549
550
551
552 private InstructionHandle findInstruction2(final Instruction i) {
553 for (InstructionHandle ih = end; ih != null; ih = ih.getPrev()) {
554 if (ih.getInstruction() == i) {
555 return ih;
556 }
557 }
558 return null;
559 }
560
561
562
563
564
565
566 public byte[] getByteCode() {
567
568 setPositions();
569 final ByteArrayOutputStream b = new ByteArrayOutputStream();
570 final DataOutputStream out = new DataOutputStream(b);
571 try {
572 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
573 final Instruction i = ih.getInstruction();
574 i.dump(out);
575 }
576 out.flush();
577 } catch (final IOException e) {
578 System.err.println(e);
579 return ArrayUtils.EMPTY_BYTE_ARRAY;
580 }
581 return b.toByteArray();
582 }
583
584
585
586
587 public InstructionHandle getEnd() {
588 return end;
589 }
590
591
592
593
594 public InstructionHandle[] getInstructionHandles() {
595 final InstructionHandle[] ihs = new InstructionHandle[length];
596 InstructionHandle ih = start;
597 for (int i = 0; i < length; i++) {
598 ihs[i] = ih;
599 ih = ih.getNext();
600 }
601 return ihs;
602 }
603
604
605
606
607
608
609
610 public int[] getInstructionPositions() {
611 return bytePositions;
612 }
613
614
615
616
617 public Instruction[] getInstructions() {
618 final List<Instruction> instructions = new ArrayList<>();
619 try (ByteSequence bytes = new ByteSequence(getByteCode())) {
620 while (bytes.available() > 0) {
621 instructions.add(Instruction.readInstruction(bytes));
622 }
623 } catch (final IOException e) {
624 throw new ClassGenException(e.toString(), e);
625 }
626 return instructions.toArray(Instruction.EMPTY_ARRAY);
627 }
628
629
630
631
632 public int getLength() {
633 return length;
634 }
635
636
637
638
639 public InstructionHandle getStart() {
640 return start;
641 }
642
643
644
645
646
647
648
649 public BranchHandle insert(final BranchInstruction i) {
650 final BranchHandle ih = BranchHandle.getBranchHandle(i);
651 insert(ih);
652 return ih;
653 }
654
655
656
657
658
659
660
661 public InstructionHandle insert(final CompoundInstruction c) {
662 return insert(c.getInstructionList());
663 }
664
665
666
667
668
669
670
671 public InstructionHandle insert(final Instruction i) {
672 final InstructionHandle ih = InstructionHandle.getInstructionHandle(i);
673 insert(ih);
674 return ih;
675 }
676
677
678
679
680
681
682
683
684 public InstructionHandle insert(final Instruction i, final CompoundInstruction c) {
685 return insert(i, c.getInstructionList());
686 }
687
688
689
690
691
692
693
694
695 public InstructionHandle insert(final Instruction i, final Instruction j) {
696 return insert(i, new InstructionList(j));
697 }
698
699
700
701
702
703
704
705
706 public InstructionHandle insert(final Instruction i, final InstructionList il) {
707 InstructionHandle ih;
708 if ((ih = findInstruction1(i)) == null) {
709 throw new ClassGenException("Instruction " + i + " is not contained in this list.");
710 }
711 return insert(ih, il);
712 }
713
714
715
716
717
718
719 private void insert(final InstructionHandle ih) {
720 if (isEmpty()) {
721 start = end = ih;
722 ih.setNext(ih.setPrev(null));
723 } else {
724 start.setPrev(ih);
725 ih.setNext(start);
726 ih.setPrev(null);
727 start = ih;
728 }
729 length++;
730 }
731
732
733
734
735
736
737
738
739 public BranchHandle insert(final InstructionHandle ih, final BranchInstruction i) {
740 final BranchHandle bh = BranchHandle.getBranchHandle(i);
741 final InstructionList il = new InstructionList();
742 il.append(bh);
743 insert(ih, il);
744 return bh;
745 }
746
747
748
749
750
751
752
753
754 public InstructionHandle insert(final InstructionHandle ih, final CompoundInstruction c) {
755 return insert(ih, c.getInstructionList());
756 }
757
758
759
760
761
762
763
764
765 public InstructionHandle insert(final InstructionHandle ih, final Instruction i) {
766 return insert(ih, new InstructionList(i));
767 }
768
769
770
771
772
773
774
775
776
777 public InstructionHandle insert(final InstructionHandle ih, final InstructionList il) {
778 if (il == null) {
779 throw new ClassGenException("Inserting null InstructionList");
780 }
781 if (il.isEmpty()) {
782 return ih;
783 }
784 final InstructionHandle prev = ih.getPrev();
785 final InstructionHandle ret = il.start;
786 ih.setPrev(il.end);
787 il.end.setNext(ih);
788 il.start.setPrev(prev);
789 if (prev != null) {
790 prev.setNext(il.start);
791 } else {
792 start = il.start;
793 }
794 length += il.length;
795 il.clear();
796 return ret;
797 }
798
799
800
801
802
803
804
805 public InstructionHandle insert(final InstructionList il) {
806 if (isEmpty()) {
807 append(il);
808 return start;
809 }
810 return insert(start, il);
811 }
812
813
814
815
816 public boolean isEmpty() {
817 return start == null;
818 }
819
820
821
822
823 @Override
824 public Iterator<InstructionHandle> iterator() {
825 return new Iterator<InstructionHandle>() {
826
827 private InstructionHandle ih = start;
828
829 @Override
830 public boolean hasNext() {
831 return ih != null;
832 }
833
834 @Override
835 public InstructionHandle next() throws NoSuchElementException {
836 if (ih == null) {
837 throw new NoSuchElementException();
838 }
839 final InstructionHandle i = ih;
840 ih = ih.getNext();
841 return i;
842 }
843
844 @Override
845 public void remove() {
846 throw new UnsupportedOperationException();
847 }
848 };
849 }
850
851
852
853
854
855
856
857 public void move(final InstructionHandle ih, final InstructionHandle target) {
858 move(ih, ih, target);
859 }
860
861
862
863
864
865
866
867
868
869
870
871
872
873 public void move(final InstructionHandle start, final InstructionHandle end, final InstructionHandle target) {
874
875 if (start == null || end == null) {
876 throw new ClassGenException("Invalid null handle: From " + start + " to " + end);
877 }
878 if (target == start || target == end) {
879 throw new ClassGenException("Invalid range: From " + start + " to " + end + " contains target " + target);
880 }
881 for (InstructionHandle ih = start; ih != end.getNext(); ih = ih.getNext()) {
882 if (ih == null) {
883 throw new ClassGenException("Invalid range: From " + start + " to " + end);
884 }
885 if (ih == target) {
886 throw new ClassGenException("Invalid range: From " + start + " to " + end + " contains target " + target);
887 }
888 }
889
890 final InstructionHandle prev = start.getPrev();
891 InstructionHandle next = end.getNext();
892 if (prev != null) {
893 prev.setNext(next);
894 } else {
895 this.start = next;
896 }
897 if (next != null) {
898 next.setPrev(prev);
899 } else {
900 this.end = prev;
901 }
902 start.setPrev(end.setNext(null));
903
904 if (target == null) {
905 if (this.start != null) {
906 this.start.setPrev(end);
907 }
908 end.setNext(this.start);
909 this.start = start;
910 } else {
911 next = target.getNext();
912 target.setNext(start);
913 start.setPrev(target);
914 end.setNext(next);
915 if (next != null) {
916 next.setPrev(end);
917 } else {
918 this.end = end;
919 }
920 }
921 }
922
923
924
925
926
927
928
929 public void redirectBranches(final InstructionHandle oldTarget, final InstructionHandle newTarget) {
930 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
931 final Instruction i = ih.getInstruction();
932 if (i instanceof BranchInstruction) {
933 final BranchInstruction b = (BranchInstruction) i;
934 final InstructionHandle target = b.getTarget();
935 if (target == oldTarget) {
936 b.setTarget(newTarget);
937 }
938 if (b instanceof Select) {
939 final InstructionHandle[] targets = ((Select) b).getTargets();
940 for (int j = 0; j < targets.length; j++) {
941 if (targets[j] == oldTarget) {
942 ((Select) b).setTarget(j, newTarget);
943 }
944 }
945 }
946 }
947 }
948 }
949
950
951
952
953
954
955
956
957
958 public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
959 for (final CodeExceptionGen exception : exceptions) {
960 if (exception.getStartPC() == oldTarget) {
961 exception.setStartPC(newTarget);
962 }
963 if (exception.getEndPC() == oldTarget) {
964 exception.setEndPC(newTarget);
965 }
966 if (exception.getHandlerPC() == oldTarget) {
967 exception.setHandlerPC(newTarget);
968 }
969 }
970 }
971
972
973
974
975
976
977
978
979
980 public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
981 for (final LocalVariableGen element : lg) {
982 final InstructionHandle start = element.getStart();
983 final InstructionHandle end = element.getEnd();
984 if (start == oldTarget) {
985 element.setStart(newTarget);
986 }
987 if (end == oldTarget) {
988 element.setEnd(newTarget);
989 }
990 }
991 }
992
993
994
995
996
997
998
999
1000 private void remove(final InstructionHandle prev, InstructionHandle next) throws TargetLostException {
1001 InstructionHandle first;
1002 InstructionHandle last;
1003 if (prev == null && next == null) {
1004 first = start;
1005 last = end;
1006 start = end = null;
1007 } else {
1008 if (prev == null) {
1009 first = start;
1010 start = next;
1011 } else {
1012 first = prev.getNext();
1013 prev.setNext(next);
1014 }
1015 if (next == null) {
1016 last = end;
1017 end = prev;
1018 } else {
1019 last = next.getPrev();
1020 next.setPrev(prev);
1021 }
1022 }
1023 first.setPrev(null);
1024 last.setNext(null);
1025 final List<InstructionHandle> targetList = new ArrayList<>();
1026 for (InstructionHandle ih = first; ih != null; ih = ih.getNext()) {
1027 ih.getInstruction().dispose();
1028 }
1029 final StringBuilder buf = new StringBuilder("{ ");
1030 for (InstructionHandle ih = first; ih != null; ih = next) {
1031 next = ih.getNext();
1032 length--;
1033 if (ih.hasTargeters()) {
1034 targetList.add(ih);
1035 buf.append(ih.toString(true)).append(" ");
1036 ih.setNext(ih.setPrev(null));
1037 } else {
1038 ih.dispose();
1039 }
1040 }
1041 buf.append("}");
1042 if (!targetList.isEmpty()) {
1043 throw new TargetLostException(targetList.toArray(InstructionHandle.EMPTY_ARRAY), buf.toString());
1044 }
1045 }
1046
1047
1048
1049
1050 public void removeObserver(final InstructionListObserver o) {
1051 if (observers != null) {
1052 observers.remove(o);
1053 }
1054 }
1055
1056
1057
1058
1059 public void replaceConstantPool(final ConstantPoolGen oldCp, final ConstantPoolGen newCp) {
1060 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1061 final Instruction i = ih.getInstruction();
1062 if (i instanceof CPInstruction) {
1063 final CPInstruction ci = (CPInstruction) i;
1064 final Constant c = oldCp.getConstant(ci.getIndex());
1065 ci.setIndex(newCp.addConstant(c, oldCp));
1066 }
1067 }
1068 }
1069
1070 public void setPositions() {
1071 setPositions(false);
1072 }
1073
1074
1075
1076
1077
1078
1079 public void setPositions(final boolean check) {
1080 int maxAdditionalBytes = 0;
1081 int additionalBytes = 0;
1082 int index = 0;
1083 int count = 0;
1084 final int[] pos = new int[length];
1085
1086
1087
1088 if (check) {
1089 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1090 final Instruction i = ih.getInstruction();
1091 if (i instanceof BranchInstruction) {
1092 Instruction inst = ((BranchInstruction) i).getTarget().getInstruction();
1093 if (!contains(inst)) {
1094 throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
1095 }
1096 if (i instanceof Select) {
1097 final InstructionHandle[] targets = ((Select) i).getTargets();
1098 for (final InstructionHandle target : targets) {
1099 inst = target.getInstruction();
1100 if (!contains(inst)) {
1101 throw new ClassGenException("Branch target of " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not in instruction list");
1102 }
1103 }
1104 }
1105 if (!(ih instanceof BranchHandle)) {
1106 throw new ClassGenException(
1107 "Branch instruction " + Const.getOpcodeName(i.getOpcode()) + ":" + inst + " not contained in BranchHandle.");
1108 }
1109 }
1110 }
1111 }
1112
1113
1114
1115 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1116 final Instruction i = ih.getInstruction();
1117 ih.setPosition(index);
1118 pos[count++] = index;
1119
1120
1121
1122
1123 switch (i.getOpcode()) {
1124 case Const.JSR:
1125 case Const.GOTO:
1126 maxAdditionalBytes += 2;
1127 break;
1128 case Const.TABLESWITCH:
1129 case Const.LOOKUPSWITCH:
1130 maxAdditionalBytes += 3;
1131 break;
1132 default:
1133
1134 break;
1135 }
1136 index += i.getLength();
1137 }
1138
1139
1140
1141
1142 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1143 additionalBytes += ih.updatePosition(additionalBytes, maxAdditionalBytes);
1144 }
1145
1146
1147
1148 index = count = 0;
1149 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1150 final Instruction i = ih.getInstruction();
1151 ih.setPosition(index);
1152 pos[count++] = index;
1153 index += i.getLength();
1154 }
1155 bytePositions = Arrays.copyOfRange(pos, 0, count);
1156 }
1157
1158
1159
1160
1161 public int size() {
1162 return length;
1163 }
1164
1165 @Override
1166 public String toString() {
1167 return toString(true);
1168 }
1169
1170
1171
1172
1173
1174 public String toString(final boolean verbose) {
1175 final StringBuilder buf = new StringBuilder();
1176 for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
1177 buf.append(ih.toString(verbose)).append("\n");
1178 }
1179 return buf.toString();
1180 }
1181
1182
1183
1184
1185
1186 public void update() {
1187 if (observers != null) {
1188 for (final InstructionListObserver observer : observers) {
1189 observer.notify(this);
1190 }
1191 }
1192 }
1193 }