1 package com.sun.org.apache.bcel.internal.generic; 2 3 56 57 import com.sun.org.apache.bcel.internal.Constants; 58 import com.sun.org.apache.bcel.internal.classfile.Constant; 59 import com.sun.org.apache.bcel.internal.util.ByteSequence; 60 import java.io.*; 61 import java.util.Iterator ; 62 import java.util.HashMap ; 63 import java.util.ArrayList ; 64 65 84 public class InstructionList implements Serializable { 85 private InstructionHandle start = null, end = null; 86 private int length = 0; private int[] byte_positions; 89 92 public InstructionList() {} 93 94 98 public InstructionList(Instruction i) { 99 append(i); 100 } 101 102 106 public InstructionList(BranchInstruction i) { 107 append(i); 108 } 109 110 116 public InstructionList(CompoundInstruction c) { 117 append(c.getInstructionList()); 118 } 119 120 123 public boolean isEmpty() { return start == null; } 125 135 public static InstructionHandle findHandle(InstructionHandle[] ihs, 136 int[] pos, int count, 137 int target) { 138 int l=0, r = count - 1; 139 140 142 do { 143 int i = (l + r) / 2; 144 int j = pos[i]; 145 146 if(j == target) return ihs[i]; 148 else if(target < j) r = i - 1; 150 else l = i + 1; 152 } while(l <= r); 153 154 return null; 155 } 156 157 165 public InstructionHandle findHandle(int pos) { 166 InstructionHandle[] ihs = getInstructionHandles(); 167 return findHandle(ihs, byte_positions, length, pos); 168 } 169 170 175 public InstructionList(byte[] code) { 176 ByteSequence bytes = new ByteSequence(code); 177 InstructionHandle[] ihs = new InstructionHandle[code.length]; 178 int[] pos = new int[code.length]; int count = 0; 181 184 try { 185 while(bytes.available() > 0) { 186 int off = bytes.getIndex(); 188 pos[count] = off; 189 190 193 Instruction i = Instruction.readInstruction(bytes); 194 InstructionHandle ih; 195 if(i instanceof BranchInstruction) ih = append((BranchInstruction)i); 197 else 198 ih = append(i); 199 200 ih.setPosition(off); 201 ihs[count] = ih; 202 203 count++; 204 } 205 } catch(IOException e) { throw new ClassGenException(e.toString()); } 206 207 byte_positions = new int[count]; System.arraycopy(pos, 0, byte_positions, 0, count); 209 210 213 for(int i=0; i < count; i++) { 214 if(ihs[i] instanceof BranchHandle) { 215 BranchInstruction bi = (BranchInstruction)ihs[i].instruction; 216 int target = bi.position + bi.getIndex(); 218 InstructionHandle ih = findHandle(ihs, pos, count, target); 220 221 if(ih == null) throw new ClassGenException("Couldn't find target for branch: " + bi); 223 224 bi.setTarget(ih); 226 if(bi instanceof Select) { Select s = (Select)bi; 229 int[] indices = s.getIndices(); 230 231 for(int j=0; j < indices.length; j++) { 232 target = bi.position + indices[j]; 233 ih = findHandle(ihs, pos, count, target); 234 235 if(ih == null) throw new ClassGenException("Couldn't find target for switch: " + bi); 237 238 s.setTarget(j, ih); } 240 } 241 } 242 } 243 } 244 245 253 public InstructionHandle append(InstructionHandle ih, InstructionList il) { 254 if(il == null) 255 throw new ClassGenException("Appending null InstructionList"); 256 257 if(il.isEmpty()) return ih; 259 260 InstructionHandle next = ih.next, ret = il.start; 261 262 ih.next = il.start; 263 il.start.prev = ih; 264 265 il.end.next = next; 266 267 if(next != null) next.prev = il.end; 269 else 270 end = il.end; 272 length += il.length; 274 il.clear(); 275 276 return ret; 277 } 278 279 287 public InstructionHandle append(Instruction i, InstructionList il) { 288 InstructionHandle ih; 289 290 if((ih = findInstruction2(i)) == null) throw new ClassGenException("Instruction " + i + 292 " is not contained in this list."); 293 294 return append(ih, il); 295 } 296 297 304 public InstructionHandle append(InstructionList il) { 305 if(il == null) 306 throw new ClassGenException("Appending null InstructionList"); 307 308 if(il.isEmpty()) return null; 310 311 if(isEmpty()) { 312 start = il.start; 313 end = il.end; 314 length = il.length; 315 316 il.clear(); 317 318 return start; 319 } else 320 return append(end, il); } 322 323 328 private void append(InstructionHandle ih) { 329 if(isEmpty()) { 330 start = end = ih; 331 ih.next = ih.prev = null; 332 } 333 else { 334 end.next = ih; 335 ih.prev = end; 336 ih.next = null; 337 end = ih; 338 } 339 340 length++; } 342 343 349 public InstructionHandle append(Instruction i) { 350 InstructionHandle ih = InstructionHandle.getInstructionHandle(i); 351 append(ih); 352 353 return ih; 354 } 355 356 362 public BranchHandle append(BranchInstruction i) { 363 BranchHandle ih = BranchHandle.getBranchHandle(i); 364 append(ih); 365 366 return ih; 367 } 368 369 377 public InstructionHandle append(Instruction i, Instruction j) { 378 return append(i, new InstructionList(j)); 379 } 380 381 388 public InstructionHandle append(Instruction i, CompoundInstruction c) { 389 return append(i, c.getInstructionList()); 390 } 391 392 398 public InstructionHandle append(CompoundInstruction c) { 399 return append(c.getInstructionList()); 400 } 401 402 409 public InstructionHandle append(InstructionHandle ih, CompoundInstruction c) { 410 return append(ih, c.getInstructionList()); 411 } 412 413 420 public InstructionHandle append(InstructionHandle ih, Instruction i) { 421 return append(ih, new InstructionList(i)); 422 } 423 424 431 public BranchHandle append(InstructionHandle ih, BranchInstruction i) { 432 BranchHandle bh = BranchHandle.getBranchHandle(i); 433 InstructionList il = new InstructionList(); 434 il.append(bh); 435 436 append(ih, il); 437 438 return bh; 439 } 440 441 449 public InstructionHandle insert(InstructionHandle ih, InstructionList il) { 450 if(il == null) 451 throw new ClassGenException("Inserting null InstructionList"); 452 453 if(il.isEmpty()) return ih; 455 456 InstructionHandle prev = ih.prev, ret = il.start; 457 458 ih.prev = il.end; 459 il.end.next = ih; 460 461 il.start.prev = prev; 462 463 if(prev != null) prev.next = il.start; 465 else 466 start = il.start; 468 length += il.length; 470 il.clear(); 471 472 return ret; 473 } 474 475 481 public InstructionHandle insert(InstructionList il) { 482 if(isEmpty()) { 483 append(il); return start; 485 } 486 else 487 return insert(start, il); 488 } 489 490 495 private void insert(InstructionHandle ih) { 496 if(isEmpty()) { 497 start = end = ih; 498 ih.next = ih.prev = null; 499 } else { 500 start.prev = ih; 501 ih.next = start; 502 ih.prev = null; 503 start = ih; 504 } 505 506 length++; 507 } 508 509 518 public InstructionHandle insert(Instruction i, InstructionList il) { 519 InstructionHandle ih; 520 521 if((ih = findInstruction1(i)) == null) 522 throw new ClassGenException("Instruction " + i + 523 " is not contained in this list."); 524 525 return insert(ih, il); 526 } 527 528 534 public InstructionHandle insert(Instruction i) { 535 InstructionHandle ih = InstructionHandle.getInstructionHandle(i); 536 insert(ih); 537 538 return ih; 539 } 540 541 547 public BranchHandle insert(BranchInstruction i) { 548 BranchHandle ih = BranchHandle.getBranchHandle(i); 549 insert(ih); 550 return ih; 551 } 552 553 561 public InstructionHandle insert(Instruction i, Instruction j) { 562 return insert(i, new InstructionList(j)); 563 } 564 565 572 public InstructionHandle insert(Instruction i, CompoundInstruction c) { 573 return insert(i, c.getInstructionList()); 574 } 575 576 582 public InstructionHandle insert(CompoundInstruction c) { 583 return insert(c.getInstructionList()); 584 } 585 586 593 public InstructionHandle insert(InstructionHandle ih, Instruction i) { 594 return insert(ih, new InstructionList(i)); 595 } 596 597 604 public InstructionHandle insert(InstructionHandle ih, CompoundInstruction c) { 605 return insert(ih, c.getInstructionList()); 606 } 607 608 615 public BranchHandle insert(InstructionHandle ih, BranchInstruction i) { 616 BranchHandle bh = BranchHandle.getBranchHandle(i); 617 InstructionList il = new InstructionList(); 618 il.append(bh); 619 620 insert(ih, il); 621 622 return bh; 623 } 624 625 636 public void move(InstructionHandle start, InstructionHandle end, InstructionHandle target) { 637 639 if((start == null) || (end == null)) 640 throw new ClassGenException("Invalid null handle: From " + start + " to " + end); 641 642 if((target == start) || (target == end)) 643 throw new ClassGenException("Invalid range: From " + start + " to " + end + 644 " contains target " + target); 645 646 for(InstructionHandle ih = start; ih != end.next; ih = ih.next) { 647 if(ih == null) throw new ClassGenException("Invalid range: From " + start + " to " + end); 649 else if(ih == target) throw new ClassGenException("Invalid range: From " + start + " to " + end + 651 " contains target " + target); 652 } 653 654 656 InstructionHandle prev = start.prev, next = end.next; 657 658 if(prev != null) 659 prev.next = next; 660 else this.start = next; 662 663 if(next != null) 664 next.prev = prev; 665 else this.end = prev; 667 668 start.prev = end.next = null; 669 670 672 if(target == null) { end.next = this.start; 674 this.start = start; 675 } else { 676 next = target.next; 677 678 target.next = start; 679 start.prev = target; 680 end.next = next; 681 682 if(next != null) 683 next.prev = end; 684 } 685 } 686 687 693 public void move(InstructionHandle ih, InstructionHandle target) { 694 move(ih, ih, target); 695 } 696 697 705 private void remove(InstructionHandle prev, InstructionHandle next) 706 throws TargetLostException 707 { 708 InstructionHandle first, last; 710 if((prev == null) && (next == null)) { first = last = start; 712 start = end = null; 713 } else { 714 if(prev == null) { first = start; 716 start = next; 717 } else { 718 first = prev.next; 719 prev.next = next; 720 } 721 722 if(next == null) { last = end; 724 end = prev; 725 } else { 726 last = next.prev; 727 next.prev = prev; 728 } 729 } 730 731 first.prev = null; last.next = null; 733 734 ArrayList target_vec = new ArrayList (); 735 736 for(InstructionHandle ih=first; ih != null; ih = ih.next) 737 ih.getInstruction().dispose(); 739 StringBuffer buf = new StringBuffer ("{ "); 740 for(InstructionHandle ih=first; ih != null; ih = next) { 741 next = ih.next; 742 length--; 743 744 if(ih.hasTargeters()) { target_vec.add(ih); 746 buf.append(ih.toString(true) + " "); 747 ih.next = ih.prev = null; 748 } else 749 ih.dispose(); 750 } 751 752 buf.append("}"); 753 754 if(!target_vec.isEmpty()) { 755 InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; 756 target_vec.toArray(targeted); 757 throw new TargetLostException(targeted, buf.toString()); 758 } 759 } 760 761 767 public void delete(InstructionHandle ih) throws TargetLostException { 768 remove(ih.prev, ih.next); 769 } 770 771 777 public void delete(Instruction i) throws TargetLostException { 778 InstructionHandle ih; 779 780 if((ih = findInstruction1(i)) == null) 781 throw new ClassGenException("Instruction " + i + 782 " is not contained in this list."); 783 delete(ih); 784 } 785 786 794 public void delete(InstructionHandle from, InstructionHandle to) 795 throws TargetLostException 796 { 797 remove(from.prev, to.next); 798 } 799 800 808 public void delete(Instruction from, Instruction to) throws TargetLostException { 809 InstructionHandle from_ih, to_ih; 810 811 if((from_ih = findInstruction1(from)) == null) 812 throw new ClassGenException("Instruction " + from + 813 " is not contained in this list."); 814 815 if((to_ih = findInstruction2(to)) == null) 816 throw new ClassGenException("Instruction " + to + 817 " is not contained in this list."); 818 delete(from_ih, to_ih); 819 } 820 821 827 private InstructionHandle findInstruction1(Instruction i) { 828 for(InstructionHandle ih=start; ih != null; ih = ih.next) 829 if(ih.instruction == i) 830 return ih; 831 832 return null; 833 } 834 835 841 private InstructionHandle findInstruction2(Instruction i) { 842 for(InstructionHandle ih=end; ih != null; ih = ih.prev) 843 if(ih.instruction == i) 844 return ih; 845 846 return null; 847 } 848 849 public boolean contains(InstructionHandle i) { 850 if(i == null) 851 return false; 852 853 for(InstructionHandle ih=start; ih != null; ih = ih.next) 854 if(ih == i) 855 return true; 856 857 return false; 858 } 859 860 public boolean contains(Instruction i) { 861 return findInstruction1(i) != null; 862 } 863 864 public void setPositions() { 865 setPositions(false); 866 } 867 868 875 public void setPositions(boolean check) { 876 int max_additional_bytes = 0, additional_bytes = 0; 877 int index = 0, count = 0; 878 int[] pos = new int[length]; 879 880 882 if(check) { 883 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 884 Instruction i = ih.instruction; 885 886 if(i instanceof BranchInstruction) { Instruction inst = ((BranchInstruction)i).getTarget().instruction; 888 if(!contains(inst)) 889 throw new ClassGenException("Branch target of " + 890 Constants.OPCODE_NAMES[i.opcode] + ":" + 891 inst + " not in instruction list"); 892 893 if(i instanceof Select) { 894 InstructionHandle[] targets = ((Select)i).getTargets(); 895 896 for(int j=0; j < targets.length; j++) { 897 inst = targets[j].instruction; 898 if(!contains(inst)) 899 throw new ClassGenException("Branch target of " + 900 Constants.OPCODE_NAMES[i.opcode] + ":" + 901 inst + " not in instruction list"); 902 } 903 } 904 905 if(!(ih instanceof BranchHandle)) 906 throw new ClassGenException("Branch instruction " + 907 Constants.OPCODE_NAMES[i.opcode] + ":" + 908 inst + " not contained in BranchHandle."); 909 910 } 911 } 912 } 913 914 917 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 918 Instruction i = ih.instruction; 919 920 ih.setPosition(index); 921 pos[count++] = index; 922 923 928 switch(i.getOpcode()) { 929 case Constants.JSR: case Constants.GOTO: 930 max_additional_bytes += 2; 931 break; 932 933 case Constants.TABLESWITCH: case Constants.LOOKUPSWITCH: 934 max_additional_bytes += 3; 935 break; 936 } 937 938 index += i.getLength(); 939 } 940 941 945 for(InstructionHandle ih=start; ih != null; ih = ih.next) 946 additional_bytes += ih.updatePosition(additional_bytes, max_additional_bytes); 947 948 951 index=count=0; 952 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 953 Instruction i = ih.instruction; 954 955 ih.setPosition(index); 956 pos[count++] = index; 957 index += i.getLength(); 958 } 959 960 byte_positions = new int[count]; System.arraycopy(pos, 0, byte_positions, 0, count); 962 } 963 964 970 public byte[] getByteCode() { 971 setPositions(); 973 974 ByteArrayOutputStream b = new ByteArrayOutputStream(); 975 DataOutputStream out = new DataOutputStream(b); 976 977 try { 978 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 979 Instruction i = ih.instruction; 980 i.dump(out); } 982 } catch(IOException e) { 983 System.err.println(e); 984 return null; 985 } 986 987 return b.toByteArray(); 988 } 989 990 993 public Instruction[] getInstructions() { 994 ByteSequence bytes = new ByteSequence(getByteCode()); 995 ArrayList instructions = new ArrayList (); 996 997 try { 998 while(bytes.available() > 0) { 999 instructions.add(Instruction.readInstruction(bytes)); 1000 } 1001 } catch(IOException e) { throw new ClassGenException(e.toString()); } 1002 1003 Instruction[] result = new Instruction[instructions.size()]; 1004 instructions.toArray(result); 1005 return result; 1006 } 1007 1008 public String toString() { 1009 return toString(true); 1010 } 1011 1012 1016 public String toString(boolean verbose) { 1017 StringBuffer buf = new StringBuffer (); 1018 1019 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 1020 buf.append(ih.toString(verbose) + "\n"); 1021 } 1022 1023 return buf.toString(); 1024 } 1025 1026 1029 public Iterator iterator() { 1030 return new Iterator () { 1031 private InstructionHandle ih = start; 1032 1033 public Object next() { 1034 InstructionHandle i = ih; 1035 ih = ih.next; 1036 return i; 1037 } 1038 1039 public void remove() { 1040 throw new UnsupportedOperationException (); 1041 } 1042 1043 public boolean hasNext() { return ih != null; } 1044 }; 1045 } 1046 1047 1050 public InstructionHandle[] getInstructionHandles() { 1051 InstructionHandle[] ihs = new InstructionHandle[length]; 1052 InstructionHandle ih = start; 1053 1054 for(int i=0; i < length; i++) { 1055 ihs[i] = ih; 1056 ih = ih.next; 1057 } 1058 1059 return ihs; 1060 } 1061 1062 1069 public int[] getInstructionPositions() { return byte_positions; } 1070 1071 1074 public InstructionList copy() { 1075 HashMap map = new HashMap (); 1076 InstructionList il = new InstructionList(); 1077 1078 1082 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 1083 Instruction i = ih.instruction; 1084 Instruction c = i.copy(); 1086 if(c instanceof BranchInstruction) 1087 map.put(ih, il.append((BranchInstruction)c)); 1088 else 1089 map.put(ih, il.append(c)); 1090 } 1091 1092 1094 InstructionHandle ih=start; 1095 InstructionHandle ch=il.start; 1096 1097 while(ih != null) { 1098 Instruction i = ih.instruction; 1099 Instruction c = ch.instruction; 1100 1101 if(i instanceof BranchInstruction) { 1102 BranchInstruction bi = (BranchInstruction)i; 1103 BranchInstruction bc = (BranchInstruction)c; 1104 InstructionHandle itarget = bi.getTarget(); 1106 bc.setTarget((InstructionHandle)map.get(itarget)); 1108 1109 if(bi instanceof Select) { InstructionHandle[] itargets = ((Select)bi).getTargets(); 1111 InstructionHandle[] ctargets = ((Select)bc).getTargets(); 1112 1113 for(int j=0; j < itargets.length; j++) { ctargets[j] = (InstructionHandle)map.get(itargets[j]); 1115 } 1116 } 1117 } 1118 1119 ih = ih.next; 1120 ch = ch.next; 1121 } 1122 1123 return il; 1124 } 1125 1126 1129 public void replaceConstantPool(ConstantPoolGen old_cp, ConstantPoolGen new_cp) { 1130 for(InstructionHandle ih=start; ih != null; ih = ih.next) { 1131 Instruction i = ih.instruction; 1132 1133 if(i instanceof CPInstruction) { 1134 CPInstruction ci = (CPInstruction)i; 1135 Constant c = old_cp.getConstant(ci.getIndex()); 1136 ci.setIndex(new_cp.addConstant(c, old_cp)); 1137 } 1138 } 1139 } 1140 1141 private void clear() { 1142 start = end = null; 1143 length = 0; 1144 } 1145 1146 1152 public void dispose() { 1153 for(InstructionHandle ih=end; ih != null; ih = ih.prev) 1155 1158 ih.dispose(); 1159 1160 clear(); 1161 } 1162 1163 1166 public InstructionHandle getStart() { return start; } 1167 1168 1171 public InstructionHandle getEnd() { return end; } 1172 1173 1176 public int getLength() { return length; } 1177 1178 1181 public int size() { return length; } 1182 1183 1190 public void redirectBranches(InstructionHandle old_target, 1191 InstructionHandle new_target) { 1192 for(InstructionHandle ih = start; ih != null; ih = ih.next) { 1193 Instruction i = ih.getInstruction(); 1194 1195 if(i instanceof BranchInstruction) { 1196 BranchInstruction b = (BranchInstruction)i; 1197 InstructionHandle target = b.getTarget(); 1198 1199 if(target == old_target) 1200 b.setTarget(new_target); 1201 1202 if(b instanceof Select) { InstructionHandle[] targets = ((Select)b).getTargets(); 1204 1205 for(int j=0; j < targets.length; j++) if(targets[j] == old_target) 1207 ((Select)b).setTarget(j, new_target); 1208 } 1209 } 1210 } 1211 } 1212 1213 1221 public void redirectLocalVariables(LocalVariableGen[] lg, 1222 InstructionHandle old_target, 1223 InstructionHandle new_target) { 1224 for(int i=0; i < lg.length; i++) { 1225 InstructionHandle start = lg[i].getStart(); 1226 InstructionHandle end = lg[i].getEnd(); 1227 1228 if(start == old_target) 1229 lg[i].setStart(new_target); 1230 1231 if(end == old_target) 1232 lg[i].setEnd(new_target); 1233 } 1234 } 1235 1236 1244 public void redirectExceptionHandlers(CodeExceptionGen[] exceptions, 1245 InstructionHandle old_target, 1246 InstructionHandle new_target) { 1247 for(int i=0; i < exceptions.length; i++) { 1248 if(exceptions[i].getStartPC() == old_target) 1249 exceptions[i].setStartPC(new_target); 1250 1251 if(exceptions[i].getEndPC() == old_target) 1252 exceptions[i].setEndPC(new_target); 1253 1254 if(exceptions[i].getHandlerPC() == old_target) 1255 exceptions[i].setHandlerPC(new_target); 1256 } 1257 } 1258 1259 private ArrayList observers; 1260 1261 1263 public void addObserver(InstructionListObserver o) { 1264 if(observers == null) 1265 observers = new ArrayList (); 1266 1267 observers.add(o); 1268 } 1269 1270 1272 public void removeObserver(InstructionListObserver o) { 1273 if(observers != null) 1274 observers.remove(o); 1275 } 1276 1277 1281 public void update() { 1282 if(observers != null) 1283 for(Iterator e = observers.iterator(); e.hasNext(); ) 1284 ((InstructionListObserver)e.next()).notify(this); 1285 } 1286} 1287 1288 | Popular Tags |