1 /* 2 * Javassist, a Java-bytecode translator toolkit. 3 * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. 4 * 5 * The contents of this file are subject to the Mozilla Public License Version 6 * 1.1 (the "License"); you may not use this file except in compliance with 7 * the License. Alternatively, the contents of this file may be used under 8 * the terms of the GNU Lesser General Public License Version 2.1 or later, 9 * or the Apache License Version 2.0. 10 * 11 * Software distributed under the License is distributed on an "AS IS" basis, 12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 * for the specific language governing rights and limitations under the 14 * License. 15 */ 16 17 package javassist.bytecode; 18 19 import java.util.ArrayList; 20 import java.util.List; 21 22 /** 23 * An iterator for editing a code attribute. 24 * 25 * <p>To directly read or edit a bytecode sequence, call {@link #byteAt(int)}, {@link #s16bitAt(int)}, 26 * {@link #writeByte(int, int)}, {@link #write16bit(int, int)}, and other methods. 27 * For example, if <code>method</code> refers to a <code>CtMethod</code> object, 28 * the following code substitutes the <code>NOP</code> instruction for the first 29 * instruction of the method: 30 * 31 * <pre> 32 * CodeAttribute ca = method.getMethodInfo().getCodeAttribute(); 33 * CodeIterator ci = ca.iterator(); 34 * ci.writeByte(Opcode.NOP, 0);</pre> 35 * 36 * <p>To visit every instruction, call {@link #next()} on a <code>CodeIterator</code>. 37 * It returns the index of the first byte of the next instruction. 38 * 39 * <p>If there are multiple <code>CodeIterator</code>s referring to the 40 * same <code>Code_attribute</code>, then inserting a gap by one 41 * <code>CodeIterator</code> will break the other 42 * <code>CodeIterator</code>. 43 * 44 * <p>This iterator does not provide <code>remove()</code>. 45 * If a piece of code in a <code>Code_attribute</code> is unnecessary, 46 * it should be overwritten with <code>NOP</code>. 47 * 48 * @see CodeAttribute#iterator() 49 */ 50 public class CodeIterator implements Opcode { 51 protected CodeAttribute codeAttr; 52 protected byte[] bytecode; 53 protected int endPos; 54 protected int currentPos; 55 protected int mark; 56 CodeIterator(CodeAttribute ca)57 protected CodeIterator(CodeAttribute ca) { 58 codeAttr = ca; 59 bytecode = ca.getCode(); 60 begin(); 61 } 62 63 /** 64 * Moves to the first instruction. 65 */ begin()66 public void begin() { 67 currentPos = mark = 0; 68 endPos = getCodeLength(); 69 } 70 71 /** 72 * Moves to the given index. 73 * 74 * <p>The index of the next instruction is set to the given index. 75 * The successive call to <code>next()</code> 76 * returns the index that has been given to <code>move()</code>. 77 * 78 * <p>Note that the index is into the byte array returned by 79 * <code>get().getCode()</code>. 80 * 81 * @see CodeAttribute#getCode() 82 */ move(int index)83 public void move(int index) { 84 currentPos = index; 85 } 86 87 /** 88 * Sets a mark to the bytecode at the given index. 89 * The mark can be used to track the position of that bytecode 90 * when code blocks are inserted. 91 * If a code block is inclusively inserted at the position of the 92 * bytecode, the mark is set to the inserted code block. 93 * 94 * @see #getMark() 95 * @since 3.11 96 */ setMark(int index)97 public void setMark(int index) { 98 mark = index; 99 } 100 101 /** 102 * Gets the index of the position of the mark set by 103 * <code>setMark</code>. 104 * 105 * @return the index of the position. 106 * @see #setMark(int) 107 * @since 3.11 108 */ getMark()109 public int getMark() { return mark; } 110 111 /** 112 * Returns a Code attribute read with this iterator. 113 */ get()114 public CodeAttribute get() { 115 return codeAttr; 116 } 117 118 /** 119 * Returns <code>code_length</code> of <code>Code_attribute</code>. 120 */ getCodeLength()121 public int getCodeLength() { 122 return bytecode.length; 123 } 124 125 /** 126 * Returns the unsigned 8bit value at the given index. 127 */ byteAt(int index)128 public int byteAt(int index) { return bytecode[index] & 0xff; } 129 130 /** 131 * Returns the signed 8bit value at the given index. 132 */ signedByteAt(int index)133 public int signedByteAt(int index) { return bytecode[index]; } 134 135 /** 136 * Writes an 8bit value at the given index. 137 */ writeByte(int value, int index)138 public void writeByte(int value, int index) { 139 bytecode[index] = (byte)value; 140 } 141 142 /** 143 * Returns the unsigned 16bit value at the given index. 144 */ u16bitAt(int index)145 public int u16bitAt(int index) { 146 return ByteArray.readU16bit(bytecode, index); 147 } 148 149 /** 150 * Returns the signed 16bit value at the given index. 151 */ s16bitAt(int index)152 public int s16bitAt(int index) { 153 return ByteArray.readS16bit(bytecode, index); 154 } 155 156 /** 157 * Writes a 16 bit integer at the index. 158 */ write16bit(int value, int index)159 public void write16bit(int value, int index) { 160 ByteArray.write16bit(value, bytecode, index); 161 } 162 163 /** 164 * Returns the signed 32bit value at the given index. 165 */ s32bitAt(int index)166 public int s32bitAt(int index) { 167 return ByteArray.read32bit(bytecode, index); 168 } 169 170 /** 171 * Writes a 32bit integer at the index. 172 */ write32bit(int value, int index)173 public void write32bit(int value, int index) { 174 ByteArray.write32bit(value, bytecode, index); 175 } 176 177 /** 178 * Writes a byte array at the index. 179 * 180 * @param code may be a zero-length array. 181 */ write(byte[] code, int index)182 public void write(byte[] code, int index) { 183 int len = code.length; 184 for (int j = 0; j < len; ++j) 185 bytecode[index++] = code[j]; 186 } 187 188 /** 189 * Returns true if there is more instructions. 190 */ hasNext()191 public boolean hasNext() { return currentPos < endPos; } 192 193 /** 194 * Returns the index of the next instruction 195 * (not the operand following the current opcode). 196 * 197 * <p>Note that the index is into the byte array returned by 198 * <code>get().getCode()</code>. 199 * 200 * @see CodeAttribute#getCode() 201 * @see CodeIterator#byteAt(int) 202 */ next()203 public int next() throws BadBytecode { 204 int pos = currentPos; 205 currentPos = nextOpcode(bytecode, pos); 206 return pos; 207 } 208 209 /** 210 * Obtains the value that the next call 211 * to <code>next()</code> will return. 212 * 213 * <p>This method is side-effects free. 214 * Successive calls to <code>lookAhead()</code> return the 215 * same value until <code>next()</code> is called. 216 */ lookAhead()217 public int lookAhead() { 218 return currentPos; 219 } 220 221 /** 222 * Moves to the instruction for 223 * either <code>super()</code> or <code>this()</code>. 224 * 225 * <p>This method skips all the instructions for computing arguments 226 * to <code>super()</code> or <code>this()</code>, which should be 227 * placed at the beginning of a constructor body. 228 * 229 * <p>This method returns the index of INVOKESPECIAL instruction 230 * executing <code>super()</code> or <code>this()</code>. 231 * A successive call to <code>next()</code> returns the 232 * index of the next instruction following that INVOKESPECIAL. 233 * 234 * <p>This method works only for a constructor. 235 * 236 * @return the index of the INVOKESPECIAL instruction, or -1 237 * if a constructor invocation is not found. 238 */ skipConstructor()239 public int skipConstructor() throws BadBytecode { 240 return skipSuperConstructor0(-1); 241 } 242 243 /** 244 * Moves to the instruction for <code>super()</code>. 245 * 246 * <p>This method skips all the instructions for computing arguments to 247 * <code>super()</code>, which should be 248 * placed at the beginning of a constructor body. 249 * 250 * <p>This method returns the index of INVOKESPECIAL instruction 251 * executing <code>super()</code>. 252 * A successive call to <code>next()</code> returns the 253 * index of the next instruction following that INVOKESPECIAL. 254 * 255 * <p>This method works only for a constructor. 256 * 257 * @return the index of the INVOKESPECIAL instruction, or -1 258 * if a super constructor invocation is not found 259 * but <code>this()</code> is found. 260 */ skipSuperConstructor()261 public int skipSuperConstructor() throws BadBytecode { 262 return skipSuperConstructor0(0); 263 } 264 265 /** 266 * Moves to the instruction for <code>this()</code>. 267 * 268 * <p>This method skips all the instructions for computing arguments to 269 * <code>this()</code>, which should be 270 * placed at the beginning of a constructor body. 271 * 272 * <p>This method returns the index of INVOKESPECIAL instruction 273 * executing <code>this()</code>. 274 * A successive call to <code>next()</code> returns the 275 * index of the next instruction following that INVOKESPECIAL. 276 * 277 * <p>This method works only for a constructor. 278 * 279 * @return the index of the INVOKESPECIAL instruction, or -1 280 * if a explicit constructor invocation is not found 281 * but <code>super()</code> is found. 282 */ skipThisConstructor()283 public int skipThisConstructor() throws BadBytecode { 284 return skipSuperConstructor0(1); 285 } 286 287 /* skipSuper 1: this(), 0: super(), -1: both. 288 */ skipSuperConstructor0(int skipThis)289 private int skipSuperConstructor0(int skipThis) throws BadBytecode { 290 begin(); 291 ConstPool cp = codeAttr.getConstPool(); 292 String thisClassName = codeAttr.getDeclaringClass(); 293 int nested = 0; 294 while (hasNext()) { 295 int index = next(); 296 int c = byteAt(index); 297 if (c == NEW) 298 ++nested; 299 else if (c == INVOKESPECIAL) { 300 int mref = ByteArray.readU16bit(bytecode, index + 1); 301 if (cp.getMethodrefName(mref).equals(MethodInfo.nameInit)) 302 if (--nested < 0) { 303 if (skipThis < 0) 304 return index; 305 306 String cname = cp.getMethodrefClassName(mref); 307 if (cname.equals(thisClassName) == (skipThis > 0)) 308 return index; 309 310 break; 311 } 312 } 313 } 314 315 begin(); 316 return -1; 317 } 318 319 /** 320 * Inserts the given bytecode sequence 321 * before the next instruction that would be returned by 322 * <code>next()</code> (not before the instruction returned 323 * by the last call to <code>next()</code>). 324 * Branch offsets and the exception table are also updated. 325 * 326 * <p>If the next instruction is at the beginning of a block statement, 327 * then the bytecode is inserted within that block. 328 * 329 * <p>An extra gap may be inserted at the end of the inserted 330 * bytecode sequence for adjusting alignment if the code attribute 331 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 332 * 333 * @param code inserted bytecode sequence. 334 * @return the index indicating the first byte of the 335 * inserted byte sequence. 336 */ insert(byte[] code)337 public int insert(byte[] code) 338 throws BadBytecode 339 { 340 return insert0(currentPos, code, false); 341 } 342 343 /** 344 * Inserts the given bytecode sequence 345 * before the instruction at the given index <code>pos</code>. 346 * Branch offsets and the exception table are also updated. 347 * 348 * <p>If the instruction at the given index is at the beginning 349 * of a block statement, 350 * then the bytecode is inserted within that block. 351 * 352 * <p>An extra gap may be inserted at the end of the inserted 353 * bytecode sequence for adjusting alignment if the code attribute 354 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 355 * 356 * <p>The index at which the byte sequence is actually inserted 357 * might be different from pos since some other bytes might be 358 * inserted at other positions (e.g. to change <code>GOTO</code> 359 * to <code>GOTO_W</code>). 360 * 361 * @param pos the index at which a byte sequence is inserted. 362 * @param code inserted bytecode sequence. 363 */ insert(int pos, byte[] code)364 public void insert(int pos, byte[] code) throws BadBytecode { 365 insert0(pos, code, false); 366 } 367 368 /** 369 * Inserts the given bytecode sequence 370 * before the instruction at the given index <code>pos</code>. 371 * Branch offsets and the exception table are also updated. 372 * 373 * <p>If the instruction at the given index is at the beginning 374 * of a block statement, 375 * then the bytecode is inserted within that block. 376 * 377 * <p>An extra gap may be inserted at the end of the inserted 378 * bytecode sequence for adjusting alignment if the code attribute 379 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 380 * 381 * @param pos the index at which a byte sequence is inserted. 382 * @param code inserted bytecode sequence. 383 * @return the index indicating the first byte of the 384 * inserted byte sequence, which might be 385 * different from pos. 386 * @since 3.11 387 */ insertAt(int pos, byte[] code)388 public int insertAt(int pos, byte[] code) throws BadBytecode { 389 return insert0(pos, code, false); 390 } 391 392 /** 393 * Inserts the given bytecode sequence exclusively 394 * before the next instruction that would be returned by 395 * <code>next()</code> (not before the instruction returned 396 * by tha last call to <code>next()</code>). 397 * Branch offsets and the exception table are also updated. 398 * 399 * <p>If the next instruction is at the beginning of a block statement, 400 * then the bytecode is excluded from that block. 401 * 402 * <p>An extra gap may be inserted at the end of the inserted 403 * bytecode sequence for adjusting alignment if the code attribute 404 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 405 * 406 * @param code inserted bytecode sequence. 407 * @return the index indicating the first byte of the 408 * inserted byte sequence. 409 */ insertEx(byte[] code)410 public int insertEx(byte[] code) 411 throws BadBytecode 412 { 413 return insert0(currentPos, code, true); 414 } 415 416 /** 417 * Inserts the given bytecode sequence exclusively 418 * before the instruction at the given index <code>pos</code>. 419 * Branch offsets and the exception table are also updated. 420 * 421 * <p>If the instruction at the given index is at the beginning 422 * of a block statement, 423 * then the bytecode is excluded from that block. 424 * 425 * <p>An extra gap may be inserted at the end of the inserted 426 * bytecode sequence for adjusting alignment if the code attribute 427 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 428 * 429 * <p>The index at which the byte sequence is actually inserted 430 * might be different from pos since some other bytes might be 431 * inserted at other positions (e.g. to change <code>GOTO</code> 432 * to <code>GOTO_W</code>). 433 * 434 * @param pos the index at which a byte sequence is inserted. 435 * @param code inserted bytecode sequence. 436 */ insertEx(int pos, byte[] code)437 public void insertEx(int pos, byte[] code) throws BadBytecode { 438 insert0(pos, code, true); 439 } 440 441 /** 442 * Inserts the given bytecode sequence exclusively 443 * before the instruction at the given index <code>pos</code>. 444 * Branch offsets and the exception table are also updated. 445 * 446 * <p>If the instruction at the given index is at the beginning 447 * of a block statement, 448 * then the bytecode is excluded from that block. 449 * 450 * <p>An extra gap may be inserted at the end of the inserted 451 * bytecode sequence for adjusting alignment if the code attribute 452 * includes <code>LOOKUPSWITCH</code> or <code>TABLESWITCH</code>. 453 * 454 * @param pos the index at which a byte sequence is inserted. 455 * @param code inserted bytecode sequence. 456 * @return the index indicating the first byte of the 457 * inserted byte sequence, which might be 458 * different from pos. 459 * @since 3.11 460 */ insertExAt(int pos, byte[] code)461 public int insertExAt(int pos, byte[] code) throws BadBytecode { 462 return insert0(pos, code, true); 463 } 464 465 /** 466 * @return the index indicating the first byte of the 467 * inserted byte sequence. 468 */ insert0(int pos, byte[] code, boolean exclusive)469 private int insert0(int pos, byte[] code, boolean exclusive) 470 throws BadBytecode 471 { 472 int len = code.length; 473 if (len <= 0) 474 return pos; 475 476 // currentPos will change. 477 pos = insertGapAt(pos, len, exclusive).position; 478 479 int p = pos; 480 for (int j = 0; j < len; ++j) 481 bytecode[p++] = code[j]; 482 483 return pos; 484 } 485 486 /** 487 * Inserts a gap 488 * before the next instruction that would be returned by 489 * <code>next()</code> (not before the instruction returned 490 * by the last call to <code>next()</code>). 491 * Branch offsets and the exception table are also updated. 492 * The inserted gap is filled with NOP. The gap length may be 493 * extended to a multiple of 4. 494 * 495 * <p>If the next instruction is at the beginning of a block statement, 496 * then the gap is inserted within that block. 497 * 498 * @param length gap length 499 * @return the index indicating the first byte of the inserted gap. 500 */ insertGap(int length)501 public int insertGap(int length) throws BadBytecode { 502 return insertGapAt(currentPos, length, false).position; 503 } 504 505 /** 506 * Inserts a gap in front of the instruction at the given 507 * index <code>pos</code>. 508 * Branch offsets and the exception table are also updated. 509 * The inserted gap is filled with NOP. The gap length may be 510 * extended to a multiple of 4. 511 * 512 * <p>If the instruction at the given index is at the beginning 513 * of a block statement, 514 * then the gap is inserted within that block. 515 * 516 * @param pos the index at which a gap is inserted. 517 * @param length gap length. 518 * @return the length of the inserted gap. 519 * It might be bigger than <code>length</code>. 520 */ insertGap(int pos, int length)521 public int insertGap(int pos, int length) throws BadBytecode { 522 return insertGapAt(pos, length, false).length; 523 } 524 525 /** 526 * Inserts an exclusive gap 527 * before the next instruction that would be returned by 528 * <code>next()</code> (not before the instruction returned 529 * by the last call to <code>next()</code>). 530 * Branch offsets and the exception table are also updated. 531 * The inserted gap is filled with NOP. The gap length may be 532 * extended to a multiple of 4. 533 * 534 * <p>If the next instruction is at the beginning of a block statement, 535 * then the gap is excluded from that block. 536 * 537 * @param length gap length 538 * @return the index indicating the first byte of the inserted gap. 539 */ insertExGap(int length)540 public int insertExGap(int length) throws BadBytecode { 541 return insertGapAt(currentPos, length, true).position; 542 } 543 544 /** 545 * Inserts an exclusive gap in front of the instruction at the given 546 * index <code>pos</code>. 547 * Branch offsets and the exception table are also updated. 548 * The inserted gap is filled with NOP. The gap length may be 549 * extended to a multiple of 4. 550 * 551 * <p>If the instruction at the given index is at the beginning 552 * of a block statement, 553 * then the gap is excluded from that block. 554 * 555 * @param pos the index at which a gap is inserted. 556 * @param length gap length. 557 * @return the length of the inserted gap. 558 * It might be bigger than <code>length</code>. 559 */ insertExGap(int pos, int length)560 public int insertExGap(int pos, int length) throws BadBytecode { 561 return insertGapAt(pos, length, true).length; 562 } 563 564 /** 565 * An inserted gap. 566 * 567 * @since 3.11 568 */ 569 public static class Gap { 570 /** 571 * The position of the gap. 572 */ 573 public int position; 574 575 /** 576 * The length of the gap. 577 */ 578 public int length; 579 } 580 581 /** 582 * Inserts an inclusive or exclusive gap in front of the instruction 583 * at the given index <code>pos</code>. 584 * Branch offsets and the exception table in the method body 585 * are also updated. The inserted gap is filled with NOP. 586 * The gap length may be extended to a multiple of 4. 587 * 588 * <p>Suppose that the instruction at the given index is at the 589 * beginning of a block statement. If the gap is inclusive, 590 * then it is included within that block. If the gap is exclusive, 591 * then it is excluded from that block. 592 * 593 * <p>The index at which the gap is actually inserted 594 * might be different from pos since some other bytes might be 595 * inserted at other positions (e.g. to change <code>GOTO</code> 596 * to <code>GOTO_W</code>). The index is available from the <code>Gap</code> 597 * object returned by this method. 598 * 599 * <p>Suppose that the gap is inserted at the position of 600 * the next instruction that would be returned by 601 * <code>next()</code> (not the last instruction returned 602 * by the last call to <code>next()</code>). The next 603 * instruction returned by <code>next()</code> after the gap is 604 * inserted is still the same instruction. It is not <code>NOP</code> 605 * at the first byte of the inserted gap. 606 * 607 * @param pos the index at which a gap is inserted. 608 * @param length gap length. 609 * @param exclusive true if exclusive, otherwise false. 610 * @return the position and the length of the inserted gap. 611 * @since 3.11 612 */ insertGapAt(int pos, int length, boolean exclusive)613 public Gap insertGapAt(int pos, int length, boolean exclusive) 614 throws BadBytecode 615 { 616 /** 617 * cursorPos indicates the next bytecode whichever exclusive is 618 * true or false. 619 */ 620 Gap gap = new Gap(); 621 if (length <= 0) { 622 gap.position = pos; 623 gap.length = 0; 624 return gap; 625 } 626 627 byte[] c; 628 int length2; 629 if (bytecode.length + length > Short.MAX_VALUE) { 630 // currentPos might change after calling insertGapCore0w(). 631 c = insertGapCore0w(bytecode, pos, length, exclusive, 632 get().getExceptionTable(), codeAttr, gap); 633 pos = gap.position; 634 length2 = length; // == gap.length 635 } 636 else { 637 int cur = currentPos; 638 c = insertGapCore0(bytecode, pos, length, exclusive, 639 get().getExceptionTable(), codeAttr); 640 // insertGapCore0() never changes pos. 641 length2 = c.length - bytecode.length; 642 gap.position = pos; 643 gap.length = length2; 644 if (cur >= pos) 645 currentPos = cur + length2; 646 647 if (mark > pos || (mark == pos && exclusive)) 648 mark += length2; 649 } 650 651 codeAttr.setCode(c); 652 bytecode = c; 653 endPos = getCodeLength(); 654 updateCursors(pos, length2); 655 return gap; 656 } 657 658 /** 659 * Is called when a gap is inserted. The default implementation is empty. 660 * A subclass can override this method so that cursors will be updated. 661 * 662 * @param pos the position where a gap is inserted. 663 * @param length the length of the gap. 664 */ updateCursors(int pos, int length)665 protected void updateCursors(int pos, int length) { 666 // empty 667 } 668 669 /** 670 * Copies and inserts the entries in the given exception table 671 * at the beginning of the exception table in the code attribute 672 * edited by this object. 673 * 674 * @param offset the value added to the code positions included 675 * in the entries. 676 */ insert(ExceptionTable et, int offset)677 public void insert(ExceptionTable et, int offset) { 678 codeAttr.getExceptionTable().add(0, et, offset); 679 } 680 681 /** 682 * Appends the given bytecode sequence at the end. 683 * 684 * @param code the bytecode appended. 685 * @return the position of the first byte of the appended bytecode. 686 */ append(byte[] code)687 public int append(byte[] code) { 688 int size = getCodeLength(); 689 int len = code.length; 690 if (len <= 0) 691 return size; 692 693 appendGap(len); 694 byte[] dest = bytecode; 695 for (int i = 0; i < len; ++i) 696 dest[i + size] = code[i]; 697 698 return size; 699 } 700 701 /** 702 * Appends a gap at the end of the bytecode sequence. 703 * 704 * @param gapLength gap length 705 */ appendGap(int gapLength)706 public void appendGap(int gapLength) { 707 byte[] code = bytecode; 708 int codeLength = code.length; 709 byte[] newcode = new byte[codeLength + gapLength]; 710 711 int i; 712 for (i = 0; i < codeLength; ++i) 713 newcode[i] = code[i]; 714 715 for (i = codeLength; i < codeLength + gapLength; ++i) 716 newcode[i] = NOP; 717 718 codeAttr.setCode(newcode); 719 bytecode = newcode; 720 endPos = getCodeLength(); 721 } 722 723 /** 724 * Copies and appends the entries in the given exception table 725 * at the end of the exception table in the code attribute 726 * edited by this object. 727 * 728 * @param offset the value added to the code positions included 729 * in the entries. 730 */ append(ExceptionTable et, int offset)731 public void append(ExceptionTable et, int offset) { 732 ExceptionTable table = codeAttr.getExceptionTable(); 733 table.add(table.size(), et, offset); 734 } 735 736 /* opcodeLegth is used for implementing nextOpcode(). 737 */ 738 private static final int opcodeLength[] = { 739 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 740 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 741 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, 742 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 743 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 744 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 745 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 746 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 747 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, 748 3, 3, 3, 3, 3, 5, 5, 3, 2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3, 749 5, 5 750 }; 751 // 0 .. LOOKUPSWITCH, TABLESWITCH, WIDE 752 753 /** 754 * Calculates the index of the next opcode. 755 */ nextOpcode(byte[] code, int index)756 static int nextOpcode(byte[] code, int index) 757 throws BadBytecode 758 { 759 int opcode; 760 try { 761 opcode = code[index] & 0xff; 762 } 763 catch (IndexOutOfBoundsException e) { 764 throw new BadBytecode("invalid opcode address"); 765 } 766 767 try { 768 int len = opcodeLength[opcode]; 769 if (len > 0) 770 return index + len; 771 else if (opcode == WIDE) 772 if (code[index + 1] == (byte)IINC) // WIDE IINC 773 return index + 6; 774 else 775 return index + 4; // WIDE ... 776 int index2 = (index & ~3) + 8; 777 if (opcode == LOOKUPSWITCH) { 778 int npairs = ByteArray.read32bit(code, index2); 779 return index2 + npairs * 8 + 4; 780 } 781 else if (opcode == TABLESWITCH) { 782 int low = ByteArray.read32bit(code, index2); 783 int high = ByteArray.read32bit(code, index2 + 4); 784 return index2 + (high - low + 1) * 4 + 8; 785 } 786 } 787 catch (IndexOutOfBoundsException e) { 788 } 789 790 // opcode is UNUSED or an IndexOutOfBoundsException was thrown. 791 throw new BadBytecode(opcode); 792 } 793 794 // methods for implementing insertGap(). 795 796 static class AlignmentException extends Exception { 797 798 /** default serialVersionUID */ 799 private static final long serialVersionUID = 1L;} 800 801 /** 802 * insertGapCore0() inserts a gap (some NOPs). 803 * It cannot handle a long code sequence more than 32K. All branch offsets must be 804 * signed 16bits. 805 * 806 * If "where" is the beginning of a block statement and exclusive is false, 807 * then the inserted gap is also included in the block statement. 808 * "where" must indicate the first byte of an opcode. 809 * The inserted gap is filled with NOP. gapLength may be extended to 810 * a multiple of 4. 811 * 812 * This method was also called from CodeAttribute.LdcEntry.doit(). 813 * 814 * @param where It must indicate the first byte of an opcode. 815 */ insertGapCore0(byte[] code, int where, int gapLength, boolean exclusive, ExceptionTable etable, CodeAttribute ca)816 static byte[] insertGapCore0(byte[] code, int where, int gapLength, 817 boolean exclusive, ExceptionTable etable, CodeAttribute ca) 818 throws BadBytecode 819 { 820 if (gapLength <= 0) 821 return code; 822 823 try { 824 return insertGapCore1(code, where, gapLength, exclusive, etable, ca); 825 } 826 catch (AlignmentException e) { 827 try { 828 return insertGapCore1(code, where, (gapLength + 3) & ~3, 829 exclusive, etable, ca); 830 } 831 catch (AlignmentException e2) { 832 throw new RuntimeException("fatal error?"); 833 } 834 } 835 } 836 insertGapCore1(byte[] code, int where, int gapLength, boolean exclusive, ExceptionTable etable, CodeAttribute ca)837 private static byte[] insertGapCore1(byte[] code, int where, int gapLength, 838 boolean exclusive, ExceptionTable etable, 839 CodeAttribute ca) 840 throws BadBytecode, AlignmentException 841 { 842 int codeLength = code.length; 843 byte[] newcode = new byte[codeLength + gapLength]; 844 insertGap2(code, where, gapLength, codeLength, newcode, exclusive); 845 etable.shiftPc(where, gapLength, exclusive); 846 LineNumberAttribute na 847 = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); 848 if (na != null) 849 na.shiftPc(where, gapLength, exclusive); 850 851 LocalVariableAttribute va = (LocalVariableAttribute)ca.getAttribute( 852 LocalVariableAttribute.tag); 853 if (va != null) 854 va.shiftPc(where, gapLength, exclusive); 855 856 LocalVariableAttribute vta 857 = (LocalVariableAttribute)ca.getAttribute( 858 LocalVariableAttribute.typeTag); 859 if (vta != null) 860 vta.shiftPc(where, gapLength, exclusive); 861 862 StackMapTable smt = (StackMapTable)ca.getAttribute(StackMapTable.tag); 863 if (smt != null) 864 smt.shiftPc(where, gapLength, exclusive); 865 866 StackMap sm = (StackMap)ca.getAttribute(StackMap.tag); 867 if (sm != null) 868 sm.shiftPc(where, gapLength, exclusive); 869 870 return newcode; 871 } 872 insertGap2(byte[] code, int where, int gapLength, int endPos, byte[] newcode, boolean exclusive)873 private static void insertGap2(byte[] code, int where, int gapLength, 874 int endPos, byte[] newcode, boolean exclusive) 875 throws BadBytecode, AlignmentException 876 { 877 int nextPos; 878 int i = 0; 879 int j = 0; 880 for (; i < endPos; i = nextPos) { 881 if (i == where) { 882 int j2 = j + gapLength; 883 while (j < j2) 884 newcode[j++] = NOP; 885 } 886 887 nextPos = nextOpcode(code, i); 888 int inst = code[i] & 0xff; 889 // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr 890 if ((153 <= inst && inst <= 168) 891 || inst == IFNULL || inst == IFNONNULL) { 892 /* 2bytes *signed* offset */ 893 int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff); 894 offset = newOffset(i, offset, where, gapLength, exclusive); 895 newcode[j] = code[i]; 896 ByteArray.write16bit(offset, newcode, j + 1); 897 j += 3; 898 } 899 else if (inst == GOTO_W || inst == JSR_W) { 900 /* 4bytes offset */ 901 int offset = ByteArray.read32bit(code, i + 1); 902 offset = newOffset(i, offset, where, gapLength, exclusive); 903 newcode[j++] = code[i]; 904 ByteArray.write32bit(offset, newcode, j); 905 j += 4; 906 } 907 else if (inst == TABLESWITCH) { 908 if (i != j && (gapLength & 3) != 0) 909 throw new AlignmentException(); 910 911 int i2 = (i & ~3) + 4; // 0-3 byte padding 912 // IBM JVM 1.4.2 cannot run the following code: 913 // int i0 = i; 914 // while (i0 < i2) 915 // newcode[j++] = code[i0++]; 916 // So extracting this code into an external method. 917 // see JIRA JASSIST-74. 918 j = copyGapBytes(newcode, j, code, i, i2); 919 920 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2), 921 where, gapLength, exclusive); 922 ByteArray.write32bit(defaultbyte, newcode, j); 923 int lowbyte = ByteArray.read32bit(code, i2 + 4); 924 ByteArray.write32bit(lowbyte, newcode, j + 4); 925 int highbyte = ByteArray.read32bit(code, i2 + 8); 926 ByteArray.write32bit(highbyte, newcode, j + 8); 927 j += 12; 928 int i0 = i2 + 12; 929 i2 = i0 + (highbyte - lowbyte + 1) * 4; 930 while (i0 < i2) { 931 int offset = newOffset(i, ByteArray.read32bit(code, i0), 932 where, gapLength, exclusive); 933 ByteArray.write32bit(offset, newcode, j); 934 j += 4; 935 i0 += 4; 936 } 937 } 938 else if (inst == LOOKUPSWITCH) { 939 if (i != j && (gapLength & 3) != 0) 940 throw new AlignmentException(); 941 942 int i2 = (i & ~3) + 4; // 0-3 byte padding 943 944 // IBM JVM 1.4.2 cannot run the following code: 945 // int i0 = i; 946 // while (i0 < i2) 947 // newcode[j++] = code[i0++]; 948 // So extracting this code into an external method. 949 // see JIRA JASSIST-74. 950 j = copyGapBytes(newcode, j, code, i, i2); 951 952 int defaultbyte = newOffset(i, ByteArray.read32bit(code, i2), 953 where, gapLength, exclusive); 954 ByteArray.write32bit(defaultbyte, newcode, j); 955 int npairs = ByteArray.read32bit(code, i2 + 4); 956 ByteArray.write32bit(npairs, newcode, j + 4); 957 j += 8; 958 int i0 = i2 + 8; 959 i2 = i0 + npairs * 8; 960 while (i0 < i2) { 961 ByteArray.copy32bit(code, i0, newcode, j); 962 int offset = newOffset(i, 963 ByteArray.read32bit(code, i0 + 4), 964 where, gapLength, exclusive); 965 ByteArray.write32bit(offset, newcode, j + 4); 966 j += 8; 967 i0 += 8; 968 } 969 } 970 else 971 while (i < nextPos) 972 newcode[j++] = code[i++]; 973 } 974 } 975 976 copyGapBytes(byte[] newcode, int j, byte[] code, int i, int iEnd)977 private static int copyGapBytes(byte[] newcode, int j, byte[] code, int i, int iEnd) { 978 switch (iEnd - i) { 979 case 4: 980 newcode[j++] = code[i++]; 981 case 3: 982 newcode[j++] = code[i++]; 983 case 2: 984 newcode[j++] = code[i++]; 985 case 1: 986 newcode[j++] = code[i++]; 987 default: 988 } 989 990 return j; 991 } 992 newOffset(int i, int offset, int where, int gapLength, boolean exclusive)993 private static int newOffset(int i, int offset, int where, 994 int gapLength, boolean exclusive) { 995 int target = i + offset; 996 if (i < where) { 997 if (where < target || (exclusive && where == target)) 998 offset += gapLength; 999 } 1000 else if (i == where) { 1001 // This code is different from the code in Branch#shiftOffset(). 1002 // see JASSIST-124. 1003 if (target < where) 1004 offset -= gapLength; 1005 } 1006 else 1007 if (target < where || (!exclusive && where == target)) 1008 offset -= gapLength; 1009 1010 return offset; 1011 } 1012 1013 static class Pointers { 1014 int cursor; 1015 int mark0, mark; 1016 ExceptionTable etable; 1017 LineNumberAttribute line; 1018 LocalVariableAttribute vars, types; 1019 StackMapTable stack; 1020 StackMap stack2; 1021 Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca)1022 Pointers(int cur, int m, int m0, ExceptionTable et, CodeAttribute ca) { 1023 cursor = cur; 1024 mark = m; 1025 mark0 = m0; 1026 etable = et; // non null 1027 line = (LineNumberAttribute)ca.getAttribute(LineNumberAttribute.tag); 1028 vars = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.tag); 1029 types = (LocalVariableAttribute)ca.getAttribute(LocalVariableAttribute.typeTag); 1030 stack = (StackMapTable)ca.getAttribute(StackMapTable.tag); 1031 stack2 = (StackMap)ca.getAttribute(StackMap.tag); 1032 } 1033 shiftPc(int where, int gapLength, boolean exclusive)1034 void shiftPc(int where, int gapLength, boolean exclusive) throws BadBytecode { 1035 if (where < cursor || (where == cursor && exclusive)) 1036 cursor += gapLength; 1037 1038 if (where < mark || (where == mark && exclusive)) 1039 mark += gapLength; 1040 1041 if (where < mark0 || (where == mark0 && exclusive)) 1042 mark0 += gapLength; 1043 1044 etable.shiftPc(where, gapLength, exclusive); 1045 if (line != null) 1046 line.shiftPc(where, gapLength, exclusive); 1047 1048 if (vars != null) 1049 vars.shiftPc(where, gapLength, exclusive); 1050 1051 if (types != null) 1052 types.shiftPc(where, gapLength, exclusive); 1053 1054 if (stack != null) 1055 stack.shiftPc(where, gapLength, exclusive); 1056 1057 if (stack2 != null) 1058 stack2.shiftPc(where, gapLength, exclusive); 1059 } 1060 shiftForSwitch(int where, int gapLength)1061 void shiftForSwitch(int where, int gapLength) throws BadBytecode { 1062 if (stack != null) 1063 stack.shiftForSwitch(where, gapLength); 1064 1065 if (stack2 != null) 1066 stack2.shiftForSwitch(where, gapLength); 1067 } 1068 } 1069 1070 /* 1071 * This method is called from CodeAttribute.LdcEntry.doit(). 1072 */ changeLdcToLdcW(byte[] code, ExceptionTable etable, CodeAttribute ca, CodeAttribute.LdcEntry ldcs)1073 static byte[] changeLdcToLdcW(byte[] code, ExceptionTable etable, 1074 CodeAttribute ca, CodeAttribute.LdcEntry ldcs) 1075 throws BadBytecode 1076 { 1077 Pointers pointers = new Pointers(0, 0, 0, etable, ca); 1078 List<Branch> jumps = makeJumpList(code, code.length, pointers); 1079 while (ldcs != null) { 1080 addLdcW(ldcs, jumps); 1081 ldcs = ldcs.next; 1082 } 1083 1084 byte[] r = insertGap2w(code, 0, 0, false, jumps, pointers); 1085 return r; 1086 } 1087 addLdcW(CodeAttribute.LdcEntry ldcs, List<Branch> jumps)1088 private static void addLdcW(CodeAttribute.LdcEntry ldcs, List<Branch> jumps) { 1089 int where = ldcs.where; 1090 LdcW ldcw = new LdcW(where, ldcs.index); 1091 int s = jumps.size(); 1092 for (int i = 0; i < s; i++) 1093 if (where < jumps.get(i).orgPos) { 1094 jumps.add(i, ldcw); 1095 return; 1096 } 1097 1098 jumps.add(ldcw); 1099 } 1100 1101 /* 1102 * insertGapCore0w() can handle a long code sequence more than 32K. 1103 * It guarantees that the length of the inserted gap (NOPs) is equal to 1104 * gapLength. No other NOPs except some NOPs following TABLESWITCH or 1105 * LOOKUPSWITCH will not be inserted. 1106 * 1107 * Note: currentPos might be moved. 1108 * 1109 * @param where It must indicate the first byte of an opcode. 1110 * @param newWhere It contains the updated index of the position where a gap 1111 * is inserted and the length of the gap. 1112 * It must not be null. 1113 */ insertGapCore0w(byte[] code, int where, int gapLength, boolean exclusive, ExceptionTable etable, CodeAttribute ca, Gap newWhere)1114 private byte[] insertGapCore0w(byte[] code, int where, int gapLength, boolean exclusive, 1115 ExceptionTable etable, CodeAttribute ca, Gap newWhere) 1116 throws BadBytecode 1117 { 1118 if (gapLength <= 0) 1119 return code; 1120 1121 Pointers pointers = new Pointers(currentPos, mark, where, etable, ca); 1122 List<Branch> jumps = makeJumpList(code, code.length, pointers); 1123 byte[] r = insertGap2w(code, where, gapLength, exclusive, jumps, pointers); 1124 currentPos = pointers.cursor; 1125 mark = pointers.mark; 1126 int where2 = pointers.mark0; 1127 if (where2 == currentPos && !exclusive) 1128 currentPos += gapLength; 1129 1130 if (exclusive) 1131 where2 -= gapLength; 1132 1133 newWhere.position = where2; 1134 newWhere.length = gapLength; 1135 return r; 1136 } 1137 insertGap2w(byte[] code, int where, int gapLength, boolean exclusive, List<Branch> jumps, Pointers ptrs)1138 private static byte[] insertGap2w(byte[] code, int where, int gapLength, 1139 boolean exclusive, List<Branch> jumps, Pointers ptrs) 1140 throws BadBytecode 1141 { 1142 if (gapLength > 0) { 1143 ptrs.shiftPc(where, gapLength, exclusive); 1144 for (Branch b:jumps) 1145 b.shift(where, gapLength, exclusive); 1146 } 1147 1148 boolean unstable = true; 1149 do { 1150 while (unstable) { 1151 unstable = false; 1152 for (Branch b:jumps) { 1153 if (b.expanded()) { 1154 unstable = true; 1155 int p = b.pos; 1156 int delta = b.deltaSize(); 1157 ptrs.shiftPc(p, delta, false); 1158 for (Branch bb:jumps) 1159 bb.shift(p, delta, false); 1160 } 1161 } 1162 } 1163 1164 for (Branch b:jumps) { 1165 int diff = b.gapChanged(); 1166 if (diff > 0) { 1167 unstable = true; 1168 int p = b.pos; 1169 ptrs.shiftPc(p, diff, false); 1170 for (Branch bb:jumps) 1171 bb.shift(p, diff, false); 1172 } 1173 } 1174 } while (unstable); 1175 1176 return makeExapndedCode(code, jumps, where, gapLength); 1177 } 1178 makeJumpList(byte[] code, int endPos, Pointers ptrs)1179 private static List<Branch> makeJumpList(byte[] code, int endPos, Pointers ptrs) 1180 throws BadBytecode 1181 { 1182 List<Branch> jumps = new ArrayList<Branch>(); 1183 int nextPos; 1184 for (int i = 0; i < endPos; i = nextPos) { 1185 nextPos = nextOpcode(code, i); 1186 int inst = code[i] & 0xff; 1187 // if<cond>, if_icmp<cond>, if_acmp<cond>, goto, jsr 1188 if ((153 <= inst && inst <= 168) 1189 || inst == IFNULL || inst == IFNONNULL) { 1190 /* 2bytes *signed* offset */ 1191 int offset = (code[i + 1] << 8) | (code[i + 2] & 0xff); 1192 Branch b; 1193 if (inst == GOTO || inst == JSR) 1194 b = new Jump16(i, offset); 1195 else 1196 b = new If16(i, offset); 1197 1198 jumps.add(b); 1199 } 1200 else if (inst == GOTO_W || inst == JSR_W) { 1201 /* 4bytes offset */ 1202 int offset = ByteArray.read32bit(code, i + 1); 1203 jumps.add(new Jump32(i, offset)); 1204 } 1205 else if (inst == TABLESWITCH) { 1206 int i2 = (i & ~3) + 4; // 0-3 byte padding 1207 int defaultbyte = ByteArray.read32bit(code, i2); 1208 int lowbyte = ByteArray.read32bit(code, i2 + 4); 1209 int highbyte = ByteArray.read32bit(code, i2 + 8); 1210 int i0 = i2 + 12; 1211 int size = highbyte - lowbyte + 1; 1212 int[] offsets = new int[size]; 1213 for (int j = 0; j < size; j++) { 1214 offsets[j] = ByteArray.read32bit(code, i0); 1215 i0 += 4; 1216 } 1217 1218 jumps.add(new Table(i, defaultbyte, lowbyte, highbyte, offsets, ptrs)); 1219 } 1220 else if (inst == LOOKUPSWITCH) { 1221 int i2 = (i & ~3) + 4; // 0-3 byte padding 1222 int defaultbyte = ByteArray.read32bit(code, i2); 1223 int npairs = ByteArray.read32bit(code, i2 + 4); 1224 int i0 = i2 + 8; 1225 int[] matches = new int[npairs]; 1226 int[] offsets = new int[npairs]; 1227 for (int j = 0; j < npairs; j++) { 1228 matches[j] = ByteArray.read32bit(code, i0); 1229 offsets[j] = ByteArray.read32bit(code, i0 + 4); 1230 i0 += 8; 1231 } 1232 1233 jumps.add(new Lookup(i, defaultbyte, matches, offsets, ptrs)); 1234 } 1235 } 1236 1237 return jumps; 1238 } 1239 makeExapndedCode(byte[] code, List<Branch> jumps, int where, int gapLength)1240 private static byte[] makeExapndedCode(byte[] code, List<Branch> jumps, 1241 int where, int gapLength) 1242 throws BadBytecode 1243 { 1244 int n = jumps.size(); 1245 int size = code.length + gapLength; 1246 for (Branch b:jumps) 1247 size += b.deltaSize(); 1248 1249 byte[] newcode = new byte[size]; 1250 int src = 0, dest = 0, bindex = 0; 1251 int len = code.length; 1252 Branch b; 1253 int bpos; 1254 if (0 < n) { 1255 b = jumps.get(0); 1256 bpos = b.orgPos; 1257 } 1258 else { 1259 b = null; 1260 bpos = len; // src will be never equal to bpos 1261 } 1262 1263 while (src < len) { 1264 if (src == where) { 1265 int pos2 = dest + gapLength; 1266 while (dest < pos2) 1267 newcode[dest++] = NOP; 1268 } 1269 1270 if (src != bpos) 1271 newcode[dest++] = code[src++]; 1272 else { 1273 int s = b.write(src, code, dest, newcode); 1274 src += s; 1275 dest += s + b.deltaSize(); 1276 if (++bindex < n) { 1277 b = jumps.get(bindex); 1278 bpos = b.orgPos; 1279 } 1280 else { 1281 b = null; 1282 bpos = len; 1283 } 1284 } 1285 } 1286 1287 return newcode; 1288 } 1289 1290 static abstract class Branch { 1291 int pos, orgPos; Branch(int p)1292 Branch(int p) { pos = orgPos = p; } shift(int where, int gapLength, boolean exclusive)1293 void shift(int where, int gapLength, boolean exclusive) { 1294 if (where < pos || (where == pos && exclusive)) 1295 pos += gapLength; 1296 } 1297 shiftOffset(int i, int offset, int where, int gapLength, boolean exclusive)1298 static int shiftOffset(int i, int offset, int where, 1299 int gapLength, boolean exclusive) { 1300 int target = i + offset; 1301 if (i < where) { 1302 if (where < target || (exclusive && where == target)) 1303 offset += gapLength; 1304 } 1305 else if (i == where) { 1306 // This code is different from the code in CodeIterator#newOffset(). 1307 // see JASSIST-124. 1308 if (target < where && exclusive) 1309 offset -= gapLength; 1310 else if (where < target && !exclusive) 1311 offset += gapLength; 1312 } 1313 else 1314 if (target < where || (!exclusive && where == target)) 1315 offset -= gapLength; 1316 1317 return offset; 1318 } 1319 expanded()1320 boolean expanded() { return false; } gapChanged()1321 int gapChanged() { return 0; } deltaSize()1322 int deltaSize() { return 0; } // newSize - oldSize 1323 1324 // This returns the original instruction size. write(int srcPos, byte[] code, int destPos, byte[] newcode)1325 abstract int write(int srcPos, byte[] code, int destPos, byte[] newcode) throws BadBytecode; 1326 } 1327 1328 /* used by changeLdcToLdcW() and CodeAttribute.LdcEntry. 1329 */ 1330 static class LdcW extends Branch { 1331 int index; 1332 boolean state; LdcW(int p, int i)1333 LdcW(int p, int i) { 1334 super(p); 1335 index = i; 1336 state = true; 1337 } 1338 1339 @Override expanded()1340 boolean expanded() { 1341 if (state) { 1342 state = false; 1343 return true; 1344 } 1345 return false; 1346 } 1347 1348 @Override deltaSize()1349 int deltaSize() { return 1; } 1350 1351 @Override write(int srcPos, byte[] code, int destPos, byte[] newcode)1352 int write(int srcPos, byte[] code, int destPos, byte[] newcode) { 1353 newcode[destPos] = LDC_W; 1354 ByteArray.write16bit(index, newcode, destPos + 1); 1355 return 2; 1356 } 1357 } 1358 1359 static abstract class Branch16 extends Branch { 1360 int offset; 1361 int state; 1362 static final int BIT16 = 0; 1363 static final int EXPAND = 1; 1364 static final int BIT32 = 2; 1365 Branch16(int p, int off)1366 Branch16(int p, int off) { 1367 super(p); 1368 offset = off; 1369 state = BIT16; 1370 } 1371 1372 @Override shift(int where, int gapLength, boolean exclusive)1373 void shift(int where, int gapLength, boolean exclusive) { 1374 offset = shiftOffset(pos, offset, where, gapLength, exclusive); 1375 super.shift(where, gapLength, exclusive); 1376 if (state == BIT16) 1377 if (offset < Short.MIN_VALUE || Short.MAX_VALUE < offset) 1378 state = EXPAND; 1379 } 1380 1381 @Override expanded()1382 boolean expanded() { 1383 if (state == EXPAND) { 1384 state = BIT32; 1385 return true; 1386 } 1387 return false; 1388 } 1389 1390 @Override deltaSize()1391 abstract int deltaSize(); write32(int src, byte[] code, int dest, byte[] newcode)1392 abstract void write32(int src, byte[] code, int dest, byte[] newcode); 1393 1394 @Override write(int src, byte[] code, int dest, byte[] newcode)1395 int write(int src, byte[] code, int dest, byte[] newcode) { 1396 if (state == BIT32) 1397 write32(src, code, dest, newcode); 1398 else { 1399 newcode[dest] = code[src]; 1400 ByteArray.write16bit(offset, newcode, dest + 1); 1401 } 1402 1403 return 3; 1404 } 1405 } 1406 1407 // GOTO or JSR 1408 static class Jump16 extends Branch16 { Jump16(int p, int off)1409 Jump16(int p, int off) { 1410 super(p, off); 1411 } 1412 1413 @Override deltaSize()1414 int deltaSize() { 1415 return state == BIT32 ? 2 : 0; 1416 } 1417 1418 @Override write32(int src, byte[] code, int dest, byte[] newcode)1419 void write32(int src, byte[] code, int dest, byte[] newcode) { 1420 newcode[dest] = (byte)(((code[src] & 0xff) == GOTO) ? GOTO_W : JSR_W); 1421 ByteArray.write32bit(offset, newcode, dest + 1); 1422 } 1423 } 1424 1425 // if<cond>, if_icmp<cond>, or if_acmp<cond> 1426 static class If16 extends Branch16 { If16(int p, int off)1427 If16(int p, int off) { 1428 super(p, off); 1429 } 1430 1431 @Override deltaSize()1432 int deltaSize() { 1433 return state == BIT32 ? 5 : 0; 1434 } 1435 1436 @Override write32(int src, byte[] code, int dest, byte[] newcode)1437 void write32(int src, byte[] code, int dest, byte[] newcode) { 1438 newcode[dest] = (byte)opcode(code[src] & 0xff); 1439 newcode[dest + 1] = 0; 1440 newcode[dest + 2] = 8; // branch_offset = 8 1441 newcode[dest + 3] = (byte)GOTO_W; 1442 ByteArray.write32bit(offset - 3, newcode, dest + 4); 1443 } 1444 opcode(int op)1445 int opcode(int op) { 1446 if (op == IFNULL) 1447 return IFNONNULL; 1448 else if (op == IFNONNULL) 1449 return IFNULL; 1450 if (((op - IFEQ) & 1) == 0) 1451 return op + 1; 1452 return op - 1; 1453 } 1454 } 1455 1456 static class Jump32 extends Branch { 1457 int offset; 1458 Jump32(int p, int off)1459 Jump32(int p, int off) { 1460 super(p); 1461 offset = off; 1462 } 1463 1464 @Override shift(int where, int gapLength, boolean exclusive)1465 void shift(int where, int gapLength, boolean exclusive) { 1466 offset = shiftOffset(pos, offset, where, gapLength, exclusive); 1467 super.shift(where, gapLength, exclusive); 1468 } 1469 1470 @Override write(int src, byte[] code, int dest, byte[] newcode)1471 int write(int src, byte[] code, int dest, byte[] newcode) { 1472 newcode[dest] = code[src]; 1473 ByteArray.write32bit(offset, newcode, dest + 1); 1474 return 5; 1475 } 1476 } 1477 1478 static abstract class Switcher extends Branch { 1479 int gap, defaultByte; 1480 int[] offsets; 1481 Pointers pointers; 1482 Switcher(int pos, int defaultByte, int[] offsets, Pointers ptrs)1483 Switcher(int pos, int defaultByte, int[] offsets, Pointers ptrs) { 1484 super(pos); 1485 this.gap = 3 - (pos & 3); 1486 this.defaultByte = defaultByte; 1487 this.offsets = offsets; 1488 this.pointers = ptrs; 1489 } 1490 1491 @Override shift(int where, int gapLength, boolean exclusive)1492 void shift(int where, int gapLength, boolean exclusive) { 1493 int p = pos; 1494 defaultByte = shiftOffset(p, defaultByte, where, gapLength, exclusive); 1495 int num = offsets.length; 1496 for (int i = 0; i < num; i++) 1497 offsets[i] = shiftOffset(p, offsets[i], where, gapLength, exclusive); 1498 1499 super.shift(where, gapLength, exclusive); 1500 } 1501 1502 @Override gapChanged()1503 int gapChanged() { 1504 int newGap = 3 - (pos & 3); 1505 if (newGap > gap) { 1506 int diff = newGap - gap; 1507 gap = newGap; 1508 return diff; 1509 } 1510 1511 return 0; 1512 } 1513 1514 @Override deltaSize()1515 int deltaSize() { 1516 return gap - (3 - (orgPos & 3)); 1517 } 1518 1519 @Override write(int src, byte[] code, int dest, byte[] newcode)1520 int write(int src, byte[] code, int dest, byte[] newcode) throws BadBytecode { 1521 int padding = 3 - (pos & 3); 1522 int nops = gap - padding; 1523 int bytecodeSize = 5 + (3 - (orgPos & 3)) + tableSize(); 1524 if (nops > 0) 1525 adjustOffsets(bytecodeSize, nops); 1526 1527 newcode[dest++] = code[src]; 1528 while (padding-- > 0) 1529 newcode[dest++] = 0; 1530 1531 ByteArray.write32bit(defaultByte, newcode, dest); 1532 int size = write2(dest + 4, newcode); 1533 dest += size + 4; 1534 while (nops-- > 0) 1535 newcode[dest++] = NOP; 1536 1537 return 5 + (3 - (orgPos & 3)) + size; 1538 } 1539 write2(int dest, byte[] newcode)1540 abstract int write2(int dest, byte[] newcode); tableSize()1541 abstract int tableSize(); 1542 1543 /* If the new bytecode size is shorter than the original, some NOPs 1544 * are appended after this branch instruction (tableswitch or 1545 * lookupswitch) to fill the gap. 1546 * This method changes a branch offset to point to the first NOP 1547 * if the offset originally points to the bytecode next to this 1548 * branch instruction. Otherwise, the bytecode would contain 1549 * dead code. It complicates the generation of StackMap and 1550 * StackMapTable. 1551 */ adjustOffsets(int size, int nops)1552 void adjustOffsets(int size, int nops) throws BadBytecode { 1553 pointers.shiftForSwitch(pos + size, nops); 1554 if (defaultByte == size) 1555 defaultByte -= nops; 1556 1557 for (int i = 0; i < offsets.length; i++) 1558 if (offsets[i] == size) 1559 offsets[i] -= nops; 1560 } 1561 } 1562 1563 static class Table extends Switcher { 1564 int low, high; 1565 Table(int pos, int defaultByte, int low, int high, int[] offsets, Pointers ptrs)1566 Table(int pos, int defaultByte, int low, int high, int[] offsets, Pointers ptrs) { 1567 super(pos, defaultByte, offsets, ptrs); 1568 this.low = low; 1569 this.high = high; 1570 } 1571 1572 @Override write2(int dest, byte[] newcode)1573 int write2(int dest, byte[] newcode) { 1574 ByteArray.write32bit(low, newcode, dest); 1575 ByteArray.write32bit(high, newcode, dest + 4); 1576 int n = offsets.length; 1577 dest += 8; 1578 for (int i = 0; i < n; i++) { 1579 ByteArray.write32bit(offsets[i], newcode, dest); 1580 dest += 4; 1581 } 1582 1583 return 8 + 4 * n; 1584 } 1585 1586 @Override tableSize()1587 int tableSize() { return 8 + 4 * offsets.length; } 1588 } 1589 1590 static class Lookup extends Switcher { 1591 int[] matches; 1592 Lookup(int pos, int defaultByte, int[] matches, int[] offsets, Pointers ptrs)1593 Lookup(int pos, int defaultByte, int[] matches, int[] offsets, Pointers ptrs) { 1594 super(pos, defaultByte, offsets, ptrs); 1595 this.matches = matches; 1596 } 1597 1598 @Override write2(int dest, byte[] newcode)1599 int write2(int dest, byte[] newcode) { 1600 int n = matches.length; 1601 ByteArray.write32bit(n, newcode, dest); 1602 dest += 4; 1603 for (int i = 0; i < n; i++) { 1604 ByteArray.write32bit(matches[i], newcode, dest); 1605 ByteArray.write32bit(offsets[i], newcode, dest + 4); 1606 dest += 8; 1607 } 1608 1609 return 4 + 8 * n; 1610 } 1611 1612 @Override tableSize()1613 int tableSize() { return 4 + 8 * matches.length; } 1614 } 1615 } 1616