1 30 package org.objectweb.asm.commons; 31 32 import java.util.ArrayList ; 33 import java.util.HashMap ; 34 import java.util.List ; 35 import java.util.Map ; 36 37 import org.objectweb.asm.Label; 38 import org.objectweb.asm.MethodAdapter; 39 import org.objectweb.asm.MethodVisitor; 40 import org.objectweb.asm.Opcodes; 41 import org.objectweb.asm.Type; 42 43 57 public class AnalyzerAdapter extends MethodAdapter { 58 59 71 public List locals; 72 73 85 public List stack; 86 87 91 private List labels; 92 93 100 private Map uninitializedTypes; 101 102 105 private int maxStack; 106 107 110 private int maxLocals; 111 112 122 public AnalyzerAdapter( 123 final String owner, 124 final int access, 125 final String name, 126 final String desc, 127 final MethodVisitor mv) 128 { 129 super(mv); 130 locals = new ArrayList (); 131 stack = new ArrayList (); 132 uninitializedTypes = new HashMap (); 133 134 if ((access & Opcodes.ACC_STATIC) == 0) { 135 if (name.equals("<init>")) { 136 locals.add(Opcodes.UNINITIALIZED_THIS); 137 } else { 138 locals.add(owner); 139 } 140 } 141 Type[] types = Type.getArgumentTypes(desc); 142 for (int i = 0; i < types.length; ++i) { 143 Type type = types[i]; 144 switch (type.getSort()) { 145 case Type.BOOLEAN: 146 case Type.CHAR: 147 case Type.BYTE: 148 case Type.SHORT: 149 case Type.INT: 150 locals.add(Opcodes.INTEGER); 151 break; 152 case Type.FLOAT: 153 locals.add(Opcodes.FLOAT); 154 break; 155 case Type.LONG: 156 locals.add(Opcodes.LONG); 157 locals.add(Opcodes.TOP); 158 break; 159 case Type.DOUBLE: 160 locals.add(Opcodes.DOUBLE); 161 locals.add(Opcodes.TOP); 162 break; 163 case Type.ARRAY: 164 locals.add(types[i].getDescriptor()); 165 break; 166 default: 168 locals.add(types[i].getInternalName()); 169 } 170 } 171 } 172 173 public void visitFrame( 174 final int type, 175 final int nLocal, 176 final Object [] local, 177 final int nStack, 178 final Object [] stack) 179 { 180 if (type != Opcodes.F_NEW) { throw new IllegalStateException ("ClassReader.accept() should be called with EXPAND_FRAMES flag"); 182 } 183 184 if (mv != null) { 185 mv.visitFrame(type, nLocal, local, nStack, stack); 186 } 187 188 if (this.locals != null) { 189 this.locals.clear(); 190 this.stack.clear(); 191 } else { 192 this.locals = new ArrayList (); 193 this.stack = new ArrayList (); 194 } 195 visitFrameTypes(nLocal, local, this.locals); 196 visitFrameTypes(nStack, stack, this.stack); 197 maxStack = Math.max(maxStack, this.stack.size()); 198 } 199 200 private void visitFrameTypes( 201 final int n, 202 final Object [] types, 203 final List result) 204 { 205 for (int i = 0; i < n; ++i) { 206 Object type = types[i]; 207 result.add(type); 208 if (type == Opcodes.LONG || type == Opcodes.DOUBLE) { 209 result.add(Opcodes.TOP); 210 } 211 } 212 } 213 214 public void visitInsn(final int opcode) { 215 if (mv != null) { 216 mv.visitInsn(opcode); 217 } 218 execute(opcode, 0, null); 219 if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN) 220 || opcode == Opcodes.ATHROW) 221 { 222 this.locals = null; 223 this.stack = null; 224 } 225 } 226 227 public void visitIntInsn(final int opcode, final int operand) { 228 if (mv != null) { 229 mv.visitIntInsn(opcode, operand); 230 } 231 execute(opcode, operand, null); 232 } 233 234 public void visitVarInsn(final int opcode, final int var) { 235 if (mv != null) { 236 mv.visitVarInsn(opcode, var); 237 } 238 execute(opcode, var, null); 239 } 240 241 public void visitTypeInsn(final int opcode, final String desc) { 242 if (opcode == Opcodes.NEW) { 243 if (labels == null) { 244 Label l = new Label(); 245 labels = new ArrayList (3); 246 labels.add(l); 247 if (mv != null) { 248 mv.visitLabel(l); 249 } 250 } 251 for (int i = 0; i < labels.size(); ++i) { 252 uninitializedTypes.put(labels.get(i), desc); 253 } 254 } 255 if (mv != null) { 256 mv.visitTypeInsn(opcode, desc); 257 } 258 execute(opcode, 0, desc); 259 } 260 261 public void visitFieldInsn( 262 final int opcode, 263 final String owner, 264 final String name, 265 final String desc) 266 { 267 if (mv != null) { 268 mv.visitFieldInsn(opcode, owner, name, desc); 269 } 270 execute(opcode, 0, desc); 271 } 272 273 public void visitMethodInsn( 274 final int opcode, 275 final String owner, 276 final String name, 277 final String desc) 278 { 279 if (mv != null) { 280 mv.visitMethodInsn(opcode, owner, name, desc); 281 } 282 pop(desc); 283 if (opcode != Opcodes.INVOKESTATIC) { 284 Object t = pop(); 285 if (opcode == Opcodes.INVOKESPECIAL && name.charAt(0) == '<') { 286 Object u; 287 if (t == Opcodes.UNINITIALIZED_THIS) { 288 u = owner; 289 } else { 290 u = uninitializedTypes.get(t); 291 } 292 for (int i = 0; i < locals.size(); ++i) { 293 if (locals.get(i) == t) { 294 locals.set(i, u); 295 } 296 } 297 for (int i = 0; i < stack.size(); ++i) { 298 if (stack.get(i) == t) { 299 stack.set(i, u); 300 } 301 } 302 } 303 } 304 pushDesc(desc); 305 labels = null; 306 } 307 308 public void visitJumpInsn(final int opcode, final Label label) { 309 if (mv != null) { 310 mv.visitJumpInsn(opcode, label); 311 } 312 execute(opcode, 0, null); 313 if (opcode == Opcodes.GOTO) { 314 this.locals = null; 315 this.stack = null; 316 } 317 } 318 319 public void visitLabel(final Label label) { 320 if (mv != null) { 321 mv.visitLabel(label); 322 } 323 if (labels == null) { 324 labels = new ArrayList (3); 325 } 326 labels.add(label); 327 } 328 329 public void visitLdcInsn(final Object cst) { 330 if (mv != null) { 331 mv.visitLdcInsn(cst); 332 } 333 if (cst instanceof Integer ) { 334 push(Opcodes.INTEGER); 335 } else if (cst instanceof Long ) { 336 push(Opcodes.LONG); 337 push(Opcodes.TOP); 338 } else if (cst instanceof Float ) { 339 push(Opcodes.FLOAT); 340 } else if (cst instanceof Double ) { 341 push(Opcodes.DOUBLE); 342 push(Opcodes.TOP); 343 } else if (cst instanceof String ) { 344 push("java/lang/String"); 345 } else if (cst instanceof Type) { 346 push("java/lang/Class"); 347 } else { 348 throw new IllegalArgumentException (); 349 } 350 labels = null; 351 } 352 353 public void visitIincInsn(final int var, final int increment) { 354 if (mv != null) { 355 mv.visitIincInsn(var, increment); 356 } 357 execute(Opcodes.IINC, var, null); 358 } 359 360 public void visitTableSwitchInsn( 361 final int min, 362 final int max, 363 final Label dflt, 364 final Label labels[]) 365 { 366 if (mv != null) { 367 mv.visitTableSwitchInsn(min, max, dflt, labels); 368 } 369 execute(Opcodes.TABLESWITCH, 0, null); 370 this.locals = null; 371 this.stack = null; 372 } 373 374 public void visitLookupSwitchInsn( 375 final Label dflt, 376 final int keys[], 377 final Label labels[]) 378 { 379 if (mv != null) { 380 mv.visitLookupSwitchInsn(dflt, keys, labels); 381 } 382 execute(Opcodes.LOOKUPSWITCH, 0, null); 383 this.locals = null; 384 this.stack = null; 385 } 386 387 public void visitMultiANewArrayInsn(final String desc, final int dims) { 388 if (mv != null) { 389 mv.visitMultiANewArrayInsn(desc, dims); 390 } 391 execute(Opcodes.MULTIANEWARRAY, dims, desc); 392 } 393 394 public void visitMaxs(final int maxStack, final int maxLocals) { 395 if (mv != null) { 396 this.maxStack = Math.max(this.maxStack, maxStack); 397 this.maxLocals = Math.max(this.maxLocals, maxLocals); 398 mv.visitMaxs(this.maxStack, this.maxLocals); 399 } 400 } 401 402 404 private Object get(final int local) { 405 maxLocals = Math.max(maxLocals, local); 406 return local < locals.size() ? locals.get(local) : Opcodes.TOP; 407 } 408 409 private void set(final int local, final Object type) { 410 maxLocals = Math.max(maxLocals, local); 411 while (local >= locals.size()) { 412 locals.add(Opcodes.TOP); 413 } 414 locals.set(local, type); 415 } 416 417 private void push(final Object type) { 418 stack.add(type); 419 maxStack = Math.max(maxStack, stack.size()); 420 } 421 422 private void pushDesc(final String desc) { 423 int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0; 424 switch (desc.charAt(index)) { 425 case 'V': 426 return; 427 case 'Z': 428 case 'C': 429 case 'B': 430 case 'S': 431 case 'I': 432 push(Opcodes.INTEGER); 433 return; 434 case 'F': 435 push(Opcodes.FLOAT); 436 return; 437 case 'J': 438 push(Opcodes.LONG); 439 push(Opcodes.TOP); 440 return; 441 case 'D': 442 push(Opcodes.DOUBLE); 443 push(Opcodes.TOP); 444 return; 445 case '[': 446 if (index == 0) { 447 push(desc); 448 } else { 449 push(desc.substring(index, desc.length())); 450 } 451 break; 452 default: 454 if (index == 0) { 455 push(desc.substring(1, desc.length() - 1)); 456 } else { 457 push(desc.substring(index + 1, desc.length() - 1)); 458 } 459 return; 460 } 461 } 462 463 private Object pop() { 464 return stack.remove(stack.size() - 1); 465 } 466 467 private void pop(final int n) { 468 int size = stack.size(); 469 int end = size - n; 470 for (int i = size - 1; i >= end; --i) { 471 stack.remove(i); 472 } 473 } 474 475 private void pop(final String desc) { 476 char c = desc.charAt(0); 477 if (c == '(') { 478 int n = 0; 479 Type[] types = Type.getArgumentTypes(desc); 480 for (int i = 0; i < types.length; ++i) { 481 n += types[i].getSize(); 482 } 483 pop(n); 484 } else if (c == 'J' || c == 'D') { 485 pop(2); 486 } else { 487 pop(1); 488 } 489 } 490 491 private void execute(final int opcode, final int iarg, final String sarg) { 492 if (this.locals == null) { 493 return; 494 } 495 Object t1, t2, t3, t4; 496 switch (opcode) { 497 case Opcodes.NOP: 498 case Opcodes.INEG: 499 case Opcodes.LNEG: 500 case Opcodes.FNEG: 501 case Opcodes.DNEG: 502 case Opcodes.I2B: 503 case Opcodes.I2C: 504 case Opcodes.I2S: 505 case Opcodes.GOTO: 506 case Opcodes.RETURN: 507 break; 508 case Opcodes.ACONST_NULL: 509 push(Opcodes.NULL); 510 break; 511 case Opcodes.ICONST_M1: 512 case Opcodes.ICONST_0: 513 case Opcodes.ICONST_1: 514 case Opcodes.ICONST_2: 515 case Opcodes.ICONST_3: 516 case Opcodes.ICONST_4: 517 case Opcodes.ICONST_5: 518 case Opcodes.BIPUSH: 519 case Opcodes.SIPUSH: 520 push(Opcodes.INTEGER); 521 break; 522 case Opcodes.LCONST_0: 523 case Opcodes.LCONST_1: 524 push(Opcodes.LONG); 525 push(Opcodes.TOP); 526 break; 527 case Opcodes.FCONST_0: 528 case Opcodes.FCONST_1: 529 case Opcodes.FCONST_2: 530 push(Opcodes.FLOAT); 531 break; 532 case Opcodes.DCONST_0: 533 case Opcodes.DCONST_1: 534 push(Opcodes.DOUBLE); 535 push(Opcodes.TOP); 536 break; 537 case Opcodes.ILOAD: 538 case Opcodes.FLOAD: 539 case Opcodes.ALOAD: 540 push(get(iarg)); 541 break; 542 case Opcodes.LLOAD: 543 case Opcodes.DLOAD: 544 push(get(iarg)); 545 push(Opcodes.TOP); 546 break; 547 case Opcodes.IALOAD: 548 case Opcodes.BALOAD: 549 case Opcodes.CALOAD: 550 case Opcodes.SALOAD: 551 pop(2); 552 push(Opcodes.INTEGER); 553 break; 554 case Opcodes.LALOAD: 555 case Opcodes.D2L: 556 pop(2); 557 push(Opcodes.LONG); 558 push(Opcodes.TOP); 559 break; 560 case Opcodes.FALOAD: 561 pop(2); 562 push(Opcodes.FLOAT); 563 break; 564 case Opcodes.DALOAD: 565 case Opcodes.L2D: 566 pop(2); 567 push(Opcodes.DOUBLE); 568 push(Opcodes.TOP); 569 break; 570 case Opcodes.AALOAD: 571 pop(1); 572 t1 = pop(); 573 pushDesc(((String ) t1).substring(1)); 574 break; 575 case Opcodes.ISTORE: 576 case Opcodes.FSTORE: 577 case Opcodes.ASTORE: 578 t1 = pop(); 579 set(iarg, t1); 580 if (iarg > 0) { 581 t2 = get(iarg - 1); 582 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { 583 set(iarg - 1, Opcodes.TOP); 584 } 585 } 586 break; 587 case Opcodes.LSTORE: 588 case Opcodes.DSTORE: 589 pop(1); 590 t1 = pop(); 591 set(iarg, t1); 592 set(iarg + 1, Opcodes.TOP); 593 if (iarg > 0) { 594 t2 = get(iarg - 1); 595 if (t2 == Opcodes.LONG || t2 == Opcodes.DOUBLE) { 596 set(iarg - 1, Opcodes.TOP); 597 } 598 } 599 break; 600 case Opcodes.IASTORE: 601 case Opcodes.BASTORE: 602 case Opcodes.CASTORE: 603 case Opcodes.SASTORE: 604 case Opcodes.FASTORE: 605 case Opcodes.AASTORE: 606 pop(3); 607 break; 608 case Opcodes.LASTORE: 609 case Opcodes.DASTORE: 610 pop(4); 611 break; 612 case Opcodes.POP: 613 case Opcodes.IFEQ: 614 case Opcodes.IFNE: 615 case Opcodes.IFLT: 616 case Opcodes.IFGE: 617 case Opcodes.IFGT: 618 case Opcodes.IFLE: 619 case Opcodes.IRETURN: 620 case Opcodes.FRETURN: 621 case Opcodes.ARETURN: 622 case Opcodes.TABLESWITCH: 623 case Opcodes.LOOKUPSWITCH: 624 case Opcodes.ATHROW: 625 case Opcodes.MONITORENTER: 626 case Opcodes.MONITOREXIT: 627 case Opcodes.IFNULL: 628 case Opcodes.IFNONNULL: 629 pop(1); 630 break; 631 case Opcodes.POP2: 632 case Opcodes.IF_ICMPEQ: 633 case Opcodes.IF_ICMPNE: 634 case Opcodes.IF_ICMPLT: 635 case Opcodes.IF_ICMPGE: 636 case Opcodes.IF_ICMPGT: 637 case Opcodes.IF_ICMPLE: 638 case Opcodes.IF_ACMPEQ: 639 case Opcodes.IF_ACMPNE: 640 case Opcodes.LRETURN: 641 case Opcodes.DRETURN: 642 pop(2); 643 break; 644 case Opcodes.DUP: 645 t1 = pop(); 646 push(t1); 647 push(t1); 648 break; 649 case Opcodes.DUP_X1: 650 t1 = pop(); 651 t2 = pop(); 652 push(t1); 653 push(t2); 654 push(t1); 655 break; 656 case Opcodes.DUP_X2: 657 t1 = pop(); 658 t2 = pop(); 659 t3 = pop(); 660 push(t1); 661 push(t3); 662 push(t2); 663 push(t1); 664 break; 665 case Opcodes.DUP2: 666 t1 = pop(); 667 t2 = pop(); 668 push(t2); 669 push(t1); 670 push(t2); 671 push(t1); 672 break; 673 case Opcodes.DUP2_X1: 674 t1 = pop(); 675 t2 = pop(); 676 t3 = pop(); 677 push(t2); 678 push(t1); 679 push(t3); 680 push(t2); 681 push(t1); 682 break; 683 case Opcodes.DUP2_X2: 684 t1 = pop(); 685 t2 = pop(); 686 t3 = pop(); 687 t4 = pop(); 688 push(t2); 689 push(t1); 690 push(t4); 691 push(t3); 692 push(t2); 693 push(t1); 694 break; 695 case Opcodes.SWAP: 696 t1 = pop(); 697 t2 = pop(); 698 push(t1); 699 push(t2); 700 break; 701 case Opcodes.IADD: 702 case Opcodes.ISUB: 703 case Opcodes.IMUL: 704 case Opcodes.IDIV: 705 case Opcodes.IREM: 706 case Opcodes.IAND: 707 case Opcodes.IOR: 708 case Opcodes.IXOR: 709 case Opcodes.ISHL: 710 case Opcodes.ISHR: 711 case Opcodes.IUSHR: 712 case Opcodes.L2I: 713 case Opcodes.D2I: 714 case Opcodes.FCMPL: 715 case Opcodes.FCMPG: 716 pop(2); 717 push(Opcodes.INTEGER); 718 break; 719 case Opcodes.LADD: 720 case Opcodes.LSUB: 721 case Opcodes.LMUL: 722 case Opcodes.LDIV: 723 case Opcodes.LREM: 724 case Opcodes.LAND: 725 case Opcodes.LOR: 726 case Opcodes.LXOR: 727 pop(4); 728 push(Opcodes.LONG); 729 push(Opcodes.TOP); 730 break; 731 case Opcodes.FADD: 732 case Opcodes.FSUB: 733 case Opcodes.FMUL: 734 case Opcodes.FDIV: 735 case Opcodes.FREM: 736 case Opcodes.L2F: 737 case Opcodes.D2F: 738 pop(2); 739 push(Opcodes.FLOAT); 740 break; 741 case Opcodes.DADD: 742 case Opcodes.DSUB: 743 case Opcodes.DMUL: 744 case Opcodes.DDIV: 745 case Opcodes.DREM: 746 pop(4); 747 push(Opcodes.DOUBLE); 748 push(Opcodes.TOP); 749 break; 750 case Opcodes.LSHL: 751 case Opcodes.LSHR: 752 case Opcodes.LUSHR: 753 pop(3); 754 push(Opcodes.LONG); 755 push(Opcodes.TOP); 756 break; 757 case Opcodes.IINC: 758 set(iarg, Opcodes.INTEGER); 759 break; 760 case Opcodes.I2L: 761 case Opcodes.F2L: 762 pop(1); 763 push(Opcodes.LONG); 764 push(Opcodes.TOP); 765 break; 766 case Opcodes.I2F: 767 pop(1); 768 push(Opcodes.FLOAT); 769 break; 770 case Opcodes.I2D: 771 case Opcodes.F2D: 772 pop(1); 773 push(Opcodes.DOUBLE); 774 push(Opcodes.TOP); 775 break; 776 case Opcodes.F2I: 777 case Opcodes.ARRAYLENGTH: 778 case Opcodes.INSTANCEOF: 779 pop(1); 780 push(Opcodes.INTEGER); 781 break; 782 case Opcodes.LCMP: 783 case Opcodes.DCMPL: 784 case Opcodes.DCMPG: 785 pop(4); 786 push(Opcodes.INTEGER); 787 break; 788 case Opcodes.JSR: 789 case Opcodes.RET: 790 throw new RuntimeException ("JSR/RET are not supported"); 791 case Opcodes.GETSTATIC: 792 pushDesc(sarg); 793 break; 794 case Opcodes.PUTSTATIC: 795 pop(sarg); 796 break; 797 case Opcodes.GETFIELD: 798 pop(1); 799 pushDesc(sarg); 800 break; 801 case Opcodes.PUTFIELD: 802 pop(sarg); 803 pop(); 804 break; 805 case Opcodes.NEW: 806 push(labels.get(0)); 807 break; 808 case Opcodes.NEWARRAY: 809 pop(); 810 switch (iarg) { 811 case Opcodes.T_BOOLEAN: 812 pushDesc("[Z"); 813 break; 814 case Opcodes.T_CHAR: 815 pushDesc("[C"); 816 break; 817 case Opcodes.T_BYTE: 818 pushDesc("[B"); 819 break; 820 case Opcodes.T_SHORT: 821 pushDesc("[S"); 822 break; 823 case Opcodes.T_INT: 824 pushDesc("[I"); 825 break; 826 case Opcodes.T_FLOAT: 827 pushDesc("[F"); 828 break; 829 case Opcodes.T_DOUBLE: 830 pushDesc("[D"); 831 break; 832 default: 834 pushDesc("[J"); 835 break; 836 } 837 break; 838 case Opcodes.ANEWARRAY: 839 pop(); 840 if (sarg.charAt(0) == '[') { 841 pushDesc("[" + sarg); 842 } else { 843 pushDesc("[L" + sarg + ";"); 844 } 845 break; 846 case Opcodes.CHECKCAST: 847 pop(); 848 if (sarg.charAt(0) == '[') { 849 pushDesc(sarg); 850 } else { 851 push(sarg); 852 } 853 break; 854 default: 856 pop(iarg); 857 pushDesc(sarg); 858 break; 859 } 860 labels = null; 861 } 862 } 863 | Popular Tags |