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 * 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 }