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