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