1 34 package jarg; 35 36 import java.util.*; 37 import org.apache.bcel.classfile.*; 38 import org.apache.bcel.generic.*; 39 import org.apache.bcel.Constants; 40 41 47 class BytecodeOptimizer { 48 private Jarg app; 49 private PackageHandler pkgh; 50 private DataflowOptimizer dfopt; 51 52 BytecodeOptimizer(Jarg app, PackageHandler pkgh) { 53 this.app = app; 54 this.pkgh = pkgh; 55 this.dfopt = new DataflowOptimizer(app); 56 } 57 58 JavaClass optimizeBytecodeOfJavaClass(JavaClass jcls) { 59 ClassGen cg = new ClassGen(jcls); 60 String clsnm = cg.getClassName(); 61 ConstantPoolGen cpg = cg.getConstantPool(); 62 Method[] ms = cg.getMethods(); 63 for (int i=0; i<ms.length; i++) { 64 Method m = ms[i]; 65 Code code = m.getCode(); 66 if (code != null) { 67 MethodGen mg = new MethodGen(m, clsnm, cpg); 68 optimizeCode(mg); 70 m = mg.getMethod(); 71 cg.setMethodAt(m, i); 72 } 73 } 74 return cg.getJavaClass(); 75 } 76 77 private void optimizeCode(MethodGen mg) { 78 for (;;) { 79 int counter = 0; 80 81 counter += dfopt.optimizingByDataflow(mg); 83 84 counter += replaceIFxxGOTO(mg); 86 87 counter += replaceIFxxnext(mg); 89 90 counter += replaceGOTORETURN(mg); 92 93 counter += redirectIFxxGOTO(mg); 95 96 counter += replaceIFxxRETURN(mg); 98 99 103 counter += replaceSTORELOADLOADIFxCMPxx(mg); 105 106 counter += replaceSTORELOAD(mg); 108 109 counter += replaceLOADLOAD(mg); 111 112 counter += replaceIMULISHL(mg); 114 115 counter += analizeLocalSlot(mg); 117 118 counter += removeXXXPOP(mg); 120 121 counter += removeNOP(mg); 123 124 counter += removeGOTOnext(mg); 126 127 counter += removeRETURNs(mg); 129 130 counter += removeGOTOs(mg); 132 133 counter += removeUnusedGOTO(mg); 135 136 if (counter == 0) { 137 break; 138 } 139 } 140 } 141 142 private int replaceGOTORETURN(MethodGen mg) { 148 InstructionList il = mg.getInstructionList(); 149 int count = 0; 150 151 for (InstructionHandle first = il.getStart(); first != null;) { 152 Instruction ins1 = first.getInstruction(); 153 if (ins1 instanceof GotoInstruction) { 154 InstructionHandle gotoTarget = ((GotoInstruction)ins1).getTarget(); 155 Instruction ins2 = gotoTarget.getInstruction(); 156 if (ins2 instanceof ReturnInstruction) { 157 InstructionHandle next = first.getNext(); 158 count ++; 159 InstructionHandle newIh = il.insert(first, ins2); 160 if (first.hasTargeters()) { 161 updateTargets(first, newIh, newIh.getPrev()); 162 } 163 deleteInstruction(il, first, first.getNext()); 164 first = next; 165 continue; 166 } 167 } 168 first = first.getNext(); 169 } 170 171 if (count > 0 && app.isVerboseBCO) { 172 System.out.println("Replaced " + count + " GOTO>>RETURN --> RETURN : " + mg.getClassName() + '#' + mg.getName()); 173 } 174 return count; 175 } 176 177 private int redirectIFxxGOTO(MethodGen mg) { 185 InstructionList il = mg.getInstructionList(); 186 int count = 0; 187 188 for (InstructionHandle first = il.getStart(); first != null;) { 189 Instruction ins1 = first.getInstruction(); 190 if (ins1 instanceof IfInstruction) { 191 InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget(); 192 Instruction ins2 = ifTarget.getInstruction(); 193 if (ins2 instanceof GotoInstruction) { 194 InstructionHandle gotoTarget = ((GotoInstruction)ins2).getTarget(); 195 count ++; 196 ((IfInstruction)ins1).setTarget(gotoTarget); 197 } 198 } 199 first = first.getNext(); 200 } 201 202 if (count > 0 && app.isVerboseBCO) { 203 System.out.println("Replaced " + count + " IFxx>>GOTO>>yyyy --> IFxx>>yyyy : " + mg.getClassName() + '#' + mg.getName()); 204 } 205 return count; 206 } 207 208 private int replaceIFxxRETURN(MethodGen mg) { 218 InstructionList il = mg.getInstructionList(); 219 int count = 0; 220 221 for (InstructionHandle first = il.getStart(); first != null;) { 222 Instruction ins1 = first.getInstruction(); 223 if (ins1 instanceof IfInstruction) { 224 InstructionHandle second = first.getNext(); 225 Instruction ins2 = second.getInstruction(); 226 if (ins2 instanceof RETURN) { 227 InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget(); 228 InstructionHandle next = second.getNext(); 229 if (ifTarget == next) { 230 { 234 InstructionHandle newIfTarget = null; 235 for (InstructionHandle last = il.getEnd(); last != null; last = last.getPrev()) { 236 Instruction lastIns = last.getInstruction(); 237 if (lastIns instanceof RETURN && last != second) { 238 newIfTarget = last; 239 break; 240 } 241 } 242 if (newIfTarget != null) { 243 count ++; 244 BranchInstruction newIns = ((IfInstruction)ins1).negate(); 245 newIns.setTarget(newIfTarget); 246 InstructionHandle newIh = il.insert(first, newIns); 247 if (first.hasTargeters()) { 248 updateTargets(first, newIh, newIh.getPrev()); 249 } 250 if (second.hasTargeters()) { 251 updateTargets(second, newIfTarget, newIfTarget.getPrev()); 252 } 253 deleteInstruction(il, first, next); 254 deleteInstruction(il, second, next); 255 first = next; 256 continue; 257 } 258 } 259 } 260 } 261 } 262 first = first.getNext(); 263 } 264 265 if (count > 0 && app.isVerboseBCO) { 266 System.out.println("Replaced " + count + " IFxx/RETURN --> IFyy : " + mg.getClassName() + '#' + mg.getName()); 267 } 268 return count; 269 } 270 271 private int replaceIFxxGOTO(MethodGen mg) { 280 InstructionList il = mg.getInstructionList(); 281 int count = 0; 282 283 for (InstructionHandle first = il.getStart(); first != null;) { 284 Instruction ins1 = first.getInstruction(); 285 if (ins1 instanceof IfInstruction) { 286 InstructionHandle second = first.getNext(); 287 Instruction ins2 = second.getInstruction(); 288 if (ins2 instanceof GotoInstruction) { 289 InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget(); 290 InstructionHandle gotoTarget = ((GotoInstruction)ins2).getTarget(); 291 InstructionHandle next = second.getNext(); 292 if (ifTarget == next) { 293 count ++; 294 BranchInstruction newIns = ((IfInstruction)ins1).negate(); 295 newIns.setTarget(gotoTarget); 296 InstructionHandle newIh = il.insert(first, newIns); 297 if (first.hasTargeters()) { 298 updateTargets(first, newIh, newIh.getPrev()); 299 } 300 deleteInstruction(il, first, next); 301 deleteInstruction(il, second, next); 302 first = next; 303 continue; 304 } 305 } 306 } 307 first = first.getNext(); 308 } 309 310 if (count > 0 && app.isVerboseBCO) { 311 System.out.println("Replaced " + count + " IFxx/GOTO --> IFyy : " + mg.getClassName() + '#' + mg.getName()); 312 } 313 return count; 314 } 315 316 private int replaceIFxxnext(MethodGen mg) { 327 InstructionList il = mg.getInstructionList(); 328 int count = 0; 329 330 for (InstructionHandle first = il.getStart(); first != null;) { 331 Instruction ins1 = first.getInstruction(); 332 if (ins1 instanceof IfInstruction) { 333 InstructionHandle ifTarget = ((IfInstruction)ins1).getTarget(); 334 InstructionHandle next = first.getNext(); 335 if (ifTarget == next) { 336 count ++; 337 InstructionHandle newIh = il.insert(first, InstructionConstants.POP); 338 if (first.hasTargeters()) { 339 updateTargets(first, newIh, newIh.getPrev()); 340 } 341 if (ins1 instanceof IF_ACMPEQ 342 || ins1 instanceof IF_ACMPNE 343 || ins1 instanceof IF_ICMPEQ 344 || ins1 instanceof IF_ICMPGE 345 || ins1 instanceof IF_ICMPGT 346 || ins1 instanceof IF_ICMPLE 347 || ins1 instanceof IF_ICMPLT 348 || ins1 instanceof IF_ICMPNE 349 ) { 350 InstructionHandle newIh2 = il.insert(first, InstructionConstants.POP); 351 } 352 deleteInstruction(il, first, next); 353 first = next; 354 continue; 355 } 356 } 357 first = first.getNext(); 358 } 359 360 if (count > 0 && app.isVerboseBCO) { 361 System.out.println("Replaced " + count + " IFxx>>next --> POP : " + mg.getClassName() + '#' + mg.getName()); 362 } 363 return count; 364 } 365 366 410 private int replaceSTORELOADLOADIFxCMPxx(MethodGen mg) { 424 InstructionList il = mg.getInstructionList(); 425 int count = 0; 426 427 for (InstructionHandle first = il.getStart(); first != null;) { 428 Instruction ins1 = first.getInstruction(); 429 if (ins1 instanceof StoreInstruction) { 430 InstructionHandle second = first.getNext(); 431 Instruction ins2 = second.getInstruction(); 432 if (ins2 instanceof LoadInstruction) { 433 InstructionHandle third = second.getNext(); 434 Instruction ins3 = third.getInstruction(); 435 if (ins3 instanceof LoadInstruction) { 436 InstructionHandle fourth = third.getNext(); 437 Instruction ins4 = fourth.getInstruction(); 438 if (ins4 instanceof IfInstruction) { 439 if (ins4 instanceof IF_ACMPEQ 440 || ins4 instanceof IF_ACMPNE 441 || ins4 instanceof IF_ICMPEQ 442 || ins4 instanceof IF_ICMPGE 443 || ins4 instanceof IF_ICMPGT 444 || ins4 instanceof IF_ICMPLE 445 || ins4 instanceof IF_ICMPLT 446 || ins4 instanceof IF_ICMPNE 447 ) { 448 int vn1 = ((StoreInstruction)ins1).getIndex(); 449 int vn2 = ((LoadInstruction)ins2).getIndex(); 450 int vn3 = ((LoadInstruction)ins3).getIndex(); 451 if (vn1 == vn3 && vn1 != vn2) { 452 InstructionHandle next = fourth.getNext(); 453 count ++; 454 ((LoadInstruction)ins2).setIndex(vn3); 455 ((LoadInstruction)ins3).setIndex(vn2); 456 if (ins4 instanceof IF_ICMPGE 457 || ins4 instanceof IF_ICMPGT 458 || ins4 instanceof IF_ICMPLE 459 || ins4 instanceof IF_ICMPLT 460 ) { 461 InstructionHandle newIh = il.insert(fourth, ((IfInstruction)ins4).negate()); 462 deleteInstruction(il, fourth, next); 463 } 464 first = next; 465 continue; 466 } 467 } 468 } 469 } 470 } 471 } 472 first = first.getNext(); 473 } 474 475 if (count > 0 && app.isVerboseBCO) { 476 System.out.println("Replaced " + count + " xSTOREn/xLOADm/xLOADn/IF_xCMPxx --> xSTOREn/xLOADn/xLOADm/IF_xCMPxx : " + mg.getClassName() + '#' + mg.getName()); 477 } 478 return count; 479 } 480 481 private int replaceLOADLOAD(MethodGen mg) { 487 InstructionList il = mg.getInstructionList(); 488 int count = 0; 489 490 for (InstructionHandle first = il.getStart(); first != null;) { 491 Instruction ins1 = first.getInstruction(); 492 if (ins1 instanceof LoadInstruction) { 493 InstructionHandle second = first.getNext(); 494 Instruction ins2 = second.getInstruction(); 495 if (ins2 instanceof LoadInstruction) { 496 InstructionHandle next = second.getNext(); 497 int vn1 = ((LoadInstruction)ins1).getIndex(); 498 int vn2 = ((LoadInstruction)ins2).getIndex(); 499 if (vn1 == vn2) { 500 count ++; 501 boolean isDUP2 = false; 502 if (ins1 instanceof LLOAD || ins1 instanceof DLOAD) { 503 isDUP2 = true; 504 } 505 InstructionHandle newIh = il.insert(second, (isDUP2) ? InstructionConstants.DUP2 : InstructionConstants.DUP); 506 if (second.hasTargeters()) { 507 updateTargets(second, newIh, newIh.getPrev()); 508 } 509 deleteInstruction(il, second, second.getNext()); 510 first = next; 511 continue; 512 } 513 } 514 } 515 first = first.getNext(); 516 } 517 518 if (count > 0 && app.isVerboseBCO) { 519 System.out.println("Replaced " + count + " xLOADn/xLOADn --> xLOADn/DUP : " + mg.getClassName() + '#' + mg.getName()); 520 } 521 return count; 522 } 523 524 private int replaceSTORELOAD(MethodGen mg) { 530 InstructionList il = mg.getInstructionList(); 531 int count = 0; 532 533 for (InstructionHandle first = il.getStart(); first != null; first = first.getNext()) { 534 Instruction ins1 = first.getInstruction(); 535 if (ins1 instanceof StoreInstruction) { 536 InstructionHandle second = first.getNext(); 537 Instruction ins2 = second.getInstruction(); 538 if (ins1 instanceof ASTORE && ins2 instanceof ALOAD) { 539 int locNo1 = ((LocalVariableInstruction)ins1).getIndex(); 540 int locNo2 = ((LocalVariableInstruction)ins2).getIndex(); 541 if (locNo1 == locNo2) { 542 if (checkTargetersOfSecond(second)) { 543 count ++; 544 replaceSTORELOAD0(il, first, second, false); 545 } 546 } 547 } else if (ins1 instanceof ISTORE && ins2 instanceof ILOAD) { 548 int locNo1 = ((LocalVariableInstruction)ins1).getIndex(); 549 int locNo2 = ((LocalVariableInstruction)ins2).getIndex(); 550 if (locNo1 == locNo2) { 551 if (checkTargetersOfSecond(second)) { 552 count ++; 553 replaceSTORELOAD0(il, first, second, false); 554 } 555 } 556 } else if (ins1 instanceof LSTORE && ins2 instanceof LLOAD) { 557 int locNo1 = ((LocalVariableInstruction)ins1).getIndex(); 558 int locNo2 = ((LocalVariableInstruction)ins2).getIndex(); 559 if (locNo1 == locNo2) { 560 if (checkTargetersOfSecond(second)) { 561 count ++; 562 replaceSTORELOAD0(il, first, second, true); 563 } 564 } 565 } else if (ins1 instanceof FSTORE && ins2 instanceof FLOAD) { 566 int locNo1 = ((LocalVariableInstruction)ins1).getIndex(); 567 int locNo2 = ((LocalVariableInstruction)ins2).getIndex(); 568 if (locNo1 == locNo2) { 569 if (checkTargetersOfSecond(second)) { 570 count ++; 571 replaceSTORELOAD0(il, first, second, false); 572 } 573 } 574 } else if (ins1 instanceof DSTORE && ins2 instanceof DLOAD) { 575 int locNo1 = ((LocalVariableInstruction)ins1).getIndex(); 576 int locNo2 = ((LocalVariableInstruction)ins2).getIndex(); 577 if (locNo1 == locNo2) { 578 if (checkTargetersOfSecond(second)) { 579 count ++; 580 replaceSTORELOAD0(il, first, second, true); 581 } 582 } 583 } 584 } 585 } 586 587 if (count > 0 && app.isVerboseBCO) { 588 System.out.println("Replaced " + count + " xSTOREn/xLOADn --> DUP/xSTOREn : " + mg.getClassName() + '#' + mg.getName()); 589 } 590 return count; 591 } 592 593 private boolean checkTargetersOfSecond(InstructionHandle second) { 594 if (second.hasTargeters()) { 595 InstructionTargeter[] ts = second.getTargeters(); 596 for (int i=0; i<ts.length; i++) { 597 InstructionTargeter t = ts[i]; 598 if (t instanceof BranchInstruction) { 599 return false; 600 } else if (t instanceof CodeExceptionGen) { 601 } else if (t instanceof LocalVariableGen) { 602 } 603 } 604 } 605 return true; 606 } 607 608 private int replaceIMULISHL(MethodGen mg) { 614 InstructionList il = mg.getInstructionList(); 615 int count = 0; 616 617 for (InstructionHandle first = il.getStart(); first != null;) { 618 Instruction ins1 = first.getInstruction(); 619 if (ins1 instanceof BIPUSH || ins1 instanceof SIPUSH || ins1 instanceof ICONST) { 620 InstructionHandle second = first.getNext(); 621 Instruction ins2 = second.getInstruction(); 622 if (ins2 instanceof IMUL && !second.hasTargeters()) { 623 InstructionHandle next = second.getNext(); 624 int vn1 = 0; 625 if (ins1 instanceof BIPUSH) { 626 Integer int1 = (Integer )((BIPUSH)ins1).getValue(); 627 vn1 = int1.intValue(); 628 } else if (ins1 instanceof SIPUSH) { 629 Integer int1 = (Integer )((SIPUSH)ins1).getValue(); 630 vn1 = int1.intValue(); 631 } else if (ins1 instanceof ICONST) { 632 Integer int1 = (Integer )((ICONST)ins1).getValue(); 633 vn1 = int1.intValue(); 634 } 635 int icn = 0; 636 switch (vn1) { 637 case 2: icn = 1; break; 638 case 4: icn = 2; break; 639 case 8: icn = 3; break; 640 } 641 if (icn > 0) { 642 count ++; 643 InstructionHandle newIh1 = il.insert(first, new ICONST(icn)); 644 InstructionHandle newIh2 = il.insert(second, new ISHL()); 645 deleteInstruction(il, first, next); 646 deleteInstruction(il, second, next); 647 first = next; 648 continue; 649 } 650 } 651 } 652 first = first.getNext(); 653 } 654 655 if (count > 0 && app.isVerboseBCO) { 656 System.out.println("Replaced " + count + " xxxx/IMUL --> ICONST_n/ISHL : " + mg.getClassName() + '#' + mg.getName()); 657 } 658 return count; 659 } 660 661 private void replaceSTORELOAD0(InstructionList il, InstructionHandle first, InstructionHandle second, boolean isDUP2) { 662 InstructionHandle newIh = il.insert(first, (isDUP2) ? InstructionConstants.DUP2 : InstructionConstants.DUP); 663 if (first.hasTargeters()) { 664 updateTargets(first, newIh, newIh.getPrev()); 665 } 666 deleteInstruction(il, second, second.getNext()); 667 } 668 669 private int analizeLocalSlot(MethodGen mg) { 674 int count = 0; 675 CodeExceptionGen[] ceg = mg.getExceptionHandlers(); 676 InstructionList il = mg.getInstructionList(); 677 678 count += analizeLocalSlot0(il, ceg, il.getStart()); 679 for (int i=0; i<ceg.length; i++) { 680 count += analizeLocalSlot0(il, ceg, ceg[i].getHandlerPC()); 681 } 682 683 if (count > 0 && app.isVerboseBCO) { 684 System.out.println("Replaced " + count + " xSTOREn --> POP unused local slot : " + mg.getClassName() + '#' + mg.getName()); 685 } 686 return count; 687 } 688 689 private int analizeLocalSlot0(InstructionList il, CodeExceptionGen[] ceg, InstructionHandle first) { 690 int count = 0; 691 for (; first != null; ) { 692 Instruction ins1 = first.getInstruction(); 693 if (ins1 instanceof StoreInstruction) { 694 int vn = ((StoreInstruction)ins1).getIndex(); 695 HashSet hset = new HashSet(); 696 boolean isUsed = checkUsedLocalSlot(first.getNext(), vn, hset); 697 if (!isUsed) { 698 for (int j=0; j<ceg.length; j++) { 699 isUsed = checkUsedLocalSlot(ceg[j].getHandlerPC(), vn, hset); 700 if (isUsed) { 701 break; 702 } 703 } 704 } 705 if (!isUsed) { 706 InstructionHandle next = first.getNext(); 707 count ++; 708 Instruction ins2 = InstructionConstants.POP; 709 if (ins1 instanceof LSTORE || ins1 instanceof DSTORE) { 710 ins2 = InstructionConstants.POP2; 711 } 712 InstructionHandle newIh = il.insert(first, ins2); 713 if (first.hasTargeters()) { 714 updateTargets(first, newIh, newIh.getPrev()); 715 } 716 deleteInstruction(il, first, first.getNext()); 717 first = next; 718 continue; 719 } 720 } 721 first = first.getNext(); 722 } 723 return count; 724 } 725 726 private boolean checkUsedLocalSlot(InstructionHandle first, int slotNo, HashSet hset) { 729 for (; first != null; first = first.getNext()) { 730 Instruction ins1 = first.getInstruction(); 731 if (ins1 instanceof ReturnInstruction) { 732 break; 733 } else if (ins1 instanceof RET) { 734 int vn = ((RET)ins1).getIndex(); 735 if (vn == slotNo) { 736 return true; 737 } 738 break; 739 } else if (ins1 instanceof IINC) { 740 int vn = ((IINC)ins1).getIndex(); 741 if (vn == slotNo) { 742 return true; 743 } 744 } else if (ins1 instanceof LoadInstruction) { 745 int vn = ((LoadInstruction)ins1).getIndex(); 746 if (vn == slotNo) { 747 return true; 748 } 749 } else if (ins1 instanceof StoreInstruction) { 750 int vn = ((StoreInstruction)ins1).getIndex(); 751 if (vn == slotNo) { 752 return false; 753 } 754 } else if (ins1 instanceof BranchInstruction) { 755 InstructionHandle target = ((BranchInstruction)ins1).getTarget(); 756 if (!hset.contains(target)) { 757 hset.add(target); 758 boolean isUsed = checkUsedLocalSlot(target, slotNo, hset); 759 if (isUsed) { 760 return true; 761 } 762 } 763 if (ins1 instanceof GotoInstruction) { 764 break; 765 } else if (ins1 instanceof Select) { 766 InstructionHandle[] targets = ((Select)ins1).getTargets(); 767 for (int i=0; i<targets.length; i++) { 768 InstructionHandle targetn = targets[i]; 769 if (!hset.contains(targetn)) { 770 hset.add(targetn); 771 boolean isUsed = checkUsedLocalSlot(targetn, slotNo, hset); 772 if (isUsed) { 773 return true; 774 } 775 } 776 } 777 } 778 } else if (ins1 instanceof ATHROW) { 779 break; 780 } 781 } 782 return false; 783 } 784 785 private int removeXXXPOP(MethodGen mg) { 791 InstructionList il = mg.getInstructionList(); 792 int count = 0; 793 794 for (InstructionHandle second = il.getStart(); second != null;) { 795 Instruction ins2 = second.getInstruction(); 796 if (ins2 instanceof POP) { 797 if (!second.hasTargeters()) { 798 InstructionHandle first = second.getPrev(); 799 Instruction ins1 = first.getInstruction(); 800 if (ins1 instanceof DUP 801 || ins1 instanceof ACONST_NULL 802 || ins1 instanceof ICONST 803 || ins1 instanceof FCONST 804 || ins1 instanceof LoadInstruction 805 || ins1 instanceof LDC 806 || ins1 instanceof LDC_W 807 ) { 808 InstructionHandle next = second.getNext(); 809 count ++; 810 deleteInstruction(il, first, next); 811 deleteInstruction(il, second, next); 812 second = next; 813 continue; 814 } 815 } 816 } else if (ins2 instanceof POP2) { 817 if (!second.hasTargeters()) { 818 InstructionHandle first = second.getPrev(); 819 Instruction ins1 = first.getInstruction(); 820 if (ins1 instanceof DUP2 821 || ins1 instanceof LCONST 822 || ins1 instanceof DCONST 823 || ins1 instanceof LoadInstruction 824 || ins1 instanceof LDC2_W 825 ) { 826 InstructionHandle next = second.getNext(); 827 count ++; 828 deleteInstruction(il, first, next); 829 deleteInstruction(il, second, next); 830 second = next; 831 continue; 832 } 833 } 834 } 835 second = second.getNext(); 836 } 837 838 if (count > 0 && app.isVerboseBCO) { 839 System.out.println("Removed " + count + " XXX/POP : " + mg.getClassName() + '#' + mg.getName()); 840 } 841 return count; 842 } 843 844 private int removeNOP(MethodGen mg) { 849 InstructionList il = mg.getInstructionList(); 850 int count = 0; 851 852 for (InstructionHandle first = il.getStart(); first != null; ) { 853 Instruction ins = first.getInstruction(); 854 if (ins instanceof NOP) { 855 InstructionHandle next = first.getNext(); 856 if (next != null) { 857 count ++; 858 deleteInstruction(il, first, next); 859 first = next; 860 continue; 861 } 862 } 863 first = first.getNext(); 864 } 865 866 if (count > 0 && app.isVerboseBCO) { 867 System.out.println("Removed " + count + " NOP : " + mg.getClassName() + '#' + mg.getName()); 868 } 869 return count; 870 } 871 872 private int removeGOTOnext(MethodGen mg) { 878 InstructionList il = mg.getInstructionList(); 879 int count = 0; 880 881 for (InstructionHandle first = il.getStart(); first != null; ) { 882 Instruction ins = first.getInstruction(); 883 if (ins instanceof GotoInstruction) { 884 InstructionHandle next = first.getNext(); 885 if (next != null) { 886 InstructionHandle gotoTarget = ((GotoInstruction)ins).getTarget(); 887 if (gotoTarget == next) { 888 count ++; 889 deleteInstruction(il, first, next); 890 first = next; 891 continue; 892 } 893 } 894 } 895 first = first.getNext(); 896 } 897 898 if (count > 0 && app.isVerboseBCO) { 899 System.out.println("Removed " + count + " GOTO next : " + mg.getClassName() + '#' + mg.getName()); 900 } 901 return count; 902 } 903 904 private int removeRETURNs(MethodGen mg) { 910 InstructionList il = mg.getInstructionList(); 911 int count = 0; 912 913 for (InstructionHandle first = il.getStart(); first != null; ) { 914 Instruction ins1 = first.getInstruction(); 915 if (ins1 instanceof ReturnInstruction) { 916 InstructionHandle next = first.getNext(); 917 if (next != null) { 918 Instruction ins2 = next.getInstruction(); 919 if (ins2 instanceof ReturnInstruction) { 920 count ++; 921 deleteInstruction(il, first, next); 922 first = next; 923 continue; 924 } 925 } 926 } 927 first = first.getNext(); 928 } 929 930 if (count > 0 && app.isVerboseBCO) { 931 System.out.println("Removed " + count + " double RETURN : " + mg.getClassName() + '#' + mg.getName()); 932 } 933 return count; 934 } 935 936 private int removeGOTOs(MethodGen mg) { 942 InstructionList il = mg.getInstructionList(); 943 int count = 0; 944 945 for (InstructionHandle first = il.getStart(); first != null; ) { 946 Instruction ins1 = first.getInstruction(); 947 if (ins1 instanceof GotoInstruction) { 948 InstructionHandle second = first.getNext(); 949 if (second != null) { 950 InstructionHandle next = second.getNext(); 951 if (next != null) { 952 Instruction ins2 = second.getInstruction(); 953 if (ins2 instanceof GotoInstruction) { 954 if (!second.hasTargeters()) { 955 count ++; 956 deleteInstruction(il, second, next); 957 first = next; 958 continue; 959 } 960 } 961 } 962 } 963 } 964 first = first.getNext(); 965 } 966 967 if (count > 0 && app.isVerboseBCO) { 968 System.out.println("Removed " + count + " double GOTO : " + mg.getClassName() + '#' + mg.getName()); 969 } 970 return count; 971 } 972 973 private int removeUnusedGOTO(MethodGen mg) { 979 InstructionList il = mg.getInstructionList(); 980 int count = 0; 981 982 for (InstructionHandle first = il.getStart(); first != null; ) { 983 Instruction ins1 = first.getInstruction(); 984 if (ins1 instanceof GotoInstruction) { 985 InstructionHandle preIh = first.getPrev(); 986 InstructionHandle next = first.getNext(); 987 if (preIh != null && next != null) { 988 Instruction ins0 = preIh.getInstruction(); 989 if (ins0 instanceof GotoInstruction 990 || ins0 instanceof ReturnInstruction 991 || ins0 instanceof ATHROW 992 ) { 993 if (!first.hasTargeters()) { 994 count ++; 995 deleteInstruction(il, first, next); 996 first = next; 997 continue; 998 } 999 } 1000 } 1001 } 1002 first = first.getNext(); 1003 } 1004 1005 if (count > 0 && app.isVerboseBCO) { 1006 System.out.println("Removed " + count + " unused GOTO : " + mg.getClassName() + '#' + mg.getName()); 1007 } 1008 return count; 1009 } 1010 1011 private void deleteInstruction(InstructionList il, InstructionHandle ih, InstructionHandle next) { 1012 InstructionHandle prev = ih.getPrev(); 1013 if (prev == null) { 1014 prev = ih.getNext(); 1015 } 1016 1017 try { 1018 il.delete(ih); 1019 } catch (TargetLostException ex) { 1020 InstructionHandle[] targets = ex.getTargets(); 1021 for (int i=0; i < targets.length; i++) { 1022 updateTargets(targets[i], next, prev); 1023 } 1024 } 1025 } 1026 1027 private void updateTargets(InstructionHandle oldTarget, InstructionHandle newTarget, InstructionHandle newTargetPrev) { 1028 InstructionTargeter[] targeters = oldTarget.getTargeters(); 1029 for (int j=0; j < targeters.length; j++) { 1030 InstructionHandle curTarget = newTarget; 1031 InstructionTargeter targeter = targeters[j]; 1032 if (targeter instanceof CodeExceptionGen) { 1033 if (((CodeExceptionGen)targeter).getEndPC() == oldTarget) { 1034 curTarget = newTargetPrev; 1035 } 1036 } 1037 targeter.updateTarget(oldTarget, curTarget); 1038 } 1039 } 1040} 1041 | Popular Tags |