1 29 30 package com.caucho.bytecode; 31 32 import com.caucho.log.Log; 33 import com.caucho.util.IntArray; 34 import com.caucho.util.L10N; 35 36 import java.util.ArrayList ; 37 import java.util.logging.Logger ; 38 39 42 public class CodeVisitor { 43 static private final Logger log = Log.open(CodeVisitor.class); 44 static private final L10N L = new L10N(CodeVisitor.class); 45 46 private JavaClass _javaClass; 47 protected CodeAttribute _codeAttr; 48 private byte []_code; 49 protected int _offset; 50 51 public CodeVisitor() 52 { 53 } 54 55 public CodeVisitor(JavaClass javaClass, CodeAttribute codeAttr) 56 { 57 init(javaClass, codeAttr); 58 } 59 60 public void init(JavaClass javaClass, CodeAttribute codeAttr) 61 { 62 _javaClass = javaClass; 63 _codeAttr = codeAttr; 64 _code = codeAttr.getCode(); 65 _offset = 0; 66 } 67 68 71 public JavaClass getJavaClass() 72 { 73 return _javaClass; 74 } 75 76 79 public CodeAttribute getCodeAttribute() 80 { 81 return _codeAttr; 82 } 83 84 87 public int getOffset() 88 { 89 return _offset; 90 } 91 92 95 public void setOffset(int offset) 96 { 97 _offset = offset; 98 } 99 100 103 public byte []getCode() 104 { 105 return _code; 106 } 107 108 111 public ArrayList <CodeAttribute.ExceptionItem> getExceptions() 112 { 113 return _codeAttr.getExceptions(); 114 } 115 116 119 public int getOpcode() 120 { 121 int op = getCode()[_offset] & 0xff; 122 123 if (op == WIDE) 124 return getCode()[_offset + 1] & 0xff; 125 else 126 return op; 127 } 128 129 132 public boolean next() 133 { 134 _offset = nextOffset(); 135 136 return _offset >= 0; 137 } 138 139 142 protected int nextOffset() 143 { 144 int opcode = getCode()[_offset] & 0xff; 145 146 int length = OP_LEN[opcode]; 147 148 switch (opcode) { 149 case GOTO: 150 case GOTO_W: 151 case RET: 152 case IRETURN: 153 case LRETURN: 154 case FRETURN: 155 case DRETURN: 156 case ARETURN: 157 case RETURN: 158 case ATHROW: 159 return -1; 160 161 case TABLESWITCH: 162 { 163 int arg = _offset + 1; 164 arg += (4 - arg % 4) % 4; 165 166 int low = getInt(arg + 4); 167 int high = getInt(arg + 8); 168 169 return arg + 12 + (high - low + 1) * 4; 170 } 171 172 case LOOKUPSWITCH: 173 { 174 return -1; 175 176 186 } 187 188 case WIDE: 189 { 190 int op2 = getCode()[_offset + 1] & 0xff; 191 192 if (op2 == IINC) 193 length = 5; 194 else 195 length = 3; 196 break; 197 } 198 } 199 200 if (length < 0 || length > 0x10) 201 throw new UnsupportedOperationException (L.l("{0}: can't handle opcode {1}", 202 "" + _offset, 203 "" + getOpcode())); 204 205 return _offset + length + 1; 206 } 207 208 211 public boolean isBranch() 212 { 213 switch (getOpcode()) { 214 case IFNULL: 215 case IFNONNULL: 216 case IFNE: 217 case IFEQ: 218 case IFLT: 219 case IFGE: 220 case IFGT: 221 case IFLE: 222 case IF_ICMPEQ: 223 case IF_ICMPNE: 224 case IF_ICMPLT: 225 case IF_ICMPGE: 226 case IF_ICMPGT: 227 case IF_ICMPLE: 228 case IF_ACMPEQ: 229 case IF_ACMPNE: 230 case JSR: 231 case JSR_W: 232 case GOTO: 233 case GOTO_W: 234 return true; 235 } 236 237 return false; 238 } 239 240 243 public int getBranchTarget() 244 { 245 switch (getOpcode()) { 246 case IFNULL: 247 case IFNONNULL: 248 case IFNE: 249 case IFEQ: 250 case IFLT: 251 case IFGE: 252 case IFGT: 253 case IFLE: 254 case IF_ICMPEQ: 255 case IF_ICMPNE: 256 case IF_ICMPLT: 257 case IF_ICMPLE: 258 case IF_ICMPGE: 259 case IF_ICMPGT: 260 case IF_ACMPEQ: 261 case IF_ACMPNE: 262 case GOTO: 263 case JSR: 264 return _offset + getShortArg(); 265 266 case GOTO_W: 267 case JSR_W: 268 return _offset + getIntArg(); 269 270 default: 271 throw new UnsupportedOperationException (); 272 } 273 } 274 275 278 public boolean isSwitch() 279 { 280 switch (getOpcode()) { 281 case TABLESWITCH: 282 case LOOKUPSWITCH: 283 return true; 284 default: 285 return false; 286 } 287 } 288 289 292 public int []getSwitchTargets() 293 { 294 switch (getOpcode()) { 295 case TABLESWITCH: 296 { 297 int arg = _offset + 1; 298 arg += (4 - arg % 4) % 4; 299 300 int low = getInt(arg + 4); 301 int high = getInt(arg + 8); 302 303 int []targets = new int[high - low + 2]; 304 targets[0] = getInt(arg) + _offset; 305 306 for (int i = 0; i <= high - low; i++) { 307 targets[i + 1] = getInt(arg + 12 + i * 4) + _offset; 308 } 309 310 return targets; 311 } 312 313 case LOOKUPSWITCH: 314 { 315 int arg = _offset + 1; 316 arg += (4 - arg % 4) % 4; 317 318 int n = getInt(arg + 4); 319 320 int []targets = new int[n + 1]; 321 targets[0] = getInt(arg) + _offset; 322 323 for (int i = 0; i < n; i++) { 324 int off = arg + 8 + i * 8 + 4; 325 326 targets[i + 1] = getInt(off) + _offset; 327 } 328 329 return targets; 330 } 331 332 default: 333 throw new UnsupportedOperationException ("getSwitchTargets"); 334 } 335 } 336 337 340 public ConstantPoolEntry getConstantArg() 341 { 342 switch (getOpcode()) { 343 case LDC: 344 return _javaClass.getConstantPool().getEntry(getByteArg()); 345 346 case LDC_W: 347 return _javaClass.getConstantPool().getEntry(getShortArg()); 348 349 default: 350 throw new UnsupportedOperationException (); 351 } 352 } 353 354 357 public int getByteArg() 358 { 359 return getCode()[_offset + 1]; 360 } 361 362 365 public int getByteArg(int offset) 366 { 367 return getByte(_offset + offset); 368 } 369 370 373 public void setByteArg(int offset, int value) 374 { 375 getCode()[_offset + offset + 0] = (byte) value; 376 } 377 378 381 public int getShortArg() 382 { 383 return getShort(_offset + 1); 384 } 385 386 389 public int getShortArg(int offset) 390 { 391 return getShort(_offset + offset); 392 } 393 394 397 public void setShortArg(int offset, int value) 398 { 399 setShort(_offset + offset, value); 400 } 401 402 405 public void setShort(int offset, int value) 406 { 407 byte []code = getCode(); 408 409 code[offset + 0] = (byte) (value >> 8); 410 code[offset + 1] = (byte) (value); 411 } 412 413 416 public int getIntArg() 417 { 418 return getInt(_offset + 1); 419 } 420 421 424 public void setInt(int offset, int value) 425 { 426 byte []code = getCode(); 427 428 code[offset + 0] = (byte) (value >> 24); 429 code[offset + 1] = (byte) (value >> 16); 430 code[offset + 2] = (byte) (value >> 8); 431 code[offset + 3] = (byte) (value); 432 } 433 434 437 public int getByte(int offset) 438 { 439 return getCode()[offset + 0] & 0xff; 440 } 441 442 445 public int getShort(int offset) 446 { 447 int b0 = getCode()[offset + 0] & 0xff; 448 int b1 = getCode()[offset + 1] & 0xff; 449 450 return (short) ((b0 << 8) + b1); 451 } 452 453 456 public int getInt(int offset) 457 { 458 byte []code = getCode(); 459 460 int b0 = code[offset + 0] & 0xff; 461 int b1 = code[offset + 1] & 0xff; 462 int b2 = code[offset + 2] & 0xff; 463 int b3 = code[offset + 3] & 0xff; 464 465 return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; 466 } 467 468 471 public void analyze(Analyzer analyzer) 472 throws Exception 473 { 474 analyze(analyzer, true); 475 } 476 477 480 public void analyze(Analyzer analyzer, boolean allowFlow) 481 throws Exception 482 { 483 analyzeImpl(analyzer, allowFlow, new IntArray(), new IntArray()); 484 } 485 486 489 protected void analyzeImpl(Analyzer analyzer, boolean allowFlow, 490 IntArray pendingTargets, 491 IntArray completedTargets) 492 throws Exception 493 { 494 setOffset(0); 495 496 pendingTargets.add(0); 497 498 ArrayList <CodeAttribute.ExceptionItem> exns; 499 exns = getExceptions(); 500 501 for (int i = 0; i < exns.size(); i++) { 502 CodeAttribute.ExceptionItem exn = exns.get(i); 503 504 pendingTargets.add(exn.getHandler()); 505 } 506 507 analyze(analyzer, allowFlow, pendingTargets, completedTargets); 508 } 509 510 513 private void analyze(Analyzer analyzer, 514 boolean allowFlow, 515 IntArray pendingTargets, 516 IntArray completedTargets) 517 throws Exception 518 { 519 pending: 520 while (pendingTargets.size() > 0) { 521 int pc = pendingTargets.pop(); 522 523 if (allowFlow) { 524 if (completedTargets.contains(pc)) 525 continue pending; 526 527 completedTargets.add(pc); 528 } 529 530 setOffset(pc); 531 532 flow: 533 do { 534 pc = getOffset(); 535 536 if (pc < 0) 537 throw new IllegalStateException (); 538 539 if (! allowFlow) { 540 if (completedTargets.contains(pc)) 541 break flow; 542 543 completedTargets.add(pc); 544 } 545 546 if (isBranch()) { 547 int targetPC = getBranchTarget(); 548 549 if (! pendingTargets.contains(targetPC)) 550 pendingTargets.add(targetPC); 551 } 552 else if (isSwitch()) { 553 int []switchTargets = getSwitchTargets(); 554 555 for (int i = 0; i < switchTargets.length; i++) { 556 if (! pendingTargets.contains(switchTargets[i])) 557 pendingTargets.add(switchTargets[i]); 558 } 559 } 560 561 analyzer.analyze(this); 562 } while (next()); 563 } 564 } 565 566 public static final int NOP = 0x00; 567 public static final int ACONST_NULL = 0x01; 568 public static final int ICONST_M1 = 0x02; 569 public static final int ICONST_0 = 0x03; 570 public static final int ICONST_1 = 0x04; 571 public static final int ICONST_2 = 0x05; 572 public static final int ICONST_3 = 0x06; 573 public static final int ICONST_4 = 0x07; 574 public static final int ICONST_5 = 0x08; 575 public static final int LCONST_0 = 0x09; 576 public static final int LCONST_1 = 0x0a; 577 public static final int FCONST_0 = 0x0b; 578 public static final int FCONST_1 = 0x0c; 579 public static final int FCONST_2 = 0x0d; 580 public static final int DCONST_0 = 0x0e; 581 public static final int DCONST_1 = 0x0f; 582 583 public static final int BIPUSH = 0x10; 584 public static final int SIPUSH = 0x11; 585 public static final int LDC = 0x12; 586 public static final int LDC_W = 0x13; 587 public static final int LDC2_W = 0x14; 588 public static final int ILOAD = 0x15; 589 public static final int LLOAD = 0x16; 590 public static final int FLOAD = 0x17; 591 public static final int DLOAD = 0x18; 592 public static final int ALOAD = 0x19; 593 public static final int ILOAD_0 = 0x1a; 594 public static final int ILOAD_1 = 0x1b; 595 public static final int ILOAD_2 = 0x1c; 596 public static final int ILOAD_3 = 0x1d; 597 public static final int LLOAD_0 = 0x1e; 598 public static final int LLOAD_1 = 0x1f; 599 600 public static final int LLOAD_2 = 0x20; 601 public static final int LLOAD_3 = 0x21; 602 public static final int FLOAD_0 = 0x22; 603 public static final int FLOAD_1 = 0x23; 604 public static final int FLOAD_2 = 0x24; 605 public static final int FLOAD_3 = 0x25; 606 public static final int DLOAD_0 = 0x26; 607 public static final int DLOAD_1 = 0x27; 608 public static final int DLOAD_2 = 0x28; 609 public static final int DLOAD_3 = 0x29; 610 public static final int ALOAD_0 = 0x2a; 611 public static final int ALOAD_1 = 0x2b; 612 public static final int ALOAD_2 = 0x2c; 613 public static final int ALOAD_3 = 0x2d; 614 public static final int IALOAD = 0x2e; 615 public static final int LALOAD = 0x2f; 616 617 public static final int FALOAD = 0x30; 618 public static final int DALOAD = 0x31; 619 public static final int AALOAD = 0x32; 620 public static final int BALOAD = 0x33; 621 public static final int CALOAD = 0x34; 622 public static final int SALOAD = 0x35; 623 public static final int ISTORE = 0x36; 624 public static final int LSTORE = 0x37; 625 public static final int FSTORE = 0x38; 626 public static final int DSTORE = 0x39; 627 public static final int ASTORE = 0x3a; 628 public static final int ISTORE_0 = 0x3b; 629 public static final int ISTORE_1 = 0x3c; 630 public static final int ISTORE_2 = 0x3d; 631 public static final int ISTORE_3 = 0x3e; 632 public static final int LSTORE_0 = 0x3f; 633 634 public static final int LSTORE_1 = 0x40; 635 public static final int LSTORE_2 = 0x41; 636 public static final int LSTORE_3 = 0x42; 637 public static final int FSTORE_0 = 0x43; 638 public static final int FSTORE_1 = 0x44; 639 public static final int FSTORE_2 = 0x45; 640 public static final int FSTORE_3 = 0x46; 641 public static final int DSTORE_0 = 0x47; 642 public static final int DSTORE_1 = 0x48; 643 public static final int DSTORE_2 = 0x49; 644 public static final int DSTORE_3 = 0x4a; 645 public static final int ASTORE_0 = 0x4b; 646 public static final int ASTORE_1 = 0x4c; 647 public static final int ASTORE_2 = 0x4d; 648 public static final int ASTORE_3 = 0x4e; 649 public static final int IASTORE = 0x4f; 650 651 public static final int LASTORE = 0x50; 652 public static final int FASTORE = 0x51; 653 public static final int DASTORE = 0x52; 654 public static final int AASTORE = 0x53; 655 public static final int BASTORE = 0x54; 656 public static final int CASTORE = 0x55; 657 public static final int SASTORE = 0x56; 658 public static final int POP = 0x57; 659 public static final int POP2 = 0x58; 660 public static final int DUP = 0x59; 661 public static final int DUP_X1 = 0x5a; 662 public static final int DUP_X2 = 0x5b; 663 public static final int DUP2 = 0x5c; 664 public static final int DUP2_X1 = 0x5d; 665 public static final int DUP2_X2 = 0x5e; 666 public static final int SWAP = 0x5f; 667 668 public static final int IADD = 0x60; 669 public static final int LADD = 0x61; 670 public static final int FADD = 0x62; 671 public static final int DADD = 0x63; 672 public static final int ISUB = 0x64; 673 public static final int LSUB = 0x65; 674 public static final int FSUB = 0x66; 675 public static final int DSUB = 0x67; 676 public static final int IMUL = 0x68; 677 public static final int LMUL = 0x69; 678 public static final int FMUL = 0x6a; 679 public static final int DMUL = 0x6b; 680 public static final int IDIV = 0x6c; 681 public static final int LDIV = 0x6d; 682 public static final int FDIV = 0x6e; 683 public static final int DDIV = 0x6f; 684 685 public static final int IREM = 0x70; 686 public static final int LREM = 0x71; 687 public static final int FREM = 0x72; 688 public static final int DREM = 0x73; 689 public static final int INEG = 0x74; 690 public static final int LNEG = 0x75; 691 public static final int FNEG = 0x76; 692 public static final int DNEG = 0x77; 693 public static final int ISHL = 0x78; 694 public static final int LSHL = 0x79; 695 public static final int ISHR = 0x7a; 696 public static final int LSHR = 0x7b; 697 public static final int IUSHR = 0x7c; 698 public static final int LUSHR = 0x7d; 699 public static final int IAND = 0x7e; 700 public static final int LAND = 0x7f; 701 702 public static final int IOR = 0x80; 703 public static final int LOR = 0x81; 704 public static final int IXOR = 0x82; 705 public static final int LXOR = 0x83; 706 public static final int IINC = 0x84; 707 public static final int I2L = 0x85; 708 public static final int I2F = 0x86; 709 public static final int I2D = 0x87; 710 public static final int L2I = 0x88; 711 public static final int L2F = 0x89; 712 public static final int L2D = 0x8a; 713 public static final int F2I = 0x8b; 714 public static final int F2L = 0x8c; 715 public static final int F2D = 0x8d; 716 public static final int D2I = 0x8e; 717 public static final int D2L = 0x8f; 718 719 public static final int D2F = 0x90; 720 public static final int I2B = 0x91; 721 public static final int I2C = 0x92; 722 public static final int I2S = 0x93; 723 public static final int LCMP = 0x94; 724 public static final int FCMPL = 0x95; 725 public static final int FCMPG = 0x96; 726 public static final int DCMPL = 0x97; 727 public static final int DCMPG = 0x98; 728 public static final int IFEQ = 0x99; 729 public static final int IFNE = 0x9a; 730 public static final int IFLT = 0x9b; 731 public static final int IFGE = 0x9c; 732 public static final int IFGT = 0x9d; 733 public static final int IFLE = 0x9e; 734 public static final int IF_ICMPEQ = 0x9f; 735 736 public static final int IF_ICMPNE = 0xa0; 737 public static final int IF_ICMPLT = 0xa1; 738 public static final int IF_ICMPGE = 0xa2; 739 public static final int IF_ICMPGT = 0xa3; 740 public static final int IF_ICMPLE = 0xa4; 741 public static final int IF_ACMPEQ = 0xa5; 742 public static final int IF_ACMPNE = 0xa6; 743 public static final int GOTO = 0xa7; 744 public static final int JSR = 0xa8; 745 public static final int RET = 0xa9; 746 public static final int TABLESWITCH = 0xaa; 747 public static final int LOOKUPSWITCH = 0xab; 748 public static final int IRETURN = 0xac; 749 public static final int LRETURN = 0xad; 750 public static final int FRETURN = 0xae; 751 public static final int DRETURN = 0xaf; 752 753 public static final int ARETURN = 0xb0; 754 public static final int RETURN = 0xb1; 755 public static final int GETSTATIC = 0xb2; 756 public static final int PUTSTATIC = 0xb3; 757 public static final int GETFIELD = 0xb4; 758 public static final int PUTFIELD = 0xb5; 759 public static final int INVOKEVIRTUAL = 0xb6; 760 public static final int INVOKESPECIAL = 0xb7; 761 public static final int INVOKESTATIC = 0xb8; 762 public static final int INVOKEINTERFACE = 0xb9; 763 public static final int RESERVED_0 = 0xba; 764 public static final int NEW = 0xbb; 765 public static final int NEWARRAY = 0xbc; 766 public static final int ANEWARRAY = 0xbd; 767 public static final int ARRAYLENGTH = 0xbe; 768 public static final int ATHROW = 0xbf; 769 770 public static final int CHECKCAST = 0xc0; 771 public static final int INSTANCEOF = 0xc1; 772 public static final int MONITORENTER = 0xc2; 773 public static final int MONITOREXIT = 0xc3; 774 public static final int WIDE = 0xc4; 775 public static final int MULTIANEWARRAY = 0xc5; 776 public static final int IFNULL = 0xc6; 777 public static final int IFNONNULL = 0xc7; 778 public static final int GOTO_W = 0xc8; 779 public static final int JSR_W = 0xc9; 780 781 783 private static final int OP_LEN[] = { 784 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 785 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 787 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 788 789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 790 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 791 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 792 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 793 794 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 795 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 796 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 99, 99, 0, 0, 0, 0, 797 0, 0, 2, 2, 2, 2, 2, 2, 2, 4, -1, 2, 1, 2, 0, 0, 798 799 2, 2, 0, 0, 99, 3, 2, 2, 4, 4, -1, -1, -1, -1, -1, -1, 800 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 801 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 802 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 803 }; 804 } 805 | Popular Tags |