1 19 20 25 26 27 28 29 30 package soot.baf; 31 import soot.options.*; 32 import soot.tagkit.*; 33 import soot.*; 34 import soot.jimple.*; 35 import soot.toolkits.graph.*; 36 import soot.util.*; 37 import java.util.*; 38 import java.io.*; 39 40 public class JasminClass extends AbstractJasminClass 41 { 42 43 public JasminClass(SootClass sootClass) 44 { 45 super(sootClass); 46 } 47 48 protected void assignColorsToLocals(Body body) 49 { 50 super.assignColorsToLocals(body); 51 52 if(Options.v().time()) 53 Timers.v().packTimer.end(); 54 55 } 56 57 protected void emitMethodBody(SootMethod method) 58 { 59 if(Options.v().time()) 60 Timers.v().buildJasminTimer.end(); 61 62 Body activeBody = method.getActiveBody(); 63 64 if(!(activeBody instanceof BafBody)) 65 throw new RuntimeException ("method: " + method.getName() + " has an invalid active body!"); 66 67 BafBody body = (BafBody) activeBody; 68 69 if(body == null) 70 throw new RuntimeException ("method: " + method.getName() + " has no active body!"); 71 72 if(Options.v().time()) 73 Timers.v().buildJasminTimer.start(); 74 75 Chain instList = body.getUnits(); 76 77 int stackLimitIndex = -1; 78 79 80 subroutineToReturnAddressSlot = new HashMap(10, 0.7f); 81 82 { 84 Iterator boxIt = body.getUnitBoxes(true).iterator(); 85 86 unitToLabel = new HashMap(instList.size() * 2 + 1, 0.7f); 87 labelCount = 0; 88 89 while(boxIt.hasNext()) 90 { 91 { 93 InstBox box = (InstBox) boxIt.next(); 94 95 if(!unitToLabel.containsKey(box.getUnit())) 96 unitToLabel.put(box.getUnit(), "label" + labelCount++); 97 } 98 } 99 } 100 101 102 103 104 Set handlerUnits = new ArraySet(body.getTraps().size()); 108 { 109 Iterator trapIt = body.getTraps().iterator(); 110 111 while(trapIt.hasNext()) 112 { 113 Trap trap = (Trap) trapIt.next(); 114 115 handlerUnits.add(trap.getHandlerUnit()); 116 if(trap.getBeginUnit() != trap.getEndUnit()) { 117 emit(".catch " + slashify(trap.getException().getName()) + " from " + 118 unitToLabel.get(trap.getBeginUnit()) + " to " + unitToLabel.get(trap.getEndUnit()) + 119 " using " + unitToLabel.get(trap.getHandlerUnit())); 120 } 121 } 122 } 123 124 { 126 int localCount = 0; 127 int[] paramSlots = new int[method.getParameterCount()]; 128 int thisSlot = 0; 129 Set assignedLocals = new HashSet(); 130 Map groupColorPairToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 131 132 localToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f); 133 134 136 { 138 List paramTypes = method.getParameterTypes(); 139 140 if(!method.isStatic()) 141 { 142 thisSlot = 0; 143 localCount++; 144 } 145 146 for(int i = 0; i < paramTypes.size(); i++) 147 { 148 paramSlots[i] = localCount; 149 localCount += sizeOfType((Type) paramTypes.get(i)); 150 } 151 } 152 153 { 155 Iterator instIt = instList.iterator(); 156 157 while(instIt.hasNext()) 158 { 159 Inst s = (Inst) instIt.next(); 160 161 if(s instanceof IdentityInst && ((IdentityInst) s).getLeftOp() instanceof Local) 162 { 163 Local l = (Local) ((IdentityInst) s).getLeftOp(); 164 IdentityRef identity = (IdentityRef) ((IdentityInst) s).getRightOp(); 165 166 int slot = 0; 167 168 if(identity instanceof ThisRef) 169 { 170 if(method.isStatic()) 171 throw new RuntimeException ("Attempting to use 'this' in static method"); 172 173 slot = thisSlot; 174 } 175 else if(identity instanceof ParameterRef) 176 slot = paramSlots[((ParameterRef) identity).getIndex()]; 177 else { 178 continue; 180 } 181 182 localToSlot.put(l, new Integer (slot)); 183 assignedLocals.add(l); 184 185 } 186 } 187 } 188 189 { 191 Iterator localIt = body.getLocals().iterator(); 192 193 while(localIt.hasNext()) 194 { 195 Local local = (Local) localIt.next(); 196 197 if(!assignedLocals.contains(local)) 198 { 199 localToSlot.put(local, new Integer (localCount)); 200 localCount += sizeOfType((Type)local.getType()); 201 assignedLocals.add(local); 202 } 203 } 204 205 if (!Modifier.isNative(method.getModifiers()) 206 && !Modifier.isAbstract(method.getModifiers())) 207 { 208 emit(" .limit stack ?"); 209 stackLimitIndex = code.size() - 1; 210 211 emit(" .limit locals " + localCount); 212 } 213 } 214 } 215 216 { 218 Iterator codeIt = instList.iterator(); 219 220 isEmittingMethodCode = true; 221 maxStackHeight = 0; 222 isNextGotoAJsr = false; 223 224 while(codeIt.hasNext()) 225 { 226 Inst s = (Inst) codeIt.next(); 227 228 if(unitToLabel.containsKey(s)) 229 emit(unitToLabel.get(s) + ":"); 230 231 { 233 emitInst(s); 234 } 235 } 236 237 isEmittingMethodCode = false; 238 239 { 241 maxStackHeight = 0; 242 if(activeBody.getUnits().size() != 0 ) { 243 BlockGraph blockGraph = new BriefBlockGraph(activeBody); 244 245 246 List blocks = blockGraph.getBlocks(); 247 248 249 if(blocks.size() != 0) { 250 List entryPoints = ((DirectedGraph)blockGraph).getHeads(); 252 Iterator entryIt = entryPoints.iterator(); 253 while(entryIt.hasNext()) { 254 Block entryBlock = (Block) entryIt.next(); 255 Integer initialHeight; 256 if(handlerUnits.contains(entryBlock.getHead())) { 257 initialHeight = new Integer (1); 258 } else { 259 initialHeight = new Integer (0); 260 } 261 if (blockToStackHeight == null){ 262 blockToStackHeight = new HashMap(); 263 } 264 blockToStackHeight.put(entryBlock, initialHeight); 265 if (blockToLogicalStackHeight == null){ 266 blockToLogicalStackHeight = new HashMap(); 267 } 268 blockToLogicalStackHeight.put(entryBlock, initialHeight); 269 } 270 271 entryIt = entryPoints.iterator(); 273 while(entryIt.hasNext()) { 274 Block nextBlock = (Block) entryIt.next(); 275 calculateStackHeight(nextBlock); 276 calculateLogicalStackHeightCheck(nextBlock); 277 } 278 } 279 } 280 } 281 if (!Modifier.isNative(method.getModifiers()) 282 && !Modifier.isAbstract(method.getModifiers())) 283 code.set(stackLimitIndex, " .limit stack " + maxStackHeight); 284 } 285 286 { 288 Iterator it = body.getTags().iterator(); 289 while(it.hasNext()) { 290 Tag t = (Tag) it.next(); 291 if(t instanceof JasminAttribute) { 292 emit(".code_attribute " + t.getName() +" \"" + ((JasminAttribute) t).getJasminValue(unitToLabel) +"\""); 293 } 294 } 295 } 296 } 297 298 299 void emitInst(Inst inst) 300 { 301 inst.apply(new InstSwitch() 302 { 303 public void caseReturnVoidInst(ReturnVoidInst i) 304 { 305 emit("return"); 306 } 307 308 public void caseReturnInst(ReturnInst i) 309 { 310 i.getOpType().apply(new TypeSwitch() 311 { 312 public void defaultCase(Type t) 313 { 314 throw new RuntimeException ("invalid return type " + t.toString()); 315 } 316 317 public void caseDoubleType(DoubleType t) 318 { 319 emit("dreturn"); 320 } 321 322 public void caseFloatType(FloatType t) 323 { 324 emit("freturn"); 325 } 326 327 public void caseIntType(IntType t) 328 { 329 emit("ireturn"); 330 } 331 332 public void caseByteType(ByteType t) 333 { 334 emit("ireturn"); 335 } 336 337 public void caseShortType(ShortType t) 338 { 339 emit("ireturn"); 340 } 341 342 public void caseCharType(CharType t) 343 { 344 emit("ireturn"); 345 } 346 347 public void caseBooleanType(BooleanType t) 348 { 349 emit("ireturn"); 350 } 351 352 public void caseLongType(LongType t) 353 { 354 emit("lreturn"); 355 } 356 357 public void caseArrayType(ArrayType t) 358 { 359 emit("areturn"); 360 } 361 362 public void caseRefType(RefType t) 363 { 364 emit("areturn"); 365 } 366 367 public void caseNullType(NullType t) 368 { 369 emit("areturn"); 370 } 371 372 }); 373 } 374 375 public void caseNopInst(NopInst i) { emit ("nop"); } 376 377 public void caseEnterMonitorInst(EnterMonitorInst i) 378 { 379 emit ("monitorenter"); 380 } 381 382 public void casePopInst(PopInst i) 383 { 384 if(i.getWordCount() == 2) { 385 emit("pop2"); 386 } 387 else 388 emit("pop"); 389 } 390 391 392 public void caseExitMonitorInst(ExitMonitorInst i) 393 { 394 emit ("monitorexit"); 395 } 396 397 public void caseGotoInst(GotoInst i) 398 { 399 emit("goto " + unitToLabel.get(i.getTarget())); 400 } 401 402 public void casePushInst(PushInst i) 403 { 404 if (i.getConstant() instanceof IntConstant) 405 { 406 IntConstant v = (IntConstant)(i.getConstant()); 407 if(v.value == -1) 408 emit("iconst_m1"); 409 else if(v.value >= 0 && v.value <= 5) 410 emit("iconst_" + v.value); 411 else if(v.value >= Byte.MIN_VALUE && 412 v.value <= Byte.MAX_VALUE) 413 emit("bipush " + v.value); 414 else if(v.value >= Short.MIN_VALUE && 415 v.value <= Short.MAX_VALUE) 416 emit("sipush " + v.value); 417 else 418 emit("ldc " + v.toString()); 419 } 420 else if (i.getConstant() instanceof StringConstant) 421 { 422 emit("ldc " + i.getConstant().toString()); 423 } 424 else if (i.getConstant() instanceof ClassConstant) 425 { 426 emit("ldc_w " + ((ClassConstant)i.getConstant()).getValue()); 427 } 428 else if (i.getConstant() instanceof DoubleConstant) 429 { 430 DoubleConstant v = (DoubleConstant)(i.getConstant()); 431 432 if((v.value == 0) && ((1.0/v.value) > 0.0)) 433 emit("dconst_0"); 434 else if(v.value == 1) 435 emit("dconst_1"); 436 else { 437 String s = v.toString(); 438 439 if(s.equals("#Infinity")) 440 s="+DoubleInfinity"; 441 442 if(s.equals("#-Infinity")) 443 s="-DoubleInfinity"; 444 445 if(s.equals("#NaN")) 446 s="+DoubleNaN"; 447 448 emit("ldc2_w " + s); 449 } 450 } 451 else if (i.getConstant() instanceof FloatConstant) 452 { 453 FloatConstant v = (FloatConstant)(i.getConstant()); 454 if((v.value == 0) && ((1.0f/v.value) > 1.0f)) 455 emit("fconst_0"); 456 else if(v.value == 1) 457 emit("fconst_1"); 458 else if(v.value == 2) 459 emit("fconst_2"); 460 else { 461 String s = v.toString(); 462 463 if(s.equals("#InfinityF")) 464 s="+FloatInfinity"; 465 if(s.equals("#-InfinityF")) 466 s="-FloatInfinity"; 467 468 if(s.equals("#NaNF")) 469 s="+FloatNaN"; 470 471 emit("ldc " + s); 472 } 473 } 474 else if (i.getConstant() instanceof LongConstant) 475 { 476 LongConstant v = (LongConstant)(i.getConstant()); 477 if(v.value == 0) 478 emit("lconst_0"); 479 else if(v.value == 1) 480 emit("lconst_1"); 481 else 482 emit("ldc2_w " + v.toString()); 483 } 484 else if (i.getConstant() instanceof NullConstant) 485 emit("aconst_null"); 486 else 487 throw new RuntimeException ("unsupported opcode"); 488 } 489 490 public void caseIdentityInst(IdentityInst i) 491 { 492 if(i.getRightOp() instanceof CaughtExceptionRef && 493 i.getLeftOp() instanceof Local) 494 { 495 int slot = ((Integer ) localToSlot.get(i.getLeftOp())).intValue(); 496 497 if(slot >= 0 && slot <= 3) 498 emit("astore_" + slot); 499 else 500 emit("astore " + slot); 501 } 502 } 503 504 public void caseStoreInst(StoreInst i) 505 { 506 final int slot = 507 ((Integer ) localToSlot.get(i.getLocal())).intValue(); 508 509 i.getOpType().apply(new TypeSwitch() 510 { 511 public void caseArrayType(ArrayType t) 512 { 513 if(slot >= 0 && slot <= 3) 514 emit("astore_" + slot); 515 else 516 emit("astore " + slot); 517 } 518 519 public void caseDoubleType(DoubleType t) 520 { 521 if(slot >= 0 && slot <= 3) 522 emit("dstore_" + slot); 523 else 524 emit("dstore " + slot); 525 } 526 527 public void caseFloatType(FloatType t) 528 { 529 if(slot >= 0 && slot <= 3) 530 emit("fstore_" + slot); 531 else 532 emit("fstore " + slot); 533 } 534 535 public void caseIntType(IntType t) 536 { 537 if(slot >= 0 && slot <= 3) 538 emit("istore_" + slot); 539 else 540 emit("istore " + slot); 541 } 542 543 public void caseByteType(ByteType t) 544 { 545 if(slot >= 0 && slot <= 3) 546 emit("istore_" + slot); 547 else 548 emit("istore " + slot); 549 } 550 551 public void caseShortType(ShortType t) 552 { 553 if(slot >= 0 && slot <= 3) 554 emit("istore_" + slot); 555 else 556 emit("istore " + slot); 557 } 558 559 public void caseCharType(CharType t) 560 { 561 if(slot >= 0 && slot <= 3) 562 emit("istore_" + slot); 563 else 564 emit("istore " + slot); 565 } 566 567 public void caseBooleanType(BooleanType t) 568 { 569 if(slot >= 0 && slot <= 3) 570 emit("istore_" + slot); 571 else 572 emit("istore " + slot); 573 } 574 575 public void caseLongType(LongType t) 576 { 577 if(slot >= 0 && slot <= 3) 578 emit("lstore_" + slot); 579 else 580 emit("lstore " + slot); 581 } 582 583 public void caseRefType(RefType t) 584 { 585 if(slot >= 0 && slot <= 3) 586 emit("astore_" + slot); 587 else 588 emit("astore " + slot); 589 } 590 591 public void caseStmtAddressType(StmtAddressType t) 592 { 593 isNextGotoAJsr = true; 594 returnAddressSlot = slot; 595 596 603 } 604 605 public void caseNullType(NullType t) 606 { 607 if(slot >= 0 && slot <= 3) 608 emit("astore_" + slot); 609 else 610 emit("astore " + slot); 611 } 612 613 public void defaultCase(Type t) 614 { 615 throw new RuntimeException ("Invalid local type:" 616 + t); 617 } 618 }); 619 } 620 621 public void caseLoadInst(LoadInst i) 622 { 623 final int slot = 624 ((Integer ) localToSlot.get(i.getLocal())).intValue(); 625 626 i.getOpType().apply(new TypeSwitch() 627 { 628 public void caseArrayType(ArrayType t) 629 { 630 if(slot >= 0 && slot <= 3) 631 emit("aload_" + slot); 632 else 633 emit("aload " + slot); 634 } 635 636 public void defaultCase(Type t) 637 { 638 throw new 639 RuntimeException ("invalid local type to load" + t); 640 } 641 642 public void caseDoubleType(DoubleType t) 643 { 644 if(slot >= 0 && slot <= 3) 645 emit("dload_" + slot); 646 else 647 emit("dload " + slot); 648 } 649 650 public void caseFloatType(FloatType t) 651 { 652 if(slot >= 0 && slot <= 3) 653 emit("fload_" + slot); 654 else 655 emit("fload " + slot); 656 } 657 658 public void caseIntType(IntType t) 659 { 660 if(slot >= 0 && slot <= 3) 661 emit("iload_" + slot); 662 else 663 emit("iload " + slot); 664 } 665 666 public void caseByteType(ByteType t) 667 { 668 if(slot >= 0 && slot <= 3) 669 emit("iload_" + slot); 670 else 671 emit("iload " + slot); 672 } 673 674 public void caseShortType(ShortType t) 675 { 676 if(slot >= 0 && slot <= 3) 677 emit("iload_" + slot); 678 else 679 emit("iload " + slot); 680 } 681 682 public void caseCharType(CharType t) 683 { 684 if(slot >= 0 && slot <= 3) 685 emit("iload_" + slot); 686 else 687 emit("iload " + slot); 688 } 689 690 public void caseBooleanType(BooleanType t) 691 { 692 if(slot >= 0 && slot <= 3) 693 emit("iload_" + slot); 694 else 695 emit("iload " + slot); 696 } 697 698 public void caseLongType(LongType t) 699 { 700 if(slot >= 0 && slot <= 3) 701 emit("lload_" + slot); 702 else 703 emit("lload " + slot); 704 } 705 706 public void caseRefType(RefType t) 707 { 708 if(slot >= 0 && slot <= 3) 709 emit("aload_" + slot); 710 else 711 emit("aload " + slot); 712 } 713 714 public void caseNullType(NullType t) 715 { 716 if(slot >= 0 && slot <= 3) 717 emit("aload_" + slot); 718 else 719 emit("aload " + slot); 720 } 721 }); 722 } 723 724 public void caseArrayWriteInst(ArrayWriteInst i) 725 { 726 i.getOpType().apply(new TypeSwitch() 727 { 728 public void caseArrayType(ArrayType t) 729 { 730 emit("aastore"); 731 } 732 733 public void caseDoubleType(DoubleType t) 734 { 735 emit("dastore"); 736 } 737 738 public void caseFloatType(FloatType t) 739 { 740 emit("fastore"); 741 } 742 743 public void caseIntType(IntType t) 744 { 745 emit("iastore"); 746 } 747 748 public void caseLongType(LongType t) 749 { 750 emit("lastore"); 751 } 752 753 public void caseRefType(RefType t) 754 { 755 emit("aastore"); 756 } 757 758 public void caseByteType(ByteType t) 759 { 760 emit("bastore"); 761 } 762 763 public void caseBooleanType(BooleanType t) 764 { 765 emit("bastore"); 766 } 767 768 public void caseCharType(CharType t) 769 { 770 emit("castore"); 771 } 772 773 public void caseShortType(ShortType t) 774 { 775 emit("sastore"); 776 } 777 778 public void defaultCase(Type t) 779 { 780 throw new RuntimeException ("Invalid type: " + t); 781 }}); 782 783 } 784 785 public void caseArrayReadInst(ArrayReadInst i) 786 { 787 i.getOpType().apply(new TypeSwitch() 788 { 789 public void caseArrayType(ArrayType ty) 790 { 791 emit("aaload"); 792 } 793 794 public void caseBooleanType(BooleanType ty) 795 { 796 emit("baload"); 797 } 798 799 public void caseByteType(ByteType ty) 800 { 801 emit("baload"); 802 } 803 804 public void caseCharType(CharType ty) 805 { 806 emit("caload"); 807 } 808 809 public void defaultCase(Type ty) 810 { 811 throw new RuntimeException ("invalid base type"); 812 } 813 814 public void caseDoubleType(DoubleType ty) 815 { 816 emit("daload"); 817 } 818 819 public void caseFloatType(FloatType ty) 820 { 821 emit("faload"); 822 } 823 824 public void caseIntType(IntType ty) 825 { 826 emit("iaload"); 827 } 828 829 public void caseLongType(LongType ty) 830 { 831 emit("laload"); 832 } 833 834 public void caseNullType(NullType ty) 835 { 836 emit("aaload"); 837 } 838 public void caseRefType(RefType ty) 839 { 840 emit("aaload"); 841 } 842 843 public void caseShortType(ShortType ty) 844 { 845 emit("saload"); 846 } 847 }); 848 } 849 850 public void caseIfNullInst(IfNullInst i) 851 { 852 emit("ifnull " + unitToLabel.get(i.getTarget())); 853 } 854 855 public void caseIfNonNullInst(IfNonNullInst i) 856 { 857 emit("ifnonnull " + unitToLabel.get(i.getTarget())); 858 } 859 860 public void caseIfEqInst(IfEqInst i) 861 { 862 emit("ifeq " + unitToLabel.get(i.getTarget())); 863 } 864 865 public void caseIfNeInst(IfNeInst i) 866 { 867 emit("ifne " + unitToLabel.get(i.getTarget())); 868 } 869 870 public void caseIfGtInst(IfGtInst i) 871 { 872 emit("ifgt " + unitToLabel.get(i.getTarget())); 873 } 874 875 public void caseIfGeInst(IfGeInst i) 876 { 877 emit("ifge " + unitToLabel.get(i.getTarget())); 878 } 879 880 public void caseIfLtInst(IfLtInst i) 881 { 882 emit("iflt " + unitToLabel.get(i.getTarget())); 883 } 884 885 public void caseIfLeInst(IfLeInst i) 886 { 887 emit("ifle " + unitToLabel.get(i.getTarget())); 888 } 889 890 public void caseIfCmpEqInst(final IfCmpEqInst i) 891 { 892 i.getOpType().apply(new TypeSwitch() 893 { 894 public void caseIntType(IntType t) 895 { 896 emit("if_icmpeq " + 897 unitToLabel.get(i.getTarget())); 898 } 899 900 public void caseBooleanType(BooleanType t) 901 { 902 emit("if_icmpeq " + 903 unitToLabel.get(i.getTarget())); 904 } 905 906 public void caseShortType(ShortType t) 907 { 908 emit("if_icmpeq " + 909 unitToLabel.get(i.getTarget())); 910 } 911 912 public void caseCharType(CharType t) 913 { 914 emit("if_icmpeq " + 915 unitToLabel.get(i.getTarget())); 916 } 917 918 public void caseByteType(ByteType t) 919 { 920 emit("if_icmpeq " + 921 unitToLabel.get(i.getTarget())); 922 } 923 924 public void caseDoubleType(DoubleType t) 925 { 926 emit("dcmpg"); 927 emit("ifeq " + 928 unitToLabel.get(i.getTarget())); 929 } 930 931 public void caseLongType(LongType t) 932 { 933 emit("lcmp"); 934 emit("ifeq " + 935 unitToLabel.get(i.getTarget())); 936 } 937 938 public void caseFloatType(FloatType t) 939 { 940 emit("fcmpg"); 941 emit("ifeq " + 942 unitToLabel.get(i.getTarget())); 943 } 944 945 public void caseArrayType(ArrayType t) 946 { 947 emit("if_acmpeq " + 948 unitToLabel.get(i.getTarget())); 949 } 950 951 public void caseRefType(RefType t) 952 { 953 emit("if_acmpeq " + 954 unitToLabel.get(i.getTarget())); 955 } 956 957 public void caseNullType(NullType t) 958 { 959 emit("if_acmpeq " + 960 unitToLabel.get(i.getTarget())); 961 } 962 963 public void defaultCase(Type t) 964 { 965 throw new RuntimeException ("invalid type"); 966 } 967 }); 968 } 969 970 public void caseIfCmpNeInst(final IfCmpNeInst i) 971 { 972 i.getOpType().apply(new TypeSwitch() 973 { 974 public void caseIntType(IntType t) 975 { 976 emit("if_icmpne " + 977 unitToLabel.get(i.getTarget())); 978 } 979 980 public void caseBooleanType(BooleanType t) 981 { 982 emit("if_icmpne " + 983 unitToLabel.get(i.getTarget())); 984 } 985 986 public void caseShortType(ShortType t) 987 { 988 emit("if_icmpne " + 989 unitToLabel.get(i.getTarget())); 990 } 991 992 public void caseCharType(CharType t) 993 { 994 emit("if_icmpne " + 995 unitToLabel.get(i.getTarget())); 996 } 997 998 public void caseByteType(ByteType t) 999 { 1000 emit("if_icmpne " + 1001 unitToLabel.get(i.getTarget())); 1002 } 1003 1004 public void caseDoubleType(DoubleType t) 1005 { 1006 emit("dcmpg"); 1007 emit("ifne " + 1008 unitToLabel.get(i.getTarget())); 1009 } 1010 1011 public void caseLongType(LongType t) 1012 { 1013 emit("lcmp"); 1014 emit("ifne " + 1015 unitToLabel.get(i.getTarget())); 1016 } 1017 1018 public void caseFloatType(FloatType t) 1019 { 1020 emit("fcmpg"); 1021 emit("ifne " + 1022 unitToLabel.get(i.getTarget())); 1023 } 1024 1025 public void caseArrayType(ArrayType t) 1026 { 1027 emit("if_acmpne " + 1028 unitToLabel.get(i.getTarget())); 1029 } 1030 1031 public void caseRefType(RefType t) 1032 { 1033 emit("if_acmpne " + 1034 unitToLabel.get(i.getTarget())); 1035 } 1036 1037 public void caseNullType(NullType t) 1038 { 1039 emit("if_acmpne " + 1040 unitToLabel.get(i.getTarget())); 1041 } 1042 1043 public void defaultCase(Type t) 1044 { 1045 throw new RuntimeException ("invalid type"); 1046 } 1047 }); 1048 } 1049 1050 public void caseIfCmpGtInst(final IfCmpGtInst i) 1051 { 1052 i.getOpType().apply(new TypeSwitch() 1053 { 1054 public void caseIntType(IntType t) 1055 { 1056 emit("if_icmpgt " + 1057 unitToLabel.get(i.getTarget())); 1058 } 1059 1060 public void caseBooleanType(BooleanType t) 1061 { 1062 emit("if_icmpgt " + 1063 unitToLabel.get(i.getTarget())); 1064 } 1065 1066 public void caseShortType(ShortType t) 1067 { 1068 emit("if_icmpgt " + 1069 unitToLabel.get(i.getTarget())); 1070 } 1071 1072 public void caseCharType(CharType t) 1073 { 1074 emit("if_icmpgt " + 1075 unitToLabel.get(i.getTarget())); 1076 } 1077 1078 public void caseByteType(ByteType t) 1079 { 1080 emit("if_icmpgt " + 1081 unitToLabel.get(i.getTarget())); 1082 } 1083 1084 public void caseDoubleType(DoubleType t) 1085 { 1086 emit("dcmpg"); 1087 emit("ifgt " + 1088 unitToLabel.get(i.getTarget())); 1089 } 1090 1091 public void caseLongType(LongType t) 1092 { 1093 emit("lcmp"); 1094 emit("ifgt " + 1095 unitToLabel.get(i.getTarget())); 1096 } 1097 1098 public void caseFloatType(FloatType t) 1099 { 1100 emit("fcmpg"); 1101 emit("ifgt " + 1102 unitToLabel.get(i.getTarget())); 1103 } 1104 1105 public void caseArrayType(ArrayType t) 1106 { 1107 emit("if_acmpgt " + 1108 unitToLabel.get(i.getTarget())); 1109 } 1110 1111 public void caseRefType(RefType t) 1112 { 1113 emit("if_acmpgt " + 1114 unitToLabel.get(i.getTarget())); 1115 } 1116 1117 public void caseNullType(NullType t) 1118 { 1119 emit("if_acmpgt " + 1120 unitToLabel.get(i.getTarget())); 1121 } 1122 1123 public void defaultCase(Type t) 1124 { 1125 throw new RuntimeException ("invalid type"); 1126 } 1127 }); 1128 } 1129 1130 public void caseIfCmpGeInst(final IfCmpGeInst i) 1131 { 1132 i.getOpType().apply(new TypeSwitch() 1133 { 1134 public void caseIntType(IntType t) 1135 { 1136 emit("if_icmpge " + 1137 unitToLabel.get(i.getTarget())); 1138 } 1139 1140 public void caseBooleanType(BooleanType t) 1141 { 1142 emit("if_icmpge " + 1143 unitToLabel.get(i.getTarget())); 1144 } 1145 1146 public void caseShortType(ShortType t) 1147 { 1148 emit("if_icmpge " + 1149 unitToLabel.get(i.getTarget())); 1150 } 1151 1152 public void caseCharType(CharType t) 1153 { 1154 emit("if_icmpge " + 1155 unitToLabel.get(i.getTarget())); 1156 } 1157 1158 public void caseByteType(ByteType t) 1159 { 1160 emit("if_icmpge " + 1161 unitToLabel.get(i.getTarget())); 1162 } 1163 1164 public void caseDoubleType(DoubleType t) 1165 { 1166 emit("dcmpg"); 1167 emit("ifge " + 1168 unitToLabel.get(i.getTarget())); 1169 } 1170 1171 public void caseLongType(LongType t) 1172 { 1173 emit("lcmp"); 1174 emit("ifge " + 1175 unitToLabel.get(i.getTarget())); 1176 } 1177 1178 public void caseFloatType(FloatType t) 1179 { 1180 emit("fcmpg"); 1181 emit("ifge " + 1182 unitToLabel.get(i.getTarget())); 1183 } 1184 1185 public void caseArrayType(ArrayType t) 1186 { 1187 emit("if_acmpge " + 1188 unitToLabel.get(i.getTarget())); 1189 } 1190 1191 public void caseRefType(RefType t) 1192 { 1193 emit("if_acmpge " + 1194 unitToLabel.get(i.getTarget())); 1195 } 1196 1197 public void caseNullType(NullType t) 1198 { 1199 emit("if_acmpge " + 1200 unitToLabel.get(i.getTarget())); 1201 } 1202 1203 public void defaultCase(Type t) 1204 { 1205 throw new RuntimeException ("invalid type"); 1206 } 1207 }); 1208 } 1209 1210 public void caseIfCmpLtInst(final IfCmpLtInst i) 1211 { 1212 i.getOpType().apply(new TypeSwitch() 1213 { 1214 public void caseIntType(IntType t) 1215 { 1216 emit("if_icmplt " + 1217 unitToLabel.get(i.getTarget())); 1218 } 1219 1220 public void caseBooleanType(BooleanType t) 1221 { 1222 emit("if_icmplt " + 1223 unitToLabel.get(i.getTarget())); 1224 } 1225 1226 public void caseShortType(ShortType t) 1227 { 1228 emit("if_icmplt " + 1229 unitToLabel.get(i.getTarget())); 1230 } 1231 1232 public void caseCharType(CharType t) 1233 { 1234 emit("if_icmplt " + 1235 unitToLabel.get(i.getTarget())); 1236 } 1237 1238 public void caseByteType(ByteType t) 1239 { 1240 emit("if_icmplt " + 1241 unitToLabel.get(i.getTarget())); 1242 } 1243 1244 public void caseDoubleType(DoubleType t) 1245 { 1246 emit("dcmpg"); 1247 emit("iflt " + 1248 unitToLabel.get(i.getTarget())); 1249 } 1250 1251 public void caseLongType(LongType t) 1252 { 1253 emit("lcmp"); 1254 emit("iflt " + 1255 unitToLabel.get(i.getTarget())); 1256 } 1257 1258 public void caseFloatType(FloatType t) 1259 { 1260 emit("fcmpg"); 1261 emit("iflt " + 1262 unitToLabel.get(i.getTarget())); 1263 } 1264 1265 public void caseArrayType(ArrayType t) 1266 { 1267 emit("if_acmplt " + 1268 unitToLabel.get(i.getTarget())); 1269 } 1270 1271 public void caseRefType(RefType t) 1272 { 1273 emit("if_acmplt " + 1274 unitToLabel.get(i.getTarget())); 1275 } 1276 1277 public void caseNullType(NullType t) 1278 { 1279 emit("if_acmplt " + 1280 unitToLabel.get(i.getTarget())); 1281 } 1282 1283 public void defaultCase(Type t) 1284 { 1285 throw new RuntimeException ("invalid type"); 1286 } 1287 }); 1288 } 1289 1290 public void caseIfCmpLeInst(final IfCmpLeInst i) 1291 { 1292 i.getOpType().apply(new TypeSwitch() 1293 { 1294 public void caseIntType(IntType t) 1295 { 1296 emit("if_icmple " + 1297 unitToLabel.get(i.getTarget())); 1298 } 1299 1300 public void caseBooleanType(BooleanType t) 1301 { 1302 emit("if_icmple " + 1303 unitToLabel.get(i.getTarget())); 1304 } 1305 1306 public void caseShortType(ShortType t) 1307 { 1308 emit("if_icmple " + 1309 unitToLabel.get(i.getTarget())); 1310 } 1311 1312 public void caseCharType(CharType t) 1313 { 1314 emit("if_icmple " + 1315 unitToLabel.get(i.getTarget())); 1316 } 1317 1318 public void caseByteType(ByteType t) 1319 { 1320 emit("if_icmple " + 1321 unitToLabel.get(i.getTarget())); 1322 } 1323 1324 public void caseDoubleType(DoubleType t) 1325 { 1326 emit("dcmpg"); 1327 emit("ifle " + 1328 unitToLabel.get(i.getTarget())); 1329 } 1330 1331 public void caseLongType(LongType t) 1332 { 1333 emit("lcmp"); 1334 emit("ifle " + 1335 unitToLabel.get(i.getTarget())); 1336 } 1337 1338 public void caseFloatType(FloatType t) 1339 { 1340 emit("fcmpg"); 1341 emit("ifle " + 1342 unitToLabel.get(i.getTarget())); 1343 } 1344 1345 public void caseArrayType(ArrayType t) 1346 { 1347 emit("if_acmple " + 1348 unitToLabel.get(i.getTarget())); 1349 } 1350 1351 public void caseRefType(RefType t) 1352 { 1353 emit("if_acmple " + 1354 unitToLabel.get(i.getTarget())); 1355 } 1356 1357 public void caseNullType(NullType t) 1358 { 1359 emit("if_acmple " + 1360 unitToLabel.get(i.getTarget())); 1361 } 1362 1363 public void defaultCase(Type t) 1364 { 1365 throw new RuntimeException ("invalid type"); 1366 } 1367 }); 1368 } 1369 1370 public void caseStaticGetInst(StaticGetInst i) 1371 { 1372 SootFieldRef field = i.getFieldRef(); 1373 emit("getstatic " + 1374 slashify(field.declaringClass().getName()) + "/" + 1375 field.name() + " " + 1376 jasminDescriptorOf(field.type())); 1377 } 1378 1379 public void caseStaticPutInst(StaticPutInst i) 1380 { 1381 emit("putstatic " + 1382 slashify(i.getFieldRef().declaringClass().getName()) + 1383 "/" + i.getFieldRef().name() + " " + 1384 jasminDescriptorOf(i.getFieldRef().type())); 1385 } 1386 1387 public void caseFieldGetInst(FieldGetInst i) 1388 { 1389 emit("getfield " + 1390 slashify(i.getFieldRef().declaringClass().getName()) + 1391 "/" + i.getFieldRef().name() + " " + 1392 jasminDescriptorOf(i.getFieldRef().type())); 1393 } 1394 1395 public void caseFieldPutInst(FieldPutInst i) 1396 { 1397 emit("putfield " + 1398 slashify(i.getFieldRef().declaringClass().getName()) + 1399 "/" + i.getFieldRef().name() + " " + 1400 jasminDescriptorOf(i.getFieldRef().type())); 1401 } 1402 1403 public void caseInstanceCastInst(InstanceCastInst i) 1404 { 1405 Type castType = i.getCastType(); 1406 1407 if(castType instanceof RefType) 1408 emit("checkcast " + slashify(castType.toString())); 1409 else if(castType instanceof ArrayType) 1410 emit("checkcast " + jasminDescriptorOf(castType)); 1411 } 1412 1413 public void caseInstanceOfInst(InstanceOfInst i) 1414 { 1415 Type checkType = i.getCheckType(); 1416 1417 if(checkType instanceof RefType) 1418 emit("instanceof " + slashify(checkType.toString())); 1419 else if(checkType instanceof ArrayType) 1420 emit("instanceof " + jasminDescriptorOf(checkType)); 1421 } 1422 1423 public void caseNewInst(NewInst i) 1424 { 1425 emit("new "+slashify(i.getBaseType().toString())); 1426 } 1427 1428 public void casePrimitiveCastInst(PrimitiveCastInst i) 1429 { 1430 emit(i.toString()); 1431 } 1432 1433 public void caseStaticInvokeInst(StaticInvokeInst i) 1434 { 1435 SootMethodRef m = i.getMethodRef(); 1436 1437 emit("invokestatic " + slashify(m.declaringClass().getName()) + "/" + 1438 m.name() + jasminDescriptorOf(m)); 1439 } 1440 1441 public void caseVirtualInvokeInst(VirtualInvokeInst i) 1442 { 1443 SootMethodRef m = i.getMethodRef(); 1444 1445 emit("invokevirtual " + slashify(m.declaringClass().getName()) + "/" + 1446 m.name() + jasminDescriptorOf(m)); 1447 } 1448 1449 public void caseInterfaceInvokeInst(InterfaceInvokeInst i) 1450 { 1451 SootMethodRef m = i.getMethodRef(); 1452 1453 emit("invokeinterface " + slashify(m.declaringClass().getName()) + "/" + 1454 m.name() + jasminDescriptorOf(m) + " " + (argCountOf(m) + 1)); 1455 } 1456 1457 public void caseSpecialInvokeInst(SpecialInvokeInst i) 1458 { 1459 SootMethodRef m = i.getMethodRef(); 1460 1461 emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" + 1462 m.name() + jasminDescriptorOf(m)); 1463 } 1464 1465 public void caseThrowInst(ThrowInst i) 1466 { 1467 emit("athrow"); 1468 } 1469 1470 public void caseCmpInst(CmpInst i) 1471 { 1472 emit("lcmp"); 1473 } 1474 1475 public void caseCmplInst(CmplInst i) 1476 { 1477 if(i.getOpType().equals(FloatType.v())) 1478 emit("fcmpl"); 1479 else 1480 emit("dcmpl"); 1481 } 1482 1483 public void caseCmpgInst(CmpgInst i) 1484 { 1485 if(i.getOpType().equals(FloatType.v())) 1486 emit("fcmpg"); 1487 else 1488 emit("dcmpg"); 1489 } 1490 1491 private void emitOpTypeInst(final String s, final OpTypeArgInst i) 1492 { 1493 i.getOpType().apply(new TypeSwitch() 1494 { 1495 private void handleIntCase() 1496 { 1497 emit("i"+s); 1498 } 1499 1500 public void caseIntType(IntType t) { handleIntCase(); } 1501 public void caseBooleanType(BooleanType t) { handleIntCase(); } 1502 public void caseShortType(ShortType t) { handleIntCase(); } 1503 public void caseCharType(CharType t) { handleIntCase(); } 1504 public void caseByteType(ByteType t) { handleIntCase(); } 1505 1506 public void caseLongType(LongType t) 1507 { 1508 emit("l"+s); 1509 } 1510 1511 public void caseDoubleType(DoubleType t) 1512 { 1513 emit("d"+s); 1514 } 1515 1516 public void caseFloatType(FloatType t) 1517 { 1518 emit("f"+s); 1519 } 1520 1521 public void defaultCase(Type t) 1522 { 1523 throw new RuntimeException ("Invalid argument type for div"); 1524 } 1525 }); 1526 } 1527 1528 public void caseAddInst(AddInst i) 1529 { 1530 emitOpTypeInst("add", i); 1531 } 1532 1533 public void caseDivInst(DivInst i) 1534 { 1535 emitOpTypeInst("div", i); 1536 } 1537 1538 public void caseSubInst(SubInst i) 1539 { 1540 emitOpTypeInst("sub", i); 1541 } 1542 1543 public void caseMulInst(MulInst i) 1544 { 1545 emitOpTypeInst("mul", i); 1546 } 1547 1548 public void caseRemInst(RemInst i) 1549 { 1550 emitOpTypeInst("rem", i); 1551 } 1552 1553 public void caseShlInst(ShlInst i) 1554 { 1555 emitOpTypeInst("shl", i); 1556 } 1557 1558 public void caseAndInst(AndInst i) 1559 { 1560 emitOpTypeInst("and", i); 1561 } 1562 1563 public void caseOrInst(OrInst i) 1564 { 1565 emitOpTypeInst("or", i); 1566 } 1567 1568 public void caseXorInst(XorInst i) 1569 { 1570 emitOpTypeInst("xor", i); 1571 } 1572 1573 public void caseShrInst(ShrInst i) 1574 { 1575 emitOpTypeInst("shr", i); 1576 } 1577 1578 public void caseUshrInst(UshrInst i) 1579 { 1580 emitOpTypeInst("ushr", i); 1581 } 1582 1583 public void caseIncInst(IncInst i) 1584 { 1585 if(((ValueBox) i.getUseBoxes().get(0)).getValue() != ((ValueBox) i.getDefBoxes().get(0)).getValue()) 1586 throw new RuntimeException ("iinc def and use boxes don't match"); 1587 1588 emit("iinc " + ((Integer ) localToSlot.get(i.getLocal())) + " " + i.getConstant()); 1589 } 1590 1591 public void caseArrayLengthInst(ArrayLengthInst i) 1592 { 1593 emit("arraylength"); 1594 } 1595 1596 public void caseNegInst(NegInst i) 1597 { 1598 emitOpTypeInst("neg", i); 1599 } 1600 1601 public void caseNewArrayInst(NewArrayInst i) 1602 { 1603 if(i.getBaseType() instanceof RefType) 1604 emit("anewarray " + slashify(i.getBaseType().toString())); 1605 else if(i.getBaseType() instanceof ArrayType) 1606 emit("anewarray " + jasminDescriptorOf(i.getBaseType())); 1607 else 1608 emit("newarray " + i.getBaseType().toString()); 1609 } 1610 1611 public void caseNewMultiArrayInst(NewMultiArrayInst i) 1612 { 1613 emit("multianewarray " + jasminDescriptorOf(i.getBaseType()) + " " + 1614 i.getDimensionCount()); 1615 } 1616 1617 public void caseLookupSwitchInst(LookupSwitchInst i) 1618 { 1619 emit("lookupswitch"); 1620 1621 List lookupValues = i.getLookupValues(); 1622 List targets = i.getTargets(); 1623 1624 for(int j = 0; j < lookupValues.size(); j++) 1625 emit(" " + lookupValues.get(j) + " : " + 1626 unitToLabel.get(targets.get(j))); 1627 1628 emit(" default : " + unitToLabel.get(i.getDefaultTarget())); 1629 } 1630 1631 public void caseTableSwitchInst(TableSwitchInst i) 1632 { 1633 emit("tableswitch " + i.getLowIndex() + " ; high = " + i.getHighIndex()); 1634 1635 List targets = i.getTargets(); 1636 1637 for(int j = 0; j < targets.size(); j++) 1638 emit(" " + unitToLabel.get(targets.get(j))); 1639 1640 emit("default : " + unitToLabel.get(i.getDefaultTarget())); 1641 } 1642 1643 private boolean isDwordType(Type t) 1644 { 1645 return t instanceof LongType || t instanceof DoubleType 1646 || t instanceof DoubleWordType; 1647 } 1648 1649 public void caseDup1Inst(Dup1Inst i) 1650 { 1651 Type firstOpType = i.getOp1Type(); 1652 if (isDwordType(firstOpType)) 1653 emit("dup2"); else 1655 emit("dup"); 1656 } 1657 1658 public void caseDup2Inst(Dup2Inst i) 1659 { 1660 Type firstOpType = i.getOp1Type(); 1661 Type secondOpType = i.getOp2Type(); 1662 if(isDwordType(firstOpType)) { 1665 emit("dup2"); if(isDwordType(secondOpType)) { 1667 emit("dup2"); } else 1669 emit("dup"); } else if(isDwordType(secondOpType)) { 1671 if(isDwordType(firstOpType)) { 1672 emit("dup2"); } else 1674 emit("dup"); 1675 emit("dup2"); } else { 1677 G.v().out.println("3000:(JasminClass): dup2 created"); 1679 emit("dup2"); } 1682 } 1683 1684 public void caseDup1_x1Inst(Dup1_x1Inst i) 1685 { 1686 Type opType = i.getOp1Type(); 1687 Type underType = i.getUnder1Type(); 1688 1689 if(isDwordType(opType)) { 1690 if(isDwordType(underType)) { 1691 emit("dup2_x2"); } else 1693 emit("dup2_x1"); } else { 1695 if(isDwordType(underType)) 1696 emit("dup_x2"); else 1698 emit("dup_x1"); } 1700 } 1701 1702 public void caseDup1_x2Inst(Dup1_x2Inst i) 1703 { 1704 Type opType = i.getOp1Type(); 1705 Type under1Type = i.getUnder1Type(); 1706 Type under2Type = i.getUnder2Type(); 1707 1708 if (isDwordType(opType)) { 1709 if (!isDwordType(under1Type) && !isDwordType(under2Type)) 1710 emit("dup2_x2"); else 1712 throw new RuntimeException ("magic not implemented yet"); 1713 } else { 1714 if (isDwordType(under1Type) || isDwordType(under2Type)) 1715 throw new RuntimeException ("magic not implemented yet"); 1716 } 1717 1718 emit("dup_x2"); } 1720 1721 public void caseDup2_x1Inst(Dup2_x1Inst i) 1722 { 1723 Type op1Type = i.getOp1Type(); 1724 Type op2Type = i.getOp2Type(); 1725 Type under1Type = i.getUnder1Type(); 1726 1727 if (isDwordType(under1Type)) { 1728 if (!isDwordType(op1Type) && !isDwordType(op2Type)) 1729 throw new RuntimeException ("magic not implemented yet"); 1730 else 1731 emit("dup2_x2"); } else { 1733 if (isDwordType(op1Type) || isDwordType(op2Type)) 1734 throw new RuntimeException ("magic not implemented yet"); 1735 } 1736 1737 emit("dup2_x1"); } 1739 1740 1741 1742 public void caseDup2_x2Inst(Dup2_x2Inst i) 1743 { 1744 Type op1Type = i.getOp1Type(); 1745 Type op2Type = i.getOp2Type(); 1746 Type under1Type = i.getUnder1Type(); 1747 Type under2Type = i.getUnder2Type(); 1748 1749 if (isDwordType(op1Type) || isDwordType(op2Type) || 1750 isDwordType(under1Type) || isDwordType(under1Type)) 1751 throw new RuntimeException ("magic not implemented yet"); 1752 1753 emit("dup2_x2"); } 1755 1756 public void caseSwapInst(SwapInst i) 1757 { 1758 emit("swap"); 1759 } 1760 1761 1762 1763 }); 1764 } 1765 1766 1767 1768 1769 private void calculateStackHeight(Block aBlock) 1770 { 1771 Iterator it = aBlock.iterator(); 1772 int blockHeight = ((Integer )blockToStackHeight.get(aBlock)).intValue(); 1773 if( blockHeight > maxStackHeight) { 1774 maxStackHeight = blockHeight; 1775 } 1776 1777 while(it.hasNext()) { 1778 Inst nInst = (Inst) it.next(); 1779 1780 blockHeight -= nInst.getInMachineCount(); 1781 1782 if(blockHeight < 0 ){ 1783 throw new RuntimeException ("Negative Stack height has been attained: \n" + 1784 "StackHeight: " + blockHeight + "\n" + 1785 "At instruction:" + nInst + "\n" + 1786 "Block:\n" + aBlock + 1787 "\n\nMethod: " + aBlock.getBody().getMethod().getName() 1788 + "\n" + aBlock.getBody().getMethod() 1789 ); 1790 } 1791 1792 blockHeight += nInst.getOutMachineCount(); 1793 if( blockHeight > maxStackHeight) { 1794 maxStackHeight = blockHeight; 1795 } 1796 } 1798 1799 1800 Iterator succs = aBlock.getSuccs().iterator(); 1801 while(succs.hasNext()) { 1802 Block b = (Block) succs.next(); 1803 Integer i = (Integer ) blockToStackHeight.get(b); 1804 if(i != null) { 1805 if(i.intValue() != blockHeight) { 1806 throw new RuntimeException ("incoherent stack height at block merge point " + b + aBlock + "\ncomputed blockHeight == " + blockHeight + " recorded blockHeight = " + i.intValue()); 1807 } 1808 1809 } else { 1810 blockToStackHeight.put(b, new Integer (blockHeight)); 1811 calculateStackHeight(b); 1812 } 1813 } 1814 } 1815 1816 1817 private void calculateLogicalStackHeightCheck(Block aBlock) 1818 { 1819 Iterator it = aBlock.iterator(); 1820 int blockHeight = ((Integer )blockToLogicalStackHeight.get(aBlock)).intValue(); 1821 1822 while(it.hasNext()) { 1823 Inst nInst = (Inst) it.next(); 1824 1825 blockHeight -= nInst.getInCount(); 1826 1827 if(blockHeight < 0 ){ 1828 throw new RuntimeException ("Negative Stack Logical height has been attained: \n" + 1829 "StackHeight: " + blockHeight + 1830 "\nAt instruction:" + nInst + 1831 "\nBlock:\n" + aBlock + 1832 "\n\nMethod: " + aBlock.getBody().getMethod().getName() 1833 + "\n" + aBlock.getBody().getMethod() 1834 ); 1835 } 1836 1837 blockHeight += nInst.getOutCount(); 1838 1839 } 1841 1842 1843 Iterator succs = aBlock.getSuccs().iterator(); 1844 while(succs.hasNext()) { 1845 Block b = (Block) succs.next(); 1846 Integer i = (Integer ) blockToLogicalStackHeight.get(b); 1847 if(i != null) { 1848 if(i.intValue() != blockHeight) { 1849 throw new RuntimeException ("incoherent logical stack height at block merge point " + b + aBlock); 1850 } 1851 1852 } else { 1853 blockToLogicalStackHeight.put(b, new Integer (blockHeight)); 1854 calculateLogicalStackHeightCheck(b); 1855 } 1856 } 1857 } 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868} 1869 1870class GroupIntPair 1871{ 1872 Object group; 1873 int x; 1874 1875 GroupIntPair(Object group, int x) 1876 { 1877 this.group = group; 1878 this.x = x; 1879 } 1880 1881 public boolean equals(Object other) 1882 { 1883 if(other instanceof GroupIntPair) 1884 return ((GroupIntPair) other).group.equals(this.group) && 1885 ((GroupIntPair) other).x == this.x; 1886 else 1887 return false; 1888 } 1889 1890 public int hashCode() 1891 { 1892 return group.hashCode() + 1013 * x; 1893 } 1894 1895 1896} 1897 | Popular Tags |