001 package serp.bytecode; 002 003 import java.io.*; 004 import java.util.*; 005 006 import serp.bytecode.lowlevel.*; 007 import 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 */ 032 public 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 * Create a new instance of an object; the <code>new</code> opcode. 1734 */ 1735 public ClassInstruction anew() { 1736 return (ClassInstruction) addInstruction(Constants.NEW); 1737 } 1738 1739 /** 1740 * Create a new instance of an object array; the <code>anew</code> opcode. 1741 */ 1742 public ClassInstruction anewarray() { 1743 return (ClassInstruction) addInstruction(Constants.ANEWARRAY); 1744 } 1745 1746 /** 1747 * Cast an object on the stack to another type; the <code>checkcast</code> 1748 * opcode. 1749 */ 1750 public ClassInstruction checkcast() { 1751 return (ClassInstruction) addInstruction(Constants.CHECKCAST); 1752 } 1753 1754 /** 1755 * Test if a stack object is an instance of a class; the 1756 * <code>instanceof</code> opcode. 1757 */ 1758 public ClassInstruction isinstance() { 1759 return (ClassInstruction) addInstruction(Constants.INSTANCEOF); 1760 } 1761 1762 /** 1763 * Create a new multidimensional array; the <code>multianewarray</code> 1764 * opcode. 1765 */ 1766 public MultiANewArrayInstruction multianewarray() { 1767 return (MultiANewArrayInstruction) addInstruction 1768 (Constants.MULTIANEWARRAY); 1769 } 1770 1771 /** 1772 * Create a new array of a primitive type; the <code>newarray</code> opcode. 1773 */ 1774 public NewArrayInstruction newarray() { 1775 return (NewArrayInstruction) addInstruction(Constants.NEWARRAY); 1776 } 1777 1778 /** 1779 * Get the length of an array on the stack; the <code>arraylength</code> 1780 * opcode. 1781 */ 1782 public Instruction arraylength() { 1783 return addInstruction(Constants.ARRAYLENGTH); 1784 } 1785 1786 /** 1787 * Throw an exception; the <code>athrow</code> opcode. 1788 */ 1789 public Instruction athrow() { 1790 return addInstruction(Constants.ATHROW); 1791 } 1792 1793 /** 1794 * The <code>monitorenter</code> opcode. 1795 */ 1796 public MonitorEnterInstruction monitorenter() { 1797 return (MonitorEnterInstruction) addInstruction(Constants.MONITORENTER); 1798 } 1799 1800 /** 1801 * The <code>monitorexit</code> opcode. 1802 */ 1803 public MonitorExitInstruction monitorexit() { 1804 return (MonitorExitInstruction) addInstruction(Constants.MONITOREXIT); 1805 } 1806 1807 ///////////////////////// 1808 // Wholisitic operations 1809 ///////////////////////// 1810 1811 /** 1812 * Return all the Instructions of this method. 1813 */ 1814 public Instruction[] getInstructions() { 1815 Instruction[] arr = new Instruction[_size]; 1816 int i = 0; 1817 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) 1818 arr[i++] = (Instruction) entry; 1819 return arr; 1820 } 1821 1822 int getLength() { 1823 // covers maxStack, maxLocals, codeLength, exceptionTableLength, 1824 // attributeCount 1825 int length = 12; 1826 1827 // add code 1828 Instruction last = getLastInstruction(); 1829 if (last != null) 1830 length += last.getByteIndex() + last.getLength(); 1831 1832 // add exception reps; each is 8 bytes 1833 length += (8 * _handlers.size()); 1834 1835 // add all attribute lengths 1836 Attribute[] attrs = getAttributes(); 1837 for (int i = 0; i < attrs.length; i++) 1838 length += (attrs[i].getLength() + 6); 1839 return length; 1840 } 1841 1842 public void acceptVisit(BCVisitor visit) { 1843 visit.enterCode(this); 1844 Instruction ins; 1845 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 1846 ins = (Instruction) entry; 1847 visit.enterInstruction(ins); 1848 ins.acceptVisit(visit); 1849 visit.exitInstruction(ins); 1850 } 1851 for (Iterator i = _handlers.iterator(); i.hasNext();) 1852 ((ExceptionHandler) i.next()).acceptVisit(visit); 1853 visitAttributes(visit); 1854 visit.exitCode(this); 1855 } 1856 1857 ////////////////////////// 1858 // Convenience operations 1859 ////////////////////////// 1860 1861 /** 1862 * Return line number information for the code. 1863 * Acts internally through the {@link Attributes} interface. 1864 * 1865 * @param add if true, a new line number table will be added 1866 * if not already present 1867 * @return the line number information, or null if none 1868 * and the <code>add</code> param is set to false 1869 */ 1870 public LineNumberTable getLineNumberTable(boolean add) { 1871 LineNumberTable attr = (LineNumberTable) getAttribute 1872 (Constants.ATTR_LINENUMBERS); 1873 1874 if (!add || (attr != null)) 1875 return attr; 1876 return (LineNumberTable) addAttribute(Constants.ATTR_LINENUMBERS); 1877 } 1878 1879 /** 1880 * Remove the line number table for the code. 1881 * Acts internally through the {@link Attributes} interface. 1882 * 1883 * @return true if there was a table to remove 1884 */ 1885 public boolean removeLineNumberTable() { 1886 return removeAttribute(Constants.ATTR_LINENUMBERS); 1887 } 1888 1889 /** 1890 * Return local variable information for the code. 1891 * Acts internally through the {@link Attributes} interface. 1892 * 1893 * @param add if true, a new local variable table will be 1894 * added if not already present 1895 * @return the local variable information, or null if none 1896 * and the <code>add</code> param is set to false 1897 */ 1898 public LocalVariableTable getLocalVariableTable(boolean add) { 1899 LocalVariableTable attr = (LocalVariableTable) getAttribute 1900 (Constants.ATTR_LOCALS); 1901 if (!add || (attr != null)) 1902 return attr; 1903 return (LocalVariableTable) addAttribute(Constants.ATTR_LOCALS); 1904 } 1905 1906 /** 1907 * Remove the local variable table for the code. 1908 * Acts internally through the {@link Attributes} interface. 1909 * 1910 * @return true if there was a table to remove 1911 */ 1912 public boolean removeLocalVariableTables() { 1913 return removeAttribute(Constants.ATTR_LOCALS); 1914 } 1915 1916 /** 1917 * Return local variable generics information for the code. 1918 * Acts internally through the {@link Attributes} interface. 1919 * 1920 * @param add if true, a new local variable type table will be 1921 * added if not already present 1922 * @return the local variable type information, or null if none 1923 * and the <code>add</code> param is set to false 1924 */ 1925 public LocalVariableTypeTable getLocalVariableTypeTable(boolean add) { 1926 LocalVariableTypeTable attr = (LocalVariableTypeTable) getAttribute 1927 (Constants.ATTR_LOCAL_TYPES); 1928 if (!add || (attr != null)) 1929 return attr; 1930 return (LocalVariableTypeTable)addAttribute(Constants.ATTR_LOCAL_TYPES); 1931 } 1932 1933 /** 1934 * Remove the local variable type table for the code. 1935 * Acts internally through the {@link Attributes} interface. 1936 * 1937 * @return true if there was a table to remove 1938 */ 1939 public boolean removeLocalVariableTypeTables() { 1940 return removeAttribute(Constants.ATTR_LOCAL_TYPES); 1941 } 1942 1943 ////////////////// 1944 // I/O operations 1945 ////////////////// 1946 1947 void read(Attribute attr) { 1948 Code orig = (Code) attr; 1949 _maxStack = orig.getMaxStack(); 1950 _maxLocals = orig.getMaxLocals(); 1951 1952 // clear existing code 1953 _head.next = _tail; 1954 _tail.prev = _head; 1955 _size = 0; 1956 _byteIndexesValid = false; 1957 beforeFirst(); 1958 _handlers.clear(); 1959 1960 // copy all instructions; don't set constant instruction values until 1961 // instruction ptrs have been updated in case the instruction width 1962 // changes because of differences in the constant pool (LDC vs LDCW) 1963 Instruction ins; 1964 Instruction origIns; 1965 for (CodeEntry entry = orig._head.next; entry != orig._tail; 1966 entry = entry.next) { 1967 origIns = (Instruction) entry; 1968 ins = createInstruction(origIns.getOpcode()); 1969 _ci.addInternal(ins); 1970 if (!(ins instanceof ConstantInstruction)) 1971 ins.read(origIns); 1972 } 1973 1974 // copy exception handlers 1975 ExceptionHandler[] origHandlers = orig.getExceptionHandlers(); 1976 ExceptionHandler handler; 1977 for (int i = 0; i < origHandlers.length; i++) { 1978 handler = addExceptionHandler(); 1979 handler.read(origHandlers[i]); 1980 handler.updateTargets(); 1981 } 1982 1983 // reset all opcode ptrs to the new copied opcodes 1984 updateInstructionPointers(); 1985 setAttributes(orig.getAttributes()); 1986 1987 // setup local variable markers 1988 LocalVariableTable locals = getLocalVariableTable(false); 1989 if (locals != null) 1990 locals.updateTargets(); 1991 1992 // setup local variable markers 1993 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false); 1994 if (localTypes != null) 1995 localTypes.updateTargets(); 1996 1997 // setup line number markers 1998 LineNumberTable lines = getLineNumberTable(false); 1999 if (lines != null) 2000 lines.updateTargets(); 2001 2002 // now copy constant instruction values 2003 CodeEntry copy = _head.next; 2004 for (CodeEntry entry = orig._head.next; entry != orig._tail; 2005 entry = entry.next, copy = copy.next) { 2006 if (entry instanceof ConstantInstruction) 2007 ((ConstantInstruction) copy).read((Instruction) entry); 2008 } 2009 beforeFirst(); 2010 } 2011 2012 void read(DataInput in, int length) throws IOException { 2013 _maxStack = in.readUnsignedShort(); 2014 _maxLocals = in.readUnsignedShort(); 2015 readCode(in, in.readInt()); 2016 2017 _handlers.clear(); 2018 int exceptionCount = in.readUnsignedShort(); 2019 ExceptionHandler excep; 2020 for (int i = 0; i < exceptionCount; i++) { 2021 excep = addExceptionHandler(); 2022 excep.read(in); 2023 excep.updateTargets(); 2024 } 2025 2026 readAttributes(in); 2027 2028 // setup local variable markers 2029 LocalVariableTable locals = getLocalVariableTable(false); 2030 if (locals != null) 2031 locals.updateTargets(); 2032 2033 // setup local variable markers 2034 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false); 2035 if (localTypes != null) 2036 localTypes.updateTargets(); 2037 2038 // setup line number markers 2039 LineNumberTable lines = getLineNumberTable(false); 2040 if (lines != null) 2041 lines.updateTargets(); 2042 } 2043 2044 void write(DataOutput out, int length) throws IOException { 2045 out.writeShort(_maxStack); 2046 out.writeShort(_maxLocals); 2047 2048 byte[] code = toByteArray(); 2049 out.writeInt(code.length); 2050 out.write(code); 2051 2052 out.writeShort(_handlers.size()); 2053 for (Iterator itr = _handlers.iterator(); itr.hasNext();) 2054 ((ExceptionHandler) itr.next()).write(out); 2055 writeAttributes(out); 2056 } 2057 2058 private void readCode(DataInput in, int len) throws IOException { 2059 _head.next = _tail; 2060 _tail.prev = _head; 2061 _size = 0; 2062 _byteIndexesValid = true; 2063 2064 beforeFirst(); 2065 Instruction ins; 2066 for (int byteIndex = 0; byteIndex < len;) { 2067 ins = createInstruction(in.readUnsignedByte()); 2068 _ci.addInternal(ins); 2069 ins.byteIndex = byteIndex; 2070 ins.read(in); 2071 byteIndex += ins.getLength(); 2072 } 2073 updateInstructionPointers(); 2074 beforeFirst(); 2075 2076 // sanity check 2077 if (!_byteIndexesValid) 2078 throw new IllegalStateException(); 2079 } 2080 2081 /** 2082 * Ensures that all the opcode targets are set up correctly. 2083 */ 2084 private void updateInstructionPointers() { 2085 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) 2086 if (entry instanceof InstructionPtr) 2087 ((InstructionPtr) entry).updateTargets(); 2088 } 2089 2090 /** 2091 * Returns the byteIndex of the given instruction. 2092 */ 2093 int getByteIndex(Instruction ins) { 2094 if (_byteIndexesValid && ins.byteIndex != -1) 2095 return ins.byteIndex; 2096 2097 int byteIndex = 0; 2098 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2099 if (entry == ins) 2100 return byteIndex; 2101 byteIndex += ((Instruction) entry).getLength(); 2102 } 2103 throw new IllegalArgumentException("ins.owner != this"); 2104 } 2105 2106 /** 2107 * Invalidate all byteindexes when the code block changes. 2108 */ 2109 void invalidateByteIndexes() { 2110 _byteIndexesValid = false; 2111 } 2112 2113 /** 2114 * Returns the instruction in this code block found at the given byte index. 2115 */ 2116 Instruction getInstruction(int byteIndex) { 2117 if (byteIndex < 0) 2118 return null; 2119 2120 int curIndex = 0; 2121 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2122 if (byteIndex == curIndex) 2123 return (Instruction) entry; 2124 curIndex += ((Instruction) entry).getLength(); 2125 } 2126 2127 // some instruction ptrs are actually to a "next" instruction, so 2128 // allow one past the end 2129 if (byteIndex == curIndex) 2130 return null; 2131 throw new IllegalArgumentException(String.valueOf(byteIndex)); 2132 } 2133 2134 /** 2135 * Return the first instruction in this code block, or null if none. 2136 */ 2137 Instruction getFirstInstruction() { 2138 return (Instruction) _head.next; 2139 } 2140 2141 /** 2142 * Return the last instruction in this code block, or null if none. 2143 */ 2144 Instruction getLastInstruction() { 2145 return (Instruction) _tail.prev; 2146 } 2147 2148 /** 2149 * Returns the number of instructions that occur before 'ins' 2150 * in this code block that 'ins' is a part of. 2151 * 2152 * @throws IllegalArgumentException if this code block is not the owner 2153 * of ins 2154 */ 2155 private int indexOf(Instruction ins) { 2156 int i = 0; 2157 for (CodeEntry entry = _head.next; entry != _tail; 2158 entry = entry.next, i++) 2159 if (entry == ins) 2160 return i; 2161 throw new IllegalArgumentException("ins.code != this"); 2162 } 2163 2164 private void writeCode(DataOutput out) throws IOException { 2165 Instruction ins; 2166 for (CodeEntry entry = _head.next; entry != _tail; entry = entry.next) { 2167 ins = (Instruction) entry; 2168 out.writeByte(ins.getOpcode()); 2169 ins.write(out); 2170 } 2171 } 2172 2173 private byte[] toByteArray() throws IOException { 2174 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 2175 DataOutputStream stream = new DataOutputStream(byteStream); 2176 try { 2177 writeCode(stream); 2178 return byteStream.toByteArray(); 2179 } finally { 2180 try { stream.close(); } catch (Exception e) {} 2181 } 2182 } 2183 2184 private void fromByteArray(byte[] code) throws IOException { 2185 if (code == null) { 2186 _head.next = _tail; 2187 _tail.prev = _head; 2188 _size = 0; 2189 } else { 2190 DataInputStream stream = new DataInputStream 2191 (new ByteArrayInputStream(code)); 2192 try { 2193 readCode(stream, code.length); 2194 } finally { 2195 try { stream.close(); } catch (Exception e) {} 2196 } 2197 } 2198 } 2199 2200 private Instruction addInstruction(Instruction ins) { 2201 _ci.add(ins); 2202 return ins; 2203 } 2204 2205 private Instruction addInstruction(int opcode) { 2206 return addInstruction(createInstruction(opcode)); 2207 } 2208 2209 /** 2210 * Creates an Instruction, with this code block as the owner. 2211 * Note that the Instruction is not added to this Code block. 2212 */ 2213 private Instruction createInstruction(int opcode) { 2214 switch (opcode) { 2215 case Constants.NOP: 2216 case Constants.ARRAYLENGTH: 2217 case Constants.ATHROW: 2218 return new Instruction(this, opcode); 2219 case Constants.ACONSTNULL: 2220 case Constants.ICONSTM1: 2221 case Constants.ICONST0: 2222 case Constants.ICONST1: 2223 case Constants.ICONST2: 2224 case Constants.ICONST3: 2225 case Constants.ICONST4: 2226 case Constants.ICONST5: 2227 case Constants.LCONST0: 2228 case Constants.LCONST1: 2229 case Constants.FCONST0: 2230 case Constants.FCONST1: 2231 case Constants.FCONST2: 2232 case Constants.DCONST0: 2233 case Constants.DCONST1: 2234 case Constants.BIPUSH: 2235 case Constants.SIPUSH: 2236 case Constants.LDC: 2237 case Constants.LDCW: 2238 case Constants.LDC2W: 2239 return new ConstantInstruction(this, opcode); 2240 case Constants.ILOAD: 2241 case Constants.LLOAD: 2242 case Constants.FLOAD: 2243 case Constants.DLOAD: 2244 case Constants.ALOAD: 2245 case Constants.ILOAD0: 2246 case Constants.ILOAD1: 2247 case Constants.ILOAD2: 2248 case Constants.ILOAD3: 2249 case Constants.LLOAD0: 2250 case Constants.LLOAD1: 2251 case Constants.LLOAD2: 2252 case Constants.LLOAD3: 2253 case Constants.FLOAD0: 2254 case Constants.FLOAD1: 2255 case Constants.FLOAD2: 2256 case Constants.FLOAD3: 2257 case Constants.DLOAD0: 2258 case Constants.DLOAD1: 2259 case Constants.DLOAD2: 2260 case Constants.DLOAD3: 2261 case Constants.ALOAD0: 2262 case Constants.ALOAD1: 2263 case Constants.ALOAD2: 2264 case Constants.ALOAD3: 2265 return new LoadInstruction(this, opcode); 2266 case Constants.IALOAD: 2267 case Constants.LALOAD: 2268 case Constants.FALOAD: 2269 case Constants.DALOAD: 2270 case Constants.AALOAD: 2271 case Constants.BALOAD: 2272 case Constants.CALOAD: 2273 case Constants.SALOAD: 2274 return new ArrayLoadInstruction(this, opcode); 2275 case Constants.ISTORE: 2276 case Constants.LSTORE: 2277 case Constants.FSTORE: 2278 case Constants.DSTORE: 2279 case Constants.ASTORE: 2280 case Constants.ISTORE0: 2281 case Constants.ISTORE1: 2282 case Constants.ISTORE2: 2283 case Constants.ISTORE3: 2284 case Constants.LSTORE0: 2285 case Constants.LSTORE1: 2286 case Constants.LSTORE2: 2287 case Constants.LSTORE3: 2288 case Constants.FSTORE0: 2289 case Constants.FSTORE1: 2290 case Constants.FSTORE2: 2291 case Constants.FSTORE3: 2292 case Constants.DSTORE0: 2293 case Constants.DSTORE1: 2294 case Constants.DSTORE2: 2295 case Constants.DSTORE3: 2296 case Constants.ASTORE0: 2297 case Constants.ASTORE1: 2298 case Constants.ASTORE2: 2299 case Constants.ASTORE3: 2300 return new StoreInstruction(this, opcode); 2301 case Constants.IASTORE: 2302 case Constants.LASTORE: 2303 case Constants.FASTORE: 2304 case Constants.DASTORE: 2305 case Constants.AASTORE: 2306 case Constants.BASTORE: 2307 case Constants.CASTORE: 2308 case Constants.SASTORE: 2309 return new ArrayStoreInstruction(this, opcode); 2310 case Constants.POP: 2311 case Constants.POP2: 2312 case Constants.DUP: 2313 case Constants.DUPX1: 2314 case Constants.DUPX2: 2315 case Constants.DUP2: 2316 case Constants.DUP2X1: 2317 case Constants.DUP2X2: 2318 case Constants.SWAP: 2319 return new StackInstruction(this, opcode); 2320 case Constants.IADD: 2321 case Constants.LADD: 2322 case Constants.FADD: 2323 case Constants.DADD: 2324 case Constants.ISUB: 2325 case Constants.LSUB: 2326 case Constants.FSUB: 2327 case Constants.DSUB: 2328 case Constants.IMUL: 2329 case Constants.LMUL: 2330 case Constants.FMUL: 2331 case Constants.DMUL: 2332 case Constants.IDIV: 2333 case Constants.LDIV: 2334 case Constants.FDIV: 2335 case Constants.DDIV: 2336 case Constants.IREM: 2337 case Constants.LREM: 2338 case Constants.FREM: 2339 case Constants.DREM: 2340 case Constants.INEG: 2341 case Constants.LNEG: 2342 case Constants.FNEG: 2343 case Constants.DNEG: 2344 case Constants.ISHL: 2345 case Constants.LSHL: 2346 case Constants.ISHR: 2347 case Constants.LSHR: 2348 case Constants.IUSHR: 2349 case Constants.LUSHR: 2350 case Constants.IAND: 2351 case Constants.LAND: 2352 case Constants.IOR: 2353 case Constants.LOR: 2354 case Constants.IXOR: 2355 case Constants.LXOR: 2356 return new MathInstruction(this, opcode); 2357 case Constants.IINC: 2358 return new IIncInstruction(this); 2359 case Constants.I2L: 2360 case Constants.I2F: 2361 case Constants.I2D: 2362 case Constants.L2I: 2363 case Constants.L2F: 2364 case Constants.L2D: 2365 case Constants.F2I: 2366 case Constants.F2L: 2367 case Constants.F2D: 2368 case Constants.D2I: 2369 case Constants.D2L: 2370 case Constants.D2F: 2371 case Constants.I2B: 2372 case Constants.I2C: 2373 case Constants.I2S: 2374 return new ConvertInstruction(this, opcode); 2375 case Constants.LCMP: 2376 case Constants.FCMPL: 2377 case Constants.FCMPG: 2378 case Constants.DCMPL: 2379 case Constants.DCMPG: 2380 return new CmpInstruction(this, opcode); 2381 case Constants.IFEQ: 2382 case Constants.IFNE: 2383 case Constants.IFLT: 2384 case Constants.IFGE: 2385 case Constants.IFGT: 2386 case Constants.IFLE: 2387 case Constants.IFICMPEQ: 2388 case Constants.IFICMPNE: 2389 case Constants.IFICMPLT: 2390 case Constants.IFICMPGE: 2391 case Constants.IFICMPGT: 2392 case Constants.IFICMPLE: 2393 case Constants.IFACMPEQ: 2394 case Constants.IFACMPNE: 2395 case Constants.IFNULL: 2396 case Constants.IFNONNULL: 2397 return new IfInstruction(this, opcode); 2398 case Constants.GOTO: 2399 case Constants.JSR: 2400 case Constants.GOTOW: 2401 case Constants.JSRW: 2402 return new GotoInstruction(this, opcode); 2403 case Constants.RET: 2404 return new RetInstruction(this); 2405 case Constants.TABLESWITCH: 2406 return new TableSwitchInstruction(this); 2407 case Constants.LOOKUPSWITCH: 2408 return new LookupSwitchInstruction(this); 2409 case Constants.IRETURN: 2410 case Constants.LRETURN: 2411 case Constants.FRETURN: 2412 case Constants.DRETURN: 2413 case Constants.ARETURN: 2414 case Constants.RETURN: 2415 return new ReturnInstruction(this, opcode); 2416 case Constants.GETSTATIC: 2417 case Constants.GETFIELD: 2418 return new GetFieldInstruction(this, opcode); 2419 case Constants.PUTSTATIC: 2420 case Constants.PUTFIELD: 2421 return new PutFieldInstruction(this, opcode); 2422 case Constants.INVOKEVIRTUAL: 2423 case Constants.INVOKESPECIAL: 2424 case Constants.INVOKESTATIC: 2425 case Constants.INVOKEINTERFACE: 2426 return new MethodInstruction(this, opcode); 2427 case Constants.NEW: 2428 case Constants.ANEWARRAY: 2429 case Constants.CHECKCAST: 2430 case Constants.INSTANCEOF: 2431 return new ClassInstruction(this, opcode); 2432 case Constants.NEWARRAY: 2433 return new NewArrayInstruction(this); 2434 case Constants.MONITORENTER: 2435 return new MonitorEnterInstruction(this); 2436 case Constants.MONITOREXIT: 2437 return new MonitorExitInstruction(this); 2438 case Constants.WIDE: 2439 return new WideInstruction(this); 2440 case Constants.MULTIANEWARRAY: 2441 return new MultiANewArrayInstruction(this); 2442 default: 2443 throw new IllegalArgumentException("Illegal opcode: " + opcode); 2444 } 2445 } 2446 2447 /** 2448 * Returns another listIterator view of the Instructions in this 2449 * code block. Useful for performing read-only searches through 2450 * Instructions without effecting the pointer location of the main 2451 * code block. 2452 */ 2453 public ListIterator listIterator() { 2454 return new CodeIterator(_head, -1); 2455 } 2456 2457 /** 2458 * Helper class to handle invalidation of instructions on removal 2459 * and notification of modification on addition. 2460 */ 2461 private class CodeIterator implements ListIterator { 2462 public static final int UNSET = -99; 2463 private CodeEntry _bn = null; // "before next" entry 2464 private Instruction _last = null; // last entry returned 2465 private int _index = UNSET; // index of _bn 2466 2467 public CodeIterator(CodeEntry entry, int index) { 2468 _bn = entry; 2469 _index = index; 2470 } 2471 2472 public boolean hasNext() { 2473 return _bn.next != _tail; 2474 } 2475 2476 public boolean hasPrevious() { 2477 return _bn != _head; 2478 } 2479 2480 public Object next() { 2481 if (!hasNext()) 2482 throw new NoSuchElementException(); 2483 2484 _bn = _bn.next; 2485 _last = (Instruction) _bn; 2486 if (_index != UNSET) 2487 _index++; 2488 return _last; 2489 } 2490 2491 public int nextIndex() { 2492 return initIndex() + 1; 2493 } 2494 2495 public Object previous() { 2496 if (!hasPrevious()) 2497 throw new NoSuchElementException(); 2498 2499 _last = (Instruction) _bn; 2500 _bn = _bn.prev; 2501 if (_index != UNSET) 2502 _index--; 2503 return _last; 2504 } 2505 2506 public int previousIndex() { 2507 return initIndex(); 2508 } 2509 2510 private int initIndex() { 2511 if (_index == UNSET) { 2512 if (_bn == _head) 2513 _index = -1; 2514 else 2515 _index = indexOf((Instruction) _bn); 2516 } 2517 return _index; 2518 } 2519 2520 public void add(Object obj) { 2521 addInternal(obj); 2522 invalidateByteIndexes(); 2523 } 2524 2525 private void addInternal(Object obj) { 2526 if (obj == null) 2527 throw new NullPointerException("obj = null"); 2528 2529 Instruction ins = (Instruction) obj; 2530 if (_size == 0) { 2531 _head.next = ins; 2532 _tail.prev = ins; 2533 ins.prev = _head; 2534 ins.next = _tail; 2535 _index = 0; 2536 } else { 2537 CodeEntry next = _bn.next; 2538 _bn.next = ins; 2539 next.prev = ins; 2540 ins.prev = _bn; 2541 ins.next = next; 2542 if (_index != UNSET) 2543 _index++; 2544 } 2545 2546 _bn = ins; 2547 _last = ins; 2548 _size++; 2549 } 2550 2551 public void set(Object obj) { 2552 if (obj == null) 2553 throw new NullPointerException("obj = null"); 2554 if (_last == null) 2555 throw new IllegalStateException(); 2556 2557 Instruction ins = (Instruction) obj; 2558 ins.prev = _last.prev; 2559 ins.next = _last.next; 2560 ins.prev.next = ins; 2561 ins.next.prev = ins; 2562 2563 replaceTarget(_last, ins); 2564 _last.invalidate(); 2565 if (_bn == _last) 2566 _bn = ins; 2567 _last = ins; 2568 invalidateByteIndexes(); 2569 } 2570 2571 public void remove() { 2572 if (_last == null) 2573 throw new IllegalStateException(); 2574 2575 if (_bn == _last) 2576 _bn = _last.prev; 2577 _index--; 2578 _last.prev.next = _last.next; 2579 _last.next.prev = _last.prev; 2580 _size--; 2581 2582 Instruction orig = _last; 2583 Instruction replace = null; 2584 if (orig.next != _tail) 2585 replace = (Instruction) orig.next; 2586 else 2587 replace = nop(); 2588 replaceTarget(orig, replace); 2589 orig.invalidate(); 2590 _last = null; 2591 invalidateByteIndexes(); 2592 } 2593 2594 private void replaceTarget(Instruction orig, Instruction replace) { 2595 for (CodeEntry entry = _head.next; entry != _tail; 2596 entry = entry.next) { 2597 if (entry instanceof InstructionPtr) 2598 ((InstructionPtr) entry).replaceTarget(orig, replace); 2599 } 2600 2601 // update the ExceptionHandler pointers 2602 ExceptionHandler[] handlers = getExceptionHandlers(); 2603 for (int i = 0; i < handlers.length; i++) 2604 handlers[i].replaceTarget(orig, replace); 2605 2606 // update LineNumber pointers 2607 LineNumberTable lineNumbers = getLineNumberTable(false); 2608 if (lineNumbers != null) 2609 lineNumbers.replaceTarget(orig, replace); 2610 2611 // update LocalVariable pointers 2612 LocalVariableTable variables = getLocalVariableTable(false); 2613 if (variables != null) 2614 variables.replaceTarget(orig, replace); 2615 2616 // update LocalVariableType pointers 2617 LocalVariableTypeTable types = getLocalVariableTypeTable(false); 2618 if (types != null) 2619 types.replaceTarget(orig, replace); 2620 } 2621 } 2622 }