Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/techtrader/modules/tools/bytecode/Code.java


1   package com.techtrader.modules.tools.bytecode;
2   
3   
4   import java.util.List;
5   import java.util.LinkedList;
6   import java.util.ListIterator;
7   import java.util.Iterator;
8   import java.io.IOException;
9   import java.io.DataInput;
10  import java.io.DataOutput;
11  import java.io.DataInputStream;
12  import java.io.DataOutputStream;
13  import java.io.ByteArrayInputStream;
14  import java.io.ByteArrayOutputStream;
15  
16  import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
17  
18  
19  /**
20   *  Representation of a code block of a class.
21   *  The methods of this class mimic those of
22   *  the same name in the {@link java.util.ListIterator} class.  Note that 
23   *  the size and index information of the Code block will change as opcodes
24   *  are added.  
25   *  <p>
26   *  Code blocks are usually obtained from a BCMethod, but can also be
27   *  constructed via the default Constructor.  Blocks created this way can
28   *  be used to provide template instructions to the various search/replace
29   *  methods in this class.
30   *  <p>
31   *  The Code class contains methods named after each JVM instruction, each
32   *  of which adds the matching opcode to the code block at the 
33   *  current iterator position.  There are also many pseudo-instruction
34   *  methods that do not have a corresponding JVM opcode, but are provided
35   *  for convenience when the exact opcode is difficult to determine at 
36   *  compile time.  Unlike the other opcode methods, these convenience 
37   *  methods have javadoc comments so that they are easy to pick out; 
38   *  they should be skimmed to get an idea of the functionality that each 
39   *  provides.  Also note that many Instructions are able to 'morph' their
40   *  opcode on the fly as the arguments to the instruction change.  Thus
41   *  the developer can initially call, for example, the aload_1 opcode, but
42   *  later change the type to load to 'int', and the opcode will automatically
43   *  morph to iload_1.
44   *  
45   *  @author    Abe White
46   */
47  public class Code
48    extends Attribute
49    implements Constants
50  {
51    private int       _maxStack  = 0;
52    private int       _maxLocals  = 0;
53    private List      _opcodes  = new LinkedList ();
54    private List       _handlers   = new LinkedList ();
55    private ListIterator  _li      = _opcodes.listIterator ();
56  
57  
58    protected Code (int nameIndex, BCEntity owner)
59    {
60      super (nameIndex, owner);
61    }
62  
63  
64    /**
65     *  The public constructor is for creating template code modules  
66      *  that can be used to produce Instructions to be used in 
67     *  matching for various search() and replace() methods.
68     */
69    public Code ()
70    {
71      // create a new empty anon class so we can use its
72      // constant pool to track the code we create
73      super (0, new BCClass ().addMethod ());
74      _nameIndex = getPool ().setUTF (0, ATTR_CODE);
75    }
76  
77  
78    /**
79     *  Get the maximum stack depth for this code block.
80     */
81    public int getMaxStack ()
82    {
83      return _maxStack;
84    }
85  
86  
87    /**
88     *  Set the maximum stack depth for this code block.
89     */
90    public void setMaxStack (int max)
91    {
92      _maxStack = max;
93    }
94  
95  
96    /**
97     *  Get the maximum number of local variables (including params)
98     *  in this method.
99     */
100   public int getMaxLocals ()
101   {
102     return _maxLocals;
103   }
104 
105   
106   /**
107    *  Set the maximum number of local variables (including params) in 
108    *  this method.
109    */
110   public void setMaxLocals (int max)
111   {
112     _maxLocals = max;
113   }
114 
115 
116   /**
117    *  Get the local variable index for the paramIndex'th parameter to 
118    *  the method.   These numbers are different because 
119    *  a) non-static methods use the 0th local variable for the 'this' ptr, and
120    *  b) double and long values occupy two spots in the local 
121    *  variable array.
122    */
123   public int getLocalsIndex (int paramIndex)
124   {
125     if (paramIndex < 0)
126       return -1;
127 
128     int pos = 0;
129     if (!((BCMethod) _owner).isStatic ())
130       pos = 1;
131 
132     String[] params = ((BCMethod) _owner).getParamTypeNames ();
133     for (int i = 0; i < paramIndex; i++, pos++)
134       if (params[i].equals ("long") || params[i].equals ("double"))
135         pos++;
136 
137     return pos;
138   }
139 
140 
141   /**
142    *  Get the next next available local variable index.
143    */
144   public int getNextLocalsIndex ()
145   {
146     calculateMaxLocals ();
147     return getMaxLocals ();
148   }
149 
150 
151   /**
152    *  Ask the code to figure out the number of locals it needs based on
153    *  the instructions used and the parameters of the method this code
154    *  block is a part of.
155    */
156   public void calculateMaxLocals ()
157   {
158     // start off assuming the max number needed is the 
159     // number for all the params
160     String[] params = ((BCMethod) _owner).getParamTypeNames ();
161     int max = 0;
162     if (params.length == 0 && !((BCMethod) _owner).isStatic ())
163       max = 1;
164     else if (params.length > 0)
165     {
166       max = getLocalsIndex (params.length - 1) + 1;
167       if (params[params.length-1].equals ("long")
168         || params[params.length-1].equals ("double"))
169         max++;
170     }  
171 
172     // check to see if there are any store instructions that
173     // try to reference beyond that point
174     Instruction ins;
175     StoreInstruction store;
176     int current;
177     for (Iterator i = _opcodes.iterator (); i.hasNext ();)
178     {
179       current = 0;
180       ins = (Instruction) i.next ();
181 
182       if (ins instanceof StoreInstruction)
183       {
184         store = (StoreInstruction) ins;
185         current = store.getIndex () + 1;
186         if (store.getType ().equals (long.class) 
187           || store.getType ().equals (double.class))  
188           current++;
189 
190         if (current > max)
191           max = current;
192       }
193     }
194 
195     setMaxLocals (max);
196   }
197 
198 
199   /**
200    *  Ask the code to figure out the maximum stack depth it needs
201    *  the instructions used.
202    */
203   public void calculateMaxStack ()
204   {
205     int stack = 0;
206     int max = 0;
207 
208     ExceptionHandler[] handlers = getExceptionHandlers ();
209     Instruction ins;
210     for (Iterator i = _opcodes.iterator (); i.hasNext ();)
211     {
212       ins = (Instruction) i.next ();
213       stack += ins.getStackChange ();
214 
215       // if this is the start of a try, the exception will be placed
216       // on the stack
217       for (int j = 0; j < handlers.length; j++)
218         if (handlers[j].getTryStart () == ins)
219           stack++;
220 
221       if (stack > max)
222         max = stack;
223     }
224 
225     setMaxStack (max);
226   }
227 
228 
229   /**
230    *  Get the exception handlers active in this code block, or an
231    *  empty array if none.
232    */
233   public ExceptionHandler[] getExceptionHandlers ()
234   {
235     return (ExceptionHandler[]) _handlers.toArray 
236       (new ExceptionHandler[_handlers.size ()]);
237   }
238 
239 
240   /**
241    *  Get 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 (Class catchType)
246   {
247     return getExceptionHandler (catchType.getName ());
248   }
249 
250 
251   /**
252    *  Get the exception handler that catches the given exception type;
253    *  if multiple handlers catch the given type, which is returned is
254    *  undefined.
255    */
256   public ExceptionHandler getExceptionHandler (String catchType)
257   {
258     ExceptionHandler next;
259     for (Iterator i = _handlers.iterator (); i.hasNext ();)
260     {
261       next = (ExceptionHandler) i.next ();
262       if (next.getCatchTypeName ().equals (catchType))
263         return next;
264     }
265 
266     return null;
267   }
268 
269 
270   /**
271    *  Get all exception handlers that catch the given exception type.
272    */
273   public ExceptionHandler[] getExceptionHandlers (Class catchType)
274   {
275     return getExceptionHandlers (catchType.getName ());
276   }
277 
278 
279   /**
280    *  Get all exception handlers that catch the given exception type.
281    */
282   public ExceptionHandler[] getExceptionHandlers (String catchType)
283   {
284     List matches = new LinkedList ();
285 
286     ExceptionHandler next;
287     for (Iterator i = _handlers.iterator (); i.hasNext ();)
288     {
289       next = (ExceptionHandler) i.next ();
290       if (next.getCatchTypeName ().equals (catchType))
291         matches.add (next);
292     }
293 
294     return (ExceptionHandler[]) matches.toArray 
295       (new ExceptionHandler[matches.size ()]);
296   }
297 
298 
299   /**
300    *  Add an exception handler to this code block.
301    */
302   public ExceptionHandler addExceptionHandler ()  
303   {
304     ExceptionHandler handler = new ExceptionHandler (this);
305     _handlers.add (handler);
306 
307     return handler;
308   }
309 
310 
311   /**
312    *  Add an exception handler to this code block.
313    *
314    *  @param  tryStart    the first instruction of the try {} block
315     *  @param  tryEnd      the last instruction of the try {} block
316    *  @param  handlerStart  the first instruction of the catch {} block
317    *  @param  catchType    the type of Exception being caught
318    */
319   public ExceptionHandler addExceptionHandler (Instruction tryStart,
320     Instruction tryEnd, Instruction handlerStart, Class catchType)
321   {
322     String catchName = null;
323     if (catchType != null)
324       catchName = catchType.getName ();
325       
326     return addExceptionHandler (tryStart, tryEnd, handlerStart, catchName);
327   }
328 
329 
330   /**
331    *  Add an exception handler to this code block.
332    *
333    *  @param  tryStart    the first instruction of the try {} block
334     *  @param  tryEnd      the last instruction of the try {} block
335    *  @param  handlerStart  the first instruction of the catch {} block
336    *  @param  catchType    the type of Exception being caught
337     */
338   public ExceptionHandler addExceptionHandler (Instruction tryStart,
339     Instruction tryEnd, Instruction handlerStart, String catchType)
340   {
341     ExceptionHandler handler = addExceptionHandler ();
342     handler.setTryStart (tryStart);
343     handler.setTryEnd (tryEnd);
344     handler.setHandlerStart (handlerStart);
345     handler.setCatchTypeName (catchType);
346 
347     return handler;
348   }
349 
350 
351   /**
352    *  Clear all exception handlers.
353    */
354   public void clearExceptionHandlers ()
355   {
356     _handlers.clear ();
357   }
358 
359 
360   /**
361    *  Remove all exception handlers that catch the given type.
362    */
363   public boolean removeExceptionHandler (Class catchType)
364   {
365     ExceptionHandler[] matches = getExceptionHandlers (catchType);
366     for (int i = 0; i < matches.length; i++)
367       removeExceptionHandler (matches[i]);
368 
369     return (matches.length > 0);
370   }
371 
372 
373   /**
374    *  Remove all exception handlers that catch the given type.
375    */
376   public boolean removeExceptionHandler (String catchType)
377   {
378     ExceptionHandler[] matches = getExceptionHandlers (catchType);
379     for (int i = 0; i < matches.length; i++)
380       removeExceptionHandler (matches[i]);
381 
382     return (matches.length > 0);
383   }
384 
385 
386   /**
387    *  Remove an exception handler from this code block.
388    */
389   public boolean removeExceptionHandler (ExceptionHandler handler)
390   {
391     if (handler == null || !_handlers.remove (handler))
392       return false;
393 
394     handler.invalidate ();
395     return true;
396   }
397 
398 
399   /**
400    *  Return the number of instructions in the method.
401    */
402   public int size ()
403   {
404     return _opcodes.size ();
405   }
406 
407 
408   /**
409     *  Reset the position of the instruction iterator to the first opcode.
410    */
411   public void beforeFirst ()
412   {
413     _li = _opcodes.listIterator ();
414   }
415 
416 
417   /**
418    *  Set the position of the instruction iterator to after the last opcode.
419    */
420   public void afterLast ()
421   {
422     _li = _opcodes.listIterator (_opcodes.size ());
423   }
424 
425 
426   /**
427    *  Position the iterator just before the given instruction.  The 
428     *  instruction must belong to this method.
429    */
430   public void before (Instruction ins)
431   {
432     Iterator instructions = _opcodes.iterator ();
433     int pos = 0;
434     for (; instructions.hasNext (); pos++)
435       if (instructions.next () == ins)
436         break;
437 
438     _li = _opcodes.listIterator (pos);
439   }
440 
441 
442   /**
443    *  Position the iterator just after the given instruction.  The 
444     *  instruction must belong to this method.
445    */
446   public void after (Instruction ins)
447   {
448     before (ins);
449     next ();
450   }
451 
452 
453   /**
454    *  Return true if a subsequent call to next() will return an instruction.
455    */
456   public boolean hasNext ()
457   {
458     return _li.hasNext ();
459   }
460 
461 
462   /**
463    *  Return true if a subsequent call to previous() will return an
464    *  instruction.
465    */
466   public boolean hasPrevious ()
467   {
468     return _li.hasPrevious ();
469   }
470 
471 
472   /**
473    *  Return the next instruction.
474    */
475   public Instruction next ()
476   {
477     return (Instruction) _li.next ();
478   }
479 
480 
481   /**
482    *  Return the index of the next instruction, or size() if at end.
483    */
484   public int nextIndex ()
485   {
486     return _li.nextIndex ();
487   }
488 
489 
490   /**
491    *  Return the previous instruction.
492    */
493   public Instruction previous ()
494   {
495     return (Instruction) _li.previous ();
496   }
497 
498 
499   /**
500    *  Return the index of the previous instruction, or -1 if at beginning.
501    */
502   public int previousIndex ()
503   {
504     return _li.previousIndex ();
505   }
506 
507 
508   /**
509    *  Place the iterator before the given list index.
510    */
511   public void before (int index)
512   {
513     _li = _opcodes.listIterator (index);
514   }
515 
516 
517   /**
518    *  Place the iterator after the given list index.
519    */
520   public void after (int index)
521   {
522     before (index);
523     next ();
524   }
525 
526 
527   /**
528    *  Find the next Instruction from the current iterator position that 
529    *  matches the given one, according to  the equals() methods of the 
530    *  Instruction types.  This allows for matching based on template
531    *  instructions, as the equals() methods of most Instructions return
532    *  true if the information for the given Instruction has not been filled
533    *  in.  If a match is found, the iterator is placed after the matching
534     *  Instruction.  If no match is found, moves the iterator to afterLast().
535     *
536    *  @return    true if match found  
537    */
538   public boolean searchForward (Instruction template)
539   {
540     Instruction next;
541     while (hasNext ())
542     {
543       next = next ();
544       if (next.equals (template))
545         return true;
546     }
547     return false;
548   }
549 
550 
551   /**
552    *  Find the closest previous Instruction from the current iterator 
553    *  position that matches the given one, according to the equals() 
554     *  methods of the Instruction types.  This allows for matching based on 
555    *  template instructions, as the equals() methods of most Instructions 
556    *  returns true if the information for the given Instruction has not been 
557    *  filled in.  If a match is found, the iterator is placed before the 
558    *  matching Instruction.  If no match is found, moves the iterator to 
559    *  beforeFirst().
560     *
561    *  @return    true if match found  
562    */
563   public boolean searchBackward (Instruction template)
564   {
565     Instruction prev;
566     while (hasPrevious ())
567     {
568       prev = previous ();
569       if (prev.equals (template))
570         return true;
571     }
572     return false;
573   }
574 
575 
576   /**
577    *  Replaces the next Instruction with the given one.  It is an error to
578    *  call this method if the iterator is afterLast().  After this 
579    *  method, the iterator will be after the newly added Instruction.
580    *  This method will also make sure that all jump points
581    *  that referenced the old opcode are updated correctly.
582     *
583    *  @return    the newly added Instruction
584    */
585   public Instruction replaceNext (Instruction with)
586   {
587     Instruction  orig = (Instruction) _li.next ();
588     Instruction  ins   = null;
589 
590     _li.remove ();
591     if (with != null)
592     {
593       // create the new Instruction and copy import the given info
594       ins = getInstruction (with.getOpCode ());
595       ins.copy (with);
596 
597       // update all jump points
598       updateJumpPoints (orig, ins);
599     }
600 
601     return ins;
602   }
603 
604 
605   /**
606    *  Replaces the previous Instruction with the given one.  It is an
607    *  error to call this method if the iterator is beforeFirst().
608     *  After this method, the iterator will be before the newly added
609    *  Instruction.  This method will also make sure that all jump points
610    *  that referenced the old opcode are updated correctly.
611    *
612    *  @return    the newly added Instruction
613    */
614   public Instruction replacePrevious (Instruction with)
615   {
616     Instruction  orig = (Instruction) _li.previous ();
617     Instruction  ins   = null;
618 
619     _li.remove ();
620     if (with != null)
621     {
622       // create the new Instruction and copy import the given info
623       ins = getInstruction (with.getOpCode ());
624       ins.copy (with);
625 
626       // update all jump points
627       updateJumpPoints (orig, ins);
628     }
629 
630     return ins;
631   }
632 
633 
634   /**
635    *  Replaces all the Instructions in this code block that match the
636    *  given template with the given Instruction.  After this method,
637    *  the iterator will be in its original position.
638    *
639    *  @return    the number of substitutions made
640    */
641   public int replaceAll (Instruction template, Instruction with)
642   {
643     // remember the iterator position
644     int pos = nextIndex ();
645 
646     beforeFirst ();
647     int count;
648     for (count = 0; searchForward (template); count++)
649       replacePrevious (with);
650 
651     before (pos);
652     return count;
653   }
654 
655 
656   /**
657    *  Equivalent to looping over each given template/replacement
658    *  pair and calling replaceAll(Instruction, Instruction) for each.
659    */
660   public int replaceAll (Instruction[] templates, Instruction[] with)
661   {
662     if (templates == null && with == null)
663       return 0;
664 
665     int count = 0;
666     for (int i = 0; i < templates.length; i++)
667     {
668       if (with == null)
669         count += replaceAll (templates[i], null);
670       else
671         count += replaceAll (templates[i], with[i]);
672     }
673 
674     return count;
675   }
676 
677 
678   /**
679    *  Update all jump points that reference the original opcode
680    *  to reference the new one.
681    */
682   private void updateJumpPoints (Instruction orig, Instruction ins)
683   {
684     ListIterator li = _opcodes.listIterator ();
685 
686     for (Instruction next; li.hasNext ();)
687     {
688       next = (Instruction) li.next ();
689       if (next instanceof JumpInstruction)
690       {
691         if (orig.equals (((JumpInstruction) next).getTarget ()))
692           ((JumpInstruction) next).setTarget (ins);
693 
694         if (next.getOpCode () == TABLESWITCH)
695           updateJumpPoints (orig, ins, (TableSwitchInstruction) next);
696         else if (next.getOpCode () == LOOKUPSWITCH)
697           updateJumpPoints (orig, ins, (LookupSwitchInstruction)next);
698       }
699     }    
700   }
701 
702 
703   private void updateJumpPoints (Instruction orig, Instruction ins,
704     TableSwitchInstruction update)
705   {  
706     Instruction[] jumps = update.getTargets ();
707 
708     for (int i = 0; i < jumps.length; i++)
709       if (orig == jumps[i])
710         jumps[i] = ins;
711 
712     update.setTargets (jumps);
713   }
714 
715 
716   private void updateJumpPoints (Instruction orig, Instruction ins,
717     LookupSwitchInstruction update)
718   {  
719     Instruction[] jumps = update.getTargets ();
720 
721     for (int i = 0; i < jumps.length; i++)
722       if (orig == jumps[i])
723         jumps[i] = ins;
724 
725     update.setCases (update.getMatches (), jumps);
726   }
727 
728 
729   /**
730     *  Remove the current instruction.
731    */
732   public void remove ()
733   {
734     _li.remove ();
735   }
736 
737 
738   public Instruction nop ()
739   {
740     return addInstruction (NOP);
741   }
742 
743 
744   /**
745    *  Load some constant onto the stack.  The ConstantInstruction type
746    *  takes any constant and correctly translates it into the proper
747    *  opcode, depending on the constant type and value.  For example, 
748    *  if the constant value is set to 0L, the opcode will be set to
749    *  lconst_0.
750    */
751   public ConstantInstruction constant ()
752   {
753     return (ConstantInstruction) addInstruction 
754       (new ConstantInstruction (this));
755   }
756 
757   
758   /**
759    *  Loads a Class constant onto the stack.
760    *  For primitive types, this translates into a 
761    *  getstatic() for the TYPE field of the primitive's wrapper type.
762    *  For non-primitives, things get much more complex.  Suffice it to
763    *  say that the operation involves adding synthetic static fields
764    *  and even methods to the class.  Note that this instruction requires
765    *  up to 3 stack positions to execute.
766    */
767   public ClassConstantInstruction classconstant ()
768   {
769     return new ClassConstantInstruction 
770       (((BCMethod) _owner).getOwner (), this, nop ());
771   }
772 
773 
774   public ConstantInstruction aconst_null ()
775   {
776     return (ConstantInstruction) addInstruction (new ConstantInstruction 
777       (this, ACONST_NULL, null));
778   }
779 
780 
781   public ConstantInstruction iconst_m1 ()
782   {
783     return (ConstantInstruction) addInstruction (new ConstantInstruction 
784       (this, ICONST_M1, new Integer (-1)));
785   }
786 
787 
788   public ConstantInstruction iconst_0 ()
789   {
790     return (ConstantInstruction) addInstruction (new ConstantInstruction 
791       (this, ICONST_0, new Integer (0)));
792   }
793 
794 
795   public ConstantInstruction iconst_1 ()
796   {
797     return (ConstantInstruction) addInstruction (new ConstantInstruction 
798       (this, ICONST_1, new Integer (1)));
799   }
800 
801 
802   public ConstantInstruction iconst_2 ()
803   {
804     return (ConstantInstruction) addInstruction (new ConstantInstruction 
805       (this, ICONST_2, new Integer (2)));
806   }
807 
808 
809   public ConstantInstruction iconst_3 ()
810   {
811     return (ConstantInstruction) addInstruction (new ConstantInstruction 
812       (this, ICONST_3, new Integer (3)));
813   }
814 
815 
816   public ConstantInstruction iconst_4 ()
817   {
818     return (ConstantInstruction) addInstruction (new ConstantInstruction 
819       (this, ICONST_4, new Integer (4)));
820   }
821 
822 
823   public ConstantInstruction iconst_5 ()
824   {
825     return (ConstantInstruction) addInstruction (new ConstantInstruction 
826       (this, ICONST_5, new Integer (5)));
827   }
828 
829 
830   public ConstantInstruction lconst_0 ()
831   {
832     return (ConstantInstruction) addInstruction (new ConstantInstruction 
833       (this, LCONST_0, new Long (0)));
834   }
835 
836 
837   public ConstantInstruction lconst_1 ()
838   {
839     return (ConstantInstruction) addInstruction (new ConstantInstruction 
840       (this, LCONST_1, new Long (1)));
841   }
842 
843 
844   public ConstantInstruction fconst_0 ()
845   {
846     return (ConstantInstruction) addInstruction (new ConstantInstruction 
847       (this, FCONST_0, new Float (0)));
848   }
849 
850 
851   public ConstantInstruction fconst_1 ()
852   {
853     return (ConstantInstruction) addInstruction (new ConstantInstruction 
854       (this, FCONST_1, new Float (1)));
855   }
856 
857 
858   public ConstantInstruction fconst_2 ()
859   {
860     return (ConstantInstruction) addInstruction (new ConstantInstruction 
861       (this, FCONST_2, new Float (2)));
862   }
863 
864 
865   public ConstantInstruction dconst_0 ()
866   {
867     return (ConstantInstruction) addInstruction (new ConstantInstruction 
868       (this, DCONST_0, new Double (0)));
869   }
870 
871 
872   public ConstantInstruction dconst_1 ()
873   {
874     return (ConstantInstruction) addInstruction (new ConstantInstruction 
875       (this, DCONST_1, new Double (1)));
876   }
877 
878 
879   public ConstantInstruction bipush ()
880   {
881     return (ConstantInstruction) addInstruction (new ConstantInstruction 
882       (this, BIPUSH, null));
883   }
884 
885 
886   public ConstantInstruction sipush ()
887   {
888     return (ConstantInstruction) addInstruction (new ConstantInstruction 
889       (this, SIPUSH, null));
890   }
891 
892 
893   public ConstantInstruction ldc ()
894   {
895     return (ConstantInstruction) addInstruction (new ConstantInstruction 
896       (this, LDC, null));
897   }
898 
899 
900   public ConstantInstruction ldc_w ()
901   {
902     return (ConstantInstruction) addInstruction (new ConstantInstruction 
903       (this, LDC_W, null));
904   }
905 
906 
907   public ConstantInstruction ldc2_w ()
908   {
909     return (ConstantInstruction) addInstruction (new ConstantInstruction 
910       (this, LDC2_W, null));
911   }
912 
913 
914   /**
915    *  This is a convenience method to load a local variable onto the stack,
916    *  if the type and index to load is not known at compile time.
917    */
918   public LoadInstruction load ()
919   {
920     return (LoadInstruction) addInstruction (new LoadInstruction (this));
921   }
922 
923 
924   public LoadInstruction iload ()
925   {
926     return (LoadInstruction) addInstruction (new LoadInstruction
927       (this, ILOAD, int.class, -1));
928   }
929 
930 
931   public LoadInstruction iload_0 ()
932   {
933     return (LoadInstruction) addInstruction (new LoadInstruction 
934       (this, ILOAD_0, int.class, 0));
935   }
936 
937 
938   public LoadInstruction iload_1 ()
939   {
940     return (LoadInstruction) addInstruction (new LoadInstruction 
941       (this, ILOAD_1, int.class, 1));
942   }
943 
944 
945   public LoadInstruction iload_2 ()
946   {
947     return (LoadInstruction) addInstruction (new LoadInstruction 
948       (this, ILOAD_2, int.class, 2));
949   }
950 
951 
952   public LoadInstruction iload_3 ()
953   {
954     return (LoadInstruction) addInstruction (new LoadInstruction 
955       (this, ILOAD_3, int.class, 3));
956   }
957 
958 
959   public LoadInstruction lload ()
960   {
961     return (LoadInstruction) addInstruction (new LoadInstruction
962       (this, LLOAD, long.class, -1));
963   }
964 
965 
966   public LoadInstruction lload_0 ()
967   {
968     return (LoadInstruction) addInstruction (new LoadInstruction
969       (this, LLOAD_0, long.class, 0));
970   }
971 
972 
973   public LoadInstruction lload_1 ()
974   {
975     return (LoadInstruction) addInstruction (new LoadInstruction
976       (this, LLOAD_1, long.class, 1));
977   }
978 
979 
980   public LoadInstruction lload_2 ()
981   {
982     return (LoadInstruction) addInstruction (new LoadInstruction
983       (this, LLOAD_2, long.class, 2));
984   }
985 
986 
987   public LoadInstruction lload_3 ()
988   {
989     return (LoadInstruction) addInstruction (new LoadInstruction
990       (this, LLOAD_3, long.class, 3));
991   }
992 
993 
994   public LoadInstruction fload ()
995   {
996     return (LoadInstruction) addInstruction (new LoadInstruction
997       (this, FLOAD, float.class, -1));
998   }
999 
1000
1001  public LoadInstruction fload_0 ()
1002  {
1003    return (LoadInstruction) addInstruction (new LoadInstruction
1004      (this, FLOAD_0, float.class, 0));
1005  }
1006
1007
1008  public LoadInstruction fload_1 ()
1009  {
1010    return (LoadInstruction) addInstruction (new LoadInstruction
1011      (this, FLOAD_1, float.class, 1));
1012  }
1013
1014
1015  public LoadInstruction fload_2 ()
1016  {
1017    return (LoadInstruction) addInstruction (new LoadInstruction
1018      (this, FLOAD_2, float.class, 2));
1019  }
1020
1021
1022  public LoadInstruction fload_3 ()
1023  {
1024    return (LoadInstruction) addInstruction (new LoadInstruction
1025      (this, FLOAD_3, float.class, 3));
1026  }
1027
1028
1029  public LoadInstruction dload ()
1030  {
1031    return (LoadInstruction) addInstruction (new LoadInstruction
1032      (this, DLOAD, double.class, -1));
1033  }
1034
1035
1036  public LoadInstruction dload_0 ()
1037  {
1038    return (LoadInstruction) addInstruction (new LoadInstruction
1039      (this, DLOAD_0, double.class, 0));
1040  }
1041
1042
1043  public LoadInstruction dload_1 ()
1044  {
1045    return (LoadInstruction) addInstruction (new LoadInstruction
1046      (this, DLOAD_1, double.class, 1));
1047  }
1048
1049
1050  public LoadInstruction dload_2 ()
1051  {
1052    return (LoadInstruction) addInstruction (new LoadInstruction
1053      (this, DLOAD_2, double.class, 2));
1054  }
1055
1056
1057  public LoadInstruction dload_3 ()
1058  {
1059    return (LoadInstruction) addInstruction (new LoadInstruction
1060      (this, DLOAD_3, double.class, 3));
1061  }
1062
1063
1064  public LoadInstruction aload ()
1065  {
1066    return (LoadInstruction) addInstruction (new LoadInstruction
1067      (this, ALOAD, Object.class, -1));
1068  }
1069
1070
1071  public LoadInstruction aload_0 ()
1072  {
1073    return (LoadInstruction) addInstruction (new LoadInstruction
1074      (this, ALOAD_0, Object.class, 0));
1075  }
1076
1077
1078  public LoadInstruction aload_1 ()
1079  {
1080    return (LoadInstruction) addInstruction (new LoadInstruction
1081      (this, ALOAD_1, Object.class, 1));
1082  }
1083
1084
1085  public LoadInstruction aload_2 ()
1086  {
1087    return (LoadInstruction) addInstruction (new LoadInstruction
1088      (this, ALOAD_2, Object.class, 2));
1089  }
1090
1091
1092  public LoadInstruction aload_3 ()
1093  {
1094    return (LoadInstruction) addInstruction (new LoadInstruction
1095      (this, ALOAD_3, Object.class, 3));
1096  }
1097
1098
1099  /**
1100   *  This is a convenience method to store a stack value into a local
1101   *  variable if the type and index to store is not known at compile time.
1102   */
1103  public StoreInstruction store ()
1104  {
1105    return (StoreInstruction) addInstruction (new StoreInstruction (this));
1106  }
1107
1108
1109  public StoreInstruction istore ()
1110  {
1111    return (StoreInstruction) addInstruction (new StoreInstruction
1112      (this, ISTORE, int.class, -1));
1113  }
1114
1115
1116  public StoreInstruction istore_0 ()
1117  {
1118    return (StoreInstruction) addInstruction (new StoreInstruction 
1119      (this, ISTORE_0, int.class, 0));
1120  }
1121
1122
1123  public StoreInstruction istore_1 ()
1124  {
1125    return (StoreInstruction) addInstruction (new StoreInstruction 
1126      (this, ISTORE_1, int.class, 1));
1127  }
1128
1129
1130  public StoreInstruction istore_2 ()
1131  {
1132    return (StoreInstruction) addInstruction (new StoreInstruction 
1133      (this, ISTORE_2, int.class, 2));
1134  }
1135
1136
1137  public StoreInstruction istore_3 ()
1138  {
1139    return (StoreInstruction) addInstruction (new StoreInstruction 
1140      (this, ISTORE_3, int.class, 3));
1141  }
1142
1143
1144  public StoreInstruction lstore ()
1145  {
1146    return (StoreInstruction) addInstruction (new StoreInstruction
1147      (this, LSTORE, long.class, -1));
1148  }
1149
1150
1151  public StoreInstruction lstore_0 ()
1152  {
1153    return (StoreInstruction) addInstruction (new StoreInstruction
1154      (this, LSTORE_0, long.class, 0));
1155  }
1156
1157
1158  public StoreInstruction lstore_1 ()
1159  {
1160    return (StoreInstruction) addInstruction (new StoreInstruction
1161      (this, LSTORE_1, long.class, 1));
1162  }
1163
1164
1165  public StoreInstruction lstore_2 ()
1166  {
1167    return (StoreInstruction) addInstruction (new StoreInstruction
1168      (this, LSTORE_2, long.class, 2));
1169  }
1170
1171
1172  public StoreInstruction lstore_3 ()
1173  {
1174    return (StoreInstruction) addInstruction (new StoreInstruction
1175      (this, LSTORE_3, long.class, 3));
1176  }
1177
1178
1179  public StoreInstruction fstore ()
1180  {
1181    return (StoreInstruction) addInstruction (new StoreInstruction
1182      (this, FSTORE, float.class, -1));
1183  }
1184
1185
1186  public StoreInstruction fstore_0 ()
1187  {
1188    return (StoreInstruction) addInstruction (new StoreInstruction
1189      (this, FSTORE_0, float.class, 0));
1190  }
1191
1192
1193  public StoreInstruction fstore_1 ()
1194  {
1195    return (StoreInstruction) addInstruction (new StoreInstruction
1196      (this, FSTORE_1, float.class, 1));
1197  }
1198
1199
1200  public StoreInstruction fstore_2 ()
1201  {
1202    return (StoreInstruction) addInstruction (new StoreInstruction
1203      (this, FSTORE_2, float.class, 2));
1204  }
1205
1206
1207  public StoreInstruction fstore_3 ()
1208  {
1209    return (StoreInstruction) addInstruction (new StoreInstruction
1210      (this, FSTORE_3, float.class, 3));
1211  }
1212
1213
1214  public StoreInstruction dstore ()
1215  {
1216    return (StoreInstruction) addInstruction (new StoreInstruction
1217      (this, DSTORE, double.class, -1));
1218  }
1219
1220
1221  public StoreInstruction dstore_0 ()
1222  {
1223    return (StoreInstruction) addInstruction (new StoreInstruction
1224      (this, DSTORE_0, double.class, 0));
1225  }
1226
1227
1228  public StoreInstruction dstore_1 ()
1229  {
1230    return (StoreInstruction) addInstruction (new StoreInstruction
1231      (this, DSTORE_1, double.class, 1));
1232  }
1233
1234
1235  public StoreInstruction dstore_2 ()
1236  {
1237    return (StoreInstruction) addInstruction (new StoreInstruction
1238      (this, DSTORE_2, double.class, 2));
1239  }
1240
1241
1242  public StoreInstruction dstore_3 ()
1243  {
1244    return (StoreInstruction) addInstruction (new StoreInstruction
1245      (this, DSTORE_3, double.class, 3));
1246  }
1247
1248
1249  public StoreInstruction astore ()
1250  {
1251    return (StoreInstruction) addInstruction (new StoreInstruction
1252      (this, ASTORE, Object.class, -1));
1253  }
1254
1255
1256  public StoreInstruction astore_0 ()
1257  {
1258    return (StoreInstruction) addInstruction (new StoreInstruction
1259      (this, ASTORE_0, Object.class, 0));
1260  }
1261
1262
1263  public StoreInstruction astore_1 ()
1264  {
1265    return (StoreInstruction) addInstruction (new StoreInstruction
1266      (this, ASTORE_1, Object.class, 1));
1267  }
1268
1269
1270  public StoreInstruction astore_2 ()
1271  {
1272    return (StoreInstruction) addInstruction (new StoreInstruction
1273      (this, ASTORE_2, Object.class, 2));
1274  }
1275
1276
1277  public StoreInstruction astore_3 ()
1278  {
1279    return (StoreInstruction) addInstruction (new StoreInstruction
1280      (this, ASTORE_3, Object.class, 3));
1281  }
1282
1283
1284  public RetInstruction ret ()
1285  {
1286    return (RetInstruction) addInstruction (new RetInstruction (this));
1287  }
1288
1289
1290  public IIncInstruction iinc ()
1291  {
1292    return (IIncInstruction) addInstruction (new IIncInstruction (this));
1293  }
1294
1295
1296  public WideInstruction wide ()
1297  {
1298    return (WideInstruction) addInstruction (new WideInstruction (this));
1299  }
1300
1301
1302  /**
1303   *  This is a convenience method to invoke the proper array load instruction
1304   *  if the type is not known at compile time.
1305   */
1306  public ArrayLoadInstruction arrayload ()
1307  {
1308    return (ArrayLoadInstruction) addInstruction 
1309      (new ArrayLoadInstruction (this));
1310  }
1311
1312
1313  public ArrayLoadInstruction iaload ()
1314  {
1315    return (ArrayLoadInstruction) addInstruction 
1316      (new ArrayLoadInstruction (this, IALOAD, int.class));
1317  }
1318
1319
1320  public ArrayLoadInstruction laload ()
1321  {
1322    return (ArrayLoadInstruction) addInstruction 
1323      (new ArrayLoadInstruction (this, LALOAD, long.class));
1324  }
1325
1326
1327  public ArrayLoadInstruction faload ()
1328  {
1329    return (ArrayLoadInstruction) addInstruction 
1330      (new ArrayLoadInstruction (this, FALOAD, float.class));
1331  }
1332
1333
1334  public ArrayLoadInstruction daload ()
1335  {
1336    return (ArrayLoadInstruction) addInstruction 
1337      (new ArrayLoadInstruction (this, DALOAD, double.class));
1338  }
1339
1340
1341  public ArrayLoadInstruction aaload ()
1342  {
1343    return (ArrayLoadInstruction) addInstruction 
1344      (new ArrayLoadInstruction (this, AALOAD, Object.class));
1345  }
1346
1347
1348  public ArrayLoadInstruction baload ()
1349  {
1350    return (ArrayLoadInstruction) addInstruction 
1351      (new ArrayLoadInstruction (this, BALOAD, byte.class));
1352  }
1353
1354
1355  public ArrayLoadInstruction caload ()
1356  {
1357    return (ArrayLoadInstruction) addInstruction 
1358      (new