KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > bytecode > Bytecode


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist.bytecode;
17
18 import javassist.CtClass;
19 import javassist.CtPrimitiveType;
20
21 /**
22  * A utility class for producing a bytecode sequence.
23  *
24  * <p>A <code>Bytecode</code> object is an unbounded array
25  * containing bytecode. For example,
26  *
27  * <ul><pre>ConstPool cp = ...; // constant pool table
28  * Bytecode b = new Bytecode(cp, 1, 0);
29  * b.addIconst(3);
30  * b.addReturn(CtClass.intType);
31  * CodeAttribute ca = b.toCodeAttribute();</ul></pre>
32  *
33  * <p>This program produces a Code attribute including a bytecode
34  * sequence:
35  *
36  * <ul><pre>iconst_3
37  * ireturn</pre></ul>
38  *
39  * @see ConstPool
40  * @see CodeAttribute
41  */

42 public class Bytecode implements Opcode {
43     /**
44      * Represents the <code>CtClass</code> file using the
45      * constant pool table given to this <code>Bytecode</code> object.
46      */

47     public static final CtClass THIS = ConstPool.THIS;
48
49     static final int bufsize = 64;
50     ConstPool constPool;
51     int maxStack, maxLocals;
52     ExceptionTable tryblocks;
53     Bytecode next;
54     byte[] buffer;
55     int num;
56
57     private int stackDepth;
58
59     /**
60      * Constructs a <code>Bytecode</code> object with an empty bytecode
61      * sequence.
62      *
63      * <p>The parameters <code>stacksize</code> and <code>localvars</code>
64      * specify initial values
65      * of <code>max_stack</code> and <code>max_locals</code>.
66      * They can be changed later.
67      *
68      * @param cp constant pool table.
69      * @param stacksize <code>max_stack</code>.
70      * @param localvars <code>max_locals</code>.
71      */

72     public Bytecode(ConstPool cp, int stacksize, int localvars) {
73         this();
74         constPool = cp;
75         maxStack = stacksize;
76         maxLocals = localvars;
77         tryblocks = new ExceptionTable(cp);
78         stackDepth = 0;
79     }
80
81     /**
82      * Constructs a <code>Bytecode</code> object with an empty bytecode
83      * sequence. The initial values of <code>max_stack</code> and
84      * <code>max_locals</code> are zero.
85      *
86      * @param cp constant pool table.
87      * @see Bytecode#setMaxStack(int)
88      * @see Bytecode#setMaxLocals(int)
89      */

90     public Bytecode(ConstPool cp) {
91         this(cp, 0, 0);
92     }
93
94     /* used in add().
95      */

96     private Bytecode() {
97         buffer = new byte[bufsize];
98         num = 0;
99         next = null;
100     }
101
102     /**
103      * Gets a constant pool table.
104      */

105     public ConstPool getConstPool() { return constPool; }
106
107     /**
108      * Returns <code>exception_table</code>.
109      */

110     public ExceptionTable getExceptionTable() { return tryblocks; }
111
112     /**
113      * Converts to a <code>CodeAttribute</code>.
114      */

115     public CodeAttribute toCodeAttribute() {
116         return new CodeAttribute(constPool, maxStack, maxLocals,
117                                  get(), tryblocks);
118     }
119
120     /**
121      * Returns the length of the bytecode sequence.
122      */

123     public int length() {
124         int len = 0;
125         Bytecode b = this;
126         while (b != null) {
127             len += b.num;
128             b = b.next;
129         }
130
131         return len;
132     }
133
134     private void copy(byte[] dest, int index) {
135         Bytecode b = this;
136         while (b != null) {
137             System.arraycopy(b.buffer, 0, dest, index, b.num);
138             index += b.num;
139             b = b.next;
140         }
141     }
142
143     /**
144      * Returns the produced bytecode sequence.
145      */

146     public byte[] get() {
147         byte[] b = new byte[length()];
148         copy(b, 0);
149         return b;
150     }
151
152     /**
153      * Gets <code>max_stack</code>.
154      */

155     public int getMaxStack() { return maxStack; }
156
157     /**
158      * Sets <code>max_stack</code>.
159      *
160      * <p>This value may be automatically updated when an instruction
161      * is appended. A <code>Bytecode</code> object maintains the current
162      * stack depth whenever an instruction is added
163      * by <code>addOpcode()</code>. For example, if DUP is appended,
164      * the current stack depth is increased by one. If the new stack
165      * depth is more than <code>max_stack</code>, then it is assigned
166      * to <code>max_stack</code>. However, if branch instructions are
167      * appended, the current stack depth may not be correctly maintained.
168      *
169      * @see #addOpcode(int)
170      */

171     public void setMaxStack(int size) {
172         maxStack = size;
173     }
174
175     /**
176      * Gets <code>max_locals</code>.
177      */

178     public int getMaxLocals() { return maxLocals; }
179
180     /**
181      * Sets <code>max_locals</code>.
182      */

183     public void setMaxLocals(int size) {
184         maxLocals = size;
185     }
186
187     /**
188      * Sets <code>max_locals</code>.
189      *
190      * <p>This computes the number of local variables
191      * used to pass method parameters and sets <code>max_locals</code>
192      * to that number plus <code>locals</code>.
193      *
194      * @param isStatic true if <code>params</code> must be
195      * interpreted as parameters to a static method.
196      * @param params parameter types.
197      * @param locals the number of local variables excluding
198      * ones used to pass parameters.
199      */

200     public void setMaxLocals(boolean isStatic, CtClass[] params,
201                              int locals) {
202         if (!isStatic)
203             ++locals;
204
205         if (params != null) {
206             CtClass doubleType = CtClass.doubleType;
207             CtClass longType = CtClass.longType;
208             int n = params.length;
209             for (int i = 0; i < n; ++i) {
210                 CtClass type = params[i];
211                 if (type == doubleType || type == longType)
212                     locals += 2;
213                 else
214                     ++locals;
215             }
216         }
217
218         maxLocals = locals;
219     }
220
221     /**
222      * Increments <code>max_locals</code>.
223      */

224     public void incMaxLocals(int diff) {
225         maxLocals += diff;
226     }
227
228     /**
229      * Adds a new entry of <code>exception_table</code>.
230      */

231     public void addExceptionHandler(int start, int end,
232                                     int handler, CtClass type) {
233         addExceptionHandler(start, end, handler,
234                             constPool.addClassInfo(type));
235     }
236
237     /**
238      * Adds a new entry of <code>exception_table</code>.
239      *
240      * @param type the fully-qualified name of a throwable class.
241      */

242     public void addExceptionHandler(int start, int end,
243                                     int handler, String JavaDoc type) {
244         addExceptionHandler(start, end, handler,
245                             constPool.addClassInfo(type));
246     }
247
248     /**
249      * Adds a new entry of <code>exception_table</code>.
250      */

251     public void addExceptionHandler(int start, int end,
252                                     int handler, int type) {
253         tryblocks.add(start, end, handler, type);
254     }
255
256     /**
257      * Returns the length of bytecode sequence
258      * that have been added so far.
259      */

260     public int currentPc() {
261         int n = 0;
262         Bytecode b = this;
263         while (b != null) {
264             n += b.num;
265             b = b.next;
266         }
267
268         return n;
269     }
270
271     /**
272      * Reads a signed 8bit value at the offset from the beginning of the
273      * bytecode sequence.
274      *
275      * @throws ArrayIndexOutOfBoundsException if offset is invalid.
276      */

277     public int read(int offset) {
278         if (offset < 0)
279             return Opcode.NOP;
280         else if (offset < num)
281             return buffer[offset];
282         else
283             try {
284                 return next.read(offset - num);
285             }
286             catch (NullPointerException JavaDoc e) {
287                 throw new ArrayIndexOutOfBoundsException JavaDoc(offset);
288             }
289     }
290
291     /**
292      * Reads a signed 16bit value at the offset from the beginning of the
293      * bytecode sequence.
294      */

295     public int read16bit(int offset) {
296         int v1 = read(offset);
297         int v2 = read(offset + 1);
298         return (v1 << 8) + (v2 & 0xff);
299     }
300
301     /**
302      * Reads a signed 32bit value at the offset from the beginning of the
303      * bytecode sequence.
304      */

305     public int read32bit(int offset) {
306         int v1 = read16bit(offset);
307         int v2 = read16bit(offset + 2);
308         return (v1 << 16) + (v2 & 0xffff);
309     }
310
311     /**
312      * Writes an 8bit value at the offset from the beginning of the
313      * bytecode sequence.
314      *
315      * @throws ArrayIndexOutOfBoundsException if offset is invalid.
316      */

317     public void write(int offset, int value) {
318         if (offset < num)
319             buffer[offset] = (byte)value;
320         else
321             try {
322                 next.write(offset - num, value);
323             }
324             catch (NullPointerException JavaDoc e) {
325                 throw new ArrayIndexOutOfBoundsException JavaDoc(offset);
326             }
327     }
328
329     /**
330      * Writes an 16bit value at the offset from the beginning of the
331      * bytecode sequence.
332      */

333     public void write16bit(int offset, int value) {
334         write(offset, value >> 8);
335         write(offset + 1, value);
336     }
337
338     /**
339      * Writes an 32bit value at the offset from the beginning of the
340      * bytecode sequence.
341      */

342     public void write32bit(int offset, int value) {
343         write16bit(offset, value >> 16);
344         write16bit(offset + 2, value);
345     }
346
347     /**
348      * Appends an 8bit value to the end of the bytecode sequence.
349      */

350     public void add(int code) {
351         if (num < bufsize)
352             buffer[num++] = (byte)code;
353         else {
354             if (next == null)
355                 next = new Bytecode();
356
357             next.add(code);
358         }
359     }
360
361     /**
362      * Appends a 32bit value to the end of the bytecode sequence.
363      */

364     public void add32bit(int value) {
365         add(value >> 24);
366         add(value >> 16);
367         add(value >> 8);
368         add(value);
369     }
370
371     /**
372      * Appends the length-byte gap to the end of the bytecode sequence.
373      *
374      * @param length the gap length in byte.
375      */

376     public void addGap(int length) {
377         if (num < bufsize) {
378             num += length;
379             if (num <= bufsize)
380                 return;
381             else {
382                 length = num - bufsize;
383                 num = bufsize;
384             }
385         }
386
387         if (next == null)
388             next = new Bytecode();
389
390         next.addGap(length);
391     }
392
393     /**
394      * Appends an 8bit opcode to the end of the bytecode sequence.
395      * The current stack depth is updated.
396      * <code>max_stack</code> is updated if the current stack depth
397      * is the deepest so far.
398      *
399      * <p>Note: some instructions such as INVOKEVIRTUAL does not
400      * update the current stack depth since the increment depends
401      * on the method signature.
402      * <code>growStack()</code> must be explicitly called.
403      */

404     public void addOpcode(int code) {
405         add(code);
406         growStack(STACK_GROW[code]);
407     }
408
409     /**
410      * Increases the current stack depth.
411      * It also updates <code>max_stack</code> if the current stack depth
412      * is the deepest so far.
413      *
414      * @param diff the number added to the current stack depth.
415      */

416     public void growStack(int diff) {
417         setStackDepth(stackDepth + diff);
418     }
419
420     /**
421      * Returns the current stack depth.
422      */

423     public int getStackDepth() { return stackDepth; }
424
425     /**
426      * Sets the current stack depth.
427      * It also updates <code>max_stack</code> if the current stack depth
428      * is the deepest so far.
429      *
430      * @param depth new value.
431      */

432     public void setStackDepth(int depth) {
433         stackDepth = depth;
434         if (stackDepth > maxStack)
435             maxStack = stackDepth;
436     }
437
438     /**
439      * Appends a 16bit value to the end of the bytecode sequence.
440      * It never changes the current stack depth.
441      */

442     public void addIndex(int index) {
443         add(index >> 8);
444         add(index);
445     }
446
447     /**
448      * Appends ALOAD or (WIDE) ALOAD_&lt;n&gt;
449      *
450      * @param n an index into the local variable array.
451      */

452     public void addAload(int n) {
453         if (n < 4)
454             addOpcode(42 + n); // aload_<n>
455
else if (n < 0x100) {
456             addOpcode(ALOAD); // aload
457
add(n);
458         }
459         else {
460             addOpcode(WIDE);
461             addOpcode(ALOAD);
462             addIndex(n);
463         }
464     }
465
466     /**
467      * Appends ASTORE or (WIDE) ASTORE_&lt;n&gt;
468      *
469      * @param n an index into the local variable array.
470      */

471     public void addAstore(int n) {
472         if (n < 4)
473             addOpcode(75 + n); // astore_<n>
474
else if (n < 0x100) {
475             addOpcode(ASTORE); // astore
476
add(n);
477         }
478         else {
479             addOpcode(WIDE);
480             addOpcode(ASTORE);
481             addIndex(n);
482         }
483     }
484
485     /**
486      * Appends ICONST or ICONST_&lt;n&gt;
487      *
488      * @param n the pushed integer constant.
489      */

490     public void addIconst(int n) {
491         if (n < 6 && -2 < n)
492             addOpcode(3 + n); // iconst_<i> -1..5
493
else if (n <= 127 && -128 <= n) {
494             addOpcode(16); // bipush
495
add(n);
496         }
497         else if (n <= 32767 && -32768 <= n) {
498             addOpcode(17); // sipush
499
add(n >> 8);
500             add(n);
501         }
502         else
503             addLdc(constPool.addIntegerInfo(n));
504     }
505
506     /**
507      * Appends an instruction for pushing zero or null on the stack.
508      * If the type is void, this method does not append any instruction.
509      *
510      * @param type the type of the zero value (or null).
511      */

512     public void addConstZero(CtClass type) {
513         if (type.isPrimitive()) {
514             if (type == CtClass.longType)
515                 addOpcode(LCONST_0);
516             else if (type == CtClass.floatType)
517                 addOpcode(FCONST_0);
518             else if (type == CtClass.doubleType)
519                 addOpcode(DCONST_0);
520             else if (type == CtClass.voidType)
521                 throw new RuntimeException JavaDoc("void type?");
522             else
523                 addOpcode(ICONST_0);
524         }
525         else
526             addOpcode(ACONST_NULL);
527     }
528
529     /**
530      * Appends ILOAD or (WIDE) ILOAD_&lt;n&gt;
531      *
532      * @param n an index into the local variable array.
533      */

534     public void addIload(int n) {
535         if (n < 4)
536             addOpcode(26 + n); // iload_<n>
537
else if (n < 0x100) {
538             addOpcode(ILOAD); // iload
539
add(n);
540         }
541         else {
542             addOpcode(WIDE);
543             addOpcode(ILOAD);
544             addIndex(n);
545         }
546     }
547
548     /**
549      * Appends ISTORE or (WIDE) ISTORE_&lt;n&gt;
550      *
551      * @param n an index into the local variable array.
552      */

553     public void addIstore(int n) {
554         if (n < 4)
555             addOpcode(59 + n); // istore_<n>
556
else if (n < 0x100) {
557             addOpcode(ISTORE); // istore
558
add(n);
559         }
560         else {
561             addOpcode(WIDE);
562             addOpcode(ISTORE);
563             addIndex(n);
564         }
565     }
566
567     /**
568      * Appends LCONST or LCONST_&lt;n&gt;
569      *
570      * @param n the pushed long integer constant.
571      */

572     public void addLconst(long n) {
573         if (n == 0 || n == 1)
574             addOpcode(9 + (int)n); // lconst_<n>
575
else
576             addLdc2w(n);
577     }
578
579     /**
580      * Appends LLOAD or (WIDE) LLOAD_&lt;n&gt;
581      *
582      * @param n an index into the local variable array.
583      */

584     public void addLload(int n) {
585         if (n < 4)
586             addOpcode(30 + n); // lload_<n>
587
else if (n < 0x100) {
588             addOpcode(LLOAD); // lload
589
add(n);
590         }
591         else {
592             addOpcode(WIDE);
593             addOpcode(LLOAD);
594             addIndex(n);
595         }
596     }
597
598     /**
599      * Appends LSTORE or LSTORE_&lt;n&gt;
600      *
601      * @param n an index into the local variable array.
602      */

603     public void addLstore(int n) {
604         if (n < 4)
605             addOpcode(63 + n); // lstore_<n>
606
else if (n < 0x100) {
607             addOpcode(LSTORE); // lstore
608
add(n);
609         }
610         else {
611             addOpcode(WIDE);
612             addOpcode(LSTORE);
613             addIndex(n);
614         }
615     }
616    
617     /**
618      * Appends DCONST or DCONST_&lt;n&gt;
619      *
620      * @param d the pushed double constant.
621      */

622     public void addDconst(double d) {
623         if (d == 0.0 || d == 1.0)
624             addOpcode(14 + (int)d); // dconst_<n>
625
else
626             addLdc2w(d);
627     }
628
629     /**
630      * Appends DLOAD or (WIDE) DLOAD_&lt;n&gt;
631      *
632      * @param n an index into the local variable array.
633      */

634     public void addDload(int n) {
635         if (n < 4)
636             addOpcode(38 + n); // dload_<n>
637
else if (n < 0x100) {
638             addOpcode(DLOAD); // dload
639
add(n);
640         }
641         else {
642             addOpcode(WIDE);
643             addOpcode(DLOAD);
644             addIndex(n);
645         }
646     }
647
648     /**
649      * Appends DSTORE or (WIDE) DSTORE_&lt;n&gt;
650      *
651      * @param n an index into the local variable array.
652      */

653     public void addDstore(int n) {
654         if (n < 4)
655             addOpcode(71 + n); // dstore_<n>
656
else if (n < 0x100) {
657             addOpcode(DSTORE); // dstore
658
add(n);
659         }
660         else {
661             addOpcode(WIDE);
662             addOpcode(DSTORE);
663             addIndex(n);
664         }
665     }
666
667     /**
668      * Appends FCONST or FCONST_&lt;n&gt;
669      *
670      * @param f the pushed float constant.
671      */

672     public void addFconst(float f) {
673         if (f == 0.0f || f == 1.0f || f == 2.0f)
674             addOpcode(11 + (int)f); // fconst_<n>
675
else
676             addLdc(constPool.addFloatInfo(f));
677     }
678
679     /**
680      * Appends FLOAD or (WIDE) FLOAD_&lt;n&gt;
681      *
682      * @param n an index into the local variable array.
683      */

684     public void addFload(int n) {
685         if (n < 4)
686             addOpcode(34 + n); // fload_<n>
687
else if (n < 0x100) {
688             addOpcode(FLOAD); // fload
689
add(n);
690         }
691         else {
692             addOpcode(WIDE);
693             addOpcode(FLOAD);
694             addIndex(n);
695         }
696     }
697
698     /**
699      * Appends FSTORE or FSTORE_&lt;n&gt;
700      *
701      * @param n an index into the local variable array.
702      */

703     public void addFstore(int n) {
704         if (n < 4)
705             addOpcode(67 + n); // fstore_<n>
706
else if (n < 0x100) {
707             addOpcode(FSTORE); // fstore
708
add(n);
709         }
710         else {
711             addOpcode(WIDE);
712             addOpcode(FSTORE);
713             addIndex(n);
714         }
715     }
716
717     /**
718      * Appends an instruction for loading a value from the
719      * local variable at the index <code>n</code>.
720      *
721      * @param n the index.
722      * @param type the type of the loaded value.
723      * @return the size of the value (1 or 2 word).
724      */

725     public int addLoad(int n, CtClass type) {
726         if (type.isPrimitive()) {
727             if (type == CtClass.booleanType || type == CtClass.charType
728                 || type == CtClass.byteType || type == CtClass.shortType
729                 || type == CtClass.intType)
730                 addIload(n);
731             else if (type == CtClass.longType) {
732                 addLload(n);
733                 return 2;
734             }
735             else if(type == CtClass.floatType)
736                 addFload(n);
737             else if(type == CtClass.doubleType) {
738                 addDload(n);
739                 return 2;
740             }
741             else
742                 throw new RuntimeException JavaDoc("void type?");
743         }
744         else
745             addAload(n);
746
747         return 1;
748     }
749
750     /**
751      * Appends an instruction for storing a value into the
752      * local variable at the index <code>n</code>.
753      *
754      * @param n the index.
755      * @param type the type of the stored value.
756      * @return 2 if the type is long or double. Otherwise 1.
757      */

758     public int addStore(int n, CtClass type) {
759         if (type.isPrimitive()) {
760             if (type == CtClass.booleanType || type == CtClass.charType
761                 || type == CtClass.byteType || type == CtClass.shortType
762                 || type == CtClass.intType)
763                 addIstore(n);
764             else if (type == CtClass.longType) {
765                 addLstore(n);
766                 return 2;
767             }
768             else if (type == CtClass.floatType)
769                 addFstore(n);
770             else if (type == CtClass.doubleType) {
771                 addDstore(n);
772                 return 2;
773             }
774             else
775                 throw new RuntimeException JavaDoc("void type?");
776         }
777         else
778             addAstore(n);
779
780         return 1;
781     }
782
783     /**
784      * Appends instructions for loading all the parameters onto the
785      * operand stack.
786      *
787      * @param offset the index of the first parameter. It is 0
788      * if the method is static. Otherwise, it is 1.
789      */

790     public int addLoadParameters(CtClass[] params, int offset) {
791         int stacksize = 0;
792         if (params != null) {
793             int n = params.length;
794             for (int i = 0; i < n; ++i)
795                 stacksize += addLoad(stacksize + offset, params[i]);
796         }
797
798         return stacksize;
799     }
800
801     /**
802      * Appends CHECKCAST.
803      *
804      * @param c the type.
805      */

806     public void addCheckcast(CtClass c) {
807         addOpcode(CHECKCAST);
808         addIndex(constPool.addClassInfo(c));
809     }
810
811     /**
812      * Appends CHECKCAST.
813      *
814      * @param classname a fully-qualified class name.
815      */

816     public void addCheckcast(String JavaDoc classname) {
817         addOpcode(CHECKCAST);
818         addIndex(constPool.addClassInfo(classname));
819     }
820
821     /**
822      * Appends INSTANCEOF.
823      *
824      * @param classname the class name.
825      */

826     public void addInstanceof(String JavaDoc classname) {
827         addOpcode(INSTANCEOF);
828         addIndex(constPool.addClassInfo(classname));
829     }
830
831     /**
832      * Appends GETFIELD.
833      *
834      * @param c the class
835      * @param name the field name
836      * @param type the descriptor of the field type.
837      *
838      * @see Descriptor#of(CtClass)
839      */

840     public void addGetfield(CtClass c, String JavaDoc name, String JavaDoc type) {
841         add(GETFIELD);
842         int ci = constPool.addClassInfo(c);
843         addIndex(constPool.addFieldrefInfo(ci, name, type));
844         growStack(Descriptor.dataSize(type) - 1);
845     }
846
847     /**
848      * Appends GETSTATIC.
849      *
850      * @param c the class
851      * @param name the field name
852      * @param type the descriptor of the field type.
853      *
854      * @see Descriptor#of(CtClass)
855      */

856     public void addGetstatic(CtClass c, String JavaDoc name, String JavaDoc type) {
857         add(GETSTATIC);
858         int ci = constPool.addClassInfo(c);
859         addIndex(constPool.addFieldrefInfo(ci, name, type));
860         growStack(Descriptor.dataSize(type));
861     }
862
863     /**
864      * Appends GETSTATIC.
865      *
866      * @param c the fully-qualified class name
867      * @param name the field name
868      * @param type the descriptor of the field type.
869      *
870      * @see Descriptor#of(CtClass)
871      */

872     public void addGetstatic(String JavaDoc c, String JavaDoc name, String JavaDoc type) {
873         add(GETSTATIC);
874         int ci = constPool.addClassInfo(c);
875         addIndex(constPool.addFieldrefInfo(ci, name, type));
876         growStack(Descriptor.dataSize(type));
877     }
878
879     /**
880      * Appends INVOKESPECIAL.
881      *
882      * @param clazz the target class.
883      * @param name the method name.
884      * @param returnType the return type.
885      * @param paramTypes the parameter types.
886      */

887     public void addInvokespecial(CtClass clazz, String JavaDoc name,
888                                  CtClass returnType, CtClass[] paramTypes) {
889         String JavaDoc desc = Descriptor.ofMethod(returnType, paramTypes);
890         addInvokespecial(clazz, name, desc);
891     }
892
893     /**
894      * Appends INVOKESPECIAL.
895      *
896      * @param clazz the target class.
897      * @param name the method name
898      * @param desc the descriptor of the method signature.
899      *
900      * @see Descriptor#ofMethod(CtClass,CtClass[])
901      * @see Descriptor#ofConstructor(CtClass[])
902      */

903     public void addInvokespecial(CtClass clazz, String JavaDoc name, String JavaDoc desc) {
904         addInvokespecial(constPool.addClassInfo(clazz), name, desc);
905     }
906
907     /**
908      * Appends INVOKESPECIAL.
909      *
910      * @param clazz the fully-qualified class name.
911      * @param name the method name
912      * @param desc the descriptor of the method signature.
913      *
914      * @see Descriptor#ofMethod(CtClass,CtClass[])
915      * @see Descriptor#ofConstructor(CtClass[])
916      */

917     public void addInvokespecial(String JavaDoc clazz, String JavaDoc name, String JavaDoc desc) {
918         addInvokespecial(constPool.addClassInfo(clazz), name, desc);
919     }
920
921     /**
922      * Appends INVOKESPECIAL.
923      *
924      * @param clazz the index of <code>CONSTANT_Class_info</code>
925      * structure.
926      * @param name the method name
927      * @param desc the descriptor of the method signature.
928      *
929      * @see Descriptor#ofMethod(CtClass,CtClass[])
930      * @see Descriptor#ofConstructor(CtClass[])
931      */

932     public void addInvokespecial(int clazz, String JavaDoc name, String JavaDoc desc) {
933         add(INVOKESPECIAL);
934         addIndex(constPool.addMethodrefInfo(clazz, name, desc));
935         growStack(Descriptor.dataSize(desc) - 1);
936     }
937
938     /**
939      * Appends INVOKESTATIC.
940      *
941      * @param clazz the target class.
942      * @param name the method name
943      * @param returnType the return type.
944      * @param paramTypes the parameter types.
945      */

946     public void addInvokestatic(CtClass clazz, String JavaDoc name,
947                                 CtClass returnType, CtClass[] paramTypes) {
948         String JavaDoc desc = Descriptor.ofMethod(returnType, paramTypes);
949         addInvokestatic(clazz, name, desc);
950     }
951
952     /**
953      * Appends INVOKESTATIC.
954      *
955      * @param clazz the target class.
956      * @param name the method name
957      * @param desc the descriptor of the method signature.
958      *
959      * @see Descriptor#ofMethod(CtClass,CtClass[])
960      */

961     public void addInvokestatic(CtClass clazz, String JavaDoc name, String JavaDoc desc) {
962         addInvokestatic(constPool.addClassInfo(clazz), name, desc);
963     }
964
965     /**
966      * Appends INVOKESTATIC.
967      *
968      * @param classname the fully-qualified class name.
969      * @param name the method name
970      * @param desc the descriptor of the method signature.
971      *
972      * @see Descriptor#ofMethod(CtClass,CtClass[])
973      */

974     public void addInvokestatic(String JavaDoc classname, String JavaDoc name, String JavaDoc desc) {
975         addInvokestatic(constPool.addClassInfo(classname), name, desc);
976     }
977
978     /**
979      * Appends INVOKESTATIC.
980      *
981      * @param clazz the index of <code>CONSTANT_Class_info</code>
982      * structure.
983      * @param name the method name
984      * @param desc the descriptor of the method signature.
985      *
986      * @see Descriptor#ofMethod(CtClass,CtClass[])
987      */

988     public void addInvokestatic(int clazz, String JavaDoc name, String JavaDoc desc) {
989         add(INVOKESTATIC);
990         addIndex(constPool.addMethodrefInfo(clazz, name, desc));
991         growStack(Descriptor.dataSize(desc));
992     }
993
994     /**
995      * Appends INVOKEVIRTUAL.
996      *
997      * <p>The specified method must not be an inherited method.
998      * It must be directly declared in the class specified
999      * in <code>clazz</code>.
1000     *
1001     * @param clazz the target class.
1002     * @param name the method name
1003     * @param returnType the return type.
1004     * @param paramTypes the parameter types.
1005     */

1006    public void addInvokevirtual(CtClass clazz, String JavaDoc name,
1007                                 CtClass returnType, CtClass[] paramTypes) {
1008        String JavaDoc desc = Descriptor.ofMethod(returnType, paramTypes);
1009        addInvokevirtual(clazz, name, desc);
1010    }
1011
1012    /**
1013     * Appends INVOKEVIRTUAL.
1014     *
1015     * <p>The specified method must not be an inherited method.
1016     * It must be directly declared in the class specified
1017     * in <code>clazz</code>.
1018     *
1019     * @param clazz the target class.
1020     * @param name the method name
1021     * @param desc the descriptor of the method signature.
1022     *
1023     * @see Descriptor#ofMethod(CtClass,CtClass[])
1024     */

1025    public void addInvokevirtual(CtClass clazz, String JavaDoc name, String JavaDoc desc) {
1026        addInvokevirtual(constPool.addClassInfo(clazz), name, desc);
1027    }
1028
1029    /**
1030     * Appends INVOKEVIRTUAL.
1031     *
1032     * <p>The specified method must not be an inherited method.
1033     * It must be directly declared in the class specified
1034     * in <code>classname</code>.
1035     *
1036     * @param classname the fully-qualified class name.
1037     * @param name the method name
1038     * @param desc the descriptor of the method signature.
1039     *
1040     * @see Descriptor#ofMethod(CtClass,CtClass[])
1041     */

1042    public void addInvokevirtual(String JavaDoc classname, String JavaDoc name, String JavaDoc desc) {
1043        addInvokevirtual(constPool.addClassInfo(classname), name, desc);
1044    }
1045
1046    /**
1047     * Appends INVOKEVIRTUAL.
1048     *
1049     * <p>The specified method must not be an inherited method.
1050     * It must be directly declared in the class specified
1051     * by <code>clazz</code>.
1052     *
1053     * @param clazz the index of <code>CONSTANT_Class_info</code>
1054     * structure.
1055     * @param name the method name
1056     * @param desc the descriptor of the method signature.
1057     *
1058     * @see Descriptor#ofMethod(CtClass,CtClass[])
1059     */

1060    public void addInvokevirtual(int clazz, String JavaDoc name, String JavaDoc desc) {
1061        add(INVOKEVIRTUAL);
1062        addIndex(constPool.addMethodrefInfo(clazz, name, desc));
1063        growStack(Descriptor.dataSize(desc) - 1);
1064    }
1065
1066    /**
1067     * Appends INVOKEINTERFACE.
1068     *
1069     * @param clazz the target class.
1070     * @param name the method name
1071     * @param returnType the return type.
1072     * @param paramTypes the parameter types.
1073     * @param count the count operand of the instruction.
1074     */

1075    public void addInvokeinterface(CtClass clazz, String JavaDoc name,
1076                                   CtClass returnType, CtClass[] paramTypes,
1077                                   int count) {
1078        String JavaDoc desc = Descriptor.ofMethod(returnType, paramTypes);
1079        addInvokeinterface(clazz, name, desc, count);
1080    }
1081
1082    /**
1083     * Appends INVOKEINTERFACE.
1084     *
1085     * @param clazz the target class.
1086     * @param name the method name
1087     * @param desc the descriptor of the method signature.
1088     * @param count the count operand of the instruction.
1089     *
1090     * @see Descriptor#ofMethod(CtClass,CtClass[])
1091     */

1092    public void addInvokeinterface(CtClass clazz, String JavaDoc name,
1093                                   String JavaDoc desc, int count) {
1094        addInvokeinterface(constPool.addClassInfo(clazz), name, desc,
1095                           count);
1096    }
1097
1098    /**
1099     * Appends INVOKEINTERFACE.
1100     *
1101     * @param classname the fully-qualified class name.
1102     * @param name the method name
1103     * @param desc the descriptor of the method signature.
1104     * @param count the count operand of the instruction.
1105     *
1106     * @see Descriptor#ofMethod(CtClass,CtClass[])
1107     */

1108    public void addInvokeinterface(String JavaDoc classname, String JavaDoc name,
1109                                   String JavaDoc desc, int count) {
1110        addInvokeinterface(constPool.addClassInfo(classname), name, desc,
1111                           count);
1112    }
1113
1114    /**
1115     * Appends INVOKEINTERFACE.
1116     *
1117     * @param clazz the index of <code>CONSTANT_Class_info</code>
1118     * structure.
1119     * @param name the method name
1120     * @param desc the descriptor of the method signature.
1121     * @param count the count operand of the instruction.
1122     *
1123     * @see Descriptor#ofMethod(CtClass,CtClass[])
1124     */

1125    public void addInvokeinterface(int clazz, String JavaDoc name,
1126                                   String JavaDoc desc, int count) {
1127        add(INVOKEINTERFACE);
1128        addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
1129        add(count);
1130        add(0);
1131        growStack(Descriptor.dataSize(desc) - 1);
1132    }
1133
1134    /**
1135     * Appends LDC or LDC_W. The pushed item is a <code>String</code>
1136     * object.
1137     *
1138     * @param s the character string pushed by LDC or LDC_W.
1139     */

1140    public void addLdc(String JavaDoc s) {
1141        addLdc(constPool.addStringInfo(s));
1142    }
1143
1144    /**
1145     * Appends LDC or LDC_W.
1146     *
1147     * @param i index into the constant pool.
1148     */

1149    public void addLdc(int i) {
1150        if (i > 0xFF) {
1151            addOpcode(LDC_W);
1152            addIndex(i);
1153        }
1154        else {
1155            addOpcode(LDC);
1156            add(i);
1157        }
1158    }
1159
1160    /**
1161     * Appends LDC2_W. The pushed item is a long value.
1162     */

1163    public void addLdc2w(long l) {
1164        addOpcode(LDC2_W);
1165        addIndex(constPool.addLongInfo(l));
1166    }
1167
1168    /**
1169     * Appends LDC2_W. The pushed item is a double value.
1170     */

1171    public void addLdc2w(double d) {
1172        addOpcode(LDC2_W);
1173        addIndex(constPool.addDoubleInfo(d));
1174    }
1175
1176    /**
1177     * Appends NEW.
1178     *
1179     * @param clazz the class of the created instance.
1180     */

1181    public void addNew(CtClass clazz) {
1182        addOpcode(NEW);
1183        addIndex(constPool.addClassInfo(clazz));
1184    }
1185
1186    /**
1187     * Appends NEW.
1188     *
1189     * @param classname the fully-qualified class name.
1190     */

1191    public void addNew(String JavaDoc classname) {
1192        addOpcode(NEW);
1193        addIndex(constPool.addClassInfo(classname));
1194    }
1195
1196    /**
1197     * Appends ANEWARRAY.
1198     *
1199     * @param classname the qualified class name of the element type.
1200     */

1201    public void addAnewarray(String JavaDoc classname) {
1202        addOpcode(ANEWARRAY);
1203        addIndex(constPool.addClassInfo(classname));
1204    }
1205
1206    /**
1207     * Appends ICONST and ANEWARRAY.
1208     *
1209     * @param clazz the elememnt type.
1210     * @param length the array length.
1211     */

1212    public void addAnewarray(CtClass clazz, int length) {
1213        addIconst(length);
1214        addOpcode(ANEWARRAY);
1215        addIndex(constPool.addClassInfo(clazz));
1216    }
1217
1218    /**
1219     * Appends NEWARRAY for primitive types.
1220     *
1221     * @param atype <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
1222     * @see Opcode
1223     */

1224    public void addNewarray(int atype, int length) {
1225        addIconst(length);
1226        addOpcode(NEWARRAY);
1227        add(atype);
1228    }
1229
1230    /**
1231     * Appends MULTINEWARRAY.
1232     *
1233     * @param clazz the array type.
1234     * @param dimensions the sizes of all dimensions.
1235     * @return the length of <code>dimensions</code>.
1236     */

1237    public int addMultiNewarray(CtClass clazz, int[] dimensions) {
1238        int len = dimensions.length;
1239        for (int i = 0; i < len; ++i)
1240            addIconst(dimensions[i]);
1241
1242        growStack(len);
1243        return addMultiNewarray(clazz, len);
1244    }
1245
1246    /**
1247     * Appends MULTINEWARRAY. The size of every dimension must have been
1248     * already pushed on the stack.
1249     *
1250     * @param clazz the array type.
1251     * @param dim the number of the dimensions.
1252     * @return the value of <code>dim</code>.
1253     */

1254    public int addMultiNewarray(CtClass clazz, int dim) {
1255        add(MULTIANEWARRAY);
1256        addIndex(constPool.addClassInfo(clazz));
1257        add(dim);
1258        growStack(1 - dim);
1259        return dim;
1260    }
1261
1262    /**
1263     * Appends MULTINEWARRAY.
1264     *
1265     * @param desc the type descriptor of the created array.
1266     * @param dim dimensions.
1267     * @return the value of <code>dim</code>.
1268     */

1269    public int addMultiNewarray(String JavaDoc desc, int dim) {
1270        add(MULTIANEWARRAY);
1271        addIndex(constPool.addClassInfo(desc));
1272        add(dim);
1273        growStack(1 - dim);
1274        return dim;
1275    }
1276
1277    /**
1278     * Appends PUTFIELD.
1279     *
1280     * @param c the target class.
1281     * @param name the field name.
1282     * @param desc the descriptor of the field type.
1283     */

1284    public void addPutfield(CtClass c, String JavaDoc name, String JavaDoc desc) {
1285        add(PUTFIELD);
1286        int ci = constPool.addClassInfo(c);
1287        addIndex(constPool.addFieldrefInfo(ci, name, desc));
1288        growStack(-1 - Descriptor.dataSize(desc));
1289    }
1290
1291    /**
1292     * Appends PUTSTATIC.
1293     *
1294     * @param c the target class.
1295     * @param name the field name.
1296     * @param desc the descriptor of the field type.
1297     */

1298    public void addPutstatic(CtClass c, String JavaDoc name, String JavaDoc desc) {
1299        add(PUTSTATIC);
1300        int ci = constPool.addClassInfo(c);
1301        addIndex(constPool.addFieldrefInfo(ci, name, desc));
1302        growStack(-Descriptor.dataSize(desc));
1303    }
1304
1305    /**
1306     * Appends ARETURN, IRETURN, .., or RETURN.
1307     *
1308     * @param type the return type.
1309     */

1310    public void addReturn(CtClass type) {
1311        if (type == null)
1312            addOpcode(RETURN);
1313        else if (type.isPrimitive()) {
1314            CtPrimitiveType ptype = (CtPrimitiveType)type;
1315            addOpcode(ptype.getReturnOp());
1316        }
1317        else
1318            addOpcode(ARETURN);
1319    }
1320
1321    /**
1322     * Appends RET.
1323     *
1324     * @param var local variable
1325     */

1326    public void addRet(int var) {
1327        if (var < 0x100) {
1328            addOpcode(RET);
1329            add(var);
1330        }
1331        else {
1332            addOpcode(WIDE);
1333            addOpcode(RET);
1334            addIndex(var);
1335        }
1336    }
1337
1338    /**
1339     * Appends instructions for executing
1340     * <code>java.lang.System.println(<i>message</i>)</code>.
1341     *
1342     * @param message printed message.
1343     */

1344    public void addPrintln(String JavaDoc message) {
1345        addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
1346        addLdc(message);
1347        addInvokevirtual("java.io.PrintStream",
1348                         "println", "(Ljava/lang/String;)V");
1349    }
1350}
1351
Popular Tags