1 20 21 package edu.umd.cs.findbugs; 22 23 import java.util.ArrayList ; 24 import java.util.BitSet ; 25 import java.util.HashMap ; 26 import java.util.List ; 27 import java.util.Map ; 28 import java.util.Stack ; 29 30 import org.apache.bcel.Repository; 31 import org.apache.bcel.classfile.Code; 32 import org.apache.bcel.classfile.CodeException; 33 import org.apache.bcel.classfile.Constant; 34 import org.apache.bcel.classfile.ConstantClass; 35 import org.apache.bcel.classfile.ConstantDouble; 36 import org.apache.bcel.classfile.ConstantFloat; 37 import org.apache.bcel.classfile.ConstantInteger; 38 import org.apache.bcel.classfile.ConstantLong; 39 import org.apache.bcel.classfile.ConstantString; 40 import org.apache.bcel.classfile.ConstantUtf8; 41 import org.apache.bcel.classfile.JavaClass; 42 import org.apache.bcel.classfile.LocalVariable; 43 import org.apache.bcel.classfile.LocalVariableTable; 44 import org.apache.bcel.classfile.Method; 45 import org.apache.bcel.generic.BasicType; 46 import org.apache.bcel.generic.Type; 47 48 import edu.umd.cs.findbugs.ba.AnalysisContext; 49 import edu.umd.cs.findbugs.ba.AnalysisFeatures; 50 import edu.umd.cs.findbugs.ba.XFactory; 51 import edu.umd.cs.findbugs.ba.XField; 52 import edu.umd.cs.findbugs.visitclass.Constants2; 53 import edu.umd.cs.findbugs.visitclass.DismantleBytecode; 54 import edu.umd.cs.findbugs.visitclass.LVTHelper; 55 import edu.umd.cs.findbugs.visitclass.PreorderVisitor; 56 57 73 public class OpcodeStack implements Constants2 74 { 75 private static final boolean DEBUG 76 = SystemProperties.getBoolean("ocstack.debug"); 77 private List <Item> stack; 78 private List <Item> lvValues; 79 private List <Integer > lastUpdate; 80 81 82 83 private boolean seenTransferOfControl = false; 84 85 private boolean useIterativeAnalysis 86 = AnalysisContext.currentAnalysisContext().getBoolProperty(AnalysisFeatures.INTERATIVE_OPCODE_STACK_ANALYSIS); 87 88 89 public static class Item 90 { 91 public static final int SIGNED_BYTE = 1; 92 public static final int RANDOM_INT = 2; 93 public static final int LOW_8_BITS_CLEAR = 3; 94 public static final int HASHCODE_INT = 4; 95 public static final int INTEGER_SUM = 5; 96 public static final int AVERAGE_COMPUTED_USING_DIVISION = 6; 97 public static final int FLOAT_MATH = 7; 98 public static final int RANDOM_INT_REMAINDER = 8; 99 public static final int HASHCODE_INT_REMAINDER = 9; 100 public static final int FILE_SEPARATOR_STRING = 10; 101 102 private static final int IS_INITIAL_PARAMETER_FLAG=1; 103 private static final int COULD_BE_ZERO_FLAG = 2; 104 private static final int IS_NULL_FLAG = 4; 105 106 public static final Object UNKNOWN = null; 107 private int specialKind; 108 private String signature; 109 private Object constValue = UNKNOWN; 110 private XField xfield; 111 private int flags; 112 private int registerNumber = -1; 114 private Object userValue = null; 117 private int fieldLoadedFromRegister = -1; 118 119 120 public int getSize() { 121 if (signature.equals("J") || signature.equals("D")) return 2; 122 return 1; 123 } 124 125 private static boolean equals(Object o1, Object o2) { 126 if (o1 == o2) return true; 127 if (o1 == null || o2 == null) return false; 128 return o1.equals(o2); 129 } 130 131 @Override 132 public int hashCode() { 133 int r = 42 + specialKind; 134 if (signature != null) 135 r+= signature.hashCode(); 136 r *= 31; 137 if (constValue != null) 138 r+= constValue.hashCode(); 139 r *= 31; 140 if (xfield != null) 141 r+= xfield.hashCode(); 142 r *= 31; 143 r += flags; 144 r *= 31; 145 r += registerNumber; 146 return r; 147 148 } 149 @Override 150 public boolean equals(Object o) { 151 if (!(o instanceof Item)) return false; 152 Item that = (Item) o; 153 154 return equals(this.signature, that.signature) 155 && equals(this.constValue, that.constValue) 156 && equals(this.xfield, that.xfield) 157 && this.specialKind == that.specialKind 158 && this.registerNumber == that.registerNumber 159 && this.flags == that.flags 160 && this.userValue == that.userValue 161 && this.fieldLoadedFromRegister == that.fieldLoadedFromRegister; 162 163 } 164 165 @Override 166 public String toString() { 167 StringBuffer buf = new StringBuffer ("< "); 168 buf.append(signature); 169 switch(specialKind) { 170 case SIGNED_BYTE: 171 buf.append(", byte_array_load"); 172 break; 173 case RANDOM_INT: 174 buf.append(", random_int"); 175 break; 176 case LOW_8_BITS_CLEAR: 177 buf.append(", low8clear"); 178 break; 179 case HASHCODE_INT: 180 buf.append(", hashcode_int"); 181 break; 182 case INTEGER_SUM: 183 buf.append(", int_sum"); 184 break; 185 case AVERAGE_COMPUTED_USING_DIVISION: 186 buf.append(", averageComputingUsingDivision"); 187 break; 188 case FLOAT_MATH: 189 buf.append(", floatMath"); 190 break; 191 case HASHCODE_INT_REMAINDER: 192 buf.append(", hashcode_int_rem"); 193 break; 194 case RANDOM_INT_REMAINDER: 195 buf.append(", random_int_rem"); 196 break; 197 case FILE_SEPARATOR_STRING: 198 buf.append(", file_separator_string"); 199 break; 200 case 0 : 201 break; 202 default: 203 buf.append(", #" + specialKind); 204 break; 205 206 } 207 if (constValue != UNKNOWN) { 208 buf.append(", "); 209 buf.append(constValue); 210 } 211 if (xfield!= UNKNOWN) { 212 buf.append(", "); 213 if (fieldLoadedFromRegister != -1) 214 buf.append(fieldLoadedFromRegister).append(':'); 215 buf.append(xfield); 216 } 217 if (isInitialParameter()) { 218 buf.append(", IP"); 219 } 220 if (isNull()) { 221 buf.append(", isNull"); 222 } 223 224 if (registerNumber != -1) { 225 buf.append(", r"); 226 buf.append(registerNumber); 227 } 228 if (isCouldBeZero()) buf.append(", cbz"); 229 buf.append(" >"); 230 return buf.toString(); 231 } 232 233 234 public static Item merge(Item i1, Item i2) { 235 if (i1 == null) return i2; 236 if (i2 == null) return i1; 237 if (i1.equals(i2)) return i1; 238 Item m = new Item(); 239 m.flags = i1.flags & i2.flags; 240 m.setCouldBeZero(i1.isCouldBeZero() || i2.isCouldBeZero()); 241 if (equals(i1.signature,i2.signature)) 242 m.signature = i1.signature; 243 if (equals(i1.constValue,i2.constValue)) 244 m.constValue = i1.constValue; 245 if (equals(i1.xfield,i2.xfield)) { 246 m.xfield = i1.xfield; 247 } 248 if (i1.registerNumber == i2.registerNumber) 249 m.registerNumber = i1.registerNumber; 250 if (i1.fieldLoadedFromRegister == i2.fieldLoadedFromRegister) 251 m.fieldLoadedFromRegister = i1.fieldLoadedFromRegister; 252 253 if (i1.specialKind == i2.specialKind) 254 m.specialKind = i1.specialKind; 255 else if (i1.specialKind == FLOAT_MATH || i2.specialKind == FLOAT_MATH) 256 m.specialKind = FLOAT_MATH; 257 if (DEBUG) System.out.println("Merge " + i1 + " and " + i2 + " gives " + m); 258 return m; 259 } 260 public Item(String signature, int constValue) { 261 this(signature, (Object )(Integer )constValue); 262 } 263 264 public Item(String signature) { 265 this(signature, UNKNOWN); 266 } 267 public Item(Item it) { 268 this.signature = it.signature; 269 this.constValue = it.constValue; 270 this.xfield = it.xfield; 271 this.registerNumber = it.registerNumber; 272 this.userValue = it.userValue; 273 this.flags = it.flags; 274 this.specialKind = it.specialKind; 275 } 276 public Item(Item it, int reg) { 277 this(it); 278 this.registerNumber = reg; 279 } 280 public Item(String signature, FieldAnnotation f) { 281 this.signature = signature; 282 if (f != null) 283 xfield = XFactory.createXField(f); 284 fieldLoadedFromRegister = -1; 285 } 286 public Item(String signature, FieldAnnotation f, int fieldLoadedFromRegister) { 287 this.signature = signature; 288 if (f != null) 289 xfield = XFactory.createXField(f); 290 this.fieldLoadedFromRegister = fieldLoadedFromRegister; 291 } 292 293 public int getFieldLoadedFromRegister() { 294 return fieldLoadedFromRegister; 295 } 296 297 public Item(String signature, Object constantValue) { 298 this.signature = signature; 299 constValue = constantValue; 300 if (constantValue instanceof Integer ) { 301 int value = (Integer ) constantValue; 302 if (value != 0 && (value & 0xff) == 0) 303 specialKind = LOW_8_BITS_CLEAR; 304 if (value == 0) setCouldBeZero(true); 305 306 } 307 else if (constantValue instanceof Long ) { 308 long value = (Long ) constantValue; 309 if (value != 0 && (value & 0xff) == 0) 310 specialKind = LOW_8_BITS_CLEAR; 311 if (value == 0) setCouldBeZero(true); 312 } 313 314 } 315 316 public Item() { 317 signature = "Ljava/lang/Object;"; 318 constValue = null; 319 setNull(true); 320 } 321 322 public JavaClass getJavaClass() throws ClassNotFoundException { 323 String baseSig; 324 325 if (isPrimitive()) 326 return null; 327 328 if (isArray()) { 329 baseSig = getElementSignature(); 330 } else { 331 baseSig = signature; 332 } 333 334 if (baseSig.length() == 0) 335 return null; 336 baseSig = baseSig.substring(1, baseSig.length() - 1); 337 baseSig = baseSig.replace('/', '.'); 338 return Repository.lookupClass(baseSig); 339 } 340 341 public boolean isArray() { 342 return signature.startsWith("["); 343 } 344 345 public String getElementSignature() { 346 if (!isArray()) 347 return signature; 348 else { 349 int pos = 0; 350 int len = signature.length(); 351 while (pos < len) { 352 if (signature.charAt(pos) != '[') 353 break; 354 pos++; 355 } 356 return signature.substring(pos); 357 } 358 } 359 360 public boolean isPrimitive() { 361 return !signature.startsWith("L"); 362 } 363 364 public int getRegisterNumber() { 365 return registerNumber; 366 } 367 public String getSignature() { 368 return signature; 369 } 370 371 public Object getConstant() { 372 return constValue; 373 } 374 375 376 @Deprecated 377 public FieldAnnotation getFieldAnnotation() { 378 return FieldAnnotation.fromXField(xfield); 379 } 380 public XField getXField() { 381 return xfield; 382 } 383 386 public void setSpecialKind(int specialKind) { 387 this.specialKind = specialKind; 388 } 389 390 393 public int getSpecialKind() { 394 return specialKind; 395 } 396 397 402 public void setUserValue(Object value) { 403 userValue = value; 404 } 405 406 public boolean couldBeZero() { 407 return isCouldBeZero(); 408 } 409 public boolean mustBeZero() { 410 Object value = getConstant(); 411 return value instanceof Number && ((Number )value).intValue() == 0; 412 } 413 418 public Object getUserValue() { 419 return userValue; 420 } 421 422 public boolean valueCouldBeNegative() { 423 return (getSpecialKind() == Item.RANDOM_INT 424 || getSpecialKind() == Item.SIGNED_BYTE 425 || getSpecialKind() == Item.HASHCODE_INT 426 || getSpecialKind() == Item.RANDOM_INT_REMAINDER || getSpecialKind() == Item.HASHCODE_INT_REMAINDER); 427 428 } 429 430 433 private void setInitialParameter(boolean isInitialParameter) { 434 setFlag(isInitialParameter, IS_INITIAL_PARAMETER_FLAG); 435 } 436 437 440 public boolean isInitialParameter() { 441 return (flags & IS_INITIAL_PARAMETER_FLAG) != 0; 442 } 443 444 447 private void setCouldBeZero(boolean couldBeZero) { 448 setFlag(couldBeZero, COULD_BE_ZERO_FLAG); 449 } 450 451 454 private boolean isCouldBeZero() { 455 return (flags & COULD_BE_ZERO_FLAG) != 0; 456 } 457 458 461 private void setNull(boolean isNull) { 462 setFlag(isNull, IS_NULL_FLAG); 463 } 464 465 private void setFlag(boolean value, int flagBit) { 466 if (value) 467 flags |= flagBit; 468 else 469 flags &= ~flagBit; 470 } 471 474 public boolean isNull() { 475 return (flags & IS_NULL_FLAG) != 0; 476 } 477 } 478 479 @Override 480 public String toString() { 481 return stack.toString() + "::" + lvValues.toString(); 482 } 483 484 public OpcodeStack() 485 { 486 stack = new ArrayList <Item>(); 487 lvValues = new ArrayList <Item>(); 488 lastUpdate = new ArrayList <Integer >(); 489 } 490 491 boolean needToMerge = true; 492 boolean reachOnlyByBranch = false; 493 public static String getExceptionSig(DismantleBytecode dbc, CodeException e) { 494 if (e.getCatchType() == 0) return "Ljava/lang/Throwable;"; 495 Constant c = dbc.getConstantPool().getConstant(e.getCatchType()); 496 if (c instanceof ConstantClass) 497 return "L"+((ConstantClass)c).getBytes(dbc.getConstantPool())+";"; 498 return "Ljava/lang/Throwable;"; 499 } 500 public void mergeJumps(DismantleBytecode dbc) { 501 502 if (!needToMerge) return; 503 needToMerge = false; 504 boolean stackUpdated = false; 505 if (convertJumpToOneZeroState == 3 || convertJumpToZeroOneState == 3) { 506 pop(); 507 Item top = new Item("I"); 508 top.setCouldBeZero(true); 509 push(top); 510 convertJumpToOneZeroState = convertJumpToZeroOneState = 0; 511 stackUpdated = true; 512 } 513 514 515 List <Item> jumpEntry = jumpEntries.get(dbc.getPC()); 516 if (jumpEntry != null) { 517 if (DEBUG) { 518 System.out.println("XXXXXXX " + reachOnlyByBranch); 519 System.out.println("merging lvValues at jump target " + dbc.getPC() + " -> " + Integer.toString(System.identityHashCode(jumpEntry),16) + " " + jumpEntry); 520 System.out.println(" current lvValues " + lvValues); 521 } 522 List <Item> jumpStackEntry = jumpStackEntries.get(dbc.getPC()); 523 if (reachOnlyByBranch) { 524 lvValues = new ArrayList <Item>(jumpEntry); 525 if (!stackUpdated) { 526 if (jumpStackEntry != null) stack = new ArrayList <Item>(jumpStackEntry); 527 else stack.clear(); 528 } 529 530 } 531 else { 532 mergeLists(lvValues, jumpEntry, false); 533 if (!stackUpdated && jumpStackEntry != null) mergeLists(stack, jumpStackEntry, false); 534 } 535 if (DEBUG) 536 System.out.println(" merged lvValues " + lvValues); 537 } 538 else if (reachOnlyByBranch && !stackUpdated) { 539 stack.clear(); 540 541 boolean foundException = false; 542 for(CodeException e : dbc.getCode().getExceptionTable()) { 543 if (e.getHandlerPC() == dbc.getPC()) { 544 push(new Item(getExceptionSig(dbc, e))); 545 foundException = true; 546 } 547 } 548 if (!foundException) 549 push(new Item("Ljava/lang/Throwable;")); 550 } 551 reachOnlyByBranch = false; 552 } 553 554 int convertJumpToOneZeroState = 0; 555 int convertJumpToZeroOneState = 0; 556 557 private void setLastUpdate(int reg, int pc) { 558 while (lastUpdate.size() <= reg) lastUpdate.add(0); 559 lastUpdate.set(reg, pc); 560 } 561 562 public int getLastUpdate(int reg) { 563 if (lastUpdate.size() <= reg) return 0; 564 return lastUpdate.get(reg); 565 } 566 567 public int getNumLastUpdates() { 568 return lastUpdate.size(); 569 } 570 public void sawOpcode(DismantleBytecode dbc, int seen) { 571 int register; 572 String signature; 573 Item it, it2, it3; 574 Constant cons; 575 if (dbc.isRegisterStore()) 576 setLastUpdate(dbc.getRegisterOperand(), dbc.getPC()); 577 mergeJumps(dbc); 578 needToMerge = true; 579 switch (seen) { 580 case ICONST_1: 581 convertJumpToOneZeroState = 1; 582 break; 583 case GOTO: 584 if (convertJumpToOneZeroState == 1 && dbc.getBranchOffset() == 4) 585 convertJumpToOneZeroState = 2; 586 else 587 convertJumpToOneZeroState = 0; 588 break; 589 case ICONST_0: 590 if (convertJumpToOneZeroState == 2) 591 convertJumpToOneZeroState = 3; 592 else convertJumpToOneZeroState = 0; 593 break; 594 default:convertJumpToOneZeroState = 0; 595 596 } 597 switch (seen) { 598 case ICONST_0: 599 convertJumpToZeroOneState = 1; 600 break; 601 case GOTO: 602 if (convertJumpToZeroOneState == 1 && dbc.getBranchOffset() == 4) 603 convertJumpToZeroOneState = 2; 604 else 605 convertJumpToZeroOneState = 0; 606 break; 607 case ICONST_1: 608 if (convertJumpToZeroOneState == 2) 609 convertJumpToZeroOneState = 3; 610 else convertJumpToZeroOneState = 0; 611 break; 612 default:convertJumpToZeroOneState = 0; 613 } 614 615 try 616 { 617 switch (seen) { 618 case ALOAD: 619 pushByLocalObjectLoad(dbc, dbc.getRegisterOperand()); 620 break; 621 622 case ALOAD_0: 623 case ALOAD_1: 624 case ALOAD_2: 625 case ALOAD_3: 626 pushByLocalObjectLoad(dbc, seen - ALOAD_0); 627 break; 628 629 case DLOAD: 630 pushByLocalLoad("D", dbc.getRegisterOperand()); 631 break; 632 633 case DLOAD_0: 634 case DLOAD_1: 635 case DLOAD_2: 636 case DLOAD_3: 637 pushByLocalLoad("D", seen - DLOAD_0); 638 break; 639 640 case FLOAD: 641 pushByLocalLoad("F", dbc.getRegisterOperand()); 642 break; 643 644 case FLOAD_0: 645 case FLOAD_1: 646 case FLOAD_2: 647 case FLOAD_3: 648 pushByLocalLoad("F", seen - FLOAD_0); 649 break; 650 651 case ILOAD: 652 pushByLocalLoad("I", dbc.getRegisterOperand()); 653 break; 654 655 case ILOAD_0: 656 case ILOAD_1: 657 case ILOAD_2: 658 case ILOAD_3: 659 pushByLocalLoad("I", seen - ILOAD_0); 660 break; 661 662 case LLOAD: 663 pushByLocalLoad("J", dbc.getRegisterOperand()); 664 break; 665 666 case LLOAD_0: 667 case LLOAD_1: 668 case LLOAD_2: 669 case LLOAD_3: 670 pushByLocalLoad("J", seen - LLOAD_0); 671 break; 672 673 674 case GETSTATIC: 675 { 676 FieldAnnotation field = FieldAnnotation.fromReferencedField(dbc); 677 Item i = new Item(dbc.getSigConstantOperand(), field, Integer.MAX_VALUE); 678 if (field.getFieldName().equals("separator") && field.getClassName().equals("java.io.File")) { 679 i.setSpecialKind(Item.FILE_SEPARATOR_STRING); 680 } 681 682 push(i); 683 break; 684 } 685 686 case LDC: 687 case LDC_W: 688 case LDC2_W: 689 cons = dbc.getConstantRefOperand(); 690 pushByConstant(dbc, cons); 691 break; 692 693 case INSTANCEOF: 694 pop(); 695 push(new Item("I")); 696 break; 697 case IFEQ: 698 case IFNE: 699 case IFLT: 700 case IFLE: 701 case IFGT: 702 case IFGE: 703 case IFNONNULL: 704 case IFNULL: 705 seenTransferOfControl = true; 706 { 707 Item top = pop(); 708 709 if (top.valueCouldBeNegative() 712 && (seen == IFLT || seen == IFLE || seen == IFGT || seen == IFGE)) { 713 int specialKind = top.getSpecialKind(); 714 for(Item item : stack) if (item != null && item.getSpecialKind() == specialKind) item.setSpecialKind(0); 715 for(Item item : lvValues) if (item != null && item.getSpecialKind() == specialKind) item.setSpecialKind(0); 716 717 } 718 } 719 addJumpValue(dbc.getBranchTarget()); 720 721 break; 722 case LOOKUPSWITCH: 723 724 case TABLESWITCH: 725 seenTransferOfControl = true; 726 pop(); 727 addJumpValue(dbc.getBranchTarget()); 728 int pc = dbc.getBranchTarget() - dbc.getBranchOffset(); 729 for(int offset : dbc.getSwitchOffsets()) 730 addJumpValue(offset+pc); 731 732 break; 733 case ARETURN: 734 case DRETURN: 735 case FRETURN: 736 737 case IRETURN: 738 case LRETURN: 739 740 seenTransferOfControl = true; 741 reachOnlyByBranch = true; 742 pop(); 743 break; 744 case MONITORENTER: 745 case MONITOREXIT: 746 case POP: 747 case PUTSTATIC: 748 pop(); 749 break; 750 751 case IF_ACMPEQ: 752 case IF_ACMPNE: 753 case IF_ICMPEQ: 754 case IF_ICMPNE: 755 case IF_ICMPLT: 756 case IF_ICMPLE: 757 case IF_ICMPGT: 758 case IF_ICMPGE: 759 760 seenTransferOfControl = true; 761 pop(2); 762 addJumpValue(dbc.getBranchTarget()); 763 break; 764 765 766 case POP2: 767 it = pop(); 768 if (it.getSize() == 1) pop(); 769 break; 770 case PUTFIELD: 771 pop(2); 772 break; 773 774 case IALOAD: 775 case SALOAD: 776 pop(2); 777 push(new Item("I")); 778 break; 779 780 case DUP: 781 handleDup(); 782 break; 783 784 case DUP2: 785 handleDup2(); 786 break; 787 788 case DUP_X1: 789 handleDupX1(); 790 break; 791 792 case DUP_X2: 793 794 handleDupX2(); 795 break; 796 797 case DUP2_X1: 798 handleDup2X1(); 799 break; 800 801 802 case IINC: 803 register = dbc.getRegisterOperand(); 804 it = getLVValue( register ); 805 it2 = new Item("I", dbc.getIntConstant()); 806 pushByIntMath( IADD, it2, it); 807 pushByLocalStore(register); 808 break; 809 810 case ATHROW: 811 pop(); 812 seenTransferOfControl = true; 813 reachOnlyByBranch = true; 814 break; 815 816 case CHECKCAST: 817 { 818 String castTo = dbc.getClassConstantOperand(); 819 820 if (castTo.charAt(0) != '[') castTo = "L" + castTo + ";"; 821 it = new Item(pop()); 822 it.signature = castTo; 823 push(it); 824 825 break; 826 827 828 } 829 case NOP: 830 break; 831 case RET: 832 case RETURN: 833 seenTransferOfControl = true; 834 reachOnlyByBranch = true; 835 break; 836 837 case GOTO: 838 case GOTO_W: seenTransferOfControl = true; 840 reachOnlyByBranch = true; 841 addJumpValue(dbc.getBranchTarget()); 842 stack.clear(); 843 844 break; 845 846 847 case SWAP: 848 handleSwap(); 849 break; 850 851 case ICONST_M1: 852 case ICONST_0: 853 case ICONST_1: 854 case ICONST_2: 855 case ICONST_3: 856 case ICONST_4: 857 case ICONST_5: 858 push(new Item("I", (seen-ICONST_0))); 859 break; 860 861 case LCONST_0: 862 case LCONST_1: 863 push(new Item("J", (long)(seen-LCONST_0))); 864 break; 865 866 case DCONST_0: 867 case DCONST_1: 868 push(new Item("D", (double)(seen-DCONST_0))); 869 break; 870 871 case FCONST_0: 872 case FCONST_1: 873 case FCONST_2: 874 push(new Item("F", (float)(seen-FCONST_0))); 875 break; 876 877 case ACONST_NULL: 878 push(new Item()); 879 break; 880 881 case ASTORE: 882 case DSTORE: 883 case FSTORE: 884 case ISTORE: 885 case LSTORE: 886 pushByLocalStore(dbc.getRegisterOperand()); 887 break; 888 889 case ASTORE_0: 890 case ASTORE_1: 891 case ASTORE_2: 892 case ASTORE_3: 893 pushByLocalStore(seen - ASTORE_0); 894 break; 895 896 case DSTORE_0: 897 case DSTORE_1: 898 case DSTORE_2: 899 case DSTORE_3: 900 pushByLocalStore(seen - DSTORE_0); 901 break; 902 903 904 case FSTORE_0: 905 case FSTORE_1: 906 case FSTORE_2: 907 case FSTORE_3: 908 pushByLocalStore(seen - FSTORE_0); 909 break; 910 911 case ISTORE_0: 912 case ISTORE_1: 913 case ISTORE_2: 914 case ISTORE_3: 915 pushByLocalStore(seen - ISTORE_0); 916 break; 917 918 case LSTORE_0: 919 case LSTORE_1: 920 case LSTORE_2: 921 case LSTORE_3: 922 pushByLocalStore(seen - LSTORE_0); 923 break; 924 925 case GETFIELD: 926 { 927 Item item = pop(); 928 int reg = item.getRegisterNumber(); 929 push(new Item(dbc.getSigConstantOperand(), 930 FieldAnnotation.fromReferencedField(dbc), reg)); 931 } 932 break; 933 934 case ARRAYLENGTH: 935 pop(); 936 push(new Item("I")); 937 break; 938 939 case BALOAD: 940 { 941 pop(2); 942 Item v = new Item("I"); 943 v.setSpecialKind(Item.SIGNED_BYTE); 944 push(v); 945 break; 946 } 947 case CALOAD: 948 pop(2); 949 push(new Item("I")); 950 break; 951 952 case DALOAD: 953 pop(2); 954 push(new Item("D")); 955 break; 956 957 case FALOAD: 958 pop(2); 959 push(new Item("F")); 960 break; 961 962 case LALOAD: 963 pop(2); 964 push(new Item("J")); 965 break; 966 967 case AASTORE: 968 case BASTORE: 969 case CASTORE: 970 case DASTORE: 971 case FASTORE: 972 case IASTORE: 973 case LASTORE: 974 case SASTORE: 975 pop(3); 976 break; 977 978 case BIPUSH: 979 case SIPUSH: 980 push(new Item("I", (Integer )dbc.getIntConstant())); 981 break; 982 983 case IADD: 984 case ISUB: 985 case IMUL: 986 case IDIV: 987 case IAND: 988 case IOR: 989 case IXOR: 990 case ISHL: 991 case ISHR: 992 case IREM: 993 case IUSHR: 994 it = pop(); 995 it2 = pop(); 996 pushByIntMath(seen, it2, it); 997 break; 998 999 case INEG: 1000 it = pop(); 1001 if (it.getConstant() != null) { 1002 push(new Item("I", ( Integer )(-(Integer ) it.getConstant()))); 1003 } else { 1004 push(new Item("I")); 1005 } 1006 break; 1007 1008 case LNEG: 1009 it = pop(); 1010 if (it.getConstant() != null) { 1011 push(new Item("J", ( Long )(-(Long ) it.getConstant()))); 1012 } else { 1013 push(new Item("J")); 1014 } 1015 break; 1016 1017 case DNEG: 1018 it = pop(); 1019 if (it.getConstant() != null) { 1020 push(new Item("D", ( Double )(-(Double ) it.getConstant()))); 1021 } else { 1022 push(new Item("D")); 1023 } 1024 break; 1025 1026 case LADD: 1027 case LSUB: 1028 case LMUL: 1029 case LDIV: 1030 case LAND: 1031 case LOR: 1032 case LXOR: 1033 case LSHL: 1034 case LSHR: 1035 case LREM: 1036 case LUSHR: 1037 1038 it = pop(); 1039 it2 = pop(); 1040 pushByLongMath(seen, it2, it); 1041 break; 1042 1043 case LCMP: 1044 handleLcmp(); 1045 break; 1046 1047 case FCMPG: 1048 case FCMPL: handleFcmp(seen); 1049 break; 1050 1051 case DCMPG: 1052 case DCMPL: 1053 handleDcmp(seen); 1054 break; 1055 1056 case FADD: 1057 case FSUB: 1058 case FMUL: 1059 case FDIV: 1060 it = pop(); 1061 it2 = pop(); 1062 pushByFloatMath(seen, it, it2); 1063 break; 1064 1065 case DADD: 1066 case DSUB: 1067 case DMUL: 1068 case DDIV: 1069 case DREM: 1070 it = pop(); 1071 it2 = pop(); 1072 pushByDoubleMath(seen, it, it2); 1073 break; 1074 1075 case I2B: 1076 it = pop(); 1077 if (it.getConstant() != null) { 1078 it =new Item("I", (byte)constantToInt(it)); 1079 } else { 1080 it = new Item("I"); 1081 } 1082 it.setSpecialKind(Item.SIGNED_BYTE); 1083 push(it); 1084 break; 1085 1086 case I2C: 1087 it = pop(); 1088 if (it.getConstant() != null) { 1089 push(new Item("I", (char)constantToInt(it))); 1090 } else { 1091 push(new Item("I")); 1092 } 1093 break; 1094 1095 case I2L: 1096 case D2L:{ 1097 it = pop(); 1098 Item newValue; 1099 if (it.getConstant() != null) { 1100 newValue = new Item("J", constantToLong(it)); 1101 } else { 1102 newValue = new Item("J"); 1103 } 1104 newValue.setSpecialKind(it.getSpecialKind()); 1105 push(newValue); 1106 } 1107 break; 1108 1109 case I2S: 1110 it = pop(); 1111 if (it.getConstant() != null) { 1112 push(new Item("I", (short)constantToInt(it))); 1113 } else { 1114 push(new Item("I")); 1115 } 1116 break; 1117 1118 case L2I: 1119 case D2I: 1120 case F2I: 1121 it = pop(); 1122 if (it.getConstant() != null) { 1123 push(new Item("I",constantToInt(it))); 1124 } else { 1125 push(new Item("I")); 1126 } 1127 break; 1128 1129 case L2F: 1130 case D2F: 1131 case I2F: 1132 it = pop(); 1133 if (it.getConstant() != null) { 1134 push(new Item("F", (Float )(constantToFloat(it)))); 1135 } else { 1136 push(new Item("F")); 1137 } 1138 break; 1139 1140 case F2D: 1141 case I2D: 1142 case L2D: 1143 it = pop(); 1144 if (it.getConstant() != null) { 1145 push(new Item("D", constantToDouble(it))); 1146 } else { 1147 push(new Item("D")); 1148 } 1149 break; 1150 1151 case NEW: 1152 pushBySignature("L" + dbc.getClassConstantOperand() + ";"); 1153 break; 1154 1155 case NEWARRAY: 1156 pop(); 1157 signature = "[" + BasicType.getType((byte)dbc.getIntConstant()).getSignature(); 1158 pushBySignature(signature); 1159 break; 1160 1161 1166 case ANEWARRAY: 1167 pop(); 1168 signature = dbc.getClassConstantOperand(); 1169 if (!signature.startsWith("[")) { 1170 signature = "[L" + signature + ";"; 1171 } 1172 pushBySignature(signature); 1173 break; 1174 1175 case MULTIANEWARRAY: 1176 int dims = dbc.getIntConstant(); 1177 while ((dims--) > 0) { 1178 pop(); 1179 } 1180 signature = dbc.getClassConstantOperand(); 1181 if (!signature.startsWith("[")) { 1182 dims = dbc.getIntConstant(); 1183 signature = ""; 1184 while ((dims--) > 0) 1185 signature += "["; 1186 signature += "L" + signature + ";"; 1187 } 1188 pushBySignature(signature); 1189 break; 1190 1191 case AALOAD: 1192 pop(); 1193 it = pop(); 1194 pushBySignature(it.getElementSignature()); 1195 break; 1196 1197 case JSR: 1198 push(new Item("")); break; 1200 1201 case INVOKEINTERFACE: 1202 case INVOKESPECIAL: 1203 case INVOKESTATIC: 1204 case INVOKEVIRTUAL: 1205 processMethodCall(dbc, seen); 1206 break; 1207 1208 default: 1209 throw new UnsupportedOperationException ("OpCode " + OPCODE_NAMES[seen] + " not supported " ); 1210 } 1211 } 1212 1213 catch (RuntimeException e) { 1214 if (DEBUG) 1219 e.printStackTrace(); 1220 clear(); 1221 } 1222 finally { 1223 if (exceptionHandlers.get(dbc.getNextPC())) 1224 push(new Item()); 1225 if (DEBUG) { 1226 System.out.println(dbc.getNextPC() + "pc : " + OPCODE_NAMES[seen] + " stack depth: " + getStackDepth()); 1227 System.out.println(this); 1228 } 1229 } 1230 } 1231 1232 1236 private int constantToInt(Item it) { 1237 return ((Number )it.getConstant()).intValue(); 1238 } 1239 1240 1244 private float constantToFloat(Item it) { 1245 return ((Number )it.getConstant()).floatValue(); 1246 } 1247 1248 1252 private double constantToDouble(Item it) { 1253 return ((Number )it.getConstant()).doubleValue(); 1254 } 1255 1256 1260 private long constantToLong(Item it) { 1261 return ((Number )it.getConstant()).longValue(); 1262 } 1263 1264 1268 private void handleDcmp(int opcode) { 1269 Item it; 1270 Item it2; 1271 1272 it = pop(); 1273 1274 it2 = pop(); 1275 if ((it.getConstant() != null) && it2.getConstant() != null) { 1276 double d = (Double ) it.getConstant(); 1277 double d2 = (Double ) it.getConstant(); 1278 if (Double.isNaN(d) || Double.isNaN(d2)) { 1279 if (opcode == DCMPG) 1280 push(new Item("I", (Integer )(1))); 1281 else 1282 push(new Item("I", (Integer )(-1))); 1283 } 1284 if (d2 < d) 1285 push(new Item("I", (Integer ) (-1) )); 1286 else if (d2 > d) 1287 push(new Item("I", (Integer )1)); 1288 else 1289 push(new Item("I", (Integer )0)); 1290 } else { 1291 push(new Item("I")); 1292 } 1293 1294 } 1295 1296 1300 private void handleFcmp(int opcode) { 1301 Item it; 1302 Item it2; 1303 it = pop(); 1304 it2 = pop(); 1305 if ((it.getConstant() != null) && it2.getConstant() != null) { 1306 float f = (Float ) it.getConstant(); 1307 float f2 = (Float ) it.getConstant(); 1308 if (Float.isNaN(f) || Float.isNaN(f2)) { 1309 if (opcode == FCMPG) 1310 push(new Item("I", (Integer )(1))); 1311 else 1312 push(new Item("I", (Integer )(-1))); 1313 } 1314 if (f2 < f) 1315 push(new Item("I", (Integer )(-1))); 1316 else if (f2 > f) 1317 push(new Item("I", (Integer )(1))); 1318 else 1319 push(new Item("I", (Integer )(0))); 1320 } else { 1321 push(new Item("I")); 1322 } 1323 } 1324 1325 1328 private void handleLcmp() { 1329 Item it; 1330 Item it2; 1331 1332 it = pop(); 1333 it2 = pop(); 1334 if ((it.getConstant() != null) && it2.getConstant() != null) { 1335 long l = (Long ) it.getConstant(); 1336 long l2 = (Long ) it.getConstant(); 1337 if (l2 < l) 1338 push(new Item("I", (Integer )(-1))); 1339 else if (l2 > l) 1340 push(new Item("I", (Integer )(1))); 1341 else 1342 push(new Item("I", (Integer )(0))); 1343 } else { 1344 push(new Item("I")); 1345 } 1346 1347 } 1348 1349 1352 private void handleSwap() { 1353 Item i1 = pop(); 1354 Item i2 = pop(); 1355 push(i1); 1356 push(i2); 1357 } 1358 1359 1362 private void handleDup() { 1363 Item it; 1364 it = pop(); 1365 push(it); 1366 push(it); 1367 } 1368 1369 1372 private void handleDupX1() { 1373 Item it; 1374 Item it2; 1375 it = pop(); 1376 it2 = pop(); 1377 push(it); 1378 push(it2); 1379 push(it); 1380 } 1381 1382 1385 private void handleDup2() { 1386 Item it, it2; 1387 it = pop(); 1388 if (it.getSize() == 2) { 1389 push(it); 1390 push(it); 1391 } 1392 else { 1393 it2 = pop(); 1394 push(it2); 1395 push(it); 1396 push(it2); 1397 push(it); 1398 } 1399 } 1400 1401 1404 private void handleDup2X1() { 1405 String signature; 1406 Item it; 1407 Item it2; 1408 Item it3; 1409 1410 it = pop(); 1411 1412 it2 = pop(); 1413 signature = it.getSignature(); 1414 if (signature.equals("J") || signature.equals("D")) { 1415 push(it); 1416 push(it2); 1417 push(it); 1418 } else { 1419 it3 = pop(); 1420 push(it2); 1421 push(it); 1422 push(it3); 1423 push(it2); 1424 push(it); 1425 } 1426 } 1427 1428 1431 private void handleDupX2() { 1432 String signature; 1433 Item it; 1434 Item it2; 1435 Item it3; 1436 it = pop(); 1437 it2 = pop(); 1438 signature = it2.getSignature(); 1439 if (signature.equals("J") || signature.equals("D")) { 1440 push(it); 1441 push(it2); 1442 push(it); 1443 } else { 1444 it3 = pop(); 1445 push(it); 1446 push(it3); 1447 push(it2); 1448 push(it); 1449 } 1450 } 1451 1452 private void processMethodCall(DismantleBytecode dbc, int seen) { 1453 String clsName = dbc.getClassConstantOperand(); 1454 String methodName = dbc.getNameConstantOperand(); 1455 String signature = dbc.getSigConstantOperand(); 1456 String appenderValue = null; 1457 Item sbItem = null; 1458 1459 if ("java/lang/StringBuffer".equals(clsName) 1461 || "java/lang/StringBuilder".equals(clsName)) { 1462 if ("<init>".equals(methodName)) { 1463 if ("(Ljava/lang/String;)V".equals(signature)) { 1464 Item i = getStackItem(0); 1465 appenderValue = (String )i.getConstant(); 1466 } else if ("()V".equals(signature)) { 1467 appenderValue = ""; 1468 } 1469 } else if ("toString".equals(methodName)) { 1470 Item i = getStackItem(0); 1471 appenderValue = (String )i.getConstant(); 1472 } else if ("append".equals(methodName) && signature.indexOf("II)") == -1) { 1473 sbItem = getStackItem(1); 1474 Item i = getStackItem(0); 1475 Object sbVal = sbItem.getConstant(); 1476 Object sVal = i.getConstant(); 1477 if ((sbVal != null) && (sVal != null)) { 1478 appenderValue = sbVal + sVal.toString(); 1479 } else if (sbItem.registerNumber >= 0) { 1480 OpcodeStack.Item item = getLVValue(sbItem.registerNumber); 1481 if (item != null) 1482 item.constValue = null; 1483 } 1484 } 1485 } 1486 1487 pushByInvoke(dbc, seen != INVOKESTATIC); 1488 1489 if (appenderValue != null) { 1490 Item i = this.getStackItem(0); 1491 i.constValue = appenderValue; 1492 if (sbItem != null) { 1493 i.registerNumber = sbItem.registerNumber; 1494 i.xfield = sbItem.xfield; 1495 i.userValue = sbItem.userValue; 1496 if (sbItem.registerNumber >= 0) 1497 setLVValue(sbItem.registerNumber, i ); 1498 } 1499 return; 1500 } 1501 1502 if ((clsName.equals("java/util/Random") || clsName.equals("java/security/SecureRandom")) && methodName.equals("nextInt") && signature.equals("()I")) { 1503 Item i = pop(); 1504 i.setSpecialKind(Item.RANDOM_INT); 1505 push(i); 1506 } 1507 else if (seen == INVOKEVIRTUAL && methodName.equals("hashCode") && signature.equals("()I") 1508 || seen == INVOKESTATIC && clsName.equals("java/lang/System") && methodName.equals("identityHashCode") && signature.equals("(Ljava/lang/Object;)I")) { 1509 Item i = pop(); 1510 i.setSpecialKind(Item.HASHCODE_INT); 1511 push(i); 1512 } 1513 1514 } 1515 1516 private void mergeLists(List <Item> mergeInto, List <Item> mergeFrom, boolean errorIfSizesDoNotMatch) { 1517 int intoSize = mergeInto.size(); 1519 int fromSize = mergeFrom.size(); 1520 if (errorIfSizesDoNotMatch && intoSize != fromSize) { 1521 if (DEBUG) { 1522 System.out.println("Bad merging items"); 1523 System.out.println("current items: " + mergeInto); 1524 System.out.println("jump items: " + mergeFrom); 1525 } 1526 } else { 1527 if (DEBUG) { 1528 System.out.println("Merging items"); 1529 System.out.println("current items: " + mergeInto); 1530 System.out.println("jump items: " + mergeFrom); 1531 } 1532 1533 for (int i = 0; i < Math.min(intoSize, fromSize); i++) 1534 mergeInto.set(i, Item.merge(mergeInto.get(i), mergeFrom.get(i))); 1535 if (DEBUG) { 1536 System.out.println("merged items: " + mergeInto); 1537 } 1538 } 1539 } 1540 1541 public void clear() { 1542 stack.clear(); 1543 lvValues.clear(); 1544 } 1545 BitSet exceptionHandlers = new BitSet (); 1546 private Map <Integer , List <Item>> jumpEntries = new HashMap <Integer , List <Item>>(); 1547 private Map <Integer , List <Item>> jumpStackEntries = new HashMap <Integer , List <Item>>(); 1548 1549 private void addJumpValue(int target) { 1550 if (DEBUG) 1551 System.out.println("Set jump entry at " + methodName + ":" + target + "pc to " + stack + " : " + lvValues ); 1552 1553 List <Item> atTarget = jumpEntries.get(target); 1554 if (atTarget == null) { 1555 if (DEBUG) 1556 System.out.println("Was null"); 1557 1558 jumpEntries.put(target, new ArrayList <Item>(lvValues)); 1559 if (false) { 1560 System.out.println("jump entires are now..."); 1561 for (Integer pc : jumpEntries.keySet()) { 1562 List <Item> list = jumpEntries.get(pc); 1563 System.out.println(pc + "pc -> " + Integer.toString(System.identityHashCode(list),16) + " " + list); 1564 }} 1565 if (stack.size() > 0) 1566 jumpStackEntries.put(target, new ArrayList <Item>(stack)); 1567 return; 1568 } 1569 mergeLists(atTarget, lvValues, false); 1570 List <Item> stackAtTarget = jumpStackEntries.get(target); 1571 if (stack.size() > 0 && stackAtTarget != null) 1572 mergeLists(stackAtTarget, stack, false); 1573 if (DEBUG) 1574 System.out.println("merge target for " + methodName + ":" + target + "pc is " + atTarget); 1575 } 1576 private String methodName; 1577 public int resetForMethodEntry(final DismantleBytecode v) { 1578 methodName = v.getMethodName(); 1579 jumpEntries.clear(); 1580 jumpStackEntries.clear(); 1581 lastUpdate.clear(); 1582 convertJumpToOneZeroState = convertJumpToZeroOneState = 0; 1583 reachOnlyByBranch = false; 1584 int result= resetForMethodEntry0(v); 1585 Code code = v.getMethod().getCode(); 1586 if (code == null) return result; 1587 1588 if (useIterativeAnalysis) { 1589 if (DEBUG) 1591 System.out.println(" --- Iterative analysis"); 1592 DismantleBytecode branchAnalysis = new DismantleBytecode() { 1593 @Override 1594 public void sawOpcode(int seen) { 1595 OpcodeStack.this.sawOpcode(this, seen); 1596 } 1597 1598 }; 1604 branchAnalysis.setupVisitorForClass(v.getThisClass()); 1605 branchAnalysis.doVisitMethod(v.getMethod()); 1606 if (!jumpEntries.isEmpty()) 1607 branchAnalysis.doVisitMethod(v.getMethod()); 1608 if (DEBUG && !jumpEntries.isEmpty()) { 1609 System.out.println("Found dataflow for jumps in " + v.getMethodName()); 1610 for (Integer pc : jumpEntries.keySet()) { 1611 List <Item> list = jumpEntries.get(pc); 1612 System.out.println(pc + " -> " + Integer.toString(System.identityHashCode(list),16) + " " + list); 1613 } 1614 } 1615 resetForMethodEntry0(v); 1616 if (DEBUG) 1617 System.out.println(" --- End of Iterative analysis"); 1618 1619 } 1620 1621 return result; 1622 1623 } 1624 1625 1626 private int resetForMethodEntry0(PreorderVisitor v) { 1627 if (DEBUG) System.out.println(" --- "); 1628 stack.clear(); 1629 lvValues.clear(); 1630 reachOnlyByBranch = false; 1631 seenTransferOfControl = false; 1632 String className = v.getClassName(); 1633 1634 String signature = v.getMethodSig(); 1635 exceptionHandlers.clear(); 1636 Method m = v.getMethod(); 1637 Code code = m.getCode(); 1638 if (code != null) 1639 { 1640 CodeException[] exceptionTable = code.getExceptionTable(); 1641 if (exceptionTable != null) 1642 for(CodeException ex : exceptionTable) 1643 exceptionHandlers.set(ex.getHandlerPC()); 1644 } 1645 if (DEBUG) System.out.println(" --- " + className 1646 + " " + m.getName() + " " + signature); 1647 Type[] argTypes = Type.getArgumentTypes(signature); 1648 int reg = 0; 1649 if (!m.isStatic()) { 1650 Item it = new Item("L" + className+";"); 1651 it.setInitialParameter(true); 1652 it.registerNumber = reg; 1653 setLVValue( reg, it); 1654 reg += it.getSize(); 1655 } 1656 for (Type argType : argTypes) { 1657 Item it = new Item(argType.getSignature()); 1658 it.registerNumber = reg; 1659 it.setInitialParameter(true); 1660 setLVValue(reg, it); 1661 reg += it.getSize(); 1662 } 1663 return reg; 1664 } 1665 1666 public int getStackDepth() { 1667 return stack.size(); 1668 } 1669 1670 public Item getStackItem(int stackOffset) { 1671 if (stackOffset < 0 || stackOffset >= stack.size()) { 1672 return new Item("Lfindbugs/OpcodeStackError;"); 1674 1675 } 1676 int tos = stack.size() - 1; 1677 int pos = tos - stackOffset; 1678 try { 1679 return stack.get(pos); 1680 } catch (ArrayIndexOutOfBoundsException e) { 1681 throw new ArrayIndexOutOfBoundsException ( 1682 "Requested item at offset " + stackOffset + " in a stack of size " + stack.size() 1683 +", made request for position " + pos); 1684 } 1685 } 1686 1687 private Item pop() { 1688 return stack.remove(stack.size()-1); 1689 } 1690 1691 private void pop(int count) 1692 { 1693 while ((count--) > 0) 1694 pop(); 1695 } 1696 1697 private void push(Item i) { 1698 stack.add(i); 1699 } 1700 1701 private void pushByConstant(DismantleBytecode dbc, Constant c) { 1702 1703 if (c instanceof ConstantClass) 1704 push(new Item("Ljava/lang/Class;", ((ConstantClass)c).getConstantValue(dbc.getConstantPool()))); 1705 else if (c instanceof ConstantInteger) 1706 push(new Item("I", (Integer )(((ConstantInteger) c).getBytes()))); 1707 else if (c instanceof ConstantString) { 1708 int s = ((ConstantString) c).getStringIndex(); 1709 push(new Item("Ljava/lang/String;", getStringFromIndex(dbc, s))); 1710 } 1711 else if (c instanceof ConstantFloat) 1712 push(new Item("F", (Float )(((ConstantFloat) c).getBytes()))); 1713 else if (c instanceof ConstantDouble) 1714 push(new Item("D", (Double )(((ConstantDouble) c).getBytes()))); 1715 else if (c instanceof ConstantLong) 1716 push(new Item("J", (Long )(((ConstantLong) c).getBytes()))); 1717 else 1718 throw new UnsupportedOperationException ("Constant type not expected" ); 1719 } 1720 1721 private void pushByLocalObjectLoad(DismantleBytecode dbc, int register) { 1722 Method m = dbc.getMethod(); 1723 LocalVariableTable lvt = m.getLocalVariableTable(); 1724 if (lvt != null) { 1725 LocalVariable lv = LVTHelper.getLocalVariableAtPC(lvt, register, dbc.getPC()); 1726 if (lv != null) { 1727 String signature = lv.getSignature(); 1728 pushByLocalLoad(signature, register); 1729 return; 1730 } 1731 } 1732 pushByLocalLoad("", register); 1733 } 1734 1735 private void pushByIntMath(int seen, Item lhs, Item rhs) { 1736 if (DEBUG) System.out.println("pushByIntMath: " + rhs.getConstant() + " " + lhs.getConstant() ); 1737 Item newValue = new Item("I"); 1738 try { 1739 1740 if ((rhs.getConstant() != null) && lhs.getConstant() != null) { 1741 Integer lhsValue = (Integer ) lhs.getConstant(); 1742 Integer rhsValue = (Integer ) rhs.getConstant(); 1743 if (seen == IADD) 1744 newValue = new Item("I",lhsValue + rhsValue); 1745 else if (seen == ISUB) 1746 newValue = new Item("I",lhsValue - rhsValue); 1747 else if (seen == IMUL) 1748 newValue = new Item("I", lhsValue * rhsValue); 1749 else if (seen == IDIV) 1750 newValue = new Item("I", lhsValue / rhsValue); 1751 else if (seen == IAND) { 1752 newValue = new Item("I", lhsValue & rhsValue); 1753 if ((rhsValue&0xff) == 0 && rhsValue != 0 || (lhsValue&0xff) == 0 && lhsValue != 0 ) 1754 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1755 1756 } else if (seen == IOR) 1757 newValue = new Item("I",lhsValue | rhsValue); 1758 else if (seen == IXOR) 1759 newValue = new Item("I",lhsValue ^ rhsValue); 1760 else if (seen == ISHL) { 1761 newValue = new Item("I",lhsValue << rhsValue); 1762 if (rhsValue >= 8) newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1763 } 1764 else if (seen == ISHR) 1765 newValue = new Item("I",lhsValue >> rhsValue); 1766 else if (seen == IREM) 1767 newValue = new Item("I", lhsValue % rhsValue); 1768 else if (seen == IUSHR) 1769 newValue = new Item("I", lhsValue >>> rhsValue); 1770 } else if (rhs.getConstant() != null && seen == ISHL && (Integer ) rhs.getConstant() >= 8) 1771 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1772 else if (lhs.getConstant() != null && seen == IAND && ((Integer ) lhs.getConstant() & 0xff) == 0) 1773 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1774 else if (rhs.getConstant() != null && seen == IAND && ((Integer ) rhs.getConstant() & 0xff) == 0) 1775 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1776 } catch (RuntimeException e) { 1777 } 1779 if (lhs.specialKind == Item.INTEGER_SUM && rhs.getConstant() != null ) { 1780 int rhsValue = (Integer ) rhs.getConstant(); 1781 if (seen == IDIV && rhsValue ==2 || seen == ISHR && rhsValue == 1) 1782 newValue.specialKind = Item.AVERAGE_COMPUTED_USING_DIVISION; 1783 } 1784 if (seen == IADD && newValue.specialKind == 0 && lhs.getConstant() == null && rhs.getConstant() == null ) 1785 newValue.specialKind = Item.INTEGER_SUM; 1786 if (seen == IREM && lhs.specialKind == Item.HASHCODE_INT) 1787 newValue.specialKind = Item.HASHCODE_INT_REMAINDER; 1788 if (seen == IREM && lhs.specialKind == Item.RANDOM_INT) 1789 newValue.specialKind = Item.RANDOM_INT_REMAINDER; 1790 if (DEBUG) System.out.println("push: " + newValue); 1791 push(newValue); 1792 } 1793 1794 private void pushByLongMath(int seen, Item lhs, Item rhs) { 1795 Item newValue = new Item("J"); 1796 try { 1797 1798 if ((rhs.getConstant() != null) && lhs.getConstant() != null) { 1799 1800 Long lhsValue = ((Long ) lhs.getConstant()); 1801 if (seen == LSHL) { 1802 newValue =new Item("J", lhsValue << ((Number ) rhs.getConstant()).intValue()); 1803 if (((Number ) rhs.getConstant()).intValue() >= 8) newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1804 } 1805 else if (seen == LSHR) 1806 newValue =new Item("J", lhsValue >> ((Number ) rhs.getConstant()).intValue()); 1807 else if (seen == LUSHR) 1808 newValue =new Item("J", lhsValue >>> ((Number ) rhs.getConstant()).intValue()); 1809 1810 else { 1811 Long rhsValue = ((Long ) rhs.getConstant()); 1812 if (seen == LADD) 1813 newValue = new Item("J", lhsValue + rhsValue); 1814 else if (seen == LSUB) 1815 newValue = new Item("J", lhsValue - rhsValue); 1816 else if (seen == LMUL) 1817 newValue = new Item("J", lhsValue * rhsValue); 1818 else if (seen == LDIV) 1819 newValue =new Item("J", lhsValue / rhsValue); 1820 else if (seen == LAND) { 1821 newValue = new Item("J", lhsValue & rhsValue); 1822 if ((rhsValue&0xff) == 0 && rhsValue != 0 || (lhsValue&0xff) == 0 && lhsValue != 0 ) 1823 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1824 } 1825 else if (seen == LOR) 1826 newValue = new Item("J", lhsValue | rhsValue); 1827 else if (seen == LXOR) 1828 newValue =new Item("J", lhsValue ^ rhsValue); 1829 else if (seen == LREM) 1830 newValue =new Item("J", lhsValue % rhsValue); 1831 } 1832 } 1833 else if (rhs.getConstant() != null && seen == LSHL && ((Integer ) rhs.getConstant()) >= 8) 1834 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1835 else if (lhs.getConstant() != null && seen == LAND && (((Long ) lhs.getConstant()) & 0xff) == 0) 1836 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1837 else if (rhs.getConstant() != null && seen == LAND && (((Long ) rhs.getConstant()) & 0xff) == 0) 1838 newValue.specialKind = Item.LOW_8_BITS_CLEAR; 1839 } catch (RuntimeException e) { 1840 } 1842 push(newValue); 1843 } 1844 1845 private void pushByFloatMath(int seen, Item it, Item it2) { 1846 Item result; 1847 if ((it.getConstant() != null) && it2.getConstant() != null) { 1848 if (seen == FADD) 1849 result =new Item("F", ((Float ) it2.getConstant()) + ((Float ) it.getConstant())); 1850 else if (seen == FSUB) 1851 result =new Item("F", ((Float ) it2.getConstant()) - ((Float ) it.getConstant())); 1852 else if (seen == FMUL) 1853 result =new Item("F", ((Float ) it2.getConstant()) * ((Float ) it.getConstant())); 1854 else if (seen == FDIV) 1855 result =new Item("F", ((Float ) it2.getConstant()) / ((Float ) it.getConstant())); 1856 else result =new Item("F"); 1857 } else { 1858 result =new Item("F"); 1859 } 1860 result.setSpecialKind(Item.FLOAT_MATH); 1861 push(result); 1862 } 1863 1864 private void pushByDoubleMath(int seen, Item it, Item it2) { 1865 Item result; 1866 if ((it.getConstant() != null) && it2.getConstant() != null) { 1867 if (seen == DADD) 1868 result = new Item("D", ((Double ) it2.getConstant()) + ((Double ) it.getConstant())); 1869 else if (seen == DSUB) 1870 result = new Item("D", ((Double ) it2.getConstant()) - ((Double ) it.getConstant())); 1871 else if (seen == DMUL) 1872 result = new Item("D", ((Double ) it2.getConstant()) * ((Double ) it.getConstant())); 1873 else if (seen == DDIV) 1874 result = new Item("D", ((Double ) it2.getConstant()) / ((Double ) it.getConstant())); 1875 else 1876 result = new Item("D"); } else { 1878 result = new Item("D"); 1879 } 1880 result.setSpecialKind(Item.FLOAT_MATH); 1881 push(result); 1882 } 1883 1884 private void pushByInvoke(DismantleBytecode dbc, boolean popThis) { 1885 String signature = dbc.getSigConstantOperand(); 1886 pop(PreorderVisitor.getNumberArguments(signature)+(popThis ? 1 : 0)); 1887 pushBySignature(Type.getReturnType(signature).getSignature()); 1888 } 1889 1890 private String getStringFromIndex(DismantleBytecode dbc, int i) { 1891 ConstantUtf8 name = (ConstantUtf8) dbc.getConstantPool().getConstant(i); 1892 return name.getBytes(); 1893 } 1894 1895 private void pushBySignature(String s) { 1896 if ("V".equals(s)) 1897 return; 1898 push(new Item(s, (Object ) null)); 1899 } 1900 1901 private void pushByLocalStore(int register) { 1902 Item it = pop(); 1903 if (it.getRegisterNumber() != register) { 1904 for(Item i : lvValues) if (i != null) { 1905 if (i.registerNumber == register) i.registerNumber = -1; 1906 if (i.fieldLoadedFromRegister == register) i.fieldLoadedFromRegister = -1; 1907 } 1908 for(Item i : stack) if (i != null) { 1909 if (i.registerNumber == register) i.registerNumber = -1; 1910 if (i.fieldLoadedFromRegister == register) i.fieldLoadedFromRegister = -1; 1911 } 1912 } 1913 setLVValue( register, it ); 1914 } 1915 1916 private void pushByLocalLoad(String signature, int register) { 1917 Item it = getLVValue(register); 1918 1919 if (it == null) { 1920 Item item = new Item(signature); 1921 item.registerNumber = register; 1922 push(item); 1923 } 1924 else if (it.getRegisterNumber() >= 0) 1925 push(it); 1926 else { 1927 push(new Item(it, register)); 1928 } 1929 } 1930 1931 private void setLVValue(int index, Item value ) { 1932 int addCount = index - lvValues.size() + 1; 1933 while ((addCount--) > 0) 1934 lvValues.add(null); 1935 if (!useIterativeAnalysis && seenTransferOfControl) 1936 value = Item.merge(value, lvValues.get(index) ); 1937 lvValues.set(index, value); 1938 } 1939 1940 private Item getLVValue(int index) { 1941 if (index >= lvValues.size()) 1942 return null; 1943 1944 return lvValues.get(index); 1945 } 1946} 1947 1948 | Popular Tags |