| 1 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.io.Serializable ; 23 import java.util.ArrayList ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 import org.apache.bcel.Constants; 29 import org.apache.bcel.classfile.Constant; 30 import org.apache.bcel.util.ByteSequence; 31 32 51 public class InstructionList implements Serializable { 52 53 private InstructionHandle start = null, end = null; 54 private int length = 0; private int[] byte_positions; 57 58 61 public InstructionList() { 62 } 63 64 65 69 public InstructionList(Instruction i) { 70 append(i); 71 } 72 73 74 78 public InstructionList(BranchInstruction i) { 79 append(i); 80 } 81 82 83 89 public InstructionList(CompoundInstruction c) { 90 append(c.getInstructionList()); 91 } 92 93 94 97 public boolean isEmpty() { 98 return start == null; 99 } 101 102 112 public static InstructionHandle findHandle( InstructionHandle[] ihs, int[] pos, int count, 113 int target ) { 114 int l = 0, r = count - 1; 115 117 do { 118 int i = (l + r) / 2; 119 int j = pos[i]; 120 if (j == target) { 121 return ihs[i]; 122 } else if (target < j) { 123 r = i - 1; 124 } else { 125 l = i + 1; 126 } 127 } while (l <= r); 128 return null; 129 } 130 131 132 140 public InstructionHandle findHandle( int pos ) { 141 InstructionHandle[] ihs = getInstructionHandles(); 142 return findHandle(ihs, byte_positions, length, pos); 143 } 144 145 146 151 public InstructionList(byte[] code) { 152 ByteSequence bytes = new ByteSequence(code); 153 InstructionHandle[] ihs = new InstructionHandle[code.length]; 154 int[] pos = new int[code.length]; int count = 0; 159 try { 160 while (bytes.available() > 0) { 161 int off = bytes.getIndex(); 163 pos[count] = off; 164 167 Instruction i = Instruction.readInstruction(bytes); 168 InstructionHandle ih; 169 if (i instanceof BranchInstruction) { 170 ih = append((BranchInstruction) i); 171 } else { 172 ih = append(i); 173 } 174 ih.setPosition(off); 175 ihs[count] = ih; 176 count++; 177 } 178 } catch (IOException e) { 179 throw new ClassGenException(e.toString()); 180 } 181 byte_positions = new int[count]; System.arraycopy(pos, 0, byte_positions, 0, count); 183 186 for (int i = 0; i < count; i++) { 187 if (ihs[i] instanceof BranchHandle) { 188 BranchInstruction bi = (BranchInstruction) ihs[i].instruction; 189 int target = bi.position + bi.getIndex(); 191 InstructionHandle ih = findHandle(ihs, pos, count, target); 193 if (ih == null) { 194 throw new ClassGenException("Couldn't find target for branch: " + bi); 195 } 196 bi.setTarget(ih); if (bi instanceof Select) { Select s = (Select) bi; 200 int[] indices = s.getIndices(); 201 for (int j = 0; j < indices.length; j++) { 202 target = bi.position + indices[j]; 203 ih = findHandle(ihs, pos, count, target); 204 if (ih == null) { 205 throw new ClassGenException("Couldn't find target for switch: " + bi); 206 } 207 s.setTarget(j, ih); } 209 } 210 } 211 } 212 } 213 214 215 223 public InstructionHandle append( InstructionHandle ih, InstructionList il ) { 224 if (il == null) { 225 throw new ClassGenException("Appending null InstructionList"); 226 } 227 if (il.isEmpty()) { 228 return ih; 229 } 230 InstructionHandle next = ih.next, ret = il.start; 231 ih.next = il.start; 232 il.start.prev = ih; 233 il.end.next = next; 234 if (next != null) { 235 next.prev = il.end; 236 } else { 237 end = il.end; } 239 length += il.length; il.clear(); 241 return ret; 242 } 243 244 245 253 public InstructionHandle append( Instruction i, InstructionList il ) { 254 InstructionHandle ih; 255 if ((ih = findInstruction2(i)) == null) { 256 throw new ClassGenException("Instruction " + i + " is not contained in this list."); 257 } 258 return append(ih, il); 259 } 260 261 262 269 public InstructionHandle append( InstructionList il ) { 270 if (il == null) { 271 throw new ClassGenException("Appending null InstructionList"); 272 } 273 if (il.isEmpty()) { 274 return null; 275 } 276 if (isEmpty()) { 277 start = il.start; 278 end = il.end; 279 length = il.length; 280 il.clear(); 281 return start; 282 } else { 283 return append(end, il); } 285 } 286 287 288 293 private void append( InstructionHandle ih ) { 294 if (isEmpty()) { 295 start = end = ih; 296 ih.next = ih.prev = null; 297 } else { 298 end.next = ih; 299 ih.prev = end; 300 ih.next = null; 301 end = ih; 302 } 303 length++; } 305 306 307 313 public InstructionHandle append( Instruction i ) { 314 InstructionHandle ih = InstructionHandle.getInstructionHandle(i); 315 append(ih); 316 return ih; 317 } 318 319 320 326 public BranchHandle append( BranchInstruction i ) { 327 BranchHandle ih = BranchHandle.getBranchHandle(i); 328 append(ih); 329 return ih; 330 } 331 332 333 341 public InstructionHandle append( Instruction i, Instruction j ) { 342 return append(i, new InstructionList(j)); 343 } 344 345 346 353 public InstructionHandle append( Instruction i, CompoundInstruction c ) { 354 return append(i, c.getInstructionList()); 355 } 356 357 358 364 public InstructionHandle append( CompoundInstruction c ) { 365 return append(c.getInstructionList()); 366 } 367 368 369 376 public InstructionHandle append( InstructionHandle ih, CompoundInstruction c ) { 377 return append(ih, c.getInstructionList()); 378 } 379 380 381 388 public InstructionHandle append( InstructionHandle ih, Instruction i ) { 389 return append(ih, new InstructionList(i)); 390 } 391 392 393 400 public BranchHandle append( InstructionHandle ih, BranchInstruction i ) { 401 BranchHandle bh = BranchHandle.getBranchHandle(i); 402 InstructionList il = new InstructionList(); 403 il.append(bh); 404 append(ih, il); 405 return bh; 406 } 407 408 409 417 public InstructionHandle insert( InstructionHandle ih, InstructionList il ) { 418 if (il == null) { 419 throw new ClassGenException("Inserting null InstructionList"); 420 } 421 if (il.isEmpty()) { 422 return ih; 423 } 424 InstructionHandle prev = ih.prev, ret = il.start; 425 ih.prev = il.end; 426 il.end.next = ih; 427 il.start.prev = prev; 428 if (prev != null) { 429 prev.next = il.start; 430 } else { 431 start = il.start; } 433 length += il.length; il.clear(); 435 return ret; 436 } 437 438 439 445 public InstructionHandle insert( InstructionList il ) { 446 if (isEmpty()) { 447 append(il); return start; 449 } else { 450 return insert(start, il); 451 } 452 } 453 454 455 460 private void insert( InstructionHandle ih ) { 461 if (isEmpty()) { 462 start = end = ih; 463 ih.next = ih.prev = null; 464 } else { 465 start.prev = ih; 466 ih.next = start; 467 ih.prev = null; 468 start = ih; 469 } 470 length++; 471 } 472 473 474 483 public InstructionHandle insert( Instruction i, InstructionList il ) { 484 InstructionHandle ih; 485 if ((ih = findInstruction1(i)) == null) { 486 throw new ClassGenException("Instruction " + i + " is not contained in this list."); 487 } 488 return insert(ih, il); 489 } 490 491 492 498 public InstructionHandle insert( Instruction i ) { 499 InstructionHandle ih = InstructionHandle.getInstructionHandle(i); 500 insert(ih); 501 return ih; 502 } 503 504 505 511 public BranchHandle insert( BranchInstruction i ) { 512 BranchHandle ih = BranchHandle.getBranchHandle(i); 513 insert(ih); 514 return ih; 515 } 516 517 518 526 public InstructionHandle insert( Instruction i, Instruction j ) { 527 return insert(i, new InstructionList(j)); 528 } 529 530 531 538 public InstructionHandle insert( Instruction i, CompoundInstruction c ) { 539 return insert(i, c.getInstructionList()); 540 } 541 542 543 549 public InstructionHandle insert( CompoundInstruction c ) { 550 return insert(c.getInstructionList()); 551 } 552 553 554 561 public InstructionHandle insert( InstructionHandle ih, Instruction i ) { 562 return insert(ih, new InstructionList(i)); 563 } 564 565 566 573 public InstructionHandle insert( InstructionHandle ih, CompoundInstruction c ) { 574 return insert(ih, c.getInstructionList()); 575 } 576 577 578 585 public BranchHandle insert( InstructionHandle ih, BranchInstruction i ) { 586 BranchHandle bh = BranchHandle.getBranchHandle(i); 587 InstructionList il = new InstructionList(); 588 il.append(bh); 589 insert(ih, il); 590 return bh; 591 } 592 593 594 605 public void move( InstructionHandle start, InstructionHandle end, InstructionHandle target ) { 606 if ((start == null) || (end == null)) { 608 throw new ClassGenException("Invalid null handle: From " + start + " to " + end); 609 } 610 if ((target == start) || (target == end)) { 611 throw new ClassGenException("Invalid range: From " + start + " to " + end 612 + " contains target " + target); 613 } 614 for (InstructionHandle ih = start; ih != end.next; ih = ih.next) { 615 if (ih == null) { 616 throw new ClassGenException("Invalid range: From " + start + " to " + end); 617 } else if (ih == target) { 618 throw new ClassGenException("Invalid range: From " + start + " to " + end 619 + " contains target " + target); 620 } 621 } 622 InstructionHandle prev = start.prev, next = end.next; 624 if (prev != null) { 625 prev.next = next; 626 } else { 627 this.start = next; 628 } 629 if (next != null) { 630 next.prev = prev; 631 } else { 632 this.end = prev; 633 } 634 start.prev = end.next = null; 635 if (target == null) { if (this.start != null) { 638 this.start.prev = end; 639 } 640 end.next = this.start; 641 this.start = start; 642 } else { 643 next = target.next; 644 target.next = start; 645 start.prev = target; 646 end.next = next; 647 if (next != null) { 648 next.prev = end; 649 } else { 650 this.end = end; 651 } 652 } 653 } 654 655 656 662 public void move( InstructionHandle ih, InstructionHandle target ) { 663 move(ih, ih, target); 664 } 665 666 667 675 private void remove( InstructionHandle prev, InstructionHandle next ) 676 throws TargetLostException { 677 InstructionHandle first, last; if ((prev == null) && (next == null)) { first = last = start; 680 start = end = null; 681 } else { 682 if (prev == null) { first = start; 684 start = next; 685 } else { 686 first = prev.next; 687 prev.next = next; 688 } 689 if (next == null) { last = end; 691 end = prev; 692 } else { 693 last = next.prev; 694 next.prev = prev; 695 } 696 } 697 first.prev = null; last.next = null; 699 List target_vec = new ArrayList (); 700 for (InstructionHandle ih = first; ih != null; ih = ih.next) { 701 ih.getInstruction().dispose(); } 703 StringBuffer buf = new StringBuffer ("{ "); 704 for (InstructionHandle ih = first; ih != null; ih = next) { 705 next = ih.next; 706 length--; 707 if (ih.hasTargeters()) { target_vec.add(ih); 709 buf.append(ih.toString(true) + " "); 710 ih.next = ih.prev = null; 711 } else { 712 ih.dispose(); 713 } 714 } 715 buf.append("}"); 716 if (!target_vec.isEmpty()) { 717 InstructionHandle[] targeted = new InstructionHandle[target_vec.size()]; 718 target_vec.toArray(targeted); 719 throw new TargetLostException(targeted, buf.toString()); 720 } 721 } 722 723 724 730 public void delete( InstructionHandle ih ) throws TargetLostException { 731 remove(ih.prev, ih.next); 732 } 733 734 735 741 public void delete( Instruction i ) throws TargetLostException { 742 InstructionHandle ih; 743 if ((ih = findInstruction1(i)) == null) { 744 throw new ClassGenException("Instruction " + i + " is not contained in this list."); 745 } 746 delete(ih); 747 } 748 749 750 758 public void delete( InstructionHandle from, InstructionHandle to ) throws TargetLostException { 759 remove(from.prev, to.next); 760 } 761 762 763 771 public void delete( Instruction from, Instruction to ) throws TargetLostException { 772 InstructionHandle from_ih, to_ih; 773 if ((from_ih = findInstruction1(from)) == null) { 774 throw new ClassGenException("Instruction " + from + " is not contained in this list."); 775 } 776 if ((to_ih = findInstruction2(to)) == null) { 777 throw new ClassGenException("Instruction " + to + " is not contained in this list."); 778 } 779 delete(from_ih, to_ih); 780 } 781 782 783 789 private InstructionHandle findInstruction1( Instruction i ) { 790 for (InstructionHandle ih = start; ih != null; ih = ih.next) { 791 if (ih.instruction == i) { 792 return ih; 793 } 794 } 795 return null; 796 } 797 798 799 805 private InstructionHandle findInstruction2( Instruction i ) { 806 for (InstructionHandle ih = end; ih != null; ih = ih.prev) { 807 if (ih.instruction == i) { 808 return ih; 809 } 810 } 811 return null; 812 } 813 814 815 public boolean contains( InstructionHandle i ) { 816 if (i == null) { 817 return false; 818 } 819 for (InstructionHandle ih = start; ih != null; ih = ih.next) { 820 if (ih == i) { 821 return true; 822 } 823 } 824 return false; 825 } 826 827 828 public boolean contains( Instruction i ) { 829 return findInstruction1(i) != null; 830 } 831 832 833 public void setPositions() { 834 setPositions(false); 835 } 836 837 838 845 public void setPositions( boolean check ) { 846 int max_additional_bytes = 0, additional_bytes = 0; 847 int index = 0, count = 0; 848 int[] pos = new int[length]; 849 851 if (check) { 852 for (InstructionHandle ih = start; ih != null; ih = ih.next) { 853 Instruction i = ih.instruction; 854 if (i instanceof BranchInstruction) { Instruction inst = ((BranchInstruction) i).getTarget().instruction; 856 if (!contains(inst)) { 857 throw new ClassGenException("Branch target of " 858 + Constants.OPCODE_NAMES[i.opcode] + ":" + inst 859 + " not in instruction list"); 860 } 861 if (i instanceof Select) { 862 InstructionHandle[] targets = ((Select) i).getTargets(); 863 for (int j = 0; j < targets.length; j++) { 864 inst = targets[j].instruction; 865 if (!contains(inst)) { 866 throw new ClassGenException("Branch target of " 867 + Constants.OPCODE_NAMES[i.opcode] + ":" + inst 868 + " not in instruction list"); 869 } 870 } 871 } 872 if (!(ih instanceof BranchHandle)) { 873 throw new ClassGenException("Branch instruction " 874 + Constants.OPCODE_NAMES[i.opcode] + ":" + inst 875 + " not contained in BranchHandle."); 876 } 877 } 878 } 879 } |