1 19 20 package jode.flow; 21 import jode.AssertError; 22 import jode.GlobalOptions; 23 import jode.type.Type; 24 import jode.decompiler.LocalInfo; 25 import jode.expr.*; 26 27 import java.util.TreeSet ; 28 import java.util.SortedSet ; 29 import java.util.Set ; 30 import java.util.Map ; 31 import java.util.Iterator ; 32 import java.lang.Comparable ; 33 34 38 public class TransformExceptionHandlers { 39 SortedSet handlers; 40 41 static class Handler implements Comparable { 42 FlowBlock start; 43 int endAddr; 44 FlowBlock handler; 45 Type type; 46 47 public Handler(FlowBlock tryBlock, int end, 48 FlowBlock catchBlock, Type type) { 49 this.start = tryBlock; 50 this.endAddr = end; 51 this.handler = catchBlock; 52 this.type = type; 53 } 54 55 public int compareTo (Object o) { 56 Handler second = (Handler) o; 57 58 59 if (start.getAddr() != second.start.getAddr()) 60 61 return second.start.getAddr() - start.getAddr(); 62 63 65 if (endAddr != second.endAddr) 66 return endAddr - second.endAddr; 67 68 69 if (handler.getAddr() != second.handler.getAddr()) 70 return handler.getAddr() - second.handler.getAddr(); 71 72 74 if (type == second.type) 75 return 0; 76 if (type == null) 77 return -1; 78 if (second.type == null) 79 return 1; 80 return type.getTypeSignature() 81 .compareTo(second.type.getTypeSignature()); 82 } 83 } 84 85 public TransformExceptionHandlers() { 86 handlers = new TreeSet (); 87 } 88 89 96 public void addHandler(FlowBlock tryBlock, int end, 97 FlowBlock catchBlock, Type type) { 98 handlers.add(new Handler(tryBlock, end, catchBlock, type)); 99 } 100 101 102 114 static void mergeTryCatch(FlowBlock tryFlow, FlowBlock catchFlow) { 115 if ((GlobalOptions.debuggingFlags 116 & GlobalOptions.DEBUG_ANALYZE) != 0) 117 GlobalOptions.err.println 118 ("mergeTryCatch(" + tryFlow.getAddr() 119 + ", " + catchFlow.getAddr() + ")"); 120 tryFlow.updateInOutCatch(catchFlow); 121 tryFlow.mergeSuccessors(catchFlow); 122 tryFlow.mergeAddr(catchFlow); 123 } 124 125 126 137 static void analyzeCatchBlock(Type type, FlowBlock tryFlow, 138 FlowBlock catchFlow) { 139 140 mergeTryCatch(tryFlow, catchFlow); 141 142 143 CatchBlock newBlock = new CatchBlock(type); 144 ((TryBlock)tryFlow.block).addCatchBlock(newBlock); 145 newBlock.setCatchBlock(catchFlow.block); 146 } 147 148 149 150 155 boolean transformSubRoutine(StructuredBlock subRoutineBlock) { 156 StructuredBlock firstBlock = subRoutineBlock; 157 if (firstBlock instanceof SequentialBlock) 158 firstBlock = subRoutineBlock.getSubBlocks()[0]; 159 160 LocalInfo local = null; 161 if (firstBlock instanceof SpecialBlock) { 162 SpecialBlock popBlock 163 = (SpecialBlock) firstBlock; 164 if (popBlock.type != SpecialBlock.POP 165 || popBlock.count != 1) 166 return false; 167 } else if (firstBlock instanceof InstructionBlock) { 168 Expression expr 169 = ((InstructionBlock) firstBlock).getInstruction(); 170 if (expr instanceof StoreInstruction 171 && ((StoreInstruction) 172 expr).getLValue() instanceof LocalStoreOperator) { 173 LocalStoreOperator store = (LocalStoreOperator) 174 ((StoreInstruction)expr).getLValue(); 175 local = store.getLocalInfo(); 176 expr = ((StoreInstruction) expr).getSubExpressions()[1]; 177 } 178 if (!(expr instanceof NopOperator)) 179 return false; 180 } else 181 return false; 182 183 187 firstBlock.removeBlock(); 188 189 196 while (subRoutineBlock instanceof SequentialBlock) 197 subRoutineBlock = subRoutineBlock.getSubBlocks()[1]; 198 199 if (subRoutineBlock instanceof RetBlock 200 && (((RetBlock) subRoutineBlock).local.equals(local))) { 201 subRoutineBlock.removeBlock(); 202 } 203 return true; 204 } 205 206 211 private void removeReturnLocal(ReturnBlock ret) { 212 StructuredBlock pred = getPredecessor(ret); 213 if (!(pred instanceof InstructionBlock)) 214 return; 215 Expression instr = ((InstructionBlock) pred).getInstruction(); 216 if (!(instr instanceof StoreInstruction)) 217 return; 218 219 Expression retInstr = ret.getInstruction(); 220 if (!(retInstr instanceof LocalLoadOperator 221 && ((StoreInstruction) instr).lvalueMatches 222 ((LocalLoadOperator) retInstr))) 223 return; 224 225 Expression rvalue = ((StoreInstruction) instr).getSubExpressions()[1]; 226 ret.setInstruction(rvalue); 227 ret.replace(ret.outer); 228 } 229 230 237 private void removeJSR(FlowBlock tryFlow, FlowBlock subRoutine) { 238 for (Jump jumps = tryFlow.removeJumps(subRoutine); 239 jumps != null; jumps = jumps.next) { 240 241 StructuredBlock prev = jumps.prev; 242 prev.removeJump(); 243 244 if (prev instanceof EmptyBlock 245 && prev.outer instanceof JsrBlock 246 && ((JsrBlock) prev.outer).isGood()) { 247 StructuredBlock next = prev.outer.getNextBlock(); 248 prev.outer.removeBlock(); 249 if (next instanceof ReturnBlock) 250 removeReturnLocal((ReturnBlock) next); 251 } else { 252 255 DescriptionBlock msg = new DescriptionBlock 256 ("ERROR: invalid jump to finally block!"); 257 prev.appendBlock(msg); 258 } 259 } 260 } 261 262 private static StructuredBlock getPredecessor(StructuredBlock stmt) 263 { 264 if (stmt.outer instanceof SequentialBlock) { 265 SequentialBlock seq = (SequentialBlock) stmt.outer; 266 if (seq.subBlocks[1] == stmt) 267 return seq.subBlocks[0]; 268 else if (seq.outer instanceof SequentialBlock) 269 return seq.outer.getSubBlocks()[0]; 270 } 271 return null; 272 } 273 274 280 private static int getMonitorExitSlot(StructuredBlock stmt) { 281 if (stmt instanceof InstructionBlock) { 282 Expression instr = ((InstructionBlock) stmt).getInstruction(); 283 if (instr instanceof MonitorExitOperator) { 284 MonitorExitOperator monExit = (MonitorExitOperator)instr; 285 if (monExit.getFreeOperandCount() == 0 286 && (monExit.getSubExpressions()[0] 287 instanceof LocalLoadOperator)) 288 return ((LocalLoadOperator) monExit.getSubExpressions()[0]) 289 .getLocalInfo().getSlot(); 290 } 291 } 292 return -1; 293 } 294 295 private boolean isMonitorExitSubRoutine(FlowBlock subRoutine, 296 LocalInfo local) { 297 if (transformSubRoutine(subRoutine.block) 298 && getMonitorExitSlot(subRoutine.block) == local.getSlot()) 299 return true; 300 return false; 301 } 302 303 private static StructuredBlock skipFinExitChain(StructuredBlock block) 304 { 305 StructuredBlock pred, result; 306 if (block instanceof ReturnBlock) 307 pred = getPredecessor(block); 308 else 309 pred = block; 310 result = null; 311 312 while (pred instanceof JsrBlock 313 || getMonitorExitSlot(pred) >= 0) { 314 result = pred; 315 pred = getPredecessor(pred); 316 } 317 return result; 318 } 319 320 321 private void checkAndRemoveJSR(FlowBlock tryFlow, 322 FlowBlock subRoutine, 323 int startOutExit, int endOutExit) { 324 Iterator iter = tryFlow.getSuccessors().iterator(); 325 dest_loop: 326 while (iter.hasNext()) { 327 FlowBlock dest = (FlowBlock) iter.next(); 328 if (dest == subRoutine) 329 continue dest_loop; 330 331 boolean isFirstJump = true; 332 for (Jump jumps = tryFlow.getJumps(dest); 333 jumps != null; jumps = jumps.next, isFirstJump = false) { 334 335 StructuredBlock prev = jumps.prev; 336 if (prev instanceof ThrowBlock) { 337 340 continue; 341 } 342 if (prev instanceof EmptyBlock 343 && prev.outer instanceof JsrBlock) { 344 347 continue; 348 } 349 StructuredBlock pred = skipFinExitChain(prev); 350 351 if (pred instanceof JsrBlock) { 352 JsrBlock jsr = (JsrBlock) pred; 353 StructuredBlock jsrInner = jsr.innerBlock; 354 if (jsrInner instanceof EmptyBlock 355 && jsrInner.jump != null 356 && jsrInner.jump.destination == subRoutine) { 357 360 jsr.setGood(true); 361 continue; 362 } 363 } 364 365 if (pred == null && isFirstJump) { 366 371 if (jumps.destination.predecessors.size() == 1 372 && jumps.destination.getAddr() >= startOutExit 373 && jumps.destination.getNextAddr() <= endOutExit) { 374 jumps.destination.analyze(startOutExit, endOutExit); 375 376 StructuredBlock sb = jumps.destination.block; 377 if (sb instanceof SequentialBlock) 378 sb = sb.getSubBlocks()[0]; 379 if (sb instanceof JsrBlock 380 && sb.getSubBlocks()[0] instanceof EmptyBlock 381 && (sb.getSubBlocks()[0].jump.destination 382 == subRoutine)) { 383 StructuredBlock jsrInner = sb.getSubBlocks()[0]; 384 jumps.destination.removeSuccessor(jsrInner.jump); 385 jsrInner.removeJump(); 386 sb.removeBlock(); 387 continue dest_loop; 388 } 389 } 390 } 391 392 395 DescriptionBlock msg 396 = new DescriptionBlock("ERROR: no jsr to finally"); 397 if (pred != null) 398 pred.prependBlock(msg); 399 else { 400 prev.appendBlock(msg); 401 msg.moveJump(prev.jump); 402 } 403 } 404 } 405 if (tryFlow.getSuccessors().contains(subRoutine)) 406 removeJSR(tryFlow, subRoutine); 407 } 408 409 private void checkAndRemoveMonitorExit(FlowBlock tryFlow, 410 LocalInfo local, 411 int start, int end) { 412 FlowBlock subRoutine = null; 413 Iterator succs = tryFlow.getSuccessors().iterator(); 414 dest_loop: 415 while (succs.hasNext()) { 416 boolean isFirstJump = true; 417 FlowBlock successor = (FlowBlock) succs.next(); 418 for (Jump jumps = tryFlow.getJumps(successor); 419 jumps != null; jumps = jumps.next, isFirstJump = false) { 420 421 StructuredBlock prev = jumps.prev; 422 if (prev instanceof ThrowBlock) { 423 426 continue; 427 } 428 if (prev instanceof EmptyBlock 429 && prev.outer instanceof JsrBlock) { 430 433 continue; 434 } 435 StructuredBlock pred = skipFinExitChain(prev); 436 if (pred instanceof JsrBlock) { 437 JsrBlock jsr = (JsrBlock) pred; 438 StructuredBlock jsrInner = jsr.innerBlock; 439 if (jsrInner instanceof EmptyBlock 440 && jsrInner.jump != null) { 441 FlowBlock dest = jsrInner.jump.destination; 442 443 if (subRoutine == null 444 && dest.getAddr() >= start 445 && dest.getNextAddr() <= end) { 446 dest.analyze(start, end); 447 if (isMonitorExitSubRoutine(dest, local)) 448 subRoutine = dest; 449 } 450 451 if (dest == subRoutine) { 452 455 jsr.setGood(true); 456 continue; 457 } 458 } 459 } else if (getMonitorExitSlot(pred) == local.getSlot()) { 460 463 pred.removeBlock(); 464 if (prev instanceof ReturnBlock) 465 removeReturnLocal((ReturnBlock) prev); 466 continue; 467 } 468 469 if (pred == null && isFirstJump) { 470 476 if (successor.predecessors.size() == 1 477 && successor.getAddr() >= start 478 && successor.getNextAddr() <= end) { 479 successor.analyze(start, end); 480 481 StructuredBlock sb = successor.block; 482 if (sb instanceof SequentialBlock) 483 sb = sb.getSubBlocks()[0]; 484 if (sb instanceof JsrBlock 485 && sb.getSubBlocks()[0] instanceof EmptyBlock) { 486 StructuredBlock jsrInner = sb.getSubBlocks()[0]; 487 FlowBlock dest = jsrInner.jump.destination; 488 if (subRoutine == null 489 && dest.getAddr() >= start 490 && dest.getNextAddr() <= end) { 491 dest.analyze(start, end); 492 if (isMonitorExitSubRoutine(dest, local)) 493 subRoutine = dest; 494 } 495 496 if (subRoutine == dest) { 497 successor.removeSuccessor(jsrInner.jump); 498 jsrInner.removeJump(); 499 sb.removeBlock(); 500 continue dest_loop; 501 } 502 } 503 if (getMonitorExitSlot(sb) == local.getSlot()) { 504 sb.removeBlock(); 505 continue dest_loop; 506 } 507 } 508 } 509 510 512 DescriptionBlock msg 513 = new DescriptionBlock("ERROR: no monitorexit"); 514 prev.appendBlock(msg); 515 msg.moveJump(jumps); 516 } 517 } 518 519 if (subRoutine != null) { 520 if (tryFlow.getSuccessors().contains(subRoutine)) 521 removeJSR(tryFlow, subRoutine); 522 if (subRoutine.predecessors.size() == 0) 523 tryFlow.mergeAddr(subRoutine); 524 } 525 } 526 527 private StoreInstruction getExceptionStore(StructuredBlock catchBlock) { 528 if (!(catchBlock instanceof SequentialBlock) 529 || !(catchBlock.getSubBlocks()[0] instanceof InstructionBlock)) 530 return null; 531 532 Expression instr = 533 ((InstructionBlock)catchBlock.getSubBlocks()[0]).getInstruction(); 534 if (!(instr instanceof StoreInstruction)) 535 return null; 536 537 StoreInstruction store = (StoreInstruction) instr; 538 if (!(store.getLValue() instanceof LocalStoreOperator 539 && store.getSubExpressions()[1] instanceof NopOperator)) 540 return null; 541 542 return store; 543 } 544 545 private boolean analyzeSynchronized(FlowBlock tryFlow, 546 FlowBlock catchFlow, 547 int endHandler) { 548 551 StructuredBlock catchBlock = catchFlow.block; 552 553 554 StoreInstruction excStore = getExceptionStore(catchBlock); 555 if (excStore != null) 556 catchBlock = catchBlock.getSubBlocks()[1]; 557 558 559 if (!(catchBlock instanceof SequentialBlock 560 && catchBlock.getSubBlocks()[0] 561 instanceof InstructionBlock)) 562 return false; 563 Expression instr = 564 ((InstructionBlock)catchBlock.getSubBlocks()[0]).getInstruction(); 565 if (!(instr instanceof MonitorExitOperator 566 && instr.getFreeOperandCount() == 0 567 && (((MonitorExitOperator)instr).getSubExpressions()[0] 568 instanceof LocalLoadOperator) 569 && catchBlock.getSubBlocks()[1] instanceof ThrowBlock)) 570 return false; 571 572 Expression throwInstr = 573 ((ThrowBlock)catchBlock.getSubBlocks()[1]).getInstruction(); 574 575 if (excStore != null) { 576 if (!(throwInstr instanceof Operator 577 && excStore.lvalueMatches((Operator)throwInstr))) 578 return false; 579 } else { 580 if (!(throwInstr instanceof NopOperator)) 581 return false; 582 } 583 584 608 609 616 catchFlow.removeSuccessor(catchBlock.getSubBlocks()[1].jump); 617 mergeTryCatch(tryFlow, catchFlow); 618 619 MonitorExitOperator monexit = (MonitorExitOperator) 620 ((InstructionBlock) catchBlock.getSubBlocks()[0]).instr; 621 LocalInfo local = 622 ((LocalLoadOperator)monexit.getSubExpressions()[0]) 623 .getLocalInfo(); 624 625 if ((GlobalOptions.debuggingFlags 626 & GlobalOptions.DEBUG_ANALYZE) != 0) 627 GlobalOptions.err.println 628 ("analyzeSynchronized(" + tryFlow.getAddr() 629 + "," + tryFlow.getNextAddr() + "," + endHandler + ")"); 630 631 checkAndRemoveMonitorExit 632 (tryFlow, local, tryFlow.getNextAddr(), endHandler); 633 634 SynchronizedBlock syncBlock = new SynchronizedBlock(local); 635 TryBlock tryBlock = (TryBlock) tryFlow.block; 636 syncBlock.replace(tryBlock); 637 syncBlock.moveJump(tryBlock.jump); 638 syncBlock.setBodyBlock(tryBlock.subBlocks.length == 1 639 ? tryBlock.subBlocks[0] : tryBlock); 640 tryFlow.lastModified = syncBlock; 641 return true; 642 } 643 644 654 private void mergeFinallyBlock(FlowBlock tryFlow, FlowBlock catchFlow, 655 StructuredBlock finallyBlock) { 656 TryBlock tryBlock = (TryBlock) tryFlow.block; 657 if (tryBlock.getSubBlocks()[0] instanceof TryBlock) { 658 662 TryBlock innerTry = (TryBlock)tryBlock.getSubBlocks()[0]; 663 innerTry.gen = tryBlock.gen; 664 innerTry.replace(tryBlock); 665 tryBlock = innerTry; 666 tryFlow.lastModified = tryBlock; 667 tryFlow.block = tryBlock; 668 } 669 670 671 mergeTryCatch(tryFlow, catchFlow); 672 FinallyBlock newBlock = new FinallyBlock(); 673 newBlock.setCatchBlock(finallyBlock); 674 tryBlock.addCatchBlock(newBlock); 675 } 676 677 private boolean analyzeFinally(FlowBlock tryFlow, 678 FlowBlock catchFlow, int end) { 679 680 699 700 StructuredBlock catchBlock = catchFlow.block; 701 StoreInstruction excStore = getExceptionStore(catchBlock); 702 if (excStore == null) 703 return false; 704 705 catchBlock = catchBlock.getSubBlocks()[1]; 706 if (!(catchBlock instanceof SequentialBlock)) 707 return false; 708 709 StructuredBlock finallyBlock = null; 710 711 if (catchBlock.getSubBlocks()[0] instanceof LoopBlock) { 712 724 LoopBlock doWhileFalse = (LoopBlock)catchBlock.getSubBlocks()[0]; 725 if (doWhileFalse.type == LoopBlock.DOWHILE 726 && doWhileFalse.cond == LoopBlock.FALSE 727 && doWhileFalse.bodyBlock instanceof SequentialBlock) { 728 if (transformSubRoutine(catchBlock.getSubBlocks()[1])) { 729 finallyBlock = catchBlock.getSubBlocks()[1]; 730 catchBlock = (SequentialBlock) doWhileFalse.bodyBlock; 731 } 732 } 733 } 734 735 if (!(catchBlock instanceof SequentialBlock 736 && catchBlock.getSubBlocks()[0] instanceof JsrBlock 737 && catchBlock.getSubBlocks()[1] instanceof ThrowBlock)) 738 739 return false; 740 741 JsrBlock jsrBlock = (JsrBlock)catchBlock.getSubBlocks()[0]; 742 ThrowBlock throwBlock = (ThrowBlock) catchBlock.getSubBlocks()[1]; 743 744 745 if (!(throwBlock.getInstruction() instanceof Operator 746 && excStore.lvalueMatches((Operator) 747 throwBlock.getInstruction()))) 748 return false; 749 750 FlowBlock subRoutine; 751 if (finallyBlock != null) { 752 756 if (!(jsrBlock.innerBlock instanceof BreakBlock)) 757 return false; 758 759 761 764 catchBlock = finallyBlock; 765 subRoutine = null; 766 catchFlow.removeSuccessor(throwBlock.jump); 767 } else { 768 if (!(jsrBlock.innerBlock instanceof EmptyBlock)) 769 return false; 770 finallyBlock = jsrBlock.innerBlock; 771 subRoutine = finallyBlock.jump.destination; 772 773 775 catchFlow.removeSuccessor(throwBlock.jump); 776 checkAndRemoveJSR(tryFlow, subRoutine, 777 tryFlow.getNextAddr(), end); 778 779 781 while (subRoutine.analyze(tryFlow.getNextAddr(), end)); 782 if (subRoutine.predecessors.size() == 1) { 783 786 catchFlow.removeSuccessor(finallyBlock.jump); 787 subRoutine.mergeAddr(catchFlow); 788 catchFlow = subRoutine; 789 790 if (!transformSubRoutine(subRoutine.block)) { 791 finallyBlock = subRoutine.block; 792 DescriptionBlock msg = new DescriptionBlock 793 ("ERROR: Missing return address handling"); 794 StructuredBlock subblock = subRoutine.block; 795 msg.replace(finallyBlock); 796 msg.appendBlock(finallyBlock); 797 } 798 finallyBlock = subRoutine.block; 799 } 800 } 801 802 804 mergeFinallyBlock(tryFlow, catchFlow, finallyBlock); 805 return true; 806 } 807 808 private boolean analyzeSpecialFinally(FlowBlock tryFlow, 809 FlowBlock catchFlow, int end) { 810 StructuredBlock finallyBlock = catchFlow.block; 811 StructuredBlock firstInstr = 812 finallyBlock instanceof SequentialBlock 813 ? finallyBlock.getSubBlocks()[0]: finallyBlock; 814 815 if (!(firstInstr instanceof SpecialBlock 816 && ((SpecialBlock)firstInstr).type == SpecialBlock.POP 817 && ((SpecialBlock)firstInstr).count == 1)) 818 return false; 819 820 824 825 827 tryFlow.lastModified = tryFlow.block.getSubBlocks()[0]; 828 FlowBlock finallyFlow; 829 if (finallyBlock instanceof SequentialBlock) { 830 finallyBlock = finallyBlock.getSubBlocks()[1]; 831 finallyFlow = null; 832 } else { 833 finallyBlock = new EmptyBlock(); 834 finallyBlock.moveJump(firstInstr.jump); 835 836 838 finallyFlow = finallyBlock.jump.destination; 839 if (tryFlow.getSuccessors().contains(finallyFlow)) { 840 Jump jumps = tryFlow.removeJumps(finallyFlow); 841 jumps = tryFlow.resolveSomeJumps(jumps, finallyFlow); 842 tryFlow.resolveRemaining(jumps); 843 } 844 } 845 846 847 Set trySuccs = tryFlow.getSuccessors(); 848 for (Iterator i = trySuccs.iterator(); i.hasNext(); ) { 849 FlowBlock succ = (FlowBlock) i.next(); 850 if (succ != FlowBlock.END_OF_METHOD) { 851 856 if (succ.block instanceof EmptyBlock 857 && succ.block.jump.destination == finallyFlow) { 858 Jump jumps = tryFlow.removeJumps(succ); 859 jumps = tryFlow.resolveSomeJumps(jumps, finallyFlow); 860 tryFlow.resolveRemaining(jumps); 861 if (succ.predecessors.size() == 0) { 862 succ.removeJumps(finallyFlow); 863 tryFlow.mergeAddr(succ); 864 } 865 continue; 866 } 867 } 868 for (Jump jumps = tryFlow.getJumps(succ); 869 jumps != null; jumps = jumps.next) { 870 if (jumps.prev instanceof ThrowBlock) 871 continue; 872 873 DescriptionBlock msg = 874 new DescriptionBlock 875 ("ERROR: doesn't go through finally block!"); 876 if (jumps.prev instanceof ReturnBlock) { 877 msg.replace(jumps.prev); 878 msg.appendBlock(jumps.prev); 879 } else { 880 jumps.prev.appendBlock(msg); 881 msg.moveJump(jumps); 882 } 883 } 884 } 885 886 mergeFinallyBlock(tryFlow, catchFlow, finallyBlock); 887 888 tryFlow.lastModified = finallyBlock; 889 return true; 890 } 891 892 void checkTryCatchOrder() { 893 897 Handler last = null; 898 for (Iterator i = handlers.iterator(); i.hasNext(); ) { 899 Handler exc = (Handler) i.next(); 900 int start = exc.start.getAddr(); 901 int end = exc.endAddr; 902 int handler = exc.handler.getAddr(); 903 if (start >= end || handler < end) 904 throw new AssertError 905 ("ExceptionHandler order failed: not " 906 + start + " < " + end + " <= " + handler); 907 if (last != null 908 && (last.start.getAddr() != start || last.endAddr != end)) { 909 913 if (end > last.start.getAddr() && end < last.endAddr) 914 throw new AssertError 915 ("Exception handlers ranges are intersecting: [" 916 + last.start.getAddr()+", "+last.endAddr+"] and [" 917 + start+", "+end+"]."); 918 } 919 last = exc; 920 } 921 } 922 923 927 public void analyze() { 928 checkTryCatchOrder(); 929 930 Iterator i = handlers.iterator(); 931 Handler exc = null; 932 Handler next = i.hasNext() ? (Handler) i.next() : null; 933 while(next != null) { 934 Handler last = exc; 935 exc = next; 936 next = i.hasNext() ? (Handler) i.next() : null; 937 int endHandler = Integer.MAX_VALUE; 938 941 if (next != null && next.endAddr > exc.endAddr) 942 endHandler = next.endAddr; 943 944 FlowBlock tryFlow = exc.start; 945 tryFlow.checkConsistent(); 946 947 if (last == null || exc.type == null 948 || last.start.getAddr() != exc.start.getAddr() 949 || last.endAddr != exc.endAddr) { 950 953 if ((GlobalOptions.debuggingFlags 954 & GlobalOptions.DEBUG_ANALYZE) != 0) 955 GlobalOptions.err.println 956 ("analyzeTry(" 957 + exc.start.getAddr() + ", " + exc.endAddr+")"); 958 while (tryFlow.analyze(tryFlow.getAddr(), exc.endAddr)); 959 960 TryBlock tryBlock = new TryBlock(tryFlow); 961 } else if (!(tryFlow.block instanceof TryBlock)) 962 throw new AssertError("no TryBlock"); 963 964 FlowBlock catchFlow = exc.handler; 965 boolean isMultiUsed = catchFlow.predecessors.size() != 0; 966 if (!isMultiUsed && next != null) { 967 for (Iterator j = handlers.tailSet(next).iterator(); 968 j.hasNext();) { 969 Handler h = (Handler) j.next(); 970 if (h.handler == catchFlow) { 971 isMultiUsed = true; 972 break; 973 } 974 } 975 } 976 977 if (isMultiUsed) { 978 982 EmptyBlock jump = new EmptyBlock(new Jump(catchFlow)); 983 FlowBlock newFlow = new FlowBlock(catchFlow.method, 984 catchFlow.getAddr()); 985 newFlow.appendBlock(jump, 0); 986 catchFlow.prevByAddr.nextByAddr = newFlow; 987 newFlow.prevByAddr = catchFlow.prevByAddr; 988 newFlow.nextByAddr = catchFlow; 989 catchFlow.prevByAddr = newFlow; 990 catchFlow = newFlow; 991 } else { 992 if ((GlobalOptions.debuggingFlags 993 & GlobalOptions.DEBUG_ANALYZE) != 0) 994 GlobalOptions.err.println 995 ("analyzeCatch(" 996 + catchFlow.getAddr() + ", " + endHandler + ")"); 997 while (catchFlow.analyze(catchFlow.getAddr(), endHandler)); 998 } 999 1000 if (exc.type != null) 1001 analyzeCatchBlock(exc.type, tryFlow, catchFlow); 1002 1003 else if (!analyzeSynchronized(tryFlow, catchFlow, endHandler) 1004 && ! analyzeFinally(tryFlow, catchFlow, endHandler) 1005 && ! analyzeSpecialFinally(tryFlow, catchFlow, 1006 endHandler)) 1007 1008 analyzeCatchBlock(Type.tObject, tryFlow, catchFlow); 1009 1010 tryFlow.checkConsistent(); 1011 if ((GlobalOptions.debuggingFlags 1012 & GlobalOptions.DEBUG_ANALYZE) != 0) 1013 GlobalOptions.err.println 1014 ("analyzeTryCatch(" + tryFlow.getAddr() + ", " 1015 + tryFlow.getNextAddr() + ") done."); 1016 } 1017 } 1018} 1019 | Popular Tags |