001package serp.bytecode; 002 003import java.io.*; 004import java.util.*; 005 006import serp.bytecode.lowlevel.*; 007import serp.bytecode.visitor.*; 008 009/** 010 * Representation of a code block of a class. 011 * The methods of this class mimic those of the same name in the 012 * {@link java.util.ListIterator} class. Note that the size and index 013 * information of the code block will change as opcodes are added. 014 * 015 * <p>Code blocks are usually obtained from a {@link BCMethod}, but can also 016 * be constructed via the default constructor. Blocks created this way can 017 * be used to provide template instructions to the various search/replace 018 * methods in this class.</p> 019 * 020 * <p>The code class contains methods named after most JVM instructions, each 021 * of which adds the matching opcode to the code block at the 022 * current iterator position. It also contains generic versions of various 023 * JVM instructions whose opcodes are not set until their properties are set 024 * with additional information. Almost all instruction types are able to 025 * 'morph' their opcode on the fly as the arguments to the instruction change. 026 * Thus the developer can initially call, for example, the <code>aload</code> 027 * opcode, but later change the type to load to <code>int</code> and the 028 * opcode will automatically morph to the <code>iload</code> opcode.</p> 029 * 030 * @author Abe White 031 */ 032public class Code extends Attribute { 033 private final CodeEntry _head; 034 private final CodeEntry _tail; 035 private CodeIterator _ci; 036 private int _maxStack = 0; 037 private int _maxLocals = 0; 038 private int _size = 0; 039 private Collection _handlers = new LinkedList(); 040 private Collection _attrs = new LinkedList(); 041 private boolean _byteIndexesValid; 042 043 Code(int nameIndex, Attributes owner) { 044 super(nameIndex, owner); 045 _head = new CodeEntry(); 046 _tail = new CodeEntry(); 047 _head.next = _tail; 048 _tail.prev = _head; 049 _ci = new CodeIterator(_head, -1); 050 } 051 052 /** 053 * The public constructor is for creating template code modules 054 * that produce {@link Instruction}s used in matching through 055 * the various <code>search</code> and <code>replace</code> methods. 056 */ 057 public Code() { 058 this(0, new Project().loadClass("", null).declareMethod("", void.class, 059 null)); 060 } 061 062 /** 063 * The owning method. 064 */ 065 public BCMethod getMethod() { 066 return (BCMethod) getOwner(); 067 } 068 069 Collection getAttributesHolder() { 070 return _attrs; 071 } 072 073 //////////////////////////// 074 // Stack, Locals operations 075 //////////////////////////// 076 077 /** 078 * Return the maximum stack depth set for this code block. 079 */ 080 public int getMaxStack() { 081 return _maxStack; 082 } 083 084 /** 085 * Set the maximum stack depth for this code block. 086 */ 087 public void setMaxStack(int max) { 088 _maxStack = max; 089 } 090 091 /** 092 * Return the maximum number of local variables (including params) 093 * set for this method. 094 */ 095 public int getMaxLocals() { 096 return _maxLocals; 097 } 098 099 /** 100 * Set the maximum number of local variables (including params) in 101 * this method. 102 */ 103 public void setMaxLocals(int max) { 104 _maxLocals = max; 105 } 106 107 /** 108 * Return the local variable index for the paramIndex'th parameter to 109 * the method. Local variable indexes differ from parameter indexes because: 110 * a) non-static methods use the 0th local variable for the 'this' ptr, and 111 * b) double and long values occupy two spots in the local variable array. 112 * Returns -1 if the given index is not valid. 113 */ 114 public int getLocalsIndex(int paramIndex) { 115 if (paramIndex < 0) 116 return -1; 117 118 int pos = 0; 119 if (!getMethod().isStatic()) 120 pos = 1; 121 String[] params = getMethod().getParamNames(); 122 for (int i = 0; i < paramIndex; i++, pos++) { 123 if (i == params.length) 124 return -1; 125 if (params[i].equals(long.class.getName()) 126 || params[i].equals(double.class.getName())) 127 pos++; 128 } 129 return pos; 130 } 131 132 /** 133 * Return the parameter index for the given local index, or -1 if 134 * the given local does not reference a param. 135 * 136 * @see #getLocalsIndex 137 */ 138 public int getParamsIndex(int localIndex) { 139 int pos = 0; 140 if (!getMethod().isStatic()) 141 pos = 1; 142 String[] params = getMethod().getParamNames(); 143 for (int i = 0; i < params.length; i++, pos++) { 144 if (localIndex == pos) 145 return i; 146 if (params[i].equals(long.class.getName()) 147 || params[i].equals(double.class.getName())) 148 pos++; 149 } 150 return -1; 151 } 152 153 /** 154 * Return the next available local variable index. 155 */ 156 public int getNextLocalsIndex() { 157 calculateMaxLocals(); 158 return getMaxLocals(); 159 } 160 161 /** 162 * Calculate and set the number of locals needed based on 163 * the instructions used and the parameters of the method this code 164 * block is a part of. 165 * 166 * @see #setMaxLocals 167 */ 168 public void calculateMaxLocals() { 169 // start off assuming the max number needed is the 170 // number for all the params 171 String[] params = getMethod().getParamNames(); 172 int max = 0; 173 if ((params.length == 0) && !getMethod().isStatic()) 174 max = 1; 175 else if (params.length > 0) { 176 max = getLocalsIndex(params.length - 1) + 1; 177 if (params[params.length - 1].equals(long.class.getName()) 178 || params[params.length - 1].equals(double.class.getName())) 179 max++; 180 } 181 182 // check to see if there are any store instructions that 183 // try to reference beyond that point 184 StoreInstruction store; 185 int current; 186 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 187 current = 0; 188 if (entry instanceof StoreInstruction) { 189 store = (StoreInstruction) entry; 190 current = store.getLocal() + 1; 191 if (store.getType().equals(long.class) 192 || store.getType().equals(double.class)) 193 current++; 194 if (current > max) 195 max = current; 196 } 197 } 198 setMaxLocals(max); 199 } 200 201 /** 202 * Calculate and set the maximum stack depth needed for 203 * the instructions used. 204 * 205 * @see #setMaxStack 206 */ 207 public void calculateMaxStack() { 208 int stack = 0; 209 int max = 0; 210 ExceptionHandler[] handlers = getExceptionHandlers(); 211 Instruction ins; 212 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 213 ins = (Instruction) entry; 214 stack += ins.getStackChange(); 215 216 // if this is the start of a try, the exception will be placed 217 // on the stack 218 for (int j = 0; j < handlers.length; j++) 219 if (handlers[j].getTryStart() == ins) 220 stack++; 221 if (stack > max) 222 max = stack; 223 } 224 setMaxStack(max); 225 } 226 227 /////////////////////////////// 228 // ExceptionHandler operations 229 /////////////////////////////// 230 231 /** 232 * Return the exception handlers active in this code block, or an 233 * empty array if none. 234 */ 235 public ExceptionHandler[] getExceptionHandlers() { 236 return (ExceptionHandler[]) _handlers.toArray 237 (new ExceptionHandler[_handlers.size()]); 238 } 239 240 /** 241 * Return the exception handler that catches the given exception type; 242 * if multiple handlers catch the given type, which is returned is 243 * undefined. 244 */ 245 public ExceptionHandler getExceptionHandler(String catchType) { 246 catchType = getProject().getNameCache().getExternalForm(catchType, 247 false); 248 String type; 249 ExceptionHandler[] handlers = getExceptionHandlers(); 250 for (int i = 0; i < handlers.length; i++) { 251 type = handlers[i].getCatchName(); 252 if ((type == null && catchType == null) 253 || (type != null && type.equals(catchType))) 254 return handlers[i]; 255 } 256 return null; 257 } 258 259 /** 260 * Return the exception handler that catches the given exception type; 261 * if multiple handlers catch the given type, which is returned is 262 * undefined. 263 */ 264 public ExceptionHandler getExceptionHandler(Class catchType) { 265 if (catchType == null) 266 return getExceptionHandler((String) null); 267 return getExceptionHandler(catchType.getName()); 268 } 269 270 /** 271 * Return the exception handler that catches the given exception type; 272 * if multiple handlers catch the given type, which is returned is 273 * undefined. 274 */ 275 public ExceptionHandler getExceptionHandler(BCClass catchType) { 276 if (catchType == null) 277 return getExceptionHandler((String) null); 278 return getExceptionHandler(catchType.getName()); 279 } 280 281 /** 282 * Return all exception handlers that catch the given exception type, 283 * or an empty array if none. 284 */ 285 public ExceptionHandler[] getExceptionHandlers(String catchType) { 286 catchType = getProject().getNameCache().getExternalForm(catchType, 287 false); 288 List matches = new LinkedList(); 289 String type; 290 ExceptionHandler[] handlers = getExceptionHandlers(); 291 for (int i = 0; i < handlers.length; i++) { 292 type = handlers[i].getCatchName(); 293 if ((type == null && catchType == null) 294 || (type != null && type.equals(catchType))) 295 matches.add(handlers[i]); 296 } 297 return (ExceptionHandler[]) matches.toArray 298 (new ExceptionHandler[matches.size()]); 299 } 300 301 /** 302 * Return all exception handlers that catch the given exception type, 303 * or an empty array if none. 304 */ 305 public ExceptionHandler[] getExceptionHandlers(Class catchType) { 306 if (catchType == null) 307 return getExceptionHandlers((String) null); 308 return getExceptionHandlers(catchType.getName()); 309 } 310 311 /** 312 * Return all exception handlers that catch the given exception type, 313 * or an empty array if none. 314 */ 315 public ExceptionHandler[] getExceptionHandlers(BCClass catchType) { 316 if (catchType == null) 317 return getExceptionHandlers((String) null); 318 return getExceptionHandlers(catchType.getName()); 319 } 320 321 /** 322 * Set the exception handlers for this code block. This method is useful 323 * for importing all handlers from another code block. Set to null or 324 * empty array if none. 325 */ 326 public void setExceptionHandlers(ExceptionHandler[] handlers) { 327 clearExceptionHandlers(); 328 if (handlers != null) 329 for (int i = 0; i < handlers.length; i++) 330 addExceptionHandler(handlers[i]); 331 } 332 333 /** 334 * Import the given exception handler from another code block. 335 */ 336 public ExceptionHandler addExceptionHandler(ExceptionHandler handler) { 337 ExceptionHandler newHandler = addExceptionHandler(); 338 newHandler.read(handler); 339 return newHandler; 340 } 341 342 /** 343 * Add an exception handler to this code block. 344 */ 345 public ExceptionHandler addExceptionHandler() { 346 ExceptionHandler handler = new ExceptionHandler(this); 347 _handlers.add(handler); 348 return handler; 349 } 350 351 /** 352 * Add an exception handler to this code block. 353 * 354 * @param tryStart the first instruction of the try {} block 355 * @param tryEnd the last instruction of the try {} block 356 * @param handlerStart the first instruction of the catch {} block 357 * @param catchType the type of exception being caught 358 */ 359 public ExceptionHandler addExceptionHandler(Instruction tryStart, 360 Instruction tryEnd, Instruction handlerStart, String catchType) { 361 ExceptionHandler handler = addExceptionHandler(); 362 handler.setTryStart(tryStart); 363 handler.setTryEnd(tryEnd); 364 handler.setHandlerStart(handlerStart); 365 handler.setCatch(catchType); 366 return handler; 367 } 368 369 /** 370 * Add an exception handler to this code block. 371 * 372 * @param tryStart the first instruction of the try {} block 373 * @param tryEnd the last instruction of the try {} block 374 * @param handlerStart the first instruction of the catch {} block 375 * @param catchType the type of exception being caught 376 */ 377 public ExceptionHandler addExceptionHandler(Instruction tryStart, 378 Instruction tryEnd, Instruction handlerStart, Class catchType) { 379 String catchName = null; 380 if (catchType != null) 381 catchName = catchType.getName(); 382 return addExceptionHandler(tryStart, tryEnd, handlerStart, catchName); 383 } 384 385 /** 386 * Add an exception handler to this code block. 387 * 388 * @param tryStart the first instruction of the try {} block 389 * @param tryEnd the last instruction of the try {} block 390 * @param handlerStart the first instruction of the catch {} block 391 * @param catchType the type of exception being caught 392 */ 393 public ExceptionHandler addExceptionHandler(Instruction tryStart, 394 Instruction tryEnd, Instruction handlerStart, BCClass catchType) { 395 String catchName = null; 396 if (catchType != null) 397 catchName = catchType.getName(); 398 return addExceptionHandler(tryStart, tryEnd, handlerStart, catchName); 399 } 400 401 /** 402 * Clear all exception handlers. 403 */ 404 public void clearExceptionHandlers() { 405 ExceptionHandler handler; 406 for (Iterator itr = _handlers.iterator(); itr.hasNext();) { 407 handler = (ExceptionHandler) itr.next(); 408 itr.remove(); 409 handler.invalidate(); 410 } 411 } 412 413 /** 414 * Remove the exception handler that catches the given type. 415 */ 416 public boolean removeExceptionHandler(String catchType) { 417 return removeExceptionHandler(getExceptionHandler(catchType)); 418 } 419 420 /** 421 * Remove the exception handler that catches the given type. 422 * 423 * @return true if the handler was removed, false otherwise 424 */ 425 public boolean removeExceptionHandler(Class catchType) { 426 if (catchType == null) 427 return removeExceptionHandler((String) null); 428 return removeExceptionHandler(catchType.getName()); 429 } 430 431 /** 432 * Remove the exception handler that catches the given type. 433 * 434 * @return true if the handler was removed, false otherwise 435 */ 436 public boolean removeExceptionHandler(BCClass catchType) { 437 if (catchType == null) 438 return removeExceptionHandler((String) null); 439 return removeExceptionHandler(catchType.getName()); 440 } 441 442 /** 443 * Remove an exception handler from this code block. The given handler 444 * must belong to this code block. 445 */ 446 public boolean removeExceptionHandler(ExceptionHandler handler) { 447 if ((handler == null) || !_handlers.remove(handler)) 448 return false; 449 handler.invalidate(); 450 return true; 451 } 452 453 ///////////////////////// 454 // Code block operations 455 ///////////////////////// 456 457 /** 458 * Return the number of instructions in the method. 459 */ 460 public int size() { 461 return _size; 462 } 463 464 /** 465 * Reset the position of the instruction iterator to the first opcode. 466 */ 467 public void beforeFirst() { 468 _ci = new CodeIterator(_head, -1); 469 } 470 471 /** 472 * Set the position of the instruction iterator to after the last opcode. 473 */ 474 public void afterLast() { 475 if (_size == 0) 476 _ci = new CodeIterator(_head, -1); 477 else 478 _ci = new CodeIterator(_tail.prev, _size - 1); 479 } 480 481 /** 482 * Position the iterator just before the given instruction. The 483 * instruction must belong to this method. 484 */ 485 public void before(Instruction ins) { 486 if (ins.getCode() != this) 487 throw new IllegalArgumentException("ins.code != this"); 488 _ci = new CodeIterator(ins.prev, CodeIterator.UNSET); 489 } 490 491 /** 492 * Position the iterator just after the given instruction. The 493 * instruction must belong to this method. 494 */ 495 public void after(Instruction ins) { 496 before(ins); 497 next(); 498 } 499 500 /** 501 * Return true if a subsequent call to {@link #next} will return an 502 * instruction. 503 */ 504 public boolean hasNext() { 505 return _ci.hasNext(); 506 } 507 508 /** 509 * Return true if a subsequent call to {@link #previous} will return an 510 * instruction. 511 */ 512 public boolean hasPrevious() { 513 return _ci.hasPrevious(); 514 } 515 516 /** 517 * Return the next instruction. 518 */ 519 public Instruction next() { 520 return (Instruction) _ci.next(); 521 } 522 523 /** 524 * Return the index of the next instruction, or {@link #size} if at end. 525 */ 526 public int nextIndex() { 527 return _ci.nextIndex(); 528 } 529 530 /** 531 * Return the previous instruction. 532 */ 533 public Instruction previous() { 534 return (Instruction) _ci.previous(); 535 } 536 537 /** 538 * Return the index of the previous instruction, or -1 if at beginning. 539 */ 540 public int previousIndex() { 541 return _ci.previousIndex(); 542 } 543 544 /** 545 * Place the iterator before the given list index. 546 */ 547 public void before(int index) { 548 if (index < 0 || index >= _size) 549 throw new IndexOutOfBoundsException(String.valueOf(index)); 550 551 CodeEntry entry = _head; 552 for (int i = 0; i < index; entry = entry.next, i++); 553 _ci = new CodeIterator(entry, index - 1); 554 } 555 556 /** 557 * Place the iterator after the given list index. 558 */ 559 public void after(int index) { 560 before(index); 561 next(); 562 } 563 564 /** 565 * Find the next instruction from the current iterator position that 566 * matches the given one, according to the {@link Object#equals} methods of 567 * the instruction types. This allows for matching based on template 568 * instructions, as the equals methods of most instructions return 569 * true if the information for the given instruction has not been filled 570 * in. If a match is found, the iterator is placed after the matching 571 * Instruction. If no match is found, moves the iterator to 572 * {@link #afterLast}. 573 * 574 * @return true if match found 575 */ 576 public boolean searchForward(Instruction template) { 577 if (template == null) 578 return false; 579 580 while (hasNext()) 581 if (template.equalsInstruction(next())) 582 return true; 583 return false; 584 } 585 586 /** 587 * Find the closest previous instruction from the current iterator 588 * position that matches the given one, according to the 589 * {@link Object#equals} methods of the instruction types. This allows 590 * for matching based on template instructions, as the equals methods of 591 * most instructions return true if the information for the given 592 * instruction has not been filled in. If a match is found, the iterator 593 * is placed before the matching Instruction. If no match is found, 594 * moves the iterator to {@link #beforeFirst}. 595 * 596 * @return true if match found 597 */ 598 public boolean searchBackward(Instruction template) { 599 if (template == null) 600 return false; 601 602 while (hasPrevious()) 603 if (template.equalsInstruction(previous())) 604 return true; 605 return false; 606 } 607 608 /** 609 * Adds a copy of the given instruction. 610 * 611 * @return the newly added instruction 612 */ 613 public Instruction add(Instruction ins) { 614 Instruction newIns = createInstruction(ins.getOpcode()); 615 newIns.read(ins); 616 _ci.add(newIns); 617 return newIns; 618 } 619 620 /** 621 * Replaces the last iterated instruction with a copy of the given one. 622 * This method will also make sure that all jump points 623 * that referenced the old opcode are updated correctly. 624 * 625 * @return the newly added instruction 626 * @see ListIterator#set 627 */ 628 public Instruction set(Instruction ins) { 629 Instruction newIns = createInstruction(ins.getOpcode()); 630 newIns.read(ins); 631 _ci.set(newIns); 632 return newIns; 633 } 634 635 /** 636 * Replaces all the instructions in this code block that match the 637 * given template with the given instruction. After this method, 638 * the iterator will be {@link #afterLast}. 639 * 640 * @return the number of substitutions made 641 */ 642 public int replace(Instruction template, Instruction with) { 643 beforeFirst(); 644 int count; 645 for (count = 0; searchForward(template); count++) 646 set(with); 647 return count; 648 } 649 650 /** 651 * Equivalent to looping over each given template/replacement 652 * pair and calling {@link #replace(Instruction,Instruction)} for each. 653 */ 654 public int replace(Instruction[] templates, Instruction[] with) { 655 if (templates == null || with == null) 656 return 0; 657 658 int count = 0; 659 for (int i = 0; i < templates.length; i++) { 660 if (with == null) 661 count += replace(templates[i], null); 662 else 663 count += replace(templates[i], with[i]); 664 } 665 return count; 666 } 667 668 /** 669 * Remove the last iterated instruction. 670 * 671 * @see ListIterator#remove 672 */ 673 public void remove() { 674 _ci.remove(); 675 } 676 677 ////////////////////////// 678 // Instruction operations 679 ////////////////////////// 680 681 /** 682 * Load a class constant onto the stack. 683 * For primitive types, this translates into a 684 * getstatic for the TYPE field of the primitive's wrapper type. 685 * For non-primitives, things get much more complex. Suffice it to 686 * say that the operation involves adding synthetic static fields 687 * and even methods to the class. Note that this instruction requires 688 * up to 3 stack positions to execute. 689 */ 690 public ClassConstantInstruction classconstant() { 691 return new ClassConstantInstruction(getMethod().getDeclarer(), this, 692 nop()); 693 } 694 695 /** 696 * Add the <code>nop</code> opcode. 697 */ 698 public Instruction nop() { 699 return addInstruction(Constants.NOP); 700 } 701 702 /** 703 * Load some constant onto the stack. The {@link ConstantInstruction} 704 * type takes any constant and correctly translates it into the proper 705 * opcode, depending on the constant type and value. For example, 706 * if the constant value is set to 0L, the opcode will be set to 707 * <code>lconst0</code>. 708 */ 709 public ConstantInstruction constant() { 710 return (ConstantInstruction) addInstruction(new ConstantInstruction 711 (this)); 712 } 713 714 /** 715 * Load a local variable onto the stack. This instruction will result 716 * in a <code>nop</code> until its type and local index are set. 717 */ 718 public LoadInstruction xload() { 719 return (LoadInstruction) addInstruction(new LoadInstruction(this)); 720 } 721 722 /** 723 * Load an int local variable onto the stack. This instruction will 724 * result in a <code>nop</code> until its local index is set. 725 */ 726 public LoadInstruction iload() { 727 return (LoadInstruction) addInstruction(new LoadInstruction(this). 728 setType(int.class)); 729 } 730 731 /** 732 * Load a long local variable onto the stack. This instruction will 733 * result in a <code>nop</code> until its local index is set. 734 */ 735 public LoadInstruction lload() { 736 return (LoadInstruction) addInstruction(new LoadInstruction(this). 737 setType(long.class)); 738 } 739 740 /** 741 * Load a float local variable onto the stack. This instruction will 742 * result in a <code>nop</code> until its local index is set. 743 */ 744 public LoadInstruction fload() { 745 return (LoadInstruction) addInstruction(new LoadInstruction(this). 746 setType(float.class)); 747 } 748 749 /** 750 * Load a double local variable onto the stack. This instruction will 751 * result in a <code>nop</code> until its local index is set. 752 */ 753 public LoadInstruction dload() { 754 return (LoadInstruction) addInstruction(new LoadInstruction(this). 755 setType(double.class)); 756 } 757 758 /** 759 * Load an object local variable onto the stack. This instruction will 760 * result in a <code>nop</code> until its local index is set. 761 */ 762 public LoadInstruction aload() { 763 return (LoadInstruction) addInstruction(new LoadInstruction(this). 764 setType(Object.class)); 765 } 766 767 /** 768 * Store a value from the stack into a local variable. This instruction 769 * will result in a <code>nop</code> until its type and local index are set. 770 */ 771 public StoreInstruction xstore() { 772 return (StoreInstruction) addInstruction(new StoreInstruction(this)); 773 } 774 775 /** 776 * Store an int value from the stack into a local variable. This 777 * instruction will result in a <code>nop</code> until its local index is 778 * set. 779 */ 780 public StoreInstruction istore() { 781 return (StoreInstruction) addInstruction(new StoreInstruction(this). 782 setType(int.class)); 783 } 784 785 /** 786 * Store a long value from the stack into a local variable. This 787 * instruction will resultin a <code>nop</code> until its local index is 788 * set. 789 */ 790 public StoreInstruction lstore() { 791 return (StoreInstruction) addInstruction(new StoreInstruction(this). 792 setType(long.class)); 793 } 794 795 /** 796 * Store a float value from the stack into a local variable. This 797 * instruction will result in a <code>nop</code> until its local index is 798 * set. 799 */ 800 public StoreInstruction fstore() { 801 return (StoreInstruction) addInstruction(new StoreInstruction(this). 802 setType(float.class)); 803 } 804 805 /** 806 * Store a double value from the stack into a local variable. This 807 * instruction will result in a <code>nop</code> until its local index is 808 * set. 809 */ 810 public StoreInstruction dstore() { 811 return (StoreInstruction) addInstruction(new StoreInstruction(this). 812 setType(double.class)); 813 } 814 815 /** 816 * Store an object value from the stack into a local variable. This 817 * instruction will result in a <code>nop</code> until its local index is 818 * set. 819 */ 820 public StoreInstruction astore() { 821 return (StoreInstruction) addInstruction(new StoreInstruction(this). 822 setType(Object.class)); 823 } 824 825 /** 826 * Add the <code>ret</code> opcode, used in implementing 827 * <code>finally</code> clauses. 828 */ 829 public RetInstruction ret() { 830 return (RetInstruction) addInstruction(Constants.RET); 831 } 832 833 /** 834 * Add the <code>iinc</code> opcode. 835 */ 836 public IIncInstruction iinc() { 837 return (IIncInstruction) addInstruction(Constants.IINC); 838 } 839 840 /** 841 * Add the <code>wide</code> opcode. 842 */ 843 public WideInstruction wide() { 844 return (WideInstruction) addInstruction(Constants.WIDE); 845 } 846 847 /** 848 * Load an array value onto the stack. This instruction will result 849 * in a <code>nop</code> until its type is set. 850 */ 851 public ArrayLoadInstruction xaload() { 852 return (ArrayLoadInstruction) addInstruction(new ArrayLoadInstruction( 853 this)); 854 } 855 856 /** 857 * Load an int array value onto the stack; the <code>iaload</code> opcode. 858 */ 859 public ArrayLoadInstruction iaload() { 860 return (ArrayLoadInstruction) addInstruction(Constants.IALOAD); 861 } 862 863 /** 864 * Load a long array value onto the stack; the <code>laload</code> opcode. 865 */ 866 public ArrayLoadInstruction laload() { 867 return (ArrayLoadInstruction) addInstruction(Constants.LALOAD); 868 } 869 870 /** 871 * Load a float array value onto the stack; the <code>faload</code> opcode. 872 */ 873 public ArrayLoadInstruction faload() { 874 return (ArrayLoadInstruction) addInstruction(Constants.FALOAD); 875 } 876 877 /** 878 * Load a double array value onto the stack; the <code>daload</code> opcode. 879 */ 880 public ArrayLoadInstruction daload() { 881 return (ArrayLoadInstruction) addInstruction(Constants.DALOAD); 882 } 883 884 /** 885 * Load an object array value onto the stack; the <code>aaload</code> 886 * opcode. 887 */ 888 public ArrayLoadInstruction aaload() { 889 return (ArrayLoadInstruction) addInstruction(Constants.AALOAD); 890 } 891 892 /** 893 * Load a byte array value onto the stack; the <code>baload</code> opcode. 894 */ 895 public ArrayLoadInstruction baload() { 896 return (ArrayLoadInstruction) addInstruction(Constants.BALOAD); 897 } 898 899 /** 900 * Load a char array value onto the stack; the <code>caload</code> opcode. 901 */ 902 public ArrayLoadInstruction caload() { 903 return (ArrayLoadInstruction) addInstruction(Constants.CALOAD); 904 } 905 906 /** 907 * Load a short array value onto the stack; the <code>saload</code> opcode. 908 */ 909 public ArrayLoadInstruction saload() { 910 return (ArrayLoadInstruction) addInstruction(Constants.SALOAD); 911 } 912 913 /** 914 * Store a value from the stack into an array. This instruction 915 * will result in a <code>nop</code> until its type is set. 916 */ 917 public ArrayStoreInstruction xastore() { 918 return (ArrayStoreInstruction) addInstruction(new ArrayStoreInstruction( 919 this)); 920 } 921 922 /** 923 * Store an int value from the stack into an array; the 924 * <code>iastore</code> opcode. 925 */ 926 public ArrayStoreInstruction iastore() { 927 return (ArrayStoreInstruction) addInstruction(Constants.IASTORE); 928 } 929 930 /** 931 * Store a long value from the stack into an array; the 932 * <code>lastore</code> opcode. 933 */ 934 public ArrayStoreInstruction lastore() { 935 return (ArrayStoreInstruction) addInstruction(Constants.LASTORE); 936 } 937 938 /** 939 * Store a float value from the stack into an array; the 940 * <code>fastore</code> opcode. 941 */ 942 public ArrayStoreInstruction fastore() { 943 return (ArrayStoreInstruction) addInstruction(Constants.FASTORE); 944 } 945 946 /** 947 * Store a double value from the stack into an array; the 948 * <code>dastore</code> opcode. 949 */ 950 public ArrayStoreInstruction dastore() { 951 return (ArrayStoreInstruction) addInstruction(Constants.DASTORE); 952 } 953 954 /** 955 * Store an object value from the stack into an array; the 956 * <code>aastore</code> opcode. 957 */ 958 public ArrayStoreInstruction aastore() { 959 return (ArrayStoreInstruction) addInstruction(Constants.AASTORE); 960 } 961 962 /** 963 * Store a byte value from the stack into an array; the 964 * <code>bastore</code> opcode. 965 */ 966 public ArrayStoreInstruction bastore() { 967 return (ArrayStoreInstruction) addInstruction(Constants.BASTORE); 968 } 969 970 /** 971 * Store a char value from the stack into an array; the 972 * <code>castore</code> opcode. 973 */ 974 public ArrayStoreInstruction castore() { 975 return (ArrayStoreInstruction) addInstruction(Constants.CASTORE); 976 } 977 978 /** 979 * Store a short value from the stack into an array; the 980 * <code>sastore</code> opcode. 981 */ 982 public ArrayStoreInstruction sastore() { 983 return (ArrayStoreInstruction) addInstruction(Constants.SASTORE); 984 } 985 986 /** 987 * The <code>pop</code> opcode. 988 */ 989 public StackInstruction pop() { 990 return (StackInstruction) addInstruction(Constants.POP); 991 } 992 993 /** 994 * The <code>pop2</code> opcode. 995 */ 996 public StackInstruction pop2() { 997 return (StackInstruction) addInstruction(Constants.POP2); 998 } 999 1000 /** 1001 * The <code>dup</code> opcode. 1002 */ 1003 public StackInstruction dup() { 1004 return (StackInstruction) addInstruction(Constants.DUP); 1005 } 1006 1007 /** 1008 * The <code>dupx1</code> opcode. 1009 */ 1010 public StackInstruction dupx1() { 1011 return (StackInstruction) addInstruction(Constants.DUPX1); 1012 } 1013 1014 /** 1015 * The <code>dupx2</code> opcode. 1016 */ 1017 public StackInstruction dupx2() { 1018 return (StackInstruction) addInstruction(Constants.DUPX2); 1019 } 1020 1021 /** 1022 * The <code>dup2</code> opcode. 1023 */ 1024 public StackInstruction dup2() { 1025 return (StackInstruction) addInstruction(Constants.DUP2); 1026 } 1027 1028 /** 1029 * The <code>dup2x1</code> opcode. 1030 */ 1031 public StackInstruction dup2x1() { 1032 return (StackInstruction) addInstruction(Constants.DUP2X1); 1033 } 1034 1035 /** 1036 * The <code>dup2x2</code> opcode. 1037 */ 1038 public StackInstruction dup2x2() { 1039 return (StackInstruction) addInstruction(Constants.DUP2X2); 1040 } 1041 1042 /** 1043 * The <code>swap</code> opcode. 1044 */ 1045 public StackInstruction swap() { 1046 return (StackInstruction) addInstruction(Constants.SWAP); 1047 } 1048 1049 /** 1050 * Perform some math operation on the stack items. This instruction will 1051 * result in a <code>nop</code> until its operation and type are set. 1052 */ 1053 public MathInstruction math() { 1054 return (MathInstruction) addInstruction(new MathInstruction(this)); 1055 } 1056 1057 /** 1058 * Add the top two stack values. This instruction will result in 1059 * a <code>nop</code> until its type is set. 1060 */ 1061 public MathInstruction xadd() { 1062 MathInstruction mi = math(); 1063 1064 return mi.setOperation(Constants.MATH_ADD); 1065 } 1066 1067 /** 1068 * Add the top two stack int values; the <code>iadd</code> opcode. 1069 */ 1070 public MathInstruction iadd() { 1071 return (MathInstruction) addInstruction(Constants.IADD); 1072 } 1073 1074 /** 1075 * Add the top two stack long values; the <code>ladd</code> opcode. 1076 */ 1077 public MathInstruction ladd() { 1078 return (MathInstruction) addInstruction(Constants.LADD); 1079 } 1080 1081 /** 1082 * Add the top two stack float values; the <code>fadd</code> opcode. 1083 */ 1084 public MathInstruction fadd() { 1085 return (MathInstruction) addInstruction(Constants.FADD); 1086 } 1087 1088 /** 1089 * Add the top two stack double values; the <code>dadd</code> opcode. 1090 */ 1091 public MathInstruction dadd() { 1092 return (MathInstruction) addInstruction(Constants.DADD); 1093 } 1094 1095 /** 1096 * Subtract the top two stack values. This instruction will result in 1097 * a <code>nop</code> until its type is set. 1098 */ 1099 public MathInstruction xsub() { 1100 MathInstruction mi = math(); 1101 return mi.setOperation(Constants.MATH_SUB); 1102 } 1103 1104 /** 1105 * Subtract the top two stack int values; the <code>isub</code> opcode. 1106 */ 1107 public MathInstruction isub() { 1108 return (MathInstruction) addInstruction(Constants.ISUB); 1109 } 1110 1111 /** 1112 * Subtract the top two stack long values; the <code>lsub</code> opcode. 1113 */ 1114 public MathInstruction lsub() { 1115 return (MathInstruction) addInstruction(Constants.LSUB); 1116 } 1117 1118 /** 1119 * Subtract the top two stack float values; the <code>fsub</code> opcode. 1120 */ 1121 public MathInstruction fsub() { 1122 return (MathInstruction) addInstruction(Constants.FSUB); 1123 } 1124 1125 /** 1126 * Subtract the top two stack double values; the <code>dsub</code> opcode. 1127 */ 1128 public MathInstruction dsub() { 1129 return (MathInstruction) addInstruction(Constants.DSUB); 1130 } 1131 1132 /** 1133 * Multiply the top two stack values. This instruction will result in 1134 * a <code>nop</code> until its type is set. 1135 */ 1136 public MathInstruction xmul() { 1137 MathInstruction mi = math(); 1138 return mi.setOperation(Constants.MATH_MUL); 1139 } 1140 1141 /** 1142 * Multiply the top two stack int values; the <code>imul</code> opcode. 1143 */ 1144 public MathInstruction imul() { 1145 return (MathInstruction) addInstruction(Constants.IMUL); 1146 } 1147 1148 /** 1149 * Multiply the top two stack long values; the <code>lmul</code> opcode. 1150 */ 1151 public MathInstruction lmul() { 1152 return (MathInstruction) addInstruction(Constants.LMUL); 1153 } 1154 1155 /** 1156 * Multiply the top two stack float values; the <code>fmul</code> opcode. 1157 */ 1158 public MathInstruction fmul() { 1159 return (MathInstruction) addInstruction(Constants.FMUL); 1160 } 1161 1162 /** 1163 * Multiply the top two stack double values; the <code>dmul</code> opcode. 1164 */ 1165 public MathInstruction dmul() { 1166 return (MathInstruction) addInstruction(Constants.DMUL); 1167 } 1168 1169 /** 1170 * Divide the top two stack values. This instruction will result in 1171 * a <code>nop</code> until its type is set. 1172 */ 1173 public MathInstruction xdiv() { 1174 MathInstruction mi = math(); 1175 return mi.setOperation(Constants.MATH_DIV); 1176 } 1177 1178 /** 1179 * Divide the top two stack int values; the <code>idiv</code> opcode. 1180 */ 1181 public MathInstruction idiv() { 1182 return (MathInstruction) addInstruction(Constants.IDIV); 1183 } 1184 1185 /** 1186 * Divide the top two stack long values; the <code>ldiv</code> opcode. 1187 */ 1188 public MathInstruction ldiv() { 1189 return (MathInstruction) addInstruction(Constants.LDIV); 1190 } 1191 1192 /** 1193 * Divide the top two stack float values; the <code>fdiv</code> opcode. 1194 */ 1195 public MathInstruction fdiv() { 1196 return (MathInstruction) addInstruction(Constants.FDIV); 1197 } 1198 1199 /** 1200 * Divide the top two stack double values; the <code>ddiv</code> opcode. 1201 */ 1202 public MathInstruction ddiv() { 1203 return (MathInstruction) addInstruction(Constants.DDIV); 1204 } 1205 1206 /** 1207 * Take the remainder of the top two stack values. This instruction will 1208 * result in a <code>nop</code> until its type is set. 1209 */ 1210 public MathInstruction xrem() { 1211 MathInstruction mi = math(); 1212 return mi.setOperation(Constants.MATH_REM); 1213 } 1214 1215 /** 1216 * Take the remainder of the top two int stack values; the 1217 * <code>irem</code> opcode. 1218 */ 1219 public MathInstruction irem() { 1220 return (MathInstruction) addInstruction(Constants.IREM); 1221 } 1222 1223 /** 1224 * Take the remainder of the top two long stack values; the 1225 * <code>lrem</code> opcode. 1226 */ 1227 public MathInstruction lrem() { 1228 return (MathInstruction) addInstruction(Constants.LREM); 1229 } 1230 1231 /** 1232 * Take the remainder of the top two float stack values; the 1233 * <code>frem</code> opcode. 1234 */ 1235 public MathInstruction frem() { 1236 return (MathInstruction) addInstruction(Constants.FREM); 1237 } 1238 1239 /** 1240 * Take the remainder of the top two double stack values; the 1241 * <code>drem</code> opcode. 1242 */ 1243 public MathInstruction drem() { 1244 return (MathInstruction) addInstruction(Constants.DREM); 1245 } 1246 1247 /** 1248 * Negate the top stack value. This instruction will result in a 1249 * <code>nop</code> until its type is set. 1250 */ 1251 public MathInstruction xneg() { 1252 MathInstruction mi = math(); 1253 return mi.setOperation(Constants.MATH_NEG); 1254 } 1255 1256 /** 1257 * Negate the top stack int value; the <code>ineg</code> opcode. 1258 */ 1259 public MathInstruction ineg() { 1260 return (MathInstruction) addInstruction(Constants.INEG); 1261 } 1262 1263 /** 1264 * Negate the top stack long value; the <code>lneg</code> opcode. 1265 */ 1266 public MathInstruction lneg() { 1267 return (MathInstruction) addInstruction(Constants.LNEG); 1268 } 1269 1270 /** 1271 * Negate the top stack float value; the <code>fneg</code> opcode. 1272 */ 1273 public MathInstruction fneg() { 1274 return (MathInstruction) addInstruction(Constants.FNEG); 1275 } 1276 1277 /** 1278 * Negate the top stack double value; the <code>dneg</code> opcode. 1279 */ 1280 public MathInstruction dneg() { 1281 return (MathInstruction) addInstruction(Constants.DNEG); 1282 } 1283 1284 /** 1285 * Shift the top stack values. This instruction will result in a 1286 * <code>nop</code> until its type is set. 1287 */ 1288 public MathInstruction xshl() { 1289 MathInstruction mi = math(); 1290 return mi.setOperation(Constants.MATH_SHL); 1291 } 1292 1293 /** 1294 * Shift the top stack int values; the <code>ishl</code> opcode. 1295 */ 1296 public MathInstruction ishl() { 1297 return (MathInstruction) addInstruction(Constants.ISHL); 1298 } 1299 1300 /** 1301 * Shift the top stack long values; the <code>lshl</code> opcode. 1302 */ 1303 public MathInstruction lshl() { 1304 return (MathInstruction) addInstruction(Constants.LSHL); 1305 } 1306 1307 /** 1308 * Shift the top stack values. This instruction will result in a 1309 * <code>nop</code> until its type is set. 1310 */ 1311 public MathInstruction xshr() { 1312 MathInstruction mi = math(); 1313 return mi.setOperation(Constants.MATH_SHR); 1314 } 1315 1316 /** 1317 * Shift the top stack int values; the <code>ishr</code> opcode. 1318 */ 1319 public MathInstruction ishr() { 1320 return (MathInstruction) addInstruction(Constants.ISHR); 1321 } 1322 1323 /** 1324 * Shift the top stack long values; the <code>lshr</code> opcode. 1325 */ 1326 public MathInstruction lshr() { 1327 return (MathInstruction) addInstruction(Constants.LSHR); 1328 } 1329 1330 /** 1331 * Shift the top stack values. This instruction will result in a 1332 * <code>nop</code> until its type is set. 1333 */ 1334 public MathInstruction xushr() { 1335 MathInstruction mi = math(); 1336 return mi.setOperation(Constants.MATH_USHR); 1337 } 1338 1339 /** 1340 * Shift the top stack int values; the <code>iushr</code> opcode. 1341 */ 1342 public MathInstruction iushr() { 1343 return (MathInstruction) addInstruction(Constants.IUSHR); 1344 } 1345 1346 /** 1347 * Shift the top stack long values; the <code>lushr</code> opcode. 1348 */ 1349 public MathInstruction lushr() { 1350 return (MathInstruction) addInstruction(Constants.LUSHR); 1351 } 1352 1353 /** 1354 * Take the mathematical and of the top two stack values. This instruction 1355 * results in a <code>nop</code> until its type is set. 1356 */ 1357 public MathInstruction xand() { 1358 MathInstruction mi = math(); 1359 return mi.setOperation(Constants.MATH_AND); 1360 } 1361 1362 /** 1363 * Take the mathematical and of the top two stack int values; the 1364 * <code>iand</code> opcode. 1365 */ 1366 public MathInstruction iand() { 1367 return (MathInstruction) addInstruction(Constants.IAND); 1368 } 1369 1370 /** 1371 * Take the mathematical and of the top two stack long values; the 1372 * <code>land</code> opcode. 1373 */ 1374 public MathInstruction land() { 1375 return (MathInstruction) addInstruction(Constants.LAND); 1376 } 1377 1378 /** 1379 * Take the mathematical or of the top two stack values. This instruction 1380 * results in a <code>nop</code> until its type is set. 1381 */ 1382 public MathInstruction xor() { 1383 MathInstruction mi = math(); 1384 return mi.setOperation(Constants.MATH_OR); 1385 } 1386 1387 /** 1388 * Take the mathematical or of the top two stack int values; the 1389 * <code>ior</code> opcode. 1390 */ 1391 public MathInstruction ior() { 1392 return (MathInstruction) addInstruction(Constants.IOR); 1393 } 1394 1395 /** 1396 * Take the mathematical or of the top two stack long values; the 1397 * <code>lor</code> opcode. 1398 */ 1399 public MathInstruction lor() { 1400 return (MathInstruction) addInstruction(Constants.LOR); 1401 } 1402 1403 /** 1404 * Take the mathematical xor of the top two stack values. This instruction 1405 * results in a <code>nop</code> until its type is set. 1406 */ 1407 public MathInstruction xxor() { 1408 MathInstruction mi = math(); 1409 return mi.setOperation(Constants.MATH_XOR); 1410 } 1411 1412 /** 1413 * Take the mathematical xor of the top two stack int values; the 1414 * <code>ixor</code> opcode. 1415 */ 1416 public MathInstruction ixor() { 1417 return (MathInstruction) addInstruction(Constants.IXOR); 1418 } 1419 1420 /** 1421 * Take the mathematical xor of the top two stack long values; the 1422 * <code>lxor</code> opcode. 1423 */ 1424 public MathInstruction lxor() { 1425 return (MathInstruction) addInstruction(Constants.LXOR); 1426 } 1427 1428 /** 1429 * Convert the top stack value to another type. This instruction 1430 * will result in a <code>nop</code> until the types to convert 1431 * between are set. 1432 */ 1433 public ConvertInstruction convert() { 1434 return (ConvertInstruction)addInstruction(new ConvertInstruction(this)); 1435 } 1436 1437 /** 1438 * Compare the top two stack values. This instruction will result in a 1439 * <code>nop</code> until its type is set. 1440 */ 1441 public CmpInstruction xcmp() { 1442 return (CmpInstruction) addInstruction(new CmpInstruction(this)); 1443 } 1444 1445 /** 1446 * Compare the top two stack values; the <code>lcmp</code> opcode. 1447 */ 1448 public CmpInstruction lcmp() { 1449 return (CmpInstruction) addInstruction(Constants.LCMP); 1450 } 1451 1452 /** 1453 * Compare the top two stack values; the <code>fcmpl</code> opcode. 1454 */ 1455 public CmpInstruction fcmpl() { 1456 return (CmpInstruction) addInstruction(Constants.FCMPL); 1457 } 1458 1459 /** 1460 * Compare the top two stack values; the <code>fcmpg</code> opcode. 1461 */ 1462 public CmpInstruction fcmpg() { 1463 return (CmpInstruction) addInstruction(Constants.FCMPG); 1464 } 1465 1466 /** 1467 * Compare the top two stack values; the <code>dcmpl</code> opcode. 1468 */ 1469 public CmpInstruction dcmpl() { 1470 return (CmpInstruction) addInstruction(Constants.DCMPL); 1471 } 1472 1473 /** 1474 * Compare the top two stack values; the <code>dcmpg</code> opcode. 1475 */ 1476 public CmpInstruction dcmpg() { 1477 return (CmpInstruction) addInstruction(Constants.DCMPG); 1478 } 1479 1480 /** 1481 * The <code>ifeq</code> opcode. 1482 */ 1483 public IfInstruction ifeq() { 1484 return (IfInstruction) addInstruction(Constants.IFEQ); 1485 } 1486 1487 /** 1488 * The <code>ifne</code> opcode. 1489 */ 1490 public IfInstruction ifne() { 1491 return (IfInstruction) addInstruction(Constants.IFNE); 1492 } 1493 1494 /** 1495 * The <code>iflt</code> opcode. 1496 */ 1497 public IfInstruction iflt() { 1498 return (IfInstruction) addInstruction(Constants.IFLT); 1499 } 1500 1501 /** 1502 * The <code>ifge</code> opcode. 1503 */ 1504 public IfInstruction ifge() { 1505 return (IfInstruction) addInstruction(Constants.IFGE); 1506 } 1507 1508 /** 1509 * The <code>ifgt</code> opcode. 1510 */ 1511 public IfInstruction ifgt() { 1512 return (IfInstruction) addInstruction(Constants.IFGT); 1513 } 1514 1515 /** 1516 * The <code>ifle</code> opcode. 1517 */ 1518 public IfInstruction ifle() { 1519 return (IfInstruction) addInstruction(Constants.IFLE); 1520 } 1521 1522 /** 1523 * The <code>ificmpeq</code> opcode. 1524 */ 1525 public IfInstruction ificmpeq() { 1526 return (IfInstruction) addInstruction(Constants.IFICMPEQ); 1527 } 1528 1529 /** 1530 * The <code>ificmpne</code> opcode. 1531 */ 1532 public IfInstruction ificmpne() { 1533 return (IfInstruction) addInstruction(Constants.IFICMPNE); 1534 } 1535 1536 /** 1537 * The <code>ificmplt</code> opcode. 1538 */ 1539 public IfInstruction ificmplt() { 1540 return (IfInstruction) addInstruction(Constants.IFICMPLT); 1541 } 1542 1543 /** 1544 * The <code>ificmpge</code> opcode. 1545 */ 1546 public IfInstruction ificmpge() { 1547 return (IfInstruction) addInstruction(Constants.IFICMPGE); 1548 } 1549 1550 /** 1551 * The <code>ificmpgt</code> opcode. 1552 */ 1553 public IfInstruction ificmpgt() { 1554 return (IfInstruction) addInstruction(Constants.IFICMPGT); 1555 } 1556 1557 /** 1558 * The <code>ificmple</code> opcode. 1559 */ 1560 public IfInstruction ificmple() { 1561 return (IfInstruction) addInstruction(Constants.IFICMPLE); 1562 } 1563 1564 /** 1565 * The <code>ifacmpeq</code> opcode. 1566 */ 1567 public IfInstruction ifacmpeq() { 1568 return (IfInstruction) addInstruction(Constants.IFACMPEQ); 1569 } 1570 1571 /** 1572 * The <code>ifacmpne</code> opcode. 1573 */ 1574 public IfInstruction ifacmpne() { 1575 return (IfInstruction) addInstruction(Constants.IFACMPNE); 1576 } 1577 1578 /** 1579 * The <code>ifnull</code> opcode. 1580 */ 1581 public IfInstruction ifnull() { 1582 return (IfInstruction) addInstruction(Constants.IFNULL); 1583 } 1584 1585 /** 1586 * The <code>ifnonnull</code> opcode. 1587 */ 1588 public IfInstruction ifnonnull() { 1589 return (IfInstruction) addInstruction(Constants.IFNONNULL); 1590 } 1591 1592 /** 1593 * The <code>go2</code> opcode. 1594 */ 1595 public JumpInstruction go2() { 1596 return (JumpInstruction) addInstruction(Constants.GOTO); 1597 } 1598 1599 /** 1600 * The <code>jsr</code> opcode used in implementing <code>finally</code> 1601 * clauses. 1602 */ 1603 public JumpInstruction jsr() { 1604 return (JumpInstruction) addInstruction(Constants.JSR); 1605 } 1606 1607 /** 1608 * The <code>tableswitch</code> opcode. 1609 */ 1610 public TableSwitchInstruction tableswitch() { 1611 return (TableSwitchInstruction) addInstruction(Constants.TABLESWITCH); 1612 } 1613 1614 /** 1615 * The <code>lookupswitch</code> opcode. 1616 */ 1617 public LookupSwitchInstruction lookupswitch() { 1618 return (LookupSwitchInstruction) addInstruction(Constants.LOOKUPSWITCH); 1619 } 1620 1621 /** 1622 * Return from a method. This method will result in a 1623 * <code>nop</code> until its type is set. 1624 */ 1625 public ReturnInstruction xreturn() { 1626 return (ReturnInstruction) addInstruction(new ReturnInstruction(this)); 1627 } 1628 1629 /** 1630 * Return void from a method; the <code>return</code> opcode. 1631 */ 1632 public ReturnInstruction vreturn() { 1633 return (ReturnInstruction) addInstruction(Constants.RETURN); 1634 } 1635 1636 /** 1637 * Return an int from a method; the <code>ireturn</code> opcode. 1638 */ 1639 public ReturnInstruction ireturn() { 1640 return (ReturnInstruction) addInstruction(Constants.IRETURN); 1641 } 1642 1643 /** 1644 * Return a long from a method; the <code>lreturn</code> opcode. 1645 */ 1646 public ReturnInstruction lreturn() { 1647 return (ReturnInstruction) addInstruction(Constants.LRETURN); 1648 } 1649 1650 /** 1651 * Return a float from a method; the <code>freturn</code> opcode. 1652 */ 1653 public ReturnInstruction freturn() { 1654 return (ReturnInstruction) addInstruction(Constants.FRETURN); 1655 } 1656 1657 /** 1658 * Return a double from a method; the <code>dreturn</code> opcode. 1659 */ 1660 public ReturnInstruction dreturn() { 1661 return (ReturnInstruction) addInstruction(Constants.DRETURN); 1662 } 1663 1664 /** 1665 * Return an object from a method; the <code>areturn</code> opcode. 1666 */ 1667 public ReturnInstruction areturn() { 1668 return (ReturnInstruction) addInstruction(Constants.ARETURN); 1669 } 1670 1671 /** 1672 * Load the value from a field onto the stack; the <code>getfield</code> 1673 * opcode. 1674 */ 1675 public GetFieldInstruction getfield() { 1676 return (GetFieldInstruction) addInstruction(Constants.GETFIELD); 1677 } 1678 1679 /** 1680 * Load the value from a static field onto the stack; the 1681 * <code>getstatic</code> opcode. 1682 */ 1683 public GetFieldInstruction getstatic() { 1684 return (GetFieldInstruction) addInstruction(Constants.GETSTATIC); 1685 } 1686 1687 /** 1688 * Place the value of a field onto the stack; the <code>putfield</code> 1689 * opcode. 1690 */ 1691 public PutFieldInstruction putfield() { 1692 return (PutFieldInstruction) addInstruction(Constants.PUTFIELD); 1693 } 1694 1695 /** 1696 * Place the value of a static field onto the stack; the 1697 * <code>putstatic</code> opcode. 1698 */ 1699 public PutFieldInstruction putstatic() { 1700 return (PutFieldInstruction) addInstruction(Constants.PUTSTATIC); 1701 } 1702 1703 /** 1704 * Invoke a virtual method; the <code>invokevirtual</code> opcode. 1705 */ 1706 public MethodInstruction invokevirtual() { 1707 return (MethodInstruction) addInstruction(Constants.INVOKEVIRTUAL); 1708 } 1709 1710 /** 1711 * Invoke a method non-virtually, as for constructors and superclass 1712 * methods; the <code>invokespecial</code> opcode. 1713 */ 1714 public MethodInstruction invokespecial() { 1715 return (MethodInstruction) addInstruction(Constants.INVOKESPECIAL); 1716 } 1717 1718 /** 1719 * Invoke a method on an interface; the <code>invokeinterface</code> opcode. 1720 */ 1721 public MethodInstruction invokeinterface() { 1722 return (MethodInstruction) addInstruction(Constants.INVOKEINTERFACE); 1723 } 1724 1725 /** 1726 * Invoke a static method; the <code>invokestatic</code> opcode. 1727 */ 1728 public MethodInstruction invokestatic() { 1729 return (MethodInstruction) addInstruction(Constants.INVOKESTATIC); 1730 } 1731 1732 /** 1733 * Invoke a dynamic method; the <code>invokedynamic</code> opcode. 1734 */ 1735 public MethodInstruction invokedynamic() { 1736 return (MethodInstruction) addInstruction(Constants.INVOKEDYNAMIC); 1737 } 1738 1739 /** 1740 * Create a new instance of an object; the <code>new</code> opcode. 1741 */ 1742 public ClassInstruction anew() { 1743 return (ClassInstruction) addInstruction(Constants.NEW); 1744 } 1745 1746 /** 1747 * Create a new instance of an object array; the <code>anew</code> opcode. 1748 */ 1749 public ClassInstruction anewarray() { 1750 return (ClassInstruction) addInstruction(Constants.ANEWARRAY); 1751 } 1752 1753 /** 1754 * Cast an object on the stack to another type; the <code>checkcast</code> 1755 * opcode. 1756 */ 1757 public ClassInstruction checkcast() { 1758 return (ClassInstruction) addInstruction(Constants.CHECKCAST); 1759 } 1760 1761 /** 1762 * Test if a stack object is an instance of a class; the 1763 * <code>instanceof</code> opcode. 1764 */ 1765 public ClassInstruction isinstance() { 1766 return (ClassInstruction) addInstruction(Constants.INSTANCEOF); 1767 } 1768 1769 /** 1770 * Create a new multidimensional array; the <code>multianewarray</code> 1771 * opcode. 1772 */ 1773 public MultiANewArrayInstruction multianewarray() { 1774 return (MultiANewArrayInstruction) addInstruction 1775 (Constants.MULTIANEWARRAY); 1776 } 1777 1778 /** 1779 * Create a new array of a primitive type; the <code>newarray</code> opcode. 1780 */ 1781 public NewArrayInstruction newarray() { 1782 return (NewArrayInstruction) addInstruction(Constants.NEWARRAY); 1783 } 1784 1785 /** 1786 * Get the length of an array on the stack; the <code>arraylength</code> 1787 * opcode. 1788 */ 1789 public Instruction arraylength() { 1790 return addInstruction(Constants.ARRAYLENGTH); 1791 } 1792 1793 /** 1794 * Throw an exception; the <code>athrow</code> opcode. 1795 */ 1796 public Instruction athrow() { 1797 return addInstruction(Constants.ATHROW); 1798 } 1799 1800 /** 1801 * The <code>monitorenter</code> opcode. 1802 */ 1803 public MonitorEnterInstruction monitorenter() { 1804 return (MonitorEnterInstruction) addInstruction(Constants.MONITORENTER); 1805 } 1806 1807 /** 1808 * The <code>monitorexit</code> opcode. 1809 */ 1810 public MonitorExitInstruction monitorexit() { 1811 return (MonitorExitInstruction) addInstruction(Constants.MONITOREXIT); 1812 } 1813 1814 ///////////////////////// 1815 // Wholisitic operations 1816 ///////////////////////// 1817 1818 /** 1819 * Return all the Instructions of this method. 1820 */ 1821 public Instruction[] getInstructions() { 1822 Instruction[] arr = new Instruction[_size]; 1823 int i = 0; 1824 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) 1825 arr[i++] = (Instruction) entry; 1826 return arr; 1827 } 1828 1829 int getLength() { 1830 // covers maxStack, maxLocals, codeLength, exceptionTableLength, 1831 // attributeCount 1832 int length = 12; 1833 1834 // add code 1835 Instruction last = getLastInstruction(); 1836 if (last != null) 1837 length += last.getByteIndex() + last.getLength(); 1838 1839 // add exception reps; each is 8 bytes 1840 length += (8 * _handlers.size()); 1841 1842 // add all attribute lengths 1843 Attribute[] attrs = getAttributes(); 1844 for (int i = 0; i < attrs.length; i++) 1845 length += (attrs[i].getLength() + 6); 1846 return length; 1847 } 1848 1849 public void acceptVisit(BCVisitor visit) { 1850 visit.enterCode(this); 1851 Instruction ins; 1852 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 1853 ins = (Instruction) entry; 1854 visit.enterInstruction(ins); 1855 ins.acceptVisit(visit); 1856 visit.exitInstruction(ins); 1857 } 1858 for (Iterator i = _handlers.iterator(); i.hasNext();) 1859 ((ExceptionHandler) i.next()).acceptVisit(visit); 1860 visitAttributes(visit); 1861 visit.exitCode(this); 1862 } 1863 1864 ////////////////////////// 1865 // Convenience operations 1866 ////////////////////////// 1867 1868 /** 1869 * Return line number information for the code. 1870 * Acts internally through the {@link Attributes} interface. 1871 * 1872 * @param add if true, a new line number table will be added 1873 * if not already present 1874 * @return the line number information, or null if none 1875 * and the <code>add</code> param is set to false 1876 */ 1877 public LineNumberTable getLineNumberTable(boolean add) { 1878 LineNumberTable attr = (LineNumberTable) getAttribute 1879 (Constants.ATTR_LINENUMBERS); 1880 1881 if (!add || (attr != null)) 1882 return attr; 1883 return (LineNumberTable) addAttribute(Constants.ATTR_LINENUMBERS); 1884 } 1885 1886 /** 1887 * Remove the line number table for the code. 1888 * Acts internally through the {@link Attributes} interface. 1889 * 1890 * @return true if there was a table to remove 1891 */ 1892 public boolean removeLineNumberTable() { 1893 return removeAttribute(Constants.ATTR_LINENUMBERS); 1894 } 1895 1896 /** 1897 * Return local variable information for the code. 1898 * Acts internally through the {@link Attributes} interface. 1899 * 1900 * @param add if true, a new local variable table will be 1901 * added if not already present 1902 * @return the local variable information, or null if none 1903 * and the <code>add</code> param is set to false 1904 */ 1905 public LocalVariableTable getLocalVariableTable(boolean add) { 1906 LocalVariableTable attr = (LocalVariableTable) getAttribute 1907 (Constants.ATTR_LOCALS); 1908 if (!add || (attr != null)) 1909 return attr; 1910 return (LocalVariableTable) addAttribute(Constants.ATTR_LOCALS); 1911 } 1912 1913 /** 1914 * Remove the local variable table for the code. 1915 * Acts internally through the {@link Attributes} interface. 1916 * 1917 * @return true if there was a table to remove 1918 */ 1919 public boolean removeLocalVariableTables() { 1920 return removeAttribute(Constants.ATTR_LOCALS); 1921 } 1922 1923 /** 1924 * Return local variable generics information for the code. 1925 * Acts internally through the {@link Attributes} interface. 1926 * 1927 * @param add if true, a new local variable type table will be 1928 * added if not already present 1929 * @return the local variable type information, or null if none 1930 * and the <code>add</code> param is set to false 1931 */ 1932 public LocalVariableTypeTable getLocalVariableTypeTable(boolean add) { 1933 LocalVariableTypeTable attr = (LocalVariableTypeTable) getAttribute 1934 (Constants.ATTR_LOCAL_TYPES); 1935 if (!add || (attr != null)) 1936 return attr; 1937 return (LocalVariableTypeTable)addAttribute(Constants.ATTR_LOCAL_TYPES); 1938 } 1939 1940 /** 1941 * Remove the local variable type table for the code. 1942 * Acts internally through the {@link Attributes} interface. 1943 * 1944 * @return true if there was a table to remove 1945 */ 1946 public boolean removeLocalVariableTypeTables() { 1947 return removeAttribute(Constants.ATTR_LOCAL_TYPES); 1948 } 1949 1950 ////////////////// 1951 // I/O operations 1952 ////////////////// 1953 1954 void read(Attribute attr) { 1955 Code orig = (Code) attr; 1956 _maxStack = orig.getMaxStack(); 1957 _maxLocals = orig.getMaxLocals(); 1958 1959 // clear existing code 1960 _head.next = _tail; 1961 _tail.prev = _head; 1962 _size = 0; 1963 _byteIndexesValid = false; 1964 beforeFirst(); 1965 _handlers.clear(); 1966 1967 // copy all instructions; don't set constant instruction values until 1968 // instruction ptrs have been updated in case the instruction width 1969 // changes because of differences in the constant pool (LDC vs LDCW) 1970 Instruction ins; 1971 Instruction origIns; 1972 for (CodeEntry entry = orig._head.next; entry != orig._tail; 1973 entry = entry.next) { 1974 origIns = (Instruction) entry; 1975 ins = createInstruction(origIns.getOpcode()); 1976 _ci.addInternal(ins); 1977 if (!(ins instanceof ConstantInstruction)) 1978 ins.read(origIns); 1979 } 1980 1981 // copy exception handlers 1982 ExceptionHandler[] origHandlers = orig.getExceptionHandlers(); 1983 ExceptionHandler handler; 1984 for (int i = 0; i < origHandlers.length; i++) { 1985 handler = addExceptionHandler(); 1986 handler.read(origHandlers[i]); 1987 handler.updateTargets(); 1988 } 1989 1990 // reset all opcode ptrs to the new copied opcodes 1991 updateInstructionPointers(); 1992 setAttributes(orig.getAttributes()); 1993 1994 // setup local variable markers 1995 LocalVariableTable locals = getLocalVariableTable(false); 1996 if (locals != null) 1997 locals.updateTargets(); 1998 1999 // setup local variable markers 2000 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false); 2001 if (localTypes != null) 2002 localTypes.updateTargets(); 2003 2004 // setup line number markers 2005 LineNumberTable lines = getLineNumberTable(false); 2006 if (lines != null) 2007 lines.updateTargets(); 2008 2009 // now copy constant instruction values 2010 CodeEntry copy = _head.next; 2011 for (CodeEntry entry = orig._head.next; entry != orig._tail; 2012 entry = entry.next, copy = copy.next) { 2013 if (entry instanceof ConstantInstruction) 2014 ((ConstantInstruction) copy).read((Instruction) entry); 2015 } 2016 beforeFirst(); 2017 } 2018 2019 void read(DataInput in, int length) throws IOException { 2020 _maxStack = in.readUnsignedShort(); 2021 _maxLocals = in.readUnsignedShort(); 2022 readCode(in, in.readInt()); 2023 2024 _handlers.clear(); 2025 int exceptionCount = in.readUnsignedShort(); 2026 ExceptionHandler excep; 2027 for (int i = 0; i < exceptionCount; i++) { 2028 excep = addExceptionHandler(); 2029 excep.read(in); 2030 excep.updateTargets(); 2031 } 2032 2033 readAttributes(in); 2034 2035 // setup local variable markers 2036 LocalVariableTable locals = getLocalVariableTable(false); 2037 if (locals != null) 2038 locals.updateTargets(); 2039 2040 // setup local variable markers 2041 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false); 2042 if (localTypes != null) 2043 localTypes.updateTargets(); 2044 2045 // setup line number markers 2046 LineNumberTable lines = getLineNumberTable(false); 2047 if (lines != null) 2048 lines.updateTargets(); 2049 } 2050 2051 void write(DataOutput out, int length) throws IOException { 2052 out.writeShort(_maxStack); 2053 out.writeShort(_maxLocals); 2054 2055 byte[] code = toByteArray(); 2056 out.writeInt(code.length); 2057 out.write(code); 2058 2059 out.writeShort(_handlers.size()); 2060 for (Iterator itr = _handlers.iterator(); itr.hasNext();) 2061 ((ExceptionHandler) itr.next()).write(out); 2062 writeAttributes(out); 2063 } 2064 2065 private void readCode(DataInput in, int len) throws IOException { 2066 _head.next = _tail; 2067 _tail.prev = _head; 2068 _size = 0; 2069 _byteIndexesValid = true; 2070 2071 beforeFirst(); 2072 Instruction ins; 2073 for (int byteIndex = 0; byteIndex < len;) { 2074 ins = createInstruction(in.readUnsignedByte()); 2075 _ci.addInternal(ins); 2076 ins.byteIndex = byteIndex; 2077 ins.read(in); 2078 byteIndex += ins.getLength(); 2079 } 2080 updateInstructionPointers(); 2081 beforeFirst(); 2082 2083 // sanity check 2084 if (!_byteIndexesValid) 2085 throw new IllegalStateException(); 2086 } 2087 2088 /** 2089 * Ensures that all the opcode targets are set up correctly. 2090 */ 2091 private void updateInstructionPointers() { 2092 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) 2093 if (entry instanceof InstructionPtr) 2094 ((InstructionPtr) entry).updateTargets(); 2095 } 2096 2097 /** 2098 * Returns the byteIndex of the given instruction. 2099 */ 2100 int getByteIndex(Instruction ins) { 2101 if (_byteIndexesValid && ins.byteIndex != -1) 2102 return ins.byteIndex; 2103 2104 int byteIndex = 0; 2105 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2106 if (entry == ins) 2107 return byteIndex; 2108 byteIndex += ((Instruction) entry).getLength(); 2109 } 2110 throw new IllegalArgumentException("ins.owner != this"); 2111 } 2112 2113 /** 2114 * Invalidate all byteindexes when the code block changes. 2115 */ 2116 void invalidateByteIndexes() { 2117 _byteIndexesValid = false; 2118 } 2119 2120 /** 2121 * Returns the instruction in this code block found at the given byte index. 2122 */ 2123 Instruction getInstruction(int byteIndex) { 2124 if (byteIndex < 0) 2125 return null; 2126 2127 int curIndex = 0; 2128 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2129 if (byteIndex == curIndex) 2130 return (Instruction) entry; 2131 curIndex += ((Instruction) entry).getLength(); 2132 } 2133 2134 // some instruction ptrs are actually to a "next" instruction, so 2135 // allow one past the end 2136 if (byteIndex == curIndex) 2137 return null; 2138 throw new IllegalArgumentException(String.valueOf(byteIndex)); 2139 } 2140 2141 /** 2142 * Return the first instruction in this code block, or null if none. 2143 */ 2144 Instruction getFirstInstruction() { 2145 return (Instruction) _head.next; 2146 } 2147 2148 /** 2149 * Return the last instruction in this code block, or null if none. 2150 */ 2151 Instruction getLastInstruction() { 2152 return (Instruction) _tail.prev; 2153 } 2154 2155 /** 2156 * Returns the number of instructions that occur before 'ins' 2157 * in this code block that 'ins' is a part of. 2158 * 2159 * @throws IllegalArgumentException if this code block is not the owner 2160 * of ins 2161 */ 2162 private int indexOf(Instruction ins) { 2163 int i = 0; 2164 for (CodeEntry entry = _head.next; entry != _tail; 2165 entry = entry.next, i++) 2166 if (entry == ins) 2167 return i; 2168 throw new IllegalArgumentException("ins.code != this"); 2169 } 2170 2171 private void writeCode(DataOutput out) throws IOException { 2172 Instruction ins; 2173 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2174 ins = (Instruction) entry; 2175 out.writeByte(ins.getOpcode()); 2176 ins.write(out); 2177 } 2178 } 2179 2180 private byte[] toByteArray() throws IOException { 2181 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 2182 DataOutputStream stream = new DataOutputStream(byteStream); 2183 try { 2184 writeCode(stream); 2185 return byteStream.toByteArray(); 2186 } finally { 2187 try { stream.close(); } catch (Exception e) {} 2188 } 2189 } 2190 2191 private void fromByteArray(byte[] code) throws IOException { 2192 if (code == null) { 2193 _head.next = _tail; 2194 _tail.prev = _head; 2195 _size = 0; 2196 } else { 2197 DataInputStream stream = new DataInputStream 2198 (new ByteArrayInputStream(code)); 2199 try { 2200 readCode(stream, code.length); 2201 } finally { 2202 try { stream.close(); } catch (Exception e) {} 2203 } 2204 } 2205 } 2206 2207 private Instruction addInstruction(Instruction ins) { 2208 _ci.add(ins); 2209 return ins; 2210 } 2211 2212 private Instruction addInstruction(int opcode) { 2213 return addInstruction(createInstruction(opcode)); 2214 } 2215 2216 /** 2217 * Creates an Instruction, with this code block as the owner. 2218 * Note that the Instruction is not added to this Code block. 2219 */ 2220 private Instruction createInstruction(int opcode) { 2221 switch (opcode) { 2222 case Constants.NOP: 2223 case Constants.ARRAYLENGTH: 2224 case Constants.ATHROW: 2225 return new Instruction(this, opcode); 2226 case Constants.ACONSTNULL: 2227 case Constants.ICONSTM1: 2228 case Constants.ICONST0: 2229 case Constants.ICONST1: 2230 case Constants.ICONST2: 2231 case Constants.ICONST3: 2232 case Constants.ICONST4: 2233 case Constants.ICONST5: 2234 case Constants.LCONST0: 2235 case Constants.LCONST1: 2236 case Constants.FCONST0: 2237 case Constants.FCONST1: 2238 case Constants.FCONST2: 2239 case Constants.DCONST0: 2240 case Constants.DCONST1: 2241 case Constants.BIPUSH: 2242 case Constants.SIPUSH: 2243 case Constants.LDC: 2244 case Constants.LDCW: 2245 case Constants.LDC2W: 2246 return new ConstantInstruction(this, opcode); 2247 case Constants.ILOAD: 2248 case Constants.LLOAD: 2249 case Constants.FLOAD: 2250 case Constants.DLOAD: 2251 case Constants.ALOAD: 2252 case Constants.ILOAD0: 2253 case Constants.ILOAD1: 2254 case Constants.ILOAD2: 2255 case Constants.ILOAD3: 2256 case Constants.LLOAD0: 2257 case Constants.LLOAD1: 2258 case Constants.LLOAD2: 2259 case Constants.LLOAD3: 2260 case Constants.FLOAD0: 2261 case Constants.FLOAD1: 2262 case Constants.FLOAD2: 2263 case Constants.FLOAD3: 2264 case Constants.DLOAD0: 2265 case Constants.DLOAD1: 2266 case Constants.DLOAD2: 2267 case Constants.DLOAD3: 2268 case Constants.ALOAD0: 2269 case Constants.ALOAD1: 2270 case Constants.ALOAD2: 2271 case Constants.ALOAD3: 2272 return new LoadInstruction(this, opcode); 2273 case Constants.IALOAD: 2274 case Constants.LALOAD: 2275 case Constants.FALOAD: 2276 case Constants.DALOAD: 2277 case Constants.AALOAD: 2278 case Constants.BALOAD: 2279 case Constants.CALOAD: 2280 case Constants.SALOAD: 2281 return new ArrayLoadInstruction(this, opcode); 2282 case Constants.ISTORE: 2283 case Constants.LSTORE: 2284 case Constants.FSTORE: 2285 case Constants.DSTORE: 2286 case Constants.ASTORE: 2287 case Constants.ISTORE0: 2288 case Constants.ISTORE1: 2289 case Constants.ISTORE2: 2290 case Constants.ISTORE3: 2291 case Constants.LSTORE0: 2292 case Constants.LSTORE1: 2293 case Constants.LSTORE2: 2294 case Constants.LSTORE3: 2295 case Constants.FSTORE0: 2296 case Constants.FSTORE1: 2297 case Constants.FSTORE2: 2298 case Constants.FSTORE3: 2299 case Constants.DSTORE0: 2300 case Constants.DSTORE1: 2301 case Constants.DSTORE2: 2302 case Constants.DSTORE3: 2303 case Constants.ASTORE0: 2304 case Constants.ASTORE1: 2305 case Constants.ASTORE2: 2306 case Constants.ASTORE3: 2307 return new StoreInstruction(this, opcode); 2308 case Constants.IASTORE: 2309 case Constants.LASTORE: 2310 case Constants.FASTORE: 2311 case Constants.DASTORE: 2312 case Constants.AASTORE: 2313 case Constants.BASTORE: 2314 case Constants.CASTORE: 2315 case Constants.SASTORE: 2316 return new ArrayStoreInstruction(this, opcode); 2317 case Constants.POP: 2318 case Constants.POP2: 2319 case Constants.DUP: 2320 case Constants.DUPX1: 2321 case Constants.DUPX2: 2322 case Constants.DUP2: 2323 case Constants.DUP2X1: 2324 case Constants.DUP2X2: 2325 case Constants.SWAP: 2326 return new StackInstruction(this, opcode); 2327 case Constants.IADD: 2328 case Constants.LADD: 2329 case Constants.FADD: 2330 case Constants.DADD: 2331 case Constants.ISUB: 2332 case Constants.LSUB: 2333 case Constants.FSUB: 2334 case Constants.DSUB: 2335 case Constants.IMUL: 2336 case Constants.LMUL: 2337 case Constants.FMUL: 2338 case Constants.DMUL: 2339 case Constants.IDIV: 2340 case Constants.LDIV: 2341 case Constants.FDIV: 2342 case Constants.DDIV: 2343 case Constants.IREM: 2344 case Constants.LREM: 2345 case Constants.FREM: 2346 case Constants.DREM: 2347 case Constants.INEG: 2348 case Constants.LNEG: 2349 case Constants.FNEG: 2350 case Constants.DNEG: 2351 case Constants.ISHL: 2352 case Constants.LSHL: 2353 case Constants.ISHR: 2354 case Constants.LSHR: 2355 case Constants.IUSHR: 2356 case Constants.LUSHR: 2357 case Constants.IAND: 2358 case Constants.LAND: 2359 case Constants.IOR: 2360 case Constants.LOR: 2361 case Constants.IXOR: 2362 case Constants.LXOR: 2363 return new MathInstruction(this, opcode); 2364 case Constants.IINC: 2365 return new IIncInstruction(this); 2366 case Constants.I2L: 2367 case Constants.I2F: 2368 case Constants.I2D: 2369 case Constants.L2I: 2370 case Constants.L2F: 2371 case Constants.L2D: 2372 case Constants.F2I: 2373 case Constants.F2L: 2374 case Constants.F2D: 2375 case Constants.D2I: 2376 case Constants.D2L: 2377 case Constants.D2F: 2378 case Constants.I2B: 2379 case Constants.I2C: 2380 case Constants.I2S: 2381 return new ConvertInstruction(this, opcode); 2382 case Constants.LCMP: 2383 case Constants.FCMPL: 2384 case Constants.FCMPG: 2385 case Constants.DCMPL: 2386 case Constants.DCMPG: 2387 return new CmpInstruction(this, opcode); 2388 case Constants.IFEQ: 2389 case Constants.IFNE: 2390 case Constants.IFLT: 2391 case Constants.IFGE: 2392 case Constants.IFGT: 2393 case Constants.IFLE: 2394 case Constants.IFICMPEQ: 2395 case Constants.IFICMPNE: 2396 case Constants.IFICMPLT: 2397 case Constants.IFICMPGE: 2398 case Constants.IFICMPGT: 2399 case Constants.IFICMPLE: 2400 case Constants.IFACMPEQ: 2401 case Constants.IFACMPNE: 2402 case Constants.IFNULL: 2403 case Constants.IFNONNULL: 2404 return new IfInstruction(this, opcode); 2405 case Constants.GOTO: 2406 case Constants.JSR: 2407 case Constants.GOTOW: 2408 case Constants.JSRW: 2409 return new GotoInstruction(this, opcode); 2410 case Constants.RET: 2411 return new RetInstruction(this); 2412 case Constants.TABLESWITCH: 2413 return new TableSwitchInstruction(this); 2414 case Constants.LOOKUPSWITCH: 2415 return new LookupSwitchInstruction(this); 2416 case Constants.IRETURN: 2417 case Constants.LRETURN: 2418 case Constants.FRETURN: 2419 case Constants.DRETURN: 2420 case Constants.ARETURN: 2421 case Constants.RETURN: 2422 return new ReturnInstruction(this, opcode); 2423 case Constants.GETSTATIC: 2424 case Constants.GETFIELD: 2425 return new GetFieldInstruction(this, opcode); 2426 case Constants.PUTSTATIC: 2427 case Constants.PUTFIELD: 2428 return new PutFieldInstruction(this, opcode); 2429 case Constants.INVOKEVIRTUAL: 2430 case Constants.INVOKESPECIAL: 2431 case Constants.INVOKESTATIC: 2432 case Constants.INVOKEINTERFACE: 2433 case Constants.INVOKEDYNAMIC: 2434 return new MethodInstruction(this, opcode); 2435 case Constants.NEW: 2436 case Constants.ANEWARRAY: 2437 case Constants.CHECKCAST: 2438 case Constants.INSTANCEOF: 2439 return new ClassInstruction(this, opcode); 2440 case Constants.NEWARRAY: 2441 return new NewArrayInstruction(this); 2442 case Constants.MONITORENTER: 2443 return new MonitorEnterInstruction(this); 2444 case Constants.MONITOREXIT: 2445 return new MonitorExitInstruction(this); 2446 case Constants.WIDE: 2447 return new WideInstruction(this); 2448 case Constants.MULTIANEWARRAY: 2449 return new MultiANewArrayInstruction(this); 2450 default: 2451 throw new IllegalArgumentException("Illegal opcode: " + opcode); 2452 } 2453 } 2454 2455 /** 2456 * Returns another listIterator view of the Instructions in this 2457 * code block. Useful for performing read-only searches through 2458 * Instructions without effecting the pointer location of the main 2459 * code block. 2460 */ 2461 public ListIterator listIterator() { 2462 return new CodeIterator(_head, -1); 2463 } 2464 2465 /** 2466 * Helper class to handle invalidation of instructions on removal 2467 * and notification of modification on addition. 2468 */ 2469 private class CodeIterator implements ListIterator { 2470 public static final int UNSET = -99; 2471 private CodeEntry _bn = null; // "before next" entry 2472 private Instruction _last = null; // last entry returned 2473 private int _index = UNSET; // index of _bn 2474 2475 public CodeIterator(CodeEntry entry, int index) { 2476 _bn = entry; 2477 _index = index; 2478 } 2479 2480 public boolean hasNext() { 2481 return _bn.next != _tail; 2482 } 2483 2484 public boolean hasPrevious() { 2485 return _bn != _head; 2486 } 2487 2488 public Object next() { 2489 if (!hasNext()) 2490 throw new NoSuchElementException(); 2491 2492 _bn = _bn.next; 2493 _last = (Instruction) _bn; 2494 if (_index != UNSET) 2495 _index++; 2496 return _last; 2497 } 2498 2499 public int nextIndex() { 2500 return initIndex() + 1; 2501 } 2502 2503 public Object previous() { 2504 if (!hasPrevious()) 2505 throw new NoSuchElementException(); 2506 2507 _last = (Instruction) _bn; 2508 _bn = _bn.prev; 2509 if (_index != UNSET) 2510 _index--; 2511 return _last; 2512 } 2513 2514 public int previousIndex() { 2515 return initIndex(); 2516 } 2517 2518 private int initIndex() { 2519 if (_index == UNSET) { 2520 if (_bn == _head) 2521 _index = -1; 2522 else 2523 _index = indexOf((Instruction) _bn); 2524 } 2525 return _index; 2526 } 2527 2528 public void add(Object obj) { 2529 addInternal(obj); 2530 invalidateByteIndexes(); 2531 } 2532 2533 private void addInternal(Object obj) { 2534 if (obj == null) 2535 throw new NullPointerException("obj = null"); 2536 2537 Instruction ins = (Instruction) obj; 2538 if (_size == 0) { 2539 _head.next = ins; 2540 _tail.prev = ins; 2541 ins.prev = _head; 2542 ins.next = _tail; 2543 _index = 0; 2544 } else { 2545 CodeEntry next = _bn.next; 2546 _bn.next = ins; 2547 next.prev = ins; 2548 ins.prev = _bn; 2549 ins.next = next; 2550 if (_index != UNSET) 2551 _index++; 2552 } 2553 2554 _bn = ins; 2555 _last = ins; 2556 _size++; 2557 } 2558 2559 public void set(Object obj) { 2560 if (obj == null) 2561 throw new NullPointerException("obj = null"); 2562 if (_last == null) 2563 throw new IllegalStateException(); 2564 2565 Instruction ins = (Instruction) obj; 2566 ins.prev = _last.prev; 2567 ins.next = _last.next; 2568 ins.prev.next = ins; 2569 ins.next.prev = ins; 2570 2571 replaceTarget(_last, ins); 2572 _last.invalidate(); 2573 if (_bn == _last) 2574 _bn = ins; 2575 _last = ins; 2576 invalidateByteIndexes(); 2577 } 2578 2579 public void remove() { 2580 if (_last == null) 2581 throw new IllegalStateException(); 2582 2583 if (_bn == _last) 2584 _bn = _last.prev; 2585 _index--; 2586 _last.prev.next = _last.next; 2587 _last.next.prev = _last.prev; 2588 _size--; 2589 2590 Instruction orig = _last; 2591 Instruction replace = null; 2592 if (orig.next != _tail) 2593 replace = (Instruction) orig.next; 2594 else 2595 replace = nop(); 2596 replaceTarget(orig, replace); 2597 orig.invalidate(); 2598 _last = null; 2599 invalidateByteIndexes(); 2600 } 2601 2602 private void replaceTarget(Instruction orig, Instruction replace) { 2603 for (CodeEntry entry = _head.next; entry != _tail; 2604 entry = entry.next) { 2605 if (entry instanceof InstructionPtr) 2606 ((InstructionPtr) entry).replaceTarget(orig, replace); 2607 } 2608 2609 // update the ExceptionHandler pointers 2610 ExceptionHandler[] handlers = getExceptionHandlers(); 2611 for (int i = 0; i < handlers.length; i++) 2612 handlers[i].replaceTarget(orig, replace); 2613 2614 // update LineNumber pointers 2615 LineNumberTable lineNumbers = getLineNumberTable(false); 2616 if (lineNumbers != null) 2617 lineNumbers.replaceTarget(orig, replace); 2618 2619 // update LocalVariable pointers 2620 LocalVariableTable variables = getLocalVariableTable(false); 2621 if (variables != null) 2622 variables.replaceTarget(orig, replace); 2623 2624 // update LocalVariableType pointers 2625 LocalVariableTypeTable types = getLocalVariableTypeTable(false); 2626 if (types != null) 2627 types.replaceTarget(orig, replace); 2628 } 2629 } 2630}