View Javadoc

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