1 package serp.bytecode;
2
3 import java.io.*;
4 import java.util.*;
5
6 import serp.bytecode.lowlevel.*;
7 import serp.bytecode.visitor.*;
8
9 /***
10 * Representation of a code block of a class.
11 * The methods of this class mimic those of the same name in the
12 * {@link java.util.ListIterator} class. Note that the size and index
13 * information of the code block will change as opcodes are added.
14 *
15 * <p>Code blocks are usually obtained from a {@link BCMethod}, but can also
16 * be constructed via the default constructor. Blocks created this way can
17 * be used to provide template instructions to the various search/replace
18 * methods in this class.</p>
19 *
20 * <p>The code class contains methods named after most JVM instructions, each
21 * of which adds the matching opcode to the code block at the
22 * current iterator position. It also contains generic versions of various
23 * JVM instructions whose opcodes are not set until their properties are set
24 * with additional information. Almost all instruction types are able to
25 * 'morph' their opcode on the fly as the arguments to the instruction change.
26 * Thus the developer can initially call, for example, the <code>aload</code>
27 * opcode, but later change the type to load to <code>int</code> and the
28 * opcode will automatically morph to the <code>iload</code> opcode.</p>
29 *
30 * @author Abe White
31 */
32 public class Code extends Attribute {
33 private final CodeEntry _head;
34 private final CodeEntry _tail;
35 private CodeIterator _ci;
36 private int _maxStack = 0;
37 private int _maxLocals = 0;
38 private int _size = 0;
39 private Collection _handlers = new LinkedList();
40 private Collection _attrs = new LinkedList();
41 private boolean _byteIndexesValid;
42
43 Code(int nameIndex, Attributes owner) {
44 super(nameIndex, owner);
45 _head = new CodeEntry();
46 _tail = new CodeEntry();
47 _head.next = _tail;
48 _tail.prev = _head;
49 _ci = new CodeIterator(_head, -1);
50 }
51
52 /***
53 * The public constructor is for creating template code modules
54 * that produce {@link Instruction}s used in matching through
55 * the various <code>search</code> and <code>replace</code> methods.
56 */
57 public Code() {
58 this(0, new Project().loadClass("", null).declareMethod("", void.class,
59 null));
60 }
61
62 /***
63 * The owning method.
64 */
65 public BCMethod getMethod() {
66 return (BCMethod) getOwner();
67 }
68
69 Collection getAttributesHolder() {
70 return _attrs;
71 }
72
73
74
75
76
77 /***
78 * Return the maximum stack depth set for this code block.
79 */
80 public int getMaxStack() {
81 return _maxStack;
82 }
83
84 /***
85 * Set the maximum stack depth for this code block.
86 */
87 public void setMaxStack(int max) {
88 _maxStack = max;
89 }
90
91 /***
92 * Return the maximum number of local variables (including params)
93 * set for this method.
94 */
95 public int getMaxLocals() {
96 return _maxLocals;
97 }
98
99 /***
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
170
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
183
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
217
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
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
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
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
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
1824
1825 int length = 12;
1826
1827
1828 Instruction last = getLastInstruction();
1829 if (last != null)
1830 length += last.getByteIndex() + last.getLength();
1831
1832
1833 length += (8 * _handlers.size());
1834
1835
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
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
1945
1946
1947 void read(Attribute attr) {
1948 Code orig = (Code) attr;
1949 _maxStack = orig.getMaxStack();
1950 _maxLocals = orig.getMaxLocals();
1951
1952
1953 _head.next = _tail;
1954 _tail.prev = _head;
1955 _size = 0;
1956 _byteIndexesValid = false;
1957 beforeFirst();
1958 _handlers.clear();
1959
1960
1961
1962
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
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
1984 updateInstructionPointers();
1985 setAttributes(orig.getAttributes());
1986
1987
1988 LocalVariableTable locals = getLocalVariableTable(false);
1989 if (locals != null)
1990 locals.updateTargets();
1991
1992
1993 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false);
1994 if (localTypes != null)
1995 localTypes.updateTargets();
1996
1997
1998 LineNumberTable lines = getLineNumberTable(false);
1999 if (lines != null)
2000 lines.updateTargets();
2001
2002
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
2029 LocalVariableTable locals = getLocalVariableTable(false);
2030 if (locals != null)
2031 locals.updateTargets();
2032
2033
2034 LocalVariableTypeTable localTypes = getLocalVariableTypeTable(false);
2035 if (localTypes != null)
2036 localTypes.updateTargets();
2037
2038
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
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
2128
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;
2464 private Instruction _last = null;
2465 private int _index = UNSET;
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
2602 ExceptionHandler[] handlers = getExceptionHandlers();
2603 for (int i = 0; i < handlers.length; i++)
2604 handlers[i].replaceTarget(orig, replace);
2605
2606
2607 LineNumberTable lineNumbers = getLineNumberTable(false);
2608 if (lineNumbers != null)
2609 lineNumbers.replaceTarget(orig, replace);
2610
2611
2612 LocalVariableTable variables = getLocalVariableTable(false);
2613 if (variables != null)
2614 variables.replaceTarget(orig, replace);
2615
2616
2617 LocalVariableTypeTable types = getLocalVariableTypeTable(false);
2618 if (types != null)
2619 types.replaceTarget(orig, replace);
2620 }
2621 }
2622 }