1/*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2007 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
16package javassist.bytecode;
17
18import javassist.CtClass;
19import javassist.CtPrimitiveType;
20
21class ByteVector implements Cloneable {
22    private byte[] buffer;
23    private int size;
24
25    public ByteVector() {
26        buffer = new byte[64];
27        size = 0;
28    }
29
30    public Object clone() throws CloneNotSupportedException {
31        ByteVector bv = (ByteVector)super.clone();
32        bv.buffer = (byte[])buffer.clone();
33        return bv;
34    }
35
36    public final int getSize() { return size; }
37
38    public final byte[] copy() {
39        byte[] b = new byte[size];
40        System.arraycopy(buffer, 0, b, 0, size);
41        return b;
42    }
43
44    public int read(int offset) {
45        if (offset < 0 || size <= offset)
46            throw new ArrayIndexOutOfBoundsException(offset);
47
48        return buffer[offset];
49    }
50
51    public void write(int offset, int value) {
52        if (offset < 0 || size <= offset)
53            throw new ArrayIndexOutOfBoundsException(offset);
54
55        buffer[offset] = (byte)value;
56    }
57
58    public void add(int code) {
59        addGap(1);
60        buffer[size - 1] = (byte)code;
61    }
62
63    public void add(int b1, int b2) {
64        addGap(2);
65        buffer[size - 2] = (byte)b1;
66        buffer[size - 1] = (byte)b2;
67    }
68
69    public void add(int b1, int b2, int b3, int b4) {
70        addGap(4);
71        buffer[size - 4] = (byte)b1;
72        buffer[size - 3] = (byte)b2;
73        buffer[size - 2] = (byte)b3;
74        buffer[size - 1] = (byte)b4;
75    }
76
77    public void addGap(int length) {
78        if (size + length > buffer.length) {
79            int newSize = size << 1;
80            if (newSize < size + length)
81                newSize = size + length;
82
83            byte[] newBuf = new byte[newSize];
84            System.arraycopy(buffer, 0, newBuf, 0, size);
85            buffer = newBuf;
86        }
87
88        size += length;
89    }
90}
91
92/**
93 * A utility class for producing a bytecode sequence.
94 *
95 * <p>A <code>Bytecode</code> object is an unbounded array
96 * containing bytecode.  For example,
97 *
98 * <ul><pre>ConstPool cp = ...;    // constant pool table
99 * Bytecode b = new Bytecode(cp, 1, 0);
100 * b.addIconst(3);
101 * b.addReturn(CtClass.intType);
102 * CodeAttribute ca = b.toCodeAttribute();</ul></pre>
103 *
104 * <p>This program produces a Code attribute including a bytecode
105 * sequence:
106 *
107 * <ul><pre>iconst_3
108 * ireturn</pre></ul>
109 *
110 * @see ConstPool
111 * @see CodeAttribute
112 */
113public class Bytecode extends ByteVector implements Cloneable, Opcode {
114    /**
115     * Represents the <code>CtClass</code> file using the
116     * constant pool table given to this <code>Bytecode</code> object.
117     */
118    public static final CtClass THIS = ConstPool.THIS;
119
120    ConstPool constPool;
121    int maxStack, maxLocals;
122    ExceptionTable tryblocks;
123    private int stackDepth;
124
125    /**
126     * Constructs a <code>Bytecode</code> object with an empty bytecode
127     * sequence.
128     *
129     * <p>The parameters <code>stacksize</code> and <code>localvars</code>
130     * specify initial values
131     * of <code>max_stack</code> and <code>max_locals</code>.
132     * They can be changed later.
133     *
134     * @param cp                constant pool table.
135     * @param stacksize         <code>max_stack</code>.
136     * @param localvars         <code>max_locals</code>.
137     */
138    public Bytecode(ConstPool cp, int stacksize, int localvars) {
139        constPool = cp;
140        maxStack = stacksize;
141        maxLocals = localvars;
142        tryblocks = new ExceptionTable(cp);
143        stackDepth = 0;
144    }
145
146    /**
147     * Constructs a <code>Bytecode</code> object with an empty bytecode
148     * sequence.  The initial values of <code>max_stack</code> and
149     * <code>max_locals</code> are zero.
150     *
151     * @param cp            constant pool table.
152     * @see Bytecode#setMaxStack(int)
153     * @see Bytecode#setMaxLocals(int)
154     */
155    public Bytecode(ConstPool cp) {
156        this(cp, 0, 0);
157    }
158
159    /**
160     * Creates and returns a copy of this object.
161     * The constant pool object is shared between this object
162     * and the cloned object.
163     */
164    public Object clone() {
165        try {
166            Bytecode bc = (Bytecode)super.clone();
167            bc.tryblocks = (ExceptionTable)tryblocks.clone();
168            return bc;
169        }
170        catch (CloneNotSupportedException cnse) {
171            throw new RuntimeException(cnse);
172        }
173    }
174
175    /**
176     * Gets a constant pool table.
177     */
178    public ConstPool getConstPool() { return constPool; }
179
180    /**
181     * Returns <code>exception_table</code>.
182     */
183    public ExceptionTable getExceptionTable() { return tryblocks; }
184
185    /**
186     * Converts to a <code>CodeAttribute</code>.
187     */
188    public CodeAttribute toCodeAttribute() {
189        return new CodeAttribute(constPool, maxStack, maxLocals,
190                                 get(), tryblocks);
191    }
192
193    /**
194     * Returns the length of the bytecode sequence.
195     */
196    public int length() {
197        return getSize();
198    }
199
200    /**
201     * Returns the produced bytecode sequence.
202     */
203    public byte[] get() {
204        return copy();
205    }
206
207    /**
208     * Gets <code>max_stack</code>.
209     */
210    public int getMaxStack() { return maxStack; }
211
212    /**
213     * Sets <code>max_stack</code>.
214     *
215     * <p>This value may be automatically updated when an instruction
216     * is appended.  A <code>Bytecode</code> object maintains the current
217     * stack depth whenever an instruction is added
218     * by <code>addOpcode()</code>.  For example, if DUP is appended,
219     * the current stack depth is increased by one.  If the new stack
220     * depth is more than <code>max_stack</code>, then it is assigned
221     * to <code>max_stack</code>.  However, if branch instructions are
222     * appended, the current stack depth may not be correctly maintained.
223     *
224     * @see #addOpcode(int)
225     */
226    public void setMaxStack(int size) {
227        maxStack = size;
228    }
229
230    /**
231     * Gets <code>max_locals</code>.
232     */
233    public int getMaxLocals() { return maxLocals; }
234
235    /**
236     * Sets <code>max_locals</code>.
237     */
238    public void setMaxLocals(int size) {
239        maxLocals = size;
240    }
241
242    /**
243     * Sets <code>max_locals</code>.
244     *
245     * <p>This computes the number of local variables
246     * used to pass method parameters and sets <code>max_locals</code>
247     * to that number plus <code>locals</code>.
248     *
249     * @param isStatic          true if <code>params</code> must be
250     *                          interpreted as parameters to a static method.
251     * @param params            parameter types.
252     * @param locals            the number of local variables excluding
253     *                          ones used to pass parameters.
254     */
255    public void setMaxLocals(boolean isStatic, CtClass[] params,
256                             int locals) {
257        if (!isStatic)
258            ++locals;
259
260        if (params != null) {
261            CtClass doubleType = CtClass.doubleType;
262            CtClass longType = CtClass.longType;
263            int n = params.length;
264            for (int i = 0; i < n; ++i) {
265                CtClass type = params[i];
266                if (type == doubleType || type == longType)
267                    locals += 2;
268                else
269                    ++locals;
270            }
271        }
272
273        maxLocals = locals;
274    }
275
276    /**
277     * Increments <code>max_locals</code>.
278     */
279    public void incMaxLocals(int diff) {
280        maxLocals += diff;
281    }
282
283    /**
284     * Adds a new entry of <code>exception_table</code>.
285     */
286    public void addExceptionHandler(int start, int end,
287                                    int handler, CtClass type) {
288        addExceptionHandler(start, end, handler,
289                            constPool.addClassInfo(type));
290    }
291
292    /**
293     * Adds a new entry of <code>exception_table</code>.
294     *
295     * @param type      the fully-qualified name of a throwable class.
296     */
297    public void addExceptionHandler(int start, int end,
298                                    int handler, String type) {
299        addExceptionHandler(start, end, handler,
300                            constPool.addClassInfo(type));
301    }
302
303    /**
304     * Adds a new entry of <code>exception_table</code>.
305     */
306    public void addExceptionHandler(int start, int end,
307                                    int handler, int type) {
308        tryblocks.add(start, end, handler, type);
309    }
310
311    /**
312     * Returns the length of bytecode sequence
313     * that have been added so far.
314     */
315    public int currentPc() {
316        return getSize();
317    }
318
319    /**
320     * Reads a signed 8bit value at the offset from the beginning of the
321     * bytecode sequence.
322     *
323     * @throws ArrayIndexOutOfBoundsException   if offset is invalid.
324     */
325    public int read(int offset) {
326        return super.read(offset);
327    }
328
329    /**
330     * Reads a signed 16bit value at the offset from the beginning of the
331     * bytecode sequence.
332     */
333    public int read16bit(int offset) {
334        int v1 = read(offset);
335        int v2 = read(offset + 1);
336        return (v1 << 8) + (v2 & 0xff);
337    }
338
339    /**
340     * Reads a signed 32bit value at the offset from the beginning of the
341     * bytecode sequence.
342     */
343    public int read32bit(int offset) {
344        int v1 = read16bit(offset);
345        int v2 = read16bit(offset + 2);
346        return (v1 << 16) + (v2 & 0xffff);
347    }
348
349    /**
350     * Writes an 8bit value at the offset from the beginning of the
351     * bytecode sequence.
352     *
353     * @throws ArrayIndexOutOfBoundsException   if offset is invalid.
354     */
355    public void write(int offset, int value) {
356        super.write(offset, value);
357    }
358
359    /**
360     * Writes an 16bit value at the offset from the beginning of the
361     * bytecode sequence.
362     */
363    public void write16bit(int offset, int value) {
364        write(offset, value >> 8);
365        write(offset + 1, value);
366    }
367
368    /**
369     * Writes an 32bit value at the offset from the beginning of the
370     * bytecode sequence.
371     */
372    public void write32bit(int offset, int value) {
373        write16bit(offset, value >> 16);
374        write16bit(offset + 2, value);
375    }
376
377    /**
378     * Appends an 8bit value to the end of the bytecode sequence.
379     */
380    public void add(int code) {
381        super.add(code);
382    }
383
384    /**
385     * Appends a 32bit value to the end of the bytecode sequence.
386     */
387    public void add32bit(int value) {
388        add(value >> 24, value >> 16, value >> 8, value);
389    }
390
391    /**
392     * Appends the length-byte gap to the end of the bytecode sequence.
393     *
394     * @param length    the gap length in byte.
395     */
396    public void addGap(int length) {
397        super.addGap(length);
398    }
399
400    /**
401     * Appends an 8bit opcode to the end of the bytecode sequence.
402     * The current stack depth is updated.
403     * <code>max_stack</code> is updated if the current stack depth
404     * is the deepest so far.
405     *
406     * <p>Note: some instructions such as INVOKEVIRTUAL does not
407     * update the current stack depth since the increment depends
408     * on the method signature.
409     * <code>growStack()</code> must be explicitly called.
410     */
411    public void addOpcode(int code) {
412        add(code);
413        growStack(STACK_GROW[code]);
414    }
415
416    /**
417     * Increases the current stack depth.
418     * It also updates <code>max_stack</code> if the current stack depth
419     * is the deepest so far.
420     *
421     * @param diff      the number added to the current stack depth.
422     */
423    public void growStack(int diff) {
424        setStackDepth(stackDepth + diff);
425    }
426
427    /**
428     * Returns the current stack depth.
429     */
430    public int getStackDepth() { return stackDepth; }
431
432    /**
433     * Sets the current stack depth.
434     * It also updates <code>max_stack</code> if the current stack depth
435     * is the deepest so far.
436     *
437     * @param depth     new value.
438     */
439    public void setStackDepth(int depth) {
440        stackDepth = depth;
441        if (stackDepth > maxStack)
442            maxStack = stackDepth;
443    }
444
445    /**
446     * Appends a 16bit value to the end of the bytecode sequence.
447     * It never changes the current stack depth.
448     */
449    public void addIndex(int index) {
450        add(index >> 8, index);
451    }
452
453    /**
454     * Appends ALOAD or (WIDE) ALOAD_&lt;n&gt;
455     *
456     * @param n         an index into the local variable array.
457     */
458    public void addAload(int n) {
459        if (n < 4)
460            addOpcode(42 + n);          // aload_<n>
461        else if (n < 0x100) {
462            addOpcode(ALOAD);           // aload
463            add(n);
464        }
465        else {
466            addOpcode(WIDE);
467            addOpcode(ALOAD);
468            addIndex(n);
469        }
470    }
471
472    /**
473     * Appends ASTORE or (WIDE) ASTORE_&lt;n&gt;
474     *
475     * @param n         an index into the local variable array.
476     */
477    public void addAstore(int n) {
478        if (n < 4)
479            addOpcode(75 + n);  // astore_<n>
480        else if (n < 0x100) {
481            addOpcode(ASTORE);          // astore
482            add(n);
483        }
484        else {
485            addOpcode(WIDE);
486            addOpcode(ASTORE);
487            addIndex(n);
488        }
489    }
490
491    /**
492     * Appends ICONST or ICONST_&lt;n&gt;
493     *
494     * @param n         the pushed integer constant.
495     */
496    public void addIconst(int n) {
497        if (n < 6 && -2 < n)
498            addOpcode(3 + n);           // iconst_<i>   -1..5
499        else if (n <= 127 && -128 <= n) {
500            addOpcode(16);              // bipush
501            add(n);
502        }
503        else if (n <= 32767 && -32768 <= n) {
504            addOpcode(17);              // sipush
505            add(n >> 8);
506            add(n);
507        }
508        else
509            addLdc(constPool.addIntegerInfo(n));
510    }
511
512    /**
513     * Appends an instruction for pushing zero or null on the stack.
514     * If the type is void, this method does not append any instruction.
515     *
516     * @param type      the type of the zero value (or null).
517     */
518    public void addConstZero(CtClass type) {
519        if (type.isPrimitive()) {
520            if (type == CtClass.longType)
521                addOpcode(LCONST_0);
522            else if (type == CtClass.floatType)
523                addOpcode(FCONST_0);
524            else if (type == CtClass.doubleType)
525                addOpcode(DCONST_0);
526            else if (type == CtClass.voidType)
527                throw new RuntimeException("void type?");
528            else
529                addOpcode(ICONST_0);
530        }
531        else
532            addOpcode(ACONST_NULL);
533    }
534
535    /**
536     * Appends ILOAD or (WIDE) ILOAD_&lt;n&gt;
537     *
538     * @param n         an index into the local variable array.
539     */
540    public void addIload(int n) {
541        if (n < 4)
542            addOpcode(26 + n);          // iload_<n>
543        else if (n < 0x100) {
544            addOpcode(ILOAD);           // iload
545            add(n);
546        }
547        else {
548            addOpcode(WIDE);
549            addOpcode(ILOAD);
550            addIndex(n);
551        }
552    }
553
554    /**
555     * Appends ISTORE or (WIDE) ISTORE_&lt;n&gt;
556     *
557     * @param n         an index into the local variable array.
558     */
559    public void addIstore(int n) {
560        if (n < 4)
561            addOpcode(59 + n);          // istore_<n>
562        else if (n < 0x100) {
563            addOpcode(ISTORE);          // istore
564            add(n);
565        }
566        else {
567            addOpcode(WIDE);
568            addOpcode(ISTORE);
569            addIndex(n);
570        }
571    }
572
573    /**
574     * Appends LCONST or LCONST_&lt;n&gt;
575     *
576     * @param n         the pushed long integer constant.
577     */
578    public void addLconst(long n) {
579        if (n == 0 || n == 1)
580            addOpcode(9 + (int)n);              // lconst_<n>
581        else
582            addLdc2w(n);
583    }
584
585    /**
586     * Appends LLOAD or (WIDE) LLOAD_&lt;n&gt;
587     *
588     * @param n         an index into the local variable array.
589     */
590    public void addLload(int n) {
591        if (n < 4)
592            addOpcode(30 + n);          // lload_<n>
593        else if (n < 0x100) {
594            addOpcode(LLOAD);           // lload
595            add(n);
596        }
597        else {
598            addOpcode(WIDE);
599            addOpcode(LLOAD);
600            addIndex(n);
601        }
602    }
603
604    /**
605     * Appends LSTORE or LSTORE_&lt;n&gt;
606     *
607     * @param n         an index into the local variable array.
608     */
609    public void addLstore(int n) {
610        if (n < 4)
611            addOpcode(63 + n);          // lstore_<n>
612        else if (n < 0x100) {
613            addOpcode(LSTORE);          // lstore
614            add(n);
615        }
616        else {
617            addOpcode(WIDE);
618            addOpcode(LSTORE);
619            addIndex(n);
620        }
621    }
622
623    /**
624     * Appends DCONST or DCONST_&lt;n&gt;
625     *
626     * @param d         the pushed double constant.
627     */
628    public void addDconst(double d) {
629        if (d == 0.0 || d == 1.0)
630            addOpcode(14 + (int)d);             // dconst_<n>
631        else
632            addLdc2w(d);
633    }
634
635    /**
636     * Appends DLOAD or (WIDE) DLOAD_&lt;n&gt;
637     *
638     * @param n         an index into the local variable array.
639     */
640    public void addDload(int n) {
641        if (n < 4)
642            addOpcode(38 + n);          // dload_<n>
643        else if (n < 0x100) {
644            addOpcode(DLOAD);           // dload
645            add(n);
646        }
647        else {
648            addOpcode(WIDE);
649            addOpcode(DLOAD);
650            addIndex(n);
651        }
652    }
653
654    /**
655     * Appends DSTORE or (WIDE) DSTORE_&lt;n&gt;
656     *
657     * @param n         an index into the local variable array.
658     */
659    public void addDstore(int n) {
660        if (n < 4)
661            addOpcode(71 + n);          // dstore_<n>
662        else if (n < 0x100) {
663            addOpcode(DSTORE);          // dstore
664            add(n);
665        }
666        else {
667            addOpcode(WIDE);
668            addOpcode(DSTORE);
669            addIndex(n);
670        }
671    }
672
673    /**
674     * Appends FCONST or FCONST_&lt;n&gt;
675     *
676     * @param f         the pushed float constant.
677     */
678    public void addFconst(float f) {
679        if (f == 0.0f || f == 1.0f || f == 2.0f)
680            addOpcode(11 + (int)f);             // fconst_<n>
681        else
682            addLdc(constPool.addFloatInfo(f));
683    }
684
685    /**
686     * Appends FLOAD or (WIDE) FLOAD_&lt;n&gt;
687     *
688     * @param n         an index into the local variable array.
689     */
690    public void addFload(int n) {
691        if (n < 4)
692            addOpcode(34 + n);          // fload_<n>
693        else if (n < 0x100) {
694            addOpcode(FLOAD);           // fload
695            add(n);
696        }
697        else {
698            addOpcode(WIDE);
699            addOpcode(FLOAD);
700            addIndex(n);
701        }
702    }
703
704    /**
705     * Appends FSTORE or FSTORE_&lt;n&gt;
706     *
707     * @param n         an index into the local variable array.
708     */
709    public void addFstore(int n) {
710        if (n < 4)
711            addOpcode(67 + n);          // fstore_<n>
712        else if (n < 0x100) {
713            addOpcode(FSTORE);          // fstore
714            add(n);
715        }
716        else {
717            addOpcode(WIDE);
718            addOpcode(FSTORE);
719            addIndex(n);
720        }
721    }
722
723    /**
724     * Appends an instruction for loading a value from the
725     * local variable at the index <code>n</code>.
726     *
727     * @param n         the index.
728     * @param type      the type of the loaded value.
729     * @return          the size of the value (1 or 2 word).
730     */
731    public int addLoad(int n, CtClass type) {
732        if (type.isPrimitive()) {
733            if (type == CtClass.booleanType || type == CtClass.charType
734                || type == CtClass.byteType || type == CtClass.shortType
735                || type == CtClass.intType)
736                addIload(n);
737            else if (type == CtClass.longType) {
738                addLload(n);
739                return 2;
740            }
741            else if(type == CtClass.floatType)
742                addFload(n);
743            else if(type == CtClass.doubleType) {
744                addDload(n);
745                return 2;
746            }
747            else
748                throw new RuntimeException("void type?");
749        }
750        else
751            addAload(n);
752
753        return 1;
754    }
755
756    /**
757     * Appends an instruction for storing a value into the
758     * local variable at the index <code>n</code>.
759     *
760     * @param n         the index.
761     * @param type      the type of the stored value.
762     * @return          2 if the type is long or double.  Otherwise 1.
763     */
764    public int addStore(int n, CtClass type) {
765        if (type.isPrimitive()) {
766            if (type == CtClass.booleanType || type == CtClass.charType
767                || type == CtClass.byteType || type == CtClass.shortType
768                || type == CtClass.intType)
769                addIstore(n);
770            else if (type == CtClass.longType) {
771                addLstore(n);
772                return 2;
773            }
774            else if (type == CtClass.floatType)
775                addFstore(n);
776            else if (type == CtClass.doubleType) {
777                addDstore(n);
778                return 2;
779            }
780            else
781                throw new RuntimeException("void type?");
782        }
783        else
784            addAstore(n);
785
786        return 1;
787    }
788
789    /**
790     * Appends instructions for loading all the parameters onto the
791     * operand stack.
792     *
793     * @param offset	the index of the first parameter.  It is 0
794     *			if the method is static.  Otherwise, it is 1.
795     */
796    public int addLoadParameters(CtClass[] params, int offset) {
797        int stacksize = 0;
798        if (params != null) {
799            int n = params.length;
800            for (int i = 0; i < n; ++i)
801                stacksize += addLoad(stacksize + offset, params[i]);
802        }
803
804        return stacksize;
805    }
806
807    /**
808     * Appends CHECKCAST.
809     *
810     * @param c         the type.
811     */
812    public void addCheckcast(CtClass c) {
813        addOpcode(CHECKCAST);
814        addIndex(constPool.addClassInfo(c));
815    }
816
817    /**
818     * Appends CHECKCAST.
819     *
820     * @param classname         a fully-qualified class name.
821     */
822    public void addCheckcast(String classname) {
823        addOpcode(CHECKCAST);
824        addIndex(constPool.addClassInfo(classname));
825    }
826
827    /**
828     * Appends INSTANCEOF.
829     *
830     * @param classname         the class name.
831     */
832    public void addInstanceof(String classname) {
833        addOpcode(INSTANCEOF);
834        addIndex(constPool.addClassInfo(classname));
835    }
836
837    /**
838     * Appends GETFIELD.
839     *
840     * @param c         the class.
841     * @param name      the field name.
842     * @param type      the descriptor of the field type.
843     *
844     * @see Descriptor#of(CtClass)
845     */
846    public void addGetfield(CtClass c, String name, String type) {
847        add(GETFIELD);
848        int ci = constPool.addClassInfo(c);
849        addIndex(constPool.addFieldrefInfo(ci, name, type));
850        growStack(Descriptor.dataSize(type) - 1);
851    }
852
853    /**
854     * Appends GETFIELD.
855     *
856     * @param c         the fully-qualified class name.
857     * @param name      the field name.
858     * @param type      the descriptor of the field type.
859     *
860     * @see Descriptor#of(CtClass)
861     */
862    public void addGetfield(String c, String name, String type) {
863        add(GETFIELD);
864        int ci = constPool.addClassInfo(c);
865        addIndex(constPool.addFieldrefInfo(ci, name, type));
866        growStack(Descriptor.dataSize(type) - 1);
867    }
868
869    /**
870     * Appends GETSTATIC.
871     *
872     * @param c         the class
873     * @param name      the field name
874     * @param type      the descriptor of the field type.
875     *
876     * @see Descriptor#of(CtClass)
877     */
878    public void addGetstatic(CtClass c, String name, String type) {
879        add(GETSTATIC);
880        int ci = constPool.addClassInfo(c);
881        addIndex(constPool.addFieldrefInfo(ci, name, type));
882        growStack(Descriptor.dataSize(type));
883    }
884
885    /**
886     * Appends GETSTATIC.
887     *
888     * @param c         the fully-qualified class name
889     * @param name      the field name
890     * @param type      the descriptor of the field type.
891     *
892     * @see Descriptor#of(CtClass)
893     */
894    public void addGetstatic(String c, String name, String type) {
895        add(GETSTATIC);
896        int ci = constPool.addClassInfo(c);
897        addIndex(constPool.addFieldrefInfo(ci, name, type));
898        growStack(Descriptor.dataSize(type));
899    }
900
901    /**
902     * Appends INVOKESPECIAL.
903     *
904     * @param clazz     the target class.
905     * @param name      the method name.
906     * @param returnType        the return type.
907     * @param paramTypes        the parameter types.
908     */
909    public void addInvokespecial(CtClass clazz, String name,
910                                 CtClass returnType, CtClass[] paramTypes) {
911        String desc = Descriptor.ofMethod(returnType, paramTypes);
912        addInvokespecial(clazz, name, desc);
913    }
914
915    /**
916     * Appends INVOKESPECIAL.
917     *
918     * @param clazz     the target class.
919     * @param name      the method name
920     * @param desc      the descriptor of the method signature.
921     *
922     * @see Descriptor#ofMethod(CtClass,CtClass[])
923     * @see Descriptor#ofConstructor(CtClass[])
924     */
925    public void addInvokespecial(CtClass clazz, String name, String desc) {
926        addInvokespecial(constPool.addClassInfo(clazz), name, desc);
927    }
928
929    /**
930     * Appends INVOKESPECIAL.
931     *
932     * @param clazz     the fully-qualified class name.
933     * @param name      the method name
934     * @param desc      the descriptor of the method signature.
935     *
936     * @see Descriptor#ofMethod(CtClass,CtClass[])
937     * @see Descriptor#ofConstructor(CtClass[])
938     */
939    public void addInvokespecial(String clazz, String name, String desc) {
940        addInvokespecial(constPool.addClassInfo(clazz), name, desc);
941    }
942
943    /**
944     * Appends INVOKESPECIAL.
945     *
946     * @param clazz     the index of <code>CONSTANT_Class_info</code>
947     *                  structure.
948     * @param name      the method name
949     * @param desc      the descriptor of the method signature.
950     *
951     * @see Descriptor#ofMethod(CtClass,CtClass[])
952     * @see Descriptor#ofConstructor(CtClass[])
953     */
954    public void addInvokespecial(int clazz, String name, String desc) {
955        add(INVOKESPECIAL);
956        addIndex(constPool.addMethodrefInfo(clazz, name, desc));
957        growStack(Descriptor.dataSize(desc) - 1);
958    }
959
960    /**
961     * Appends INVOKESTATIC.
962     *
963     * @param clazz     the target class.
964     * @param name      the method name
965     * @param returnType        the return type.
966     * @param paramTypes        the parameter types.
967     */
968    public void addInvokestatic(CtClass clazz, String name,
969                                CtClass returnType, CtClass[] paramTypes) {
970        String desc = Descriptor.ofMethod(returnType, paramTypes);
971        addInvokestatic(clazz, name, desc);
972    }
973
974    /**
975     * Appends INVOKESTATIC.
976     *
977     * @param clazz     the target class.
978     * @param name      the method name
979     * @param desc      the descriptor of the method signature.
980     *
981     * @see Descriptor#ofMethod(CtClass,CtClass[])
982     */
983    public void addInvokestatic(CtClass clazz, String name, String desc) {
984        addInvokestatic(constPool.addClassInfo(clazz), name, desc);
985    }
986
987    /**
988     * Appends INVOKESTATIC.
989     *
990     * @param classname the fully-qualified class name.
991     * @param name      the method name
992     * @param desc      the descriptor of the method signature.
993     *
994     * @see Descriptor#ofMethod(CtClass,CtClass[])
995     */
996    public void addInvokestatic(String classname, String name, String desc) {
997        addInvokestatic(constPool.addClassInfo(classname), name, desc);
998    }
999
1000    /**
1001     * Appends INVOKESTATIC.
1002     *
1003     * @param clazz     the index of <code>CONSTANT_Class_info</code>
1004     *                  structure.
1005     * @param name      the method name
1006     * @param desc      the descriptor of the method signature.
1007     *
1008     * @see Descriptor#ofMethod(CtClass,CtClass[])
1009     */
1010    public void addInvokestatic(int clazz, String name, String desc) {
1011        add(INVOKESTATIC);
1012        addIndex(constPool.addMethodrefInfo(clazz, name, desc));
1013        growStack(Descriptor.dataSize(desc));
1014    }
1015
1016    /**
1017     * Appends INVOKEVIRTUAL.
1018     *
1019     * <p>The specified method must not be an inherited method.
1020     * It must be directly declared in the class specified
1021     * in <code>clazz</code>.
1022     *
1023     * @param clazz     the target class.
1024     * @param name      the method name
1025     * @param returnType        the return type.
1026     * @param paramTypes        the parameter types.
1027     */
1028    public void addInvokevirtual(CtClass clazz, String name,
1029                                 CtClass returnType, CtClass[] paramTypes) {
1030        String desc = Descriptor.ofMethod(returnType, paramTypes);
1031        addInvokevirtual(clazz, name, desc);
1032    }
1033
1034    /**
1035     * Appends INVOKEVIRTUAL.
1036     *
1037     * <p>The specified method must not be an inherited method.
1038     * It must be directly declared in the class specified
1039     * in <code>clazz</code>.
1040     *
1041     * @param clazz     the target class.
1042     * @param name      the method name
1043     * @param desc      the descriptor of the method signature.
1044     *
1045     * @see Descriptor#ofMethod(CtClass,CtClass[])
1046     */
1047    public void addInvokevirtual(CtClass clazz, String name, String desc) {
1048        addInvokevirtual(constPool.addClassInfo(clazz), name, desc);
1049    }
1050
1051    /**
1052     * Appends INVOKEVIRTUAL.
1053     *
1054     * <p>The specified method must not be an inherited method.
1055     * It must be directly declared in the class specified
1056     * in <code>classname</code>.
1057     *
1058     * @param classname the fully-qualified class name.
1059     * @param name      the method name
1060     * @param desc      the descriptor of the method signature.
1061     *
1062     * @see Descriptor#ofMethod(CtClass,CtClass[])
1063     */
1064    public void addInvokevirtual(String classname, String name, String desc) {
1065        addInvokevirtual(constPool.addClassInfo(classname), name, desc);
1066    }
1067
1068    /**
1069     * Appends INVOKEVIRTUAL.
1070     *
1071     * <p>The specified method must not be an inherited method.
1072     * It must be directly declared in the class specified
1073     * by <code>clazz</code>.
1074     *
1075     * @param clazz     the index of <code>CONSTANT_Class_info</code>
1076     *                  structure.
1077     * @param name      the method name
1078     * @param desc      the descriptor of the method signature.
1079     *
1080     * @see Descriptor#ofMethod(CtClass,CtClass[])
1081     */
1082    public void addInvokevirtual(int clazz, String name, String desc) {
1083        add(INVOKEVIRTUAL);
1084        addIndex(constPool.addMethodrefInfo(clazz, name, desc));
1085        growStack(Descriptor.dataSize(desc) - 1);
1086    }
1087
1088    /**
1089     * Appends INVOKEINTERFACE.
1090     *
1091     * @param clazz     the target class.
1092     * @param name      the method name
1093     * @param returnType        the return type.
1094     * @param paramTypes        the parameter types.
1095     * @param count     the count operand of the instruction.
1096     */
1097    public void addInvokeinterface(CtClass clazz, String name,
1098                                   CtClass returnType, CtClass[] paramTypes,
1099                                   int count) {
1100        String desc = Descriptor.ofMethod(returnType, paramTypes);
1101        addInvokeinterface(clazz, name, desc, count);
1102    }
1103
1104    /**
1105     * Appends INVOKEINTERFACE.
1106     *
1107     * @param clazz     the target class.
1108     * @param name      the method name
1109     * @param desc      the descriptor of the method signature.
1110     * @param count     the count operand of the instruction.
1111     *
1112     * @see Descriptor#ofMethod(CtClass,CtClass[])
1113     */
1114    public void addInvokeinterface(CtClass clazz, String name,
1115                                   String desc, int count) {
1116        addInvokeinterface(constPool.addClassInfo(clazz), name, desc,
1117                           count);
1118    }
1119
1120    /**
1121     * Appends INVOKEINTERFACE.
1122     *
1123     * @param classname the fully-qualified class name.
1124     * @param name      the method name
1125     * @param desc      the descriptor of the method signature.
1126     * @param count     the count operand of the instruction.
1127     *
1128     * @see Descriptor#ofMethod(CtClass,CtClass[])
1129     */
1130    public void addInvokeinterface(String classname, String name,
1131                                   String desc, int count) {
1132        addInvokeinterface(constPool.addClassInfo(classname), name, desc,
1133                           count);
1134    }
1135
1136    /**
1137     * Appends INVOKEINTERFACE.
1138     *
1139     * @param clazz     the index of <code>CONSTANT_Class_info</code>
1140     *                  structure.
1141     * @param name      the method name
1142     * @param desc      the descriptor of the method signature.
1143     * @param count     the count operand of the instruction.
1144     *
1145     * @see Descriptor#ofMethod(CtClass,CtClass[])
1146     */
1147    public void addInvokeinterface(int clazz, String name,
1148                                   String desc, int count) {
1149        add(INVOKEINTERFACE);
1150        addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
1151        add(count);
1152        add(0);
1153        growStack(Descriptor.dataSize(desc) - 1);
1154    }
1155
1156    /**
1157     * Appends LDC or LDC_W.  The pushed item is a <code>String</code>
1158     * object.
1159     *
1160     * @param s         the character string pushed by LDC or LDC_W.
1161     */
1162    public void addLdc(String s) {
1163        addLdc(constPool.addStringInfo(s));
1164    }
1165
1166    /**
1167     * Appends LDC or LDC_W.
1168     *
1169     * @param i         index into the constant pool.
1170     */
1171    public void addLdc(int i) {
1172        if (i > 0xFF) {
1173            addOpcode(LDC_W);
1174            addIndex(i);
1175        }
1176        else {
1177            addOpcode(LDC);
1178            add(i);
1179        }
1180    }
1181
1182    /**
1183     * Appends LDC2_W.  The pushed item is a long value.
1184     */
1185    public void addLdc2w(long l) {
1186        addOpcode(LDC2_W);
1187        addIndex(constPool.addLongInfo(l));
1188    }
1189
1190    /**
1191     * Appends LDC2_W.  The pushed item is a double value.
1192     */
1193    public void addLdc2w(double d) {
1194        addOpcode(LDC2_W);
1195        addIndex(constPool.addDoubleInfo(d));
1196    }
1197
1198    /**
1199     * Appends NEW.
1200     *
1201     * @param clazz     the class of the created instance.
1202     */
1203    public void addNew(CtClass clazz) {
1204        addOpcode(NEW);
1205        addIndex(constPool.addClassInfo(clazz));
1206    }
1207
1208    /**
1209     * Appends NEW.
1210     *
1211     * @param classname         the fully-qualified class name.
1212     */
1213    public void addNew(String classname) {
1214        addOpcode(NEW);
1215        addIndex(constPool.addClassInfo(classname));
1216    }
1217
1218    /**
1219     * Appends ANEWARRAY.
1220     *
1221     * @param classname         the qualified class name of the element type.
1222     */
1223    public void addAnewarray(String classname) {
1224        addOpcode(ANEWARRAY);
1225        addIndex(constPool.addClassInfo(classname));
1226    }
1227
1228    /**
1229     * Appends ICONST and ANEWARRAY.
1230     *
1231     * @param clazz     the elememnt type.
1232     * @param length    the array length.
1233     */
1234    public void addAnewarray(CtClass clazz, int length) {
1235        addIconst(length);
1236        addOpcode(ANEWARRAY);
1237        addIndex(constPool.addClassInfo(clazz));
1238    }
1239
1240    /**
1241     * Appends NEWARRAY for primitive types.
1242     *
1243     * @param atype     <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
1244     * @see Opcode
1245     */
1246    public void addNewarray(int atype, int length) {
1247        addIconst(length);
1248        addOpcode(NEWARRAY);
1249        add(atype);
1250    }
1251
1252    /**
1253     * Appends MULTINEWARRAY.
1254     *
1255     * @param clazz             the array type.
1256     * @param dimensions        the sizes of all dimensions.
1257     * @return          the length of <code>dimensions</code>.
1258     */
1259    public int addMultiNewarray(CtClass clazz, int[] dimensions) {
1260        int len = dimensions.length;
1261        for (int i = 0; i < len; ++i)
1262            addIconst(dimensions[i]);
1263
1264        growStack(len);
1265        return addMultiNewarray(clazz, len);
1266    }
1267
1268    /**
1269     * Appends MULTINEWARRAY.  The size of every dimension must have been
1270     * already pushed on the stack.
1271     *
1272     * @param clazz             the array type.
1273     * @param dim               the number of the dimensions.
1274     * @return                  the value of <code>dim</code>.
1275     */
1276    public int addMultiNewarray(CtClass clazz, int dim) {
1277        add(MULTIANEWARRAY);
1278        addIndex(constPool.addClassInfo(clazz));
1279        add(dim);
1280        growStack(1 - dim);
1281        return dim;
1282    }
1283
1284    /**
1285     * Appends MULTINEWARRAY.
1286     *
1287     * @param desc      the type descriptor of the created array.
1288     * @param dim       dimensions.
1289     * @return          the value of <code>dim</code>.
1290     */
1291    public int addMultiNewarray(String desc, int dim) {
1292        add(MULTIANEWARRAY);
1293        addIndex(constPool.addClassInfo(desc));
1294        add(dim);
1295        growStack(1 - dim);
1296        return dim;
1297    }
1298
1299    /**
1300     * Appends PUTFIELD.
1301     *
1302     * @param c         the target class.
1303     * @param name      the field name.
1304     * @param desc      the descriptor of the field type.
1305     */
1306    public void addPutfield(CtClass c, String name, String desc) {
1307        addPutfield0(c, null, name, desc);
1308    }
1309
1310    /**
1311     * Appends PUTFIELD.
1312     *
1313     * @param classname         the fully-qualified name of the target class.
1314     * @param name      the field name.
1315     * @param desc      the descriptor of the field type.
1316     */
1317    public void addPutfield(String classname, String name, String desc) {
1318        // if classnaem is null, the target class is THIS.
1319        addPutfield0(null, classname, name, desc);
1320    }
1321
1322    private void addPutfield0(CtClass target, String classname,
1323                              String name, String desc) {
1324        add(PUTFIELD);
1325        // target is null if it represents THIS.
1326        int ci = classname == null ? constPool.addClassInfo(target)
1327                                   : constPool.addClassInfo(classname);
1328        addIndex(constPool.addFieldrefInfo(ci, name, desc));
1329        growStack(-1 - Descriptor.dataSize(desc));
1330    }
1331
1332    /**
1333     * Appends PUTSTATIC.
1334     *
1335     * @param c         the target class.
1336     * @param name      the field name.
1337     * @param desc      the descriptor of the field type.
1338     */
1339    public void addPutstatic(CtClass c, String name, String desc) {
1340        addPutstatic0(c, null, name, desc);
1341    }
1342
1343    /**
1344     * Appends PUTSTATIC.
1345     *
1346     * @param classname         the fully-qualified name of the target class.
1347     * @param fieldName         the field name.
1348     * @param desc              the descriptor of the field type.
1349     */
1350    public void addPutstatic(String classname, String fieldName, String desc) {
1351        // if classname is null, the target class is THIS.
1352        addPutstatic0(null, classname, fieldName, desc);
1353    }
1354
1355    private void addPutstatic0(CtClass target, String classname,
1356                               String fieldName, String desc) {
1357        add(PUTSTATIC);
1358        // target is null if it represents THIS.
1359        int ci = classname == null ? constPool.addClassInfo(target)
1360                                : constPool.addClassInfo(classname);
1361        addIndex(constPool.addFieldrefInfo(ci, fieldName, desc));
1362        growStack(-Descriptor.dataSize(desc));
1363    }
1364
1365    /**
1366     * Appends ARETURN, IRETURN, .., or RETURN.
1367     *
1368     * @param type      the return type.
1369     */
1370    public void addReturn(CtClass type) {
1371        if (type == null)
1372            addOpcode(RETURN);
1373        else if (type.isPrimitive()) {
1374            CtPrimitiveType ptype = (CtPrimitiveType)type;
1375            addOpcode(ptype.getReturnOp());
1376        }
1377        else
1378            addOpcode(ARETURN);
1379    }
1380
1381    /**
1382     * Appends RET.
1383     *
1384     * @param var       local variable
1385     */
1386    public void addRet(int var) {
1387        if (var < 0x100) {
1388            addOpcode(RET);
1389            add(var);
1390        }
1391        else {
1392            addOpcode(WIDE);
1393            addOpcode(RET);
1394            addIndex(var);
1395        }
1396    }
1397
1398    /**
1399     * Appends instructions for executing
1400     * <code>java.lang.System.println(<i>message</i>)</code>.
1401     *
1402     * @param message           printed message.
1403     */
1404    public void addPrintln(String message) {
1405        addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
1406        addLdc(message);
1407        addInvokevirtual("java.io.PrintStream",
1408                         "println", "(Ljava/lang/String;)V");
1409    }
1410}
1411