1 19 20 package jode.bytecode; 21 import jode.GlobalOptions; 22 import java.io.DataInputStream ; 23 import java.io.DataOutputStream ; 24 import java.io.ByteArrayInputStream ; 25 import java.io.InputStream ; 26 import java.io.EOFException ; 27 import java.io.IOException ; 28 import java.util.BitSet ; 29 import java.util.Stack ; 30 import java.util.Vector ; 31 import java.util.Enumeration ; 32 import java.util.NoSuchElementException ; 33 34 import java.util.List ; 35 import java.util.AbstractSequentialList ; 36 import java.util.Iterator ; 37 import java.util.ListIterator ; 38 39 40 48 public class BytecodeInfo extends BinaryInfo implements Opcodes { 49 50 private MethodInfo methodInfo; 51 private int maxStack, maxLocals; 52 private Handler[] exceptionHandlers; 53 private LocalVariableInfo[] lvt; 54 private LineNumber[] lnt; 55 56 60 private Instruction[] instrs; 61 62 private InstructionList instructions; 63 64 private class InstructionList extends AbstractSequentialList { 65 Instruction borderInstr; 66 int instructionCount = 0; 67 68 InstructionList() { 69 borderInstr = new Instruction(opc_impdep1); 72 borderInstr.nextByAddr = borderInstr.prevByAddr = borderInstr; 73 } 74 75 public int size() { 76 return instructionCount; 77 } 78 79 Instruction get0(int index) { 80 Instruction instr = borderInstr; 81 if (index < instructionCount / 2) { 82 for (int i=0; i <= index; i++) 83 instr = instr.nextByAddr; 84 } else { 85 for (int i=instructionCount; i > index; i--) 86 instr = instr.prevByAddr; 87 } 88 return instr; 89 } 90 91 public Object get(int index) { 92 if (index < 0 || index >= instructionCount) 93 throw new IllegalArgumentException (); 94 return get0(index); 95 } 96 97 public boolean add(Object o) { 98 99 instructionCount++; 100 borderInstr.prevByAddr.appendInstruction((Instruction) o, 101 BytecodeInfo.this); 102 return true; 103 } 104 105 public ListIterator listIterator(final int startIndex) { 106 if (startIndex < 0 || startIndex > instructionCount) 107 throw new IllegalArgumentException (); 108 return new ListIterator () { 109 Instruction instr = get0(startIndex); 110 Instruction toRemove = null; 111 int index = startIndex; 112 113 public boolean hasNext() { 114 return index < instructionCount; 115 } 116 117 public boolean hasPrevious() { 118 return index > 0; 119 } 120 121 public Object next() { 122 if (index >= instructionCount) 123 throw new NoSuchElementException (); 124 index++; 125 toRemove = instr; 126 instr = instr.nextByAddr; 127 return toRemove; 129 } 130 131 public Object previous() { 132 if (index == 0) 133 throw new NoSuchElementException (); 134 index--; 135 instr = instr.prevByAddr; 136 toRemove = instr; 137 return toRemove; 139 } 140 141 public int nextIndex() { 142 return index; 143 } 144 145 public int previousIndex() { 146 return index - 1; 147 } 148 149 public void remove() { 150 if (toRemove == null) 151 throw new IllegalStateException (); 152 instructionCount--; 154 if (instr == toRemove) 155 instr = instr.nextByAddr; 156 else 157 index--; 158 toRemove.removeInstruction(BytecodeInfo.this); 159 toRemove = null; 160 } 161 162 public void add(Object o) { 163 instructionCount++; 164 index++; 165 instr.prevByAddr.appendInstruction((Instruction) o, 170 BytecodeInfo.this); 171 toRemove = null; 172 } 173 174 public void set(Object o) { 175 if (toRemove == null) 176 throw new IllegalStateException (); 177 toRemove.replaceInstruction((Instruction) o, 181 BytecodeInfo.this); 182 if (instr == toRemove) 183 instr = (Instruction) o; 184 toRemove = (Instruction) o; 185 } 186 }; 187 } 188 189 void setLastAddr(int addr) { 190 borderInstr.setAddr(addr); 191 } 192 193 int getCodeLength() { 194 return borderInstr.getAddr(); 195 } 196 } 197 198 public BytecodeInfo(MethodInfo mi) { 199 methodInfo = mi; 200 } 201 202 private final static Object [] constants = { 203 null, 204 new Integer (-1), new Integer (0), new Integer (1), 205 new Integer (2), new Integer (3), new Integer (4), new Integer (5), 206 new Long (0), new Long (1), 207 new Float (0), new Float (1), new Float (2), 208 new Double (0), new Double (1) 209 }; 210 211 protected void readAttribute(String name, int length, ConstantPool cp, 212 DataInputStream input, 213 int howMuch) throws IOException { 214 if ((howMuch & KNOWNATTRIBS) != 0 215 && name.equals("LocalVariableTable")) { 216 if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0) 217 GlobalOptions.err.println("LocalVariableTable of "+methodInfo); 218 int count = input.readUnsignedShort(); 219 if (length != 2 + count * 10) { 220 if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0) 221 GlobalOptions.err.println("Illegal LVT length, ignoring it"); 222 return; 223 } 224 lvt = new LocalVariableInfo[count]; 225 for (int i=0; i < count; i++) { 226 lvt[i] = new LocalVariableInfo(); 227 int start = input.readUnsignedShort(); 228 int end = start + input.readUnsignedShort(); 229 int nameIndex = input.readUnsignedShort(); 230 int typeIndex = input.readUnsignedShort(); 231 int slot = input.readUnsignedShort(); 232 Instruction startInstr = 233 start >= 0 && start < instrs.length ? instrs[start] : null; 234 Instruction endInstr; 235 if (end >=0 && end < instrs.length) 236 endInstr = instrs[end] == null ? null 237 : instrs[end].getPrevByAddr(); 238 else { 239 endInstr = null; 240 for (int nr = instrs.length - 1; nr >= 0; nr--) { 241 if (instrs[nr] != null) { 242 if (instrs[nr].getNextAddr() == end) 243 endInstr = instrs[nr]; 244 break; 245 } 246 } 247 } 248 249 if (startInstr == null 250 || endInstr == null 251 || nameIndex == 0 || typeIndex == 0 252 || slot >= maxLocals 253 || cp.getTag(nameIndex) != cp.UTF8 254 || cp.getTag(typeIndex) != cp.UTF8) { 255 256 if ((GlobalOptions.debuggingFlags 259 & GlobalOptions.DEBUG_LVT) != 0) 260 GlobalOptions.err.println 261 ("Illegal entry, ignoring LVT"); 262 lvt = null; 263 return; 264 } 265 lvt[i].start = startInstr; 266 lvt[i].end = endInstr; 267 lvt[i].name = cp.getUTF8(nameIndex); 268 lvt[i].type = cp.getUTF8(typeIndex); 269 lvt[i].slot = slot; 270 if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_LVT) != 0) 271 GlobalOptions.err.println("\t" + lvt[i].name + ": " 272 + lvt[i].type 273 +" range "+start+" - "+end 274 +" slot "+slot); 275 } 276 } else if ((howMuch & KNOWNATTRIBS) != 0 277 && name.equals("LineNumberTable")) { 278 int count = input.readUnsignedShort(); 279 if (length != 2 + count * 4) { 280 GlobalOptions.err.println 281 ("Illegal LineNumberTable, ignoring it"); 282 return; 283 } 284 lnt = new LineNumber[count]; 285 for (int i = 0; i < count; i++) { 286 lnt[i] = new LineNumber(); 287 int start = input.readUnsignedShort(); 288 Instruction startInstr = instrs[start]; 289 if (startInstr == null) { 290 GlobalOptions.err.println 291 ("Illegal entry, ignoring LineNumberTable table"); 292 lnt = null; 293 return; 294 } 295 lnt[i].start = startInstr; 296 lnt[i].linenr = input.readUnsignedShort(); 297 } 298 } else 299 super.readAttribute(name, length, cp, input, howMuch); 300 } 301 302 public void read(ConstantPool cp, 303 DataInputStream input) throws IOException { 304 maxStack = input.readUnsignedShort(); 305 maxLocals = input.readUnsignedShort(); 306 instructions = new InstructionList(); 307 int codeLength = input.readInt(); 308 instrs = new Instruction[codeLength]; 309 int[][] succAddrs = new int[codeLength][]; 310 { 311 int addr = 0; 312 while (addr < codeLength) { 313 Instruction instr; 314 int length; 315 int opcode = input.readUnsignedByte(); 316 if ((GlobalOptions.debuggingFlags 317 & GlobalOptions.DEBUG_BYTECODE) != 0) 318 if ((GlobalOptions.debuggingFlags 319 & GlobalOptions.DEBUG_BYTECODE) != 0) 320 GlobalOptions.err.print(addr+": "+opcodeString[opcode]); 321 322 switch (opcode) { 323 case opc_wide: { 324 int wideopcode = input.readUnsignedByte(); 325 switch (wideopcode) { 326 case opc_iload: case opc_fload: case opc_aload: 327 case opc_istore: case opc_fstore: case opc_astore: { 328 int slot = input.readUnsignedShort(); 329 if (slot >= maxLocals) 330 throw new ClassFormatError 331 ("Invalid local slot "+slot); 332 instr = new Instruction(wideopcode); 333 instr.setLocalSlot(slot); 334 length = 4; 335 if ((GlobalOptions.debuggingFlags 336 & GlobalOptions.DEBUG_BYTECODE) != 0) 337 GlobalOptions.err.print 338 (" " + opcodeString[wideopcode] + " " + slot); 339 break; 340 } 341 case opc_lload: case opc_dload: 342 case opc_lstore: case opc_dstore: { 343 int slot = input.readUnsignedShort(); 344 if (slot >= maxLocals-1) 345 throw new ClassFormatError 346 ("Invalid local slot "+slot); 347 instr = new Instruction(wideopcode); 348 instr.setLocalSlot(slot); 349 length = 4; 350 if ((GlobalOptions.debuggingFlags 351 & GlobalOptions.DEBUG_BYTECODE) != 0) 352 GlobalOptions.err.print 353 (" " + opcodeString[wideopcode] + " " + slot); 354 break; 355 } 356 case opc_ret: { 357 int slot = input.readUnsignedShort(); 358 if (slot >= maxLocals) 359 throw new ClassFormatError 360 ("Invalid local slot "+slot); 361 instr = new Instruction(wideopcode); 362 instr.setLocalSlot(slot); 363 length = 4; 364 if ((GlobalOptions.debuggingFlags 365 & GlobalOptions.DEBUG_BYTECODE) != 0) 366 GlobalOptions.err.print(" ret "+slot); 367 break; 368 } 369 case opc_iinc: { 370 int slot = input.readUnsignedShort(); 371 if (slot >= maxLocals) 372 throw new ClassFormatError 373 ("Invalid local slot "+slot); 374 instr = new Instruction(wideopcode); 375 instr.setLocalSlot(slot); 376 instr.setIncrement(input.readShort()); 377 length = 6; 378 if ((GlobalOptions.debuggingFlags 379 & GlobalOptions.DEBUG_BYTECODE) != 0) 380 GlobalOptions.err.print 381 (" iinc " + slot + " " + instr.getIncrement()); 382 break; 383 } 384 default: 385 throw new ClassFormatError ("Invalid wide opcode " 386 +wideopcode); 387 } 388 break; 389 } 390 case opc_iload_0: case opc_iload_1: 391 case opc_iload_2: case opc_iload_3: 392 case opc_lload_0: case opc_lload_1: 393 case opc_lload_2: case opc_lload_3: 394 case opc_fload_0: case opc_fload_1: 395 case opc_fload_2: case opc_fload_3: 396 case opc_dload_0: case opc_dload_1: 397 case opc_dload_2: case opc_dload_3: 398 case opc_aload_0: case opc_aload_1: 399 case opc_aload_2: case opc_aload_3: { 400 int slot = (opcode-opc_iload_0) & 3; 401 if (slot >= maxLocals) 402 throw new ClassFormatError 403 ("Invalid local slot "+slot); 404 instr = new Instruction(opc_iload + 405 (opcode-opc_iload_0)/4); 406 instr.setLocalSlot(slot); 407 length = 1; 408 break; 409 } 410 case opc_istore_0: case opc_istore_1: 411 case opc_istore_2: case opc_istore_3: 412 case opc_fstore_0: case opc_fstore_1: 413 case opc_fstore_2: case opc_fstore_3: 414 case opc_astore_0: case opc_astore_1: 415 case opc_astore_2: case opc_astore_3: { 416 int slot = (opcode-opc_istore_0) & 3; 417 if (slot >= maxLocals) 418 throw new ClassFormatError 419 ("Invalid local slot "+slot); 420 instr = new Instruction(opc_istore + 421 (opcode-opc_istore_0)/4); 422 instr.setLocalSlot(slot); 423 length = 1; 424 break; 425 } 426 case opc_lstore_0: case opc_lstore_1: 427 case opc_lstore_2: case opc_lstore_3: 428 case opc_dstore_0: case opc_dstore_1: 429 case opc_dstore_2: case opc_dstore_3: { 430 int slot = (opcode-opc_istore_0) & 3; 431 if (slot >= maxLocals-1) 432 throw new ClassFormatError 433 ("Invalid local slot "+slot); 434 instr = new Instruction(opc_istore 435 + (opcode-opc_istore_0)/4); 436 instr.setLocalSlot(slot); 437 length = 1; 438 break; 439 } 440 case opc_iload: case opc_fload: case opc_aload: 441 case opc_istore: case opc_fstore: case opc_astore: { 442 int slot = input.readUnsignedByte(); 443 if (slot >= maxLocals) 444 throw new ClassFormatError 445 ("Invalid local slot "+slot); 446 instr = new Instruction(opcode); 447 instr.setLocalSlot(slot); 448 length = 2; 449 if ((GlobalOptions.debuggingFlags 450 & GlobalOptions.DEBUG_BYTECODE) != 0) 451 GlobalOptions.err.print(" "+slot); 452 break; 453 } 454 case opc_lstore: case opc_dstore: 455 case opc_lload: case opc_dload: { 456 int slot = input.readUnsignedByte(); 457 if (slot >= maxLocals - 1) 458 throw new ClassFormatError 459 ("Invalid local slot "+slot); 460 instr = new Instruction(opcode); 461 instr.setLocalSlot(slot); 462 length = 2; 463 if ((GlobalOptions.debuggingFlags 464 & GlobalOptions.DEBUG_BYTECODE) != 0) 465 GlobalOptions.err.print(" "+slot); 466 break; 467 } 468 case opc_ret: { 469 int slot = input.readUnsignedByte(); 470 if (slot >= maxLocals) 471 throw new ClassFormatError 472 ("Invalid local slot "+slot); 473 instr = new Instruction(opcode); 474 instr.setLocalSlot(slot); 475 length = 2; 476 if ((GlobalOptions.debuggingFlags 477 & GlobalOptions.DEBUG_BYTECODE) != 0) 478 GlobalOptions.err.print(" "+slot); 479 break; 480 } 481 case opc_aconst_null: 482 case opc_iconst_m1: 483 case opc_iconst_0: case opc_iconst_1: case opc_iconst_2: 484 case opc_iconst_3: case opc_iconst_4: case opc_iconst_5: 485 case opc_fconst_0: case opc_fconst_1: case opc_fconst_2: 486 instr = new Instruction(opc_ldc); 487 instr.setConstant 488 (constants[opcode - opc_aconst_null]); 489 length = 1; 490 break; 491 case opc_lconst_0: case opc_lconst_1: 492 case opc_dconst_0: case opc_dconst_1: 493 instr = new Instruction(opc_ldc2_w); 494 instr.setConstant 495 (constants[opcode - opc_aconst_null]); 496 length = 1; 497 break; 498 case opc_bipush: 499 instr = new Instruction(opc_ldc); 500 instr.setConstant(new Integer (input.readByte())); 501 length = 2; 502 break; 503 case opc_sipush: 504 instr = new Instruction(opc_ldc); 505 instr.setConstant(new Integer (input.readShort())); 506 length = 3; 507 break; 508 case opc_ldc: { 509 int index = input.readUnsignedByte(); 510 int tag = cp.getTag(index); 511 if (tag != cp.STRING 512 && tag != cp.INTEGER && tag != cp.FLOAT) 513 throw new ClassFormatException 514 ("wrong constant tag: "+tag); 515 instr = new Instruction(opcode); 516 instr.setConstant(cp.getConstant(index)); 517 length = 2; 518 break; 519 } 520 case opc_ldc_w: { 521 int index = input.readUnsignedShort(); 522 int tag = cp.getTag(index); 523 if (tag != cp.STRING 524 && tag != cp.INTEGER && tag != cp.FLOAT) 525 throw new ClassFormatException 526 ("wrong constant tag: "+tag); 527 instr = new Instruction(opc_ldc); 528 instr.setConstant(cp.getConstant(index)); 529 length = 3; 530 break; 531 } 532 case opc_ldc2_w: { 533 int index = input.readUnsignedShort(); 534 int tag = cp.getTag(index); 535 if (tag != cp.LONG && tag != cp.DOUBLE) 536 throw new ClassFormatException 537 ("wrong constant tag: "+tag); 538 instr = new Instruction(opcode); 539 instr.setConstant(cp.getConstant(index)); 540 length = 3; 541 break; 542 } 543 case opc_iinc: { 544 int slot = input.readUnsignedByte(); 545 if (slot >= maxLocals) 546 throw new ClassFormatError 547 ("Invalid local slot "+slot); 548 instr = new Instruction(opcode); 549 instr.setLocalSlot(slot); 550 instr.setIncrement(input.readByte()); 551 length = 3; 552 if ((GlobalOptions.debuggingFlags 553 & GlobalOptions.DEBUG_BYTECODE) != 0) 554 GlobalOptions.err.print 555 (" " + slot + " " + instr.getIncrement()); 556 break; 557 } 558 case opc_goto: 559 case opc_jsr: 560 case opc_ifeq: case opc_ifne: 561 case opc_iflt: case opc_ifge: 562 case opc_ifgt: case opc_ifle: 563 case opc_if_icmpeq: case opc_if_icmpne: 564 case opc_if_icmplt: case opc_if_icmpge: 565 case opc_if_icmpgt: case opc_if_icmple: 566 case opc_if_acmpeq: case opc_if_acmpne: 567 case opc_ifnull: case opc_ifnonnull: 568 instr = new Instruction(opcode); 569 length = 3; 570 succAddrs[addr] = new int[] { addr+input.readShort() }; 571 if ((GlobalOptions.debuggingFlags 572 & GlobalOptions.DEBUG_BYTECODE) != 0) 573 GlobalOptions.err.print(" "+succAddrs[addr][0]); 574 break; 575 576 case opc_goto_w: 577 case opc_jsr_w: 578 instr = new Instruction(opcode - (opc_goto_w - opc_goto)); 579 length = 5; 580 succAddrs[addr] = new int[] { addr+input.readInt() }; 581 if ((GlobalOptions.debuggingFlags 582 & GlobalOptions.DEBUG_BYTECODE) != 0) 583 GlobalOptions.err.print(" "+succAddrs[addr][0]); 584 break; 585 586 case opc_tableswitch: { 587 length = 3 - (addr % 4); 588 input.readFully(new byte[length]); 589 int def = input.readInt(); 590 int low = input.readInt(); 591 int high = input.readInt(); 592 int[] dests = new int[high-low+1]; 593 int npairs = 0; 594 for (int i=0; i < dests.length; i++) { 595 dests[i] = input.readInt(); 596 if (dests[i] != def) 597 npairs++; 598 } 599 instr = new Instruction(opc_lookupswitch); 600 succAddrs[addr] = new int[npairs + 1]; 601 int[] values = new int[npairs]; 602 int pos = 0; 603 for (int i=0; i < dests.length; i++) { 604 if (dests[i] != def) { 605 values[pos] = i+low; 606 succAddrs[addr][pos] = addr + dests[i]; 607 pos++; 608 } 609 } 610 succAddrs[addr][npairs] = addr + def; 611 instr.setValues(values); 612 length += 13 + 4 * (high-low+1); 613 break; 614 } 615 case opc_lookupswitch: { 616 length = 3 - (addr % 4); 617 input.readFully(new byte[length]); 618 int def = input.readInt(); 619 int npairs = input.readInt(); 620 instr = new Instruction(opcode); 621 succAddrs[addr] = new int[npairs + 1]; 622 int[] values = new int[npairs]; 623 for (int i=0; i < npairs; i++) { 624 values[i] = input.readInt(); 625 if (i > 0 && values[i-1] >= values[i]) 626 throw new ClassFormatException 627 ("lookupswitch not sorted"); 628 succAddrs[addr][i] = addr + input.readInt(); 629 } 630 succAddrs[addr][npairs] = addr + def; 631 instr.setValues(values); 632 length += 9 + 8 * npairs; 633 break; 634 } 635 636 case opc_getstatic: 637 case opc_getfield: 638 case opc_putstatic: 639 case opc_putfield: 640 case opc_invokespecial: 641 case opc_invokestatic: 642 case opc_invokevirtual: { 643 int index = input.readUnsignedShort(); 644 int tag = cp.getTag(index); 645 if (opcode < opc_invokevirtual) { 646 if (tag != cp.FIELDREF) 647 throw new ClassFormatException 648 ("field tag mismatch: "+tag); 649 } else { 650 if (tag != cp.METHODREF) 651 throw new ClassFormatException 652 ("method tag mismatch: "+tag); 653 } 654 Reference ref = cp.getRef(index); 655 if (ref.getName().charAt(0) == '<' 656 && (!ref.getName().equals("<init>") 657 || opcode != opc_invokespecial)) 658 throw new ClassFormatException 659 ("Illegal call of special method/field "+ref); 660 instr = new Instruction(opcode); 661 instr.setReference(ref); 662 length = 3; 663 if ((GlobalOptions.debuggingFlags 664 & GlobalOptions.DEBUG_BYTECODE) != 0) 665 GlobalOptions.err.print(" "+ref); 666 break; 667 } 668 case opc_invokeinterface: { 669 int index = input.readUnsignedShort(); 670 int tag = cp.getTag(index); 671 if (tag != cp.INTERFACEMETHODREF) 672 throw new ClassFormatException 673 ("interface tag mismatch: "+tag); 674 Reference ref = cp.getRef(index); 675 if (ref.getName().charAt(0) == '<') 676 throw new ClassFormatException 677 ("Illegal call of special method "+ref); 678 int nargs = input.readUnsignedByte(); 679 if (TypeSignature.getArgumentSize(ref.getType()) 680 != nargs - 1) 681 throw new ClassFormatException 682 ("Interface nargs mismatch: "+ref+" vs. "+nargs); 683 if (input.readUnsignedByte() != 0) 684 throw new ClassFormatException 685 ("Interface reserved param not zero"); 686 687 instr = new Instruction(opcode); 688 instr.setReference(ref); 689 length = 5; 690 if ((GlobalOptions.debuggingFlags 691 & GlobalOptions.DEBUG_BYTECODE) != 0) 692 GlobalOptions.err.print(" "+ref); 693 break; 694 } 695 696 case opc_new: 697 case opc_checkcast: 698 case opc_instanceof: { 699 String type = cp.getClassType(input.readUnsignedShort()); 700 if (opcode == opc_new && type.charAt(0) == '[') 701 throw new ClassFormatException 702 ("Can't create array with opc_new"); 703 instr = new Instruction(opcode); 704 instr.setClazzType(type); 705 length = 3; 706 if ((GlobalOptions.debuggingFlags 707 & GlobalOptions.DEBUG_BYTECODE) != 0) 708 GlobalOptions.err.print(" "+type); 709 break; 710 } 711 case opc_multianewarray: { 712 String type = cp.getClassType(input.readUnsignedShort()); 713 int dims = input.readUnsignedByte(); 714 if (dims == 0) 715 throw new ClassFormatException 716 ("multianewarray dimension is 0."); 717 for (int i=0; i < dims; i++) { 718 723 if (type.charAt(i) != '[') 724 throw new ClassFormatException 725 ("multianewarray called for non array:"+ type); 726 } 727 instr = new Instruction(opcode); 728 instr.setClazzType(type); 729 instr.setDimensions(dims); 730 length = 4; 731 if ((GlobalOptions.debuggingFlags 732 & GlobalOptions.DEBUG_BYTECODE) != 0) 733 GlobalOptions.err.print(" " + type + " " + dims); 734 break; 735 } 736 case opc_anewarray: { 737 String type = cp.getClassType(input.readUnsignedShort()); 738 instr = new Instruction(opc_multianewarray); 739 instr.setClazzType(("["+type).intern()); 740 instr.setDimensions(1); 741 length = 3; 742 if ((GlobalOptions.debuggingFlags 743 & GlobalOptions.DEBUG_BYTECODE) != 0) 744 GlobalOptions.err.print(" "+type); 745 break; 746 } 747 case opc_newarray: { 748 char sig = newArrayTypes.charAt 749 (input.readUnsignedByte()-4); 750 String type = new String (new char[] { '[', sig }); 751 if ((GlobalOptions.debuggingFlags 752 & GlobalOptions.DEBUG_BYTECODE) != 0) 753 GlobalOptions.err.print(" "+type); 754 instr = new Instruction(opc_multianewarray); 755 instr.setClazzType(type); 756 instr.setDimensions(1); 757 length = 2; 758 break; 759 } 760 761 case opc_nop: 762 case opc_iaload: case opc_laload: case opc_faload: 763 case opc_daload: case opc_aaload: 764 case opc_baload: case opc_caload: case opc_saload: 765 case opc_iastore: case opc_lastore: case opc_fastore: 766 case opc_dastore: case opc_aastore: 767 case opc_bastore: case opc_castore: case opc_sastore: 768 case opc_pop: case opc_pop2: 769 case opc_dup: case opc_dup_x1: case opc_dup_x2: 770 case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: 771 case opc_swap: 772 case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: 773 case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: 774 case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: 775 case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: 776 case opc_irem: case opc_lrem: case opc_frem: case opc_drem: 777 case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: 778 case opc_ishl: case opc_lshl: 779 case opc_ishr: case opc_lshr: 780 case opc_iushr: case opc_lushr: 781 case opc_iand: case opc_land: 782 case opc_ior: case opc_lor: 783 case opc_ixor: case opc_lxor: 784 case opc_i2l: case opc_i2f: case opc_i2d: 785 case opc_l2i: case opc_l2f: case opc_l2d: 786 case opc_f2i: case opc_f2l: case opc_f2d: 787 case opc_d2i: case opc_d2l: case opc_d2f: 788 case opc_i2b: case opc_i2c: case opc_i2s: 789 case opc_lcmp: case opc_fcmpl: case opc_fcmpg: 790 case opc_dcmpl: case opc_dcmpg: 791 case opc_ireturn: case opc_lreturn: 792 case opc_freturn: case opc_dreturn: case opc_areturn: 793 case opc_return: 794 case opc_athrow: 795 case opc_arraylength: 796 case opc_monitorenter: case opc_monitorexit: 797 instr = new Instruction(opcode); 798 length = 1; 799 break; 800 default: 801 throw new ClassFormatError ("Invalid opcode "+opcode); 802 } 803 if ((GlobalOptions.debuggingFlags 804 & GlobalOptions.DEBUG_BYTECODE) != 0) 805 GlobalOptions.err.println(); 806 807 instrs[addr] = instr; 808 instructions.add(instr); 809 810 addr += length; 811 instructions.setLastAddr(addr); 812 } 813 if (addr != codeLength) 814 throw new ClassFormatError ("last instruction too long"); 815 } 816 for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { 817 Instruction instr = (Instruction) iter.next(); 818 int addr = instr.getAddr(); 819 if (succAddrs[addr] != null) { 820 int length = succAddrs[addr].length; 821 Instruction[] succs = new Instruction[length]; 822 for (int i=0; i < length; i++) { 823 int succAddr = succAddrs[addr][i]; 824 if (succAddr < 0 || succAddr > codeLength 825 || instrs[succAddr] == null) 826 throw new ClassFormatException 827 ("Illegal jump target at " 828 +this+"@"+addr); 829 succs[i] = instrs[succAddr]; 830 } 831 instr.setSuccs(succs); 832 } 833 } 834 succAddrs = null; 835 836 { 837 int handlersLength = input.readUnsignedShort(); 838 exceptionHandlers = new Handler[handlersLength]; 839 for (int i=0; i< handlersLength; i ++) { 840 exceptionHandlers[i] = new Handler(); 841 exceptionHandlers[i].start 842 = instrs[input.readUnsignedShort()]; 843 exceptionHandlers[i].end 844 = instrs[input.readUnsignedShort()].getPrevByAddr(); 845 exceptionHandlers[i].catcher 846 = instrs[input.readUnsignedShort()]; 847 int index = input.readUnsignedShort(); 848 exceptionHandlers[i].type = (index == 0) ? null 849 : cp.getClassName(index); 850 851 if (exceptionHandlers[i].catcher.getOpcode() == opc_athrow) { 852 856 handlersLength--; 857 i--; 858 continue; 859 } 860 861 if (exceptionHandlers[i].start.getAddr() 862 <= exceptionHandlers[i].catcher.getAddr() 863 && exceptionHandlers[i].end.getAddr() 864 >= exceptionHandlers[i].catcher.getAddr()) 865 { 866 871 if (exceptionHandlers[i].start 872 == exceptionHandlers[i].catcher) { 873 handlersLength--; 874 i--; 875 } else { 876 exceptionHandlers[i].end = 877 exceptionHandlers[i].catcher.getPrevByAddr(); 878 } 879 } 880 } 881 if (handlersLength < exceptionHandlers.length) { 882 Handler[] newHandlers = new Handler[handlersLength]; 883 System.arraycopy(exceptionHandlers, 0, newHandlers, 0, 884 handlersLength); 885 exceptionHandlers = newHandlers; 886 } 887 } 888 readAttributes(cp, input, FULLINFO); 889 instrs = null; 890 } 891 892 public void dumpCode(java.io.PrintWriter output) { 893 for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { 894 Instruction instr = (Instruction) iter.next(); 895 output.println(instr.getDescription() + " " 896 + Integer.toHexString(hashCode())); 897 Instruction[] succs = instr.getSuccs(); 898 if (succs != null) { 899 output.print("\tsuccs: "+succs[0]); 900 for (int i = 1; i < succs.length; i++) 901 output.print(", "+succs[i]); 902 output.println(); 903 } 904 if (instr.getPreds() != null) { 905 output.print("\tpreds: " + instr.getPreds()[0]); 906 for (int i=1; i < instr.getPreds().length; i++) 907 output.print(", " + instr.getPreds()[i]); 908 output.println(); 909 } 910 } 911 for (int i=0; i< exceptionHandlers.length; i++) { 912 output.println("catch " + exceptionHandlers[i].type 913 + " from " + exceptionHandlers[i].start 914 + " to " + exceptionHandlers[i].end 915 + " catcher " + exceptionHandlers[i].catcher); 916 } 917 } 918 919 public void reserveSmallConstants(GrowableConstantPool gcp) { 920 next_instr: 921 for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { 922 Instruction instr = (Instruction) iter.next(); 923 if (instr.getOpcode() == opc_ldc) { 924 Object constant = instr.getConstant(); 925 if (constant == null) 926 continue next_instr; 927 for (int i=1; i < constants.length; i++) { 928 if (constant.equals(constants[i])) 929 continue next_instr; 930 } 931 if (constant instanceof Integer ) { 932 int value = ((Integer ) constant).intValue(); 933 if (value >= Short.MIN_VALUE 934 && value <= Short.MAX_VALUE) 935 continue next_instr; 936 } 937 gcp.reserveConstant(constant); 938 } 939 } 940 } 941 942 private void calculateMaxStack() { 943 maxStack = 0; 944 int[] stackHeights = new int[instructions.getCodeLength()]; 945 int[] poppush = new int[2]; 946 Stack todo = new Stack (); 947 948 for (int i=0; i < stackHeights.length; i++) 949 stackHeights[i] = -1; 950 951 stackHeights[0] = 0; 952 todo.push(instructions.get(0)); 953 while (!todo.isEmpty()) { 954 Instruction instr = (Instruction) todo.pop(); 955 Instruction next = instr.getNextByAddr(); 956 Instruction[] succs = instr.getSuccs(); 957 int addr = instr.getAddr(); 958 instr.getStackPopPush(poppush); 959 int sh = stackHeights[addr] - poppush[0] + poppush[1]; 960 if (maxStack < sh) 963 maxStack = sh; 964 if (instr.getOpcode() == opc_jsr) { 965 if (stackHeights[next.getAddr()] == -1) { 966 stackHeights[next.getAddr()] = sh - 1; 967 todo.push(next); 968 } 969 if (stackHeights[succs[0].getAddr()] == -1) { 970 stackHeights[succs[0].getAddr()] = sh; 971 todo.push(succs[0]); 972 } 973 } else { 974 if (succs != null) { 975 for (int i=0; i < succs.length; i++) { 976 if (stackHeights[succs[i].getAddr()] == -1) { 977 stackHeights[succs[i].getAddr()] = sh; 978 todo.push(succs[i]); 979 } 980 } 981 } 982 if (!instr.doesAlwaysJump() 983 && stackHeights[next.getAddr()] == -1) { 984 stackHeights[next.getAddr()] = sh; 985 todo.push(next); 986 } 987 } 988 for (int i=0; i< exceptionHandlers.length; i++) { 989 if (exceptionHandlers[i].start.compareTo(instr) <= 0 990 && exceptionHandlers[i].end.compareTo(instr) >= 0) { 991 int catcher = exceptionHandlers[i].catcher.getAddr(); 992 if (stackHeights[catcher] == -1) { 993 stackHeights[catcher] = 1; 994 todo.push(exceptionHandlers[i].catcher); 995 } 996 } 997 } 998 } 999 } 1001 1002 public void prepareWriting(GrowableConstantPool gcp) { 1003 1005 int addr = 0; 1006 maxLocals = (methodInfo.isStatic() ? 0 : 1) + 1007 TypeSignature.getArgumentSize(methodInfo.getType()); 1008 1009 for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { 1010 Instruction instr = (Instruction) iter.next(); 1011 int opcode = instr.getOpcode(); 1012 instr.setAddr(addr); 1013 int length; 1014 switch_opc: 1015 switch (opcode) { 1016 case opc_ldc: 1017 case opc_ldc2_w: { 1018 Object constant = instr.getConstant(); 1019 if (constant == null) { 1020 length = 1; 1021 break switch_opc; 1022 } 1023 for (int i=1; i < constants.length; i++) { 1024 if (constant.equals(constants[i])) { 1025 length = 1; 1026 break switch_opc; 1027 } 1028 } 1029 if (opcode == opc_ldc2_w) { 1030 gcp.putLongConstant(constant); 1031 length = 3; 1032 break switch_opc; 1033 } 1034 if (constant instanceof Integer ) { 1035 int value = ((Integer ) constant).intValue(); 1036 if (value >= Byte.MIN_VALUE 1037 && value <= Byte.MAX_VALUE) { 1038 length = 2; 1039 break switch_opc; 1040 } else if (value >= Short.MIN_VALUE 1041 && value <= Short.MAX_VALUE) { 1042 length = 3; 1043 break switch_opc; 1044 } 1045 } 1046 if (gcp.putConstant(constant) < 256) { 1047 length = 2; 1048 } else { 1049 length = 3; 1050 } 1051 break; 1052 } 1053 case opc_iinc: { 1054 int slot = instr.getLocalSlot(); 1055 int increment = instr.getIncrement(); 1056 if (slot < 256 1057 && increment >= Byte.MIN_VALUE 1058 && increment <= Byte.MAX_VALUE) 1059 length = 3; 1060 else 1061 length = 6; 1062 if (slot >= maxLocals) 1063 maxLocals = slot + 1; 1064 break; 1065 } 1066 case opc_iload: case opc_fload: case opc_aload: 1067 case opc_istore: case opc_fstore: case opc_astore: { 1068 int slot = instr.getLocalSlot(); 1069 if (slot < 4) 1070 length = 1; 1071 else if (slot < 256) 1072 length = 2; 1073 else 1074 length = 4; 1075 if (slot >= maxLocals) 1076 maxLocals = slot + 1; 1077 break; 1078 } 1079 case opc_lload: case opc_dload: 1080 case opc_lstore: case opc_dstore: { 1081 int slot = instr.getLocalSlot(); 1082 if (slot < 4) 1083 length = 1; 1084 else if (slot < 256) 1085 length = 2; 1086 else 1087 length = 4; 1088 if (slot+1 >= maxLocals) 1089 maxLocals = slot + 2; 1090 break; 1091 } 1092 case opc_ret: { 1093 int slot = instr.getLocalSlot(); 1094 if (slot < 256) 1095 length = 2; 1096 else 1097 length = 4; 1098 if (slot >= maxLocals) 1099 maxLocals = slot + 1; 1100 break; 1101 } 1102 case opc_lookupswitch: { 1103 length = 3-(addr % 4); 1104 int[] values = instr.getValues(); 1105 int npairs = values.length; 1106 if (npairs > 0) { 1107 int tablesize = values[npairs-1] - values[0] + 1; 1108 if (4 + tablesize * 4 < 8 * npairs) { 1109 length += 13 + 4 * tablesize; 1111 break; 1112 } 1113 } 1114 length += 9 + 8 * npairs; 1116 break; 1117 } 1118 case opc_goto: case opc_jsr: { 1119 int dist = instr.getSingleSucc().getAddr() - instr.getAddr(); 1120 if (dist < Short.MIN_VALUE || dist > Short.MAX_VALUE) { 1121 1122 length = 5; 1123 break; 1124 } 1125 1126 } 1127 case opc_ifeq: case opc_ifne: 1128 case opc_iflt: case opc_ifge: 1129 case opc_ifgt: case opc_ifle: 1130 case opc_if_icmpeq: case opc_if_icmpne: 1131 case opc_if_icmplt: case opc_if_icmpge: 1132 case opc_if_icmpgt: case opc_if_icmple: 1133 case opc_if_acmpeq: case opc_if_acmpne: 1134 case opc_ifnull: case opc_ifnonnull: 1135 length = 3; 1136 break; 1137 case opc_multianewarray: { 1138 if (instr.getDimensions() == 1) { 1139 String clazz = instr.getClazzType().substring(1); 1140 if (newArrayTypes.indexOf(clazz.charAt(0)) != -1) { 1141 length = 2; 1142 } else { 1143 gcp.putClassType(clazz); 1144 length = 3; 1145 } 1146 } else { 1147 gcp.putClassType(instr.getClazzType()); 1148 length = 4; 1149 } 1150 break; 1151 } 1152 case opc_getstatic: 1153 case opc_getfield: 1154 case opc_putstatic: 1155 case opc_putfield: 1156 gcp.putRef(gcp.FIELDREF, instr.getReference()); 1157 length = 3; 1158 break; 1159 case opc_invokespecial: 1160 case opc_invokestatic: 1161 case opc_invokevirtual: 1162 gcp.putRef(gcp.METHODREF, instr.getReference()); 1163 length = 3; 1164 break; 1165 case opc_invokeinterface: 1166 gcp.putRef(gcp.INTERFACEMETHODREF, instr.getReference()); 1167 length = 5; 1168 break; 1169 case opc_new: 1170 case opc_checkcast: 1171 case opc_instanceof: 1172 gcp.putClassType(instr.getClazzType()); 1173 length = 3; 1174 break; 1175 case opc_nop: 1176 case opc_iaload: case opc_laload: case opc_faload: 1177 case opc_daload: case opc_aaload: 1178 case opc_baload: case opc_caload: case opc_saload: 1179 case opc_iastore: case opc_lastore: case opc_fastore: 1180 case opc_dastore: case opc_aastore: 1181 case opc_bastore: case opc_castore: case opc_sastore: 1182 case opc_pop: case opc_pop2: 1183 case opc_dup: case opc_dup_x1: case opc_dup_x2: 1184 case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: 1185 case opc_swap: 1186 case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: 1187 case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: 1188 case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: 1189 case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: 1190 case opc_irem: case opc_lrem: case opc_frem: case opc_drem: 1191 case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: 1192 case opc_ishl: case opc_lshl: 1193 case opc_ishr: case opc_lshr: 1194 case opc_iushr: case opc_lushr: 1195 case opc_iand: case opc_land: 1196 case opc_ior: case opc_lor: 1197 case opc_ixor: case opc_lxor: 1198 case opc_i2l: case opc_i2f: case opc_i2d: 1199 case opc_l2i: case opc_l2f: case opc_l2d: 1200 case opc_f2i: case opc_f2l: case opc_f2d: 1201 case opc_d2i: case opc_d2l: case opc_d2f: 1202 case opc_i2b: case opc_i2c: case opc_i2s: 1203 case opc_lcmp: case opc_fcmpl: case opc_fcmpg: 1204 case opc_dcmpl: case opc_dcmpg: 1205 case opc_ireturn: case opc_lreturn: 1206 case opc_freturn: case opc_dreturn: case opc_areturn: 1207 case opc_return: 1208 case opc_athrow: 1209 case opc_arraylength: 1210 case opc_monitorenter: case opc_monitorexit: 1211 length = 1; 1212 break; 1213 default: 1214 throw new ClassFormatError ("Invalid opcode "+opcode); 1215 } 1216 addr += length; 1217 } 1218 instructions.setLastAddr(addr); 1219 try { 1220 calculateMaxStack(); 1221 } catch (RuntimeException ex) { 1222 ex.printStackTrace(); 1223 dumpCode(GlobalOptions.err); 1224 } 1225 for (int i=0; i< exceptionHandlers.length; i++) 1226 if (exceptionHandlers[i].type != null) 1227 gcp.putClassName(exceptionHandlers[i].type); 1228 if (lvt != null) { 1229 gcp.putUTF8("LocalVariableTable"); 1230 for (int i=0; i < lvt.length; i++) { 1231 gcp.putUTF8(lvt[i].name); 1232 gcp.putUTF8(lvt[i].type); 1233 } 1234 } 1235 if (lnt != null) 1236 gcp.putUTF8("LineNumberTable"); 1237 prepareAttributes(gcp); 1238 } 1239 1240 protected int getKnownAttributeCount() { 1241 int count = 0; 1242 if (lvt != null) 1243 count++; 1244 if (lnt != null) 1245 count++; 1246 return count; 1247 } 1248 1249 public void writeKnownAttributes(GrowableConstantPool gcp, 1250 DataOutputStream output) 1251 throws IOException { 1252 if (lvt != null) { 1253 output.writeShort(gcp.putUTF8("LocalVariableTable")); 1254 int count = lvt.length; 1255 int length = 2 + 10 * count; 1256 output.writeInt(length); 1257 output.writeShort(count); 1258 for (int i=0; i < count; i++) { 1259 output.writeShort(lvt[i].start.getAddr()); 1260 output.writeShort(lvt[i].end.getAddr() + lvt[i].end.getLength() 1261 - lvt[i].start.getAddr()); 1262 output.writeShort(gcp.putUTF8(lvt[i].name)); 1263 output.writeShort(gcp.putUTF8(lvt[i].type)); 1264 output.writeShort(lvt[i].slot); 1265 } 1266 } 1267 if (lnt != null) { 1268 output.writeShort(gcp.putUTF8("LineNumberTable")); 1269 int count = lnt.length; 1270 int length = 2 + 4 * count; 1271 output.writeInt(length); 1272 output.writeShort(count); 1273 for (int i=0; i < count; i++) { 1274 output.writeShort(lnt[i].start.getAddr()); 1275 output.writeShort(lnt[i].linenr); 1276 } 1277 } 1278 } 1279 1280 public void write(GrowableConstantPool gcp, 1281 DataOutputStream output) throws IOException { 1282 output.writeShort(maxStack); 1283 output.writeShort(maxLocals); 1284 output.writeInt(instructions.getCodeLength()); 1285 for (Iterator iter = instructions.iterator(); iter.hasNext(); ) { 1286 Instruction instr = (Instruction) iter.next(); 1287 int opcode = instr.getOpcode(); 1288 switch_opc: 1289 switch (opcode) { 1290 case opc_iload: case opc_lload: 1291 case opc_fload: case opc_dload: case opc_aload: 1292 case opc_istore: case opc_lstore: 1293 case opc_fstore: case opc_dstore: case opc_astore: { 1294 int slot = instr.getLocalSlot(); 1295 if (slot < 4) { 1296 if (opcode < opc_istore) 1297 output.writeByte(opc_iload_0 1298 + 4*(opcode-opc_iload) 1299 + slot); 1300 else 1301 output.writeByte(opc_istore_0 1302 + 4*(opcode-opc_istore) 1303 + slot); 1304 } else if (slot < 256) { 1305 output.writeByte(opcode); 1306 output.writeByte(slot); 1307 } else { 1308 output.writeByte(opc_wide); 1309 output.writeByte(opcode); 1310 output.writeShort(slot); 1311 } 1312 break; 1313 } 1314 case opc_ret: { 1315 int slot = instr.getLocalSlot(); 1316 if (slot < 256) { 1317 output.writeByte(opcode); 1318 output.writeByte(slot); 1319 } else { 1320 output.writeByte(opc_wide); 1321 output.writeByte(opcode); 1322 output.writeShort(slot); 1323 } 1324 break; 1325 } 1326 case opc_ldc: 1327 case opc_ldc2_w: { 1328 Object constant = instr.getConstant(); 1329 if (constant == null) { 1330 output.writeByte(opc_aconst_null); 1331 break switch_opc; 1332 } 1333 for (int i=1; i < constants.length; i++) { 1334 if (constant.equals(constants[i])) { 1335 output.writeByte(opc_aconst_null + i); 1336 break switch_opc; 1337 } 1338 } 1339 if (opcode == opc_ldc2_w) { 1340 output.writeByte(opcode); 1341 output.writeShort(gcp.putLongConstant(constant)); 1342 } else { 1343 if (constant instanceof Integer ) { 1344 int value = ((Integer ) constant).intValue(); 1345 if (value >= Byte.MIN_VALUE 1346 && value <= Byte.MAX_VALUE) { 1347 1348 output.writeByte(opc_bipush); 1349 output.writeByte(((Integer )constant) 1350 .intValue()); 1351 break switch_opc; 1352 } else if (value >= Short.MIN_VALUE 1353 && value <= Short.MAX_VALUE) { 1354 output.writeByte(opc_sipush); 1355 output.writeShort(((Integer )constant) 1356 .intValue()); 1357 break switch_opc; 1358 } 1359 } 1360 if (instr.getLength() == 2) { 1361 output.writeByte(opc_ldc); 1362 output.writeByte(gcp.putConstant(constant)); 1363 } else { 1364 output.writeByte(opc_ldc_w); 1365 output.writeShort(gcp.putConstant(constant)); 1366 } 1367 } 1368 break; 1369 } 1370 case opc_iinc: { 1371 int slot = instr.getLocalSlot(); 1372 int incr = instr.getIncrement(); 1373 if (instr.getLength() == 3) { 1374 output.writeByte(opcode); 1375 output.writeByte(slot); 1376 output.writeByte(incr); 1377 } else { 1378 output.writeByte(opc_wide); 1379 output.writeByte(opcode); 1380 output.writeShort(slot); 1381 output.writeShort(incr); 1382 } 1383 break; 1384 } 1385 case opc_goto: 1386 case opc_jsr: 1387 if (instr.getLength() == 5) { 1388 1389 output.writeByte(opcode + (opc_goto_w - opc_goto)); 1390 output.writeInt(instr.getSingleSucc().getAddr() 1391 - instr.getAddr()); 1392 break; 1393 } 1394 1395 case opc_ifeq: case opc_ifne: 1396 case opc_iflt: case opc_ifge: 1397 case opc_ifgt: case opc_ifle: 1398 case opc_if_icmpeq: case opc_if_icmpne: 1399 case opc_if_icmplt: case opc_if_icmpge: 1400 case opc_if_icmpgt: case opc_if_icmple: 1401 case opc_if_acmpeq: case opc_if_acmpne: 1402 case opc_ifnull: case opc_ifnonnull: 1403 output.writeByte(opcode); 1404 output.writeShort(instr.getSingleSucc().getAddr() 1405 - instr.getAddr()); 1406 break; 1407 1408 case opc_lookupswitch: { 1409 int align = 3-(instr.getAddr() % 4); 1410 int[] values = instr.getValues(); 1411 int npairs = values.length; 1412 int defAddr = instr.getSuccs()[npairs].getAddr() 1413 - instr.getAddr(); 1414 1415 if (npairs > 0) { 1416 int tablesize = values[npairs-1] - values[0] + 1; 1417 if (4 + tablesize * 4 < 8 * npairs) { 1418 output.writeByte(opc_tableswitch); 1420 output.write(new byte[align]); 1421 1422 output.writeInt(defAddr); 1423 1424 output.writeInt(values[0]); 1425 1426 output.writeInt(values[npairs-1]); 1427 int pos = values[0]; 1428 for (int i = 0; i < npairs; i++) { 1429 while (pos++ < values[i]) 1430 output.writeInt(defAddr); 1431 output.writeInt(instr.getSuccs()[i].getAddr() 1432 - instr.getAddr()); 1433 } 1434 break; 1435 } 1436 } 1437 output.writeByte(opc_lookupswitch); 1439 output.write(new byte[align]); 1440 1441 output.writeInt(defAddr); 1442 output.writeInt(npairs); 1443 for (int i=0; i < npairs; i++) { 1444 output.writeInt(values[i]); 1445 output.writeInt(instr.getSuccs()[i].getAddr() 1446 -instr.getAddr()); 1447 } 1448 break; 1449 } 1450 1451 case opc_getstatic: 1452 case opc_getfield: 1453 case opc_putstatic: 1454 case opc_putfield: 1455 output.writeByte(opcode); 1456 output.writeShort(gcp.putRef(gcp.FIELDREF, 1457 instr.getReference())); 1458 break; 1459 1460 case opc_invokespecial: 1461 case opc_invokestatic: 1462 case opc_invokeinterface: 1463 case opc_invokevirtual: { 1464 Reference ref = instr.getReference(); 1465 output.writeByte(opcode); 1466 if (opcode == opc_invokeinterface) { 1467 output.writeShort(gcp.putRef(gcp.INTERFACEMETHODREF, ref)); 1468 output.writeByte 1469 (TypeSignature.getArgumentSize(ref.getType()) + 1); 1470 output.writeByte(0); 1471 } else 1472 output.writeShort(gcp.putRef(gcp.METHODREF, ref)); 1473 break; 1474 } 1475 case opc_new: 1476 case opc_checkcast: 1477 case opc_instanceof: 1478 output.writeByte(opcode); 1479 output.writeShort(gcp.putClassType(instr.getClazzType())); 1480 break; 1481 case opc_multianewarray: 1482 if (instr.getDimensions() == 1) { 1483 String clazz = instr.getClazzType().substring(1); 1484 int index = newArrayTypes.indexOf(clazz.charAt(0)); 1485 if (index != -1) { 1486 output.writeByte(opc_newarray); 1487 output.writeByte(index + 4); 1488 } else { 1489 output.writeByte(opc_anewarray); 1490 output.writeShort(gcp.putClassType(clazz)); 1491 } 1492 } else { 1493 output.writeByte(opcode); 1494 output.writeShort(gcp.putClassType(instr.getClazzType())); 1495 output.writeByte(instr.getDimensions()); 1496 } 1497 break; 1498 1499 case opc_nop: 1500 case opc_iaload: case opc_laload: case opc_faload: 1501 case opc_daload: case opc_aaload: 1502 case opc_baload: case opc_caload: case opc_saload: 1503 case opc_iastore: case opc_lastore: case opc_fastore: 1504 case opc_dastore: case opc_aastore: 1505 case opc_bastore: case opc_castore: case opc_sastore: 1506 case opc_pop: case opc_pop2: 1507 case opc_dup: case opc_dup_x1: case opc_dup_x2: 1508 case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: 1509 case opc_swap: 1510 case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: 1511 case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: 1512 case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: 1513 case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: 1514 case opc_irem: case opc_lrem: case opc_frem: case opc_drem: 1515 case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: 1516 case opc_ishl: case opc_lshl: 1517 case opc_ishr: case opc_lshr: 1518 case opc_iushr: case opc_lushr: 1519 case opc_iand: case opc_land: 1520 case opc_ior: case opc_lor: 1521 case opc_ixor: case opc_lxor: 1522 case opc_i2l: case opc_i2f: case opc_i2d: 1523 case opc_l2i: case opc_l2f: case opc_l2d: 1524 case opc_f2i: case opc_f2l: case opc_f2d: 1525 case opc_d2i: case opc_d2l: case opc_d2f: 1526 case opc_i2b: case opc_i2c: case opc_i2s: 1527 case opc_lcmp: case opc_fcmpl: case opc_fcmpg: 1528 case opc_dcmpl: case opc_dcmpg: 1529 case opc_ireturn: case opc_lreturn: 1530 case opc_freturn: case opc_dreturn: case opc_areturn: 1531 case opc_return: 1532 case opc_athrow: 1533 case opc_arraylength: 1534 case opc_monitorenter: case opc_monitorexit: 1535 output.writeByte(opcode); 1536 break; 1537 default: 1538 throw new ClassFormatError ("Invalid opcode "+opcode); 1539 } 1540 } 1541 1542 output.writeShort(exceptionHandlers.length); 1543 for (int i=0; i< exceptionHandlers.length; i++) { 1544 output.writeShort(exceptionHandlers[i].start.getAddr()); 1545 output.writeShort(exceptionHandlers[i].end.getNextByAddr().getAddr()); 1546 output.writeShort(exceptionHandlers[i].catcher.getAddr()); 1547 output.writeShort((exceptionHandlers[i].type == null) ? 0 1548 : gcp.putClassName(exceptionHandlers[i].type)); 1549 } 1550 writeAttributes(gcp, output); 1551 } 1552 1553 public void dropInfo(int howMuch) { 1554 if ((howMuch & KNOWNATTRIBS) != 0) { 1555 lvt = null; 1556 lnt = null; 1557 } 1558 super.dropInfo(howMuch); 1559 } 1560 1561 public int getSize() { 1562 1578 int size = 0; 1579 if (lvt != null) 1580 size += 8 + lvt.length * 10; 1581 if (lnt != null) 1582 size += 8 + lnt.length * 4; 1583 return 10 + instructions.getCodeLength() 1584 + exceptionHandlers.length * 8 1585 + getAttributeSize() + size; 1586 } 1587 1588 public int getMaxStack() { 1589 return maxStack; 1590 } 1591 1592 public int getMaxLocals() { 1593 return maxLocals; 1594 } 1595 1596 public MethodInfo getMethodInfo() { 1597 return methodInfo; 1598 } 1599 1600 public List getInstructions() { 1601 return instructions; 1602 } 1603 1604 public Handler[] getExceptionHandlers() { 1605 return exceptionHandlers; 1606 } 1607 1608 public LocalVariableInfo[] getLocalVariableTable() { 1609 return lvt; 1610 } 1611 1612 public LineNumber[] getLineNumberTable() { 1613 return lnt; 1614 } 1615 1616 public void setExceptionHandlers(Handler[] handlers) { 1617 exceptionHandlers = handlers; 1618 } 1619 1620 public void setLocalVariableTable(LocalVariableInfo[] newLvt) { 1621 lvt = newLvt; 1622 } 1623 1624 public void setLineNumberTable(LineNumber[] newLnt) { 1625 lnt = newLnt; 1626 } 1627 1628 public String toString() { 1629 return "Bytecode "+methodInfo; 1630 } 1631} 1632 | Popular Tags |