KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > cglib > core > CodeEmitter


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  * if any, must include the following acknowledgment:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowledgment may appear in the software itself,
24  * if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  * not be used to endorse or promote products derived from this
28  * software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  * nor may "Apache" appear in their name, without prior written
33  * permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation. For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  */

54 package org.logicalcobwebs.cglib.core;
55
56 import java.io.*;
57 import java.lang.reflect.Method JavaDoc;
58 import java.util.*;
59 import org.logicalcobwebs.asm.*;
60
61 /**
62  * @author Juozas Baliuka, Chris Nokleberg
63  */

64 public class CodeEmitter extends RemappingCodeVisitor {
65     private static final Signature BOOLEAN_VALUE =
66       TypeUtils.parseSignature("boolean booleanValue()");
67     private static final Signature CHAR_VALUE =
68       TypeUtils.parseSignature("char charValue()");
69     private static final Signature LONG_VALUE =
70       TypeUtils.parseSignature("long longValue()");
71     private static final Signature DOUBLE_VALUE =
72       TypeUtils.parseSignature("double doubleValue()");
73     private static final Signature FLOAT_VALUE =
74       TypeUtils.parseSignature("float floatValue()");
75     private static final Signature INT_VALUE =
76       TypeUtils.parseSignature("int intValue()");
77     private static final Signature CSTRUCT_NULL =
78       TypeUtils.parseConstructor("");
79     private static final Signature CSTRUCT_STRING =
80       TypeUtils.parseConstructor("String");
81
82     public static final int ADD = Constants.IADD;
83     public static final int MUL = Constants.IMUL;
84     public static final int XOR = Constants.IXOR;
85     public static final int USHR = Constants.IUSHR;
86     public static final int SUB = Constants.ISUB;
87     public static final int DIV = Constants.IDIV;
88     public static final int NEG = Constants.INEG;
89     public static final int REM = Constants.IREM;
90     public static final int AND = Constants.IAND;
91     public static final int OR = Constants.IOR;
92
93     public static final int GT = Constants.IFGT;
94     public static final int LT = Constants.IFLT;
95     public static final int GE = Constants.IFGE;
96     public static final int LE = Constants.IFLE;
97     public static final int NE = Constants.IFNE;
98     public static final int EQ = Constants.IFEQ;
99
100     private ClassEmitter ce;
101     private State state;
102
103     private static class State {
104         int access;
105         Signature sig;
106         Type[] argumentTypes;
107         int localOffset;
108         Type[] exceptionTypes;
109
110         State(int access, Signature sig, Type[] exceptionTypes) {
111             this.access = access;
112             this.sig = sig;
113             this.exceptionTypes = exceptionTypes;
114             localOffset = TypeUtils.isStatic(access) ? 0 : 1;
115             argumentTypes = sig.getArgumentTypes();
116         }
117     }
118
119     CodeEmitter(ClassEmitter ce, CodeVisitor cv, int access, Signature sig, Type[] exceptionTypes) {
120         super(cv, access, sig.getArgumentTypes());
121         this.ce = ce;
122         state = new State(access, sig, exceptionTypes);
123     }
124
125     public CodeEmitter(CodeEmitter wrap) {
126         super(wrap);
127         this.ce = wrap.ce;
128         this.state = wrap.state;
129     }
130
131     public boolean isStaticHook() {
132         return false;
133     }
134
135     public Signature getSignature() {
136         return state.sig;
137     }
138
139     public Type getReturnType() {
140         return state.sig.getReturnType();
141     }
142
143     /* wait until these are needed
144     public Type[] getArgumentTypes() {
145         return state.argumentTypes;
146     }
147
148     public Type[] getExceptionTypes() {
149         return state.getExceptionTypes();
150     }
151     */

152
153     public ClassEmitter getClassEmitter() {
154         return ce;
155     }
156
157     public void end_method() {
158         visitMaxs(0, 0);
159     }
160
161     public Block begin_block() {
162         return new Block(this);
163     }
164
165     public void catch_exception(Block block, Type exception) {
166         if (block.getEnd() == null) {
167             throw new IllegalStateException JavaDoc("end of block is unset");
168         }
169         cv.visitTryCatchBlock(block.getStart(),
170                               block.getEnd(),
171                               mark(),
172                               exception.getInternalName());
173     }
174
175     public void goTo(Label label) { cv.visitJumpInsn(Constants.GOTO, label); }
176     public void ifnull(Label label) { cv.visitJumpInsn(Constants.IFNULL, label); }
177     public void ifnonnull(Label label) { cv.visitJumpInsn(Constants.IFNONNULL, label); }
178
179     public void if_jump(int mode, Label label) {
180         cv.visitJumpInsn(mode, label);
181     }
182
183     public void if_icmp(int mode, Label label) {
184         if_cmp(Type.INT_TYPE, mode, label);
185     }
186
187     public void if_cmp(Type type, int mode, Label label) {
188         int intOp = -1;
189         int jumpmode = mode;
190         switch (mode) {
191         case GE: jumpmode = LT; break;
192         case LE: jumpmode = GT; break;
193         }
194         switch (type.getSort()) {
195         case Type.LONG:
196             cv.visitInsn(Constants.LCMP);
197             break;
198         case Type.DOUBLE:
199             cv.visitInsn(Constants.DCMPG);
200             break;
201         case Type.FLOAT:
202             cv.visitInsn(Constants.FCMPG);
203             break;
204         case Type.ARRAY:
205         case Type.OBJECT:
206             switch (mode) {
207             case EQ:
208                 cv.visitJumpInsn(Constants.IF_ACMPEQ, label);
209                 return;
210             case NE:
211                 cv.visitJumpInsn(Constants.IF_ACMPNE, label);
212                 return;
213             }
214             throw new IllegalArgumentException JavaDoc("Bad comparison for type " + type);
215         default:
216             switch (mode) {
217             case EQ: intOp = Constants.IF_ICMPEQ; break;
218             case NE: intOp = Constants.IF_ICMPNE; break;
219             case GE: swap(); /* fall through */
220             case LT: intOp = Constants.IF_ICMPLT; break;
221             case LE: swap(); /* fall through */
222             case GT: intOp = Constants.IF_ICMPGT; break;
223             }
224             cv.visitJumpInsn(intOp, label);
225             return;
226         }
227         if_jump(jumpmode, label);
228     }
229
230     public void pop() { cv.visitInsn(Constants.POP); }
231     public void pop2() { cv.visitInsn(Constants.POP2); }
232     public void dup() { cv.visitInsn(Constants.DUP); }
233     public void dup2() { cv.visitInsn(Constants.DUP2); }
234     public void dup_x1() { cv.visitInsn(Constants.DUP_X1); }
235     public void dup_x2() { cv.visitInsn(Constants.DUP_X2); }
236     public void dup2_x1() { cv.visitInsn(Constants.DUP2_X1); }
237     public void dup2_x2() { cv.visitInsn(Constants.DUP2_X2); }
238     public void swap() { cv.visitInsn(Constants.SWAP); }
239     public void aconst_null() { cv.visitInsn(Constants.ACONST_NULL); }
240
241     public void swap(Type prev, Type type) {
242         if (type.getSize() == 1) {
243             if (prev.getSize() == 1) {
244                 swap(); // same as dup_x1(), pop();
245
} else {
246                 dup_x2();
247                 pop();
248             }
249         } else {
250             if (prev.getSize() == 1) {
251                 dup2_x1();
252                 pop2();
253             } else {
254                 dup2_x2();
255                 pop2();
256             }
257         }
258     }
259
260     public void monitorenter() { cv.visitInsn(Constants.MONITORENTER); }
261     public void monitorexit() { cv.visitInsn(Constants.MONITOREXIT); }
262
263     public void math(int op, Type type) { cv.visitInsn(type.getOpcode(op)); }
264
265     public void array_load(Type type) { cv.visitInsn(type.getOpcode(Constants.IALOAD)); }
266     public void array_store(Type type) { cv.visitInsn(type.getOpcode(Constants.IASTORE)); }
267
268     /**
269      * Casts from one primitive numeric type to another
270      */

271     public void cast_numeric(Type from, Type to) {
272         if (from != to) {
273             if (from == Type.DOUBLE_TYPE) {
274                 if (to == Type.FLOAT_TYPE) {
275                     cv.visitInsn(Constants.D2F);
276                 } else if (to == Type.LONG_TYPE) {
277                     cv.visitInsn(Constants.D2L);
278                 } else {
279                     cv.visitInsn(Constants.D2I);
280                     cast_numeric(Type.INT_TYPE, to);
281                 }
282             } else if (from == Type.FLOAT_TYPE) {
283                 if (to == Type.DOUBLE_TYPE) {
284                     cv.visitInsn(Constants.F2D);
285                 } else if (to == Type.LONG_TYPE) {
286                     cv.visitInsn(Constants.F2L);
287                 } else {
288                     cv.visitInsn(Constants.F2I);
289                     cast_numeric(Type.INT_TYPE, to);
290                 }
291             } else if (from == Type.LONG_TYPE) {
292                 if (to == Type.DOUBLE_TYPE) {
293                     cv.visitInsn(Constants.L2D);
294                 } else if (to == Type.FLOAT_TYPE) {
295                     cv.visitInsn(Constants.L2F);
296                 } else {
297                     cv.visitInsn(Constants.L2I);
298                     cast_numeric(Type.INT_TYPE, to);
299                 }
300             } else {
301                 if (to == Type.BYTE_TYPE) {
302                     cv.visitInsn(Constants.I2B);
303                 } else if (to == Type.CHAR_TYPE) {
304                     cv.visitInsn(Constants.I2C);
305                 } else if (to == Type.DOUBLE_TYPE) {
306                     cv.visitInsn(Constants.I2D);
307                 } else if (to == Type.FLOAT_TYPE) {
308                     cv.visitInsn(Constants.I2F);
309                 } else if (to == Type.LONG_TYPE) {
310                     cv.visitInsn(Constants.I2L);
311                 } else if (to == Type.SHORT_TYPE) {
312                     cv.visitInsn(Constants.I2S);
313                 }
314             }
315         }
316     }
317
318     public void push(int i) {
319         if (i < -1) {
320             cv.visitLdcInsn(new Integer JavaDoc(i));
321         } else if (i <= 5) {
322             cv.visitInsn(TypeUtils.ICONST(i));
323         } else if (i <= Byte.MAX_VALUE) {
324             cv.visitIntInsn(Constants.BIPUSH, i);
325         } else if (i <= Short.MAX_VALUE) {
326             cv.visitIntInsn(Constants.SIPUSH, i);
327         } else {
328             cv.visitLdcInsn(new Integer JavaDoc(i));
329         }
330     }
331     
332     public void push(long value) {
333         if (value == 0L || value == 1L) {
334             cv.visitInsn(TypeUtils.LCONST(value));
335         } else {
336             cv.visitLdcInsn(new Long JavaDoc(value));
337         }
338     }
339     
340     public void push(float value) {
341         if (value == 0f || value == 1f || value == 2f) {
342             cv.visitInsn(TypeUtils.FCONST(value));
343         } else {
344             cv.visitLdcInsn(new Float JavaDoc(value));
345         }
346     }
347     public void push(double value) {
348         if (value == 0d || value == 1d) {
349             cv.visitInsn(TypeUtils.DCONST(value));
350         } else {
351             cv.visitLdcInsn(new Double JavaDoc(value));
352         }
353     }
354     
355     public void push(String JavaDoc value) {
356         cv.visitLdcInsn(value);
357     }
358
359     public void newarray() {
360         newarray(Constants.TYPE_OBJECT);
361     }
362
363     public void newarray(Type type) {
364         if (TypeUtils.isPrimitive(type)) {
365             cv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type));
366         } else {
367             emit_type(Constants.ANEWARRAY, type);
368         }
369     }
370     
371     public void arraylength() {
372         cv.visitInsn(Constants.ARRAYLENGTH);
373     }
374     
375     public void load_this() {
376         if (TypeUtils.isStatic(state.access)) {
377             throw new IllegalStateException JavaDoc("no 'this' pointer within static method");
378         }
379         cv.visitVarInsn(Constants.ALOAD, 0);
380     }
381     
382     /**
383      * Pushes all of the arguments of the current method onto the stack.
384      */

385     public void load_args() {
386         load_args(0, state.argumentTypes.length);
387     }
388
389     /**
390      * Pushes the specified argument of the current method onto the stack.
391      * @param index the zero-based index into the argument list
392      */

393     public void load_arg(int index) {
394         load_local(state.argumentTypes[index],
395                    state.localOffset + skipArgs(index));
396     }
397
398     // zero-based (see load_this)
399
public void load_args(int fromArg, int count) {
400         int pos = state.localOffset + skipArgs(fromArg);
401         for (int i = 0; i < count; i++) {
402             Type t = state.argumentTypes[fromArg + i];
403             load_local(t, pos);
404             pos += t.getSize();
405         }
406     }
407     
408     private int skipArgs(int numArgs) {
409         int amount = 0;
410         for (int i = 0; i < numArgs; i++) {
411             amount += state.argumentTypes[i].getSize();
412         }
413         return amount;
414     }
415
416     private void load_local(Type t, int pos) {
417         // TODO: make t == null ok?
418
cv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos);
419     }
420
421     private void store_local(Type t, int pos) {
422         // TODO: make t == null ok?
423
cv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos);
424     }
425     
426     public void iinc(Local local, int amount) {
427         cv.visitIincInsn(local.getIndex(), amount);
428     }
429     
430     public void store_local(Local local) {
431         store_local(local.getType(), local.getIndex());
432     }
433     
434     public void load_local(Local local) {
435         load_local(local.getType(), local.getIndex());
436     }
437
438     public void return_value() {
439         cv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN));
440     }
441
442     public void getfield(String JavaDoc name) {
443         ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
444         int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD;
445         emit_field(opcode, ce.getClassType(), name, info.type);
446     }
447     
448     public void putfield(String JavaDoc name) {
449         ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
450         int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD;
451         emit_field(opcode, ce.getClassType(), name, info.type);
452     }
453
454     public void super_getfield(String JavaDoc name, Type type) {
455         emit_field(Constants.GETFIELD, ce.getSuperType(), name, type);
456     }
457     
458     public void super_putfield(String JavaDoc name, Type type) {
459         emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type);
460     }
461
462     public void super_getstatic(String JavaDoc name, Type type) {
463         emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type);
464     }
465     
466     public void super_putstatic(String JavaDoc name, Type type) {
467         emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type);
468     }
469
470     public void getfield(Type owner, String JavaDoc name, Type type) {
471         emit_field(Constants.GETFIELD, owner, name, type);
472     }
473     
474     public void putfield(Type owner, String JavaDoc name, Type type) {
475         emit_field(Constants.PUTFIELD, owner, name, type);
476     }
477
478     public void getstatic(Type owner, String JavaDoc name, Type type) {
479         emit_field(Constants.GETSTATIC, owner, name, type);
480     }
481     
482     public void putstatic(Type owner, String JavaDoc name, Type type) {
483         emit_field(Constants.PUTSTATIC, owner, name, type);
484     }
485
486     // package-protected for EmitUtils, try to fix
487
void emit_field(int opcode, Type ctype, String JavaDoc name, Type ftype) {
488         cv.visitFieldInsn(opcode,
489                           ctype.getInternalName(),
490                           name,
491                           ftype.getDescriptor());
492     }
493
494     public void super_invoke() {
495         super_invoke(state.sig);
496     }
497
498     public void super_invoke(Signature sig) {
499         emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig);
500     }
501
502     public void invoke_constructor(Type type) {
503         invoke_constructor(type, CSTRUCT_NULL);
504     }
505
506     public void super_invoke_constructor() {
507         invoke_constructor(ce.getSuperType());
508     }
509     
510     public void invoke_constructor_this() {
511         invoke_constructor(ce.getClassType());
512     }
513
514     private void emit_invoke(int opcode, Type type, Signature sig) {
515         if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) &&
516             ((opcode == Constants.INVOKEVIRTUAL) ||
517              (opcode == Constants.INVOKESTATIC))) {
518             // TODO: error
519
}
520         cv.visitMethodInsn(opcode,
521                            type.getInternalName(),
522                            sig.getName(),
523                            sig.getDescriptor());
524     }
525     
526     public void invoke_interface(Type owner, Signature sig) {
527         emit_invoke(Constants.INVOKEINTERFACE, owner, sig);
528     }
529
530     public void invoke_virtual(Type owner, Signature sig) {
531         emit_invoke(Constants.INVOKEVIRTUAL, owner, sig);
532     }
533
534     public void invoke_static(Type owner, Signature sig) {
535         emit_invoke(Constants.INVOKESTATIC, owner, sig);
536     }
537
538     public void invoke_virtual_this(Signature sig) {
539         invoke_virtual(ce.getClassType(), sig);
540     }
541
542     public void invoke_static_this(Signature sig) {
543         invoke_static(ce.getClassType(), sig);
544     }
545
546     public void invoke_constructor(Type type, Signature sig) {
547         emit_invoke(Constants.INVOKESPECIAL, type, sig);
548     }
549
550     public void invoke_constructor_this(Signature sig) {
551         invoke_constructor(ce.getClassType(), sig);
552     }
553
554     public void super_invoke_constructor(Signature sig) {
555         invoke_constructor(ce.getSuperType(), sig);
556     }
557     
558     public void new_instance_this() {
559         new_instance(ce.getClassType());
560     }
561
562     public void new_instance(Type type) {
563         emit_type(Constants.NEW, type);
564     }
565
566     private void emit_type(int opcode, Type type) {
567         String JavaDoc desc;
568         if (TypeUtils.isArray(type)) {
569             desc = type.getDescriptor();
570         } else {
571             desc = type.getInternalName();
572         }
573         cv.visitTypeInsn(opcode, desc);
574     }
575
576     public void aaload(int index) {
577         push(index);
578         aaload();
579     }
580
581     public void aaload() { cv.visitInsn(Constants.AALOAD); }
582     public void aastore() { cv.visitInsn(Constants.AASTORE); }
583     public void athrow() { cv.visitInsn(Constants.ATHROW); }
584
585     public Label make_label() {
586         return new Label();
587     }
588     
589     public Local make_local() {
590         return make_local(Constants.TYPE_OBJECT);
591     }
592     
593     public Local make_local(Type type) {
594         return new Local(nextLocal(type.getSize()), type);
595     }
596
597     public void checkcast_this() {
598         checkcast(ce.getClassType());
599     }
600     
601     public void checkcast(Type type) {
602         if (!type.equals(Constants.TYPE_OBJECT)) {
603             emit_type(Constants.CHECKCAST, type);
604         }
605     }
606
607     public void instance_of(Type type) {
608         emit_type(Constants.INSTANCEOF, type);
609     }
610     
611     public void instance_of_this() {
612         instance_of(ce.getClassType());
613     }
614
615     public void process_switch(int[] keys, ProcessSwitchCallback callback) {
616         float density;
617         if (keys.length == 0) {
618             density = 0;
619         } else {
620             density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1);
621         }
622         process_switch(keys, callback, density >= 0.5f);
623     }
624
625     public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) {
626         if (!isSorted(keys))
627             throw new IllegalArgumentException JavaDoc("keys to switch must be sorted ascending");
628         Label def = make_label();
629         Label end = make_label();
630
631         try {
632             if (keys.length > 0) {
633                 int len = keys.length;
634                 int min = keys[0];
635                 int max = keys[len - 1];
636                 int range = max - min + 1;
637
638                 if (useTable) {
639                     Label[] labels = new Label[range];
640                     Arrays.fill(labels, def);
641                     for (int i = 0; i < len; i++) {
642                         labels[keys[i] - min] = make_label();
643                     }
644                     cv.visitTableSwitchInsn(min, max, def, labels);
645                     for (int i = 0; i < range; i++) {
646                         Label label = labels[i];
647                         if (label != def) {
648                             mark(label);
649                             callback.processCase(i + min, end);
650                         }
651                     }
652                 } else {
653                     Label[] labels = new Label[len];
654                     for (int i = 0; i < len; i++) {
655                         labels[i] = make_label();
656                     }
657                     cv.visitLookupSwitchInsn(def, keys, labels);
658                     for (int i = 0; i < len; i++) {
659                         mark(labels[i]);
660                         callback.processCase(keys[i], end);
661                     }
662                 }
663             }
664
665             mark(def);
666             callback.processDefault();
667             mark(end);
668
669         } catch (RuntimeException JavaDoc e) {
670             throw e;
671         } catch (Error JavaDoc e) {
672             throw e;
673         } catch (Exception JavaDoc e) {
674             throw new CodeGenerationException(e);
675         }
676     }
677
678     private static boolean isSorted(int[] keys) {
679         for (int i = 1; i < keys.length; i++) {
680             if (keys[i] < keys[i - 1])
681                 return false;
682         }
683         return true;
684     }
685
686     public void mark(Label label) {
687         cv.visitLabel(label);
688     }
689
690     Label mark() {
691         Label label = make_label();
692         cv.visitLabel(label);
693         return label;
694     }
695
696     public void push(boolean value) {
697         push(value ? 1 : 0);
698     }
699
700     /**
701      * Toggles the integer on the top of the stack from 1 to 0 or vice versa
702      */

703     public void not() {
704         push(1);
705         math(XOR, Type.INT_TYPE);
706     }
707
708     public void throw_exception(Type type, String JavaDoc msg) {
709         new_instance(type);
710         dup();
711         push(msg);
712         invoke_constructor(type, CSTRUCT_STRING);
713         athrow();
714     }
715
716     /**
717      * If the argument is a primitive class, replaces the primitive value
718      * on the top of the stack with the wrapped (Object) equivalent. For
719      * example, char -> Character.
720      * If the class is Void, a null is pushed onto the stack instead.
721      * @param type the class indicating the current type of the top stack value
722      */

723     public void box(Type type) {
724         if (TypeUtils.isPrimitive(type)) {
725             if (type == Type.VOID_TYPE) {
726                 aconst_null();
727             } else {
728                 Type boxed = TypeUtils.getBoxedType(type);
729                 new_instance(boxed);
730                 if (type.getSize() == 2) {
731                     // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
732
dup_x2();
733                     dup_x2();
734                     pop();
735                 } else {
736                     // p -> po -> opo -> oop -> o
737
dup_x1();
738                     swap();
739                 }
740                 invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type }));
741             }
742         }
743     }
744     
745     /**
746      * If the argument is a primitive class, replaces the object
747      * on the top of the stack with the unwrapped (primitive)
748      * equivalent. For example, Character -> char.
749      * @param type the class indicating the desired type of the top stack value
750      * @return true if the value was unboxed
751      */

752     public void unbox(Type type) {
753         Type t = Constants.TYPE_NUMBER;
754         Signature sig = null;
755         switch (type.getSort()) {
756         case Type.VOID:
757             return;
758         case Type.CHAR:
759             t = Constants.TYPE_CHARACTER;
760             sig = CHAR_VALUE;
761             break;
762         case Type.BOOLEAN:
763             t = Constants.TYPE_BOOLEAN;
764             sig = BOOLEAN_VALUE;
765             break;
766         case Type.DOUBLE:
767             sig = DOUBLE_VALUE;
768             break;
769         case Type.FLOAT:
770             sig = FLOAT_VALUE;
771             break;
772         case Type.LONG:
773             sig = LONG_VALUE;
774             break;
775         case Type.INT:
776         case Type.SHORT:
777         case Type.BYTE:
778             sig = INT_VALUE;
779         }
780
781         if (sig == null) {
782             checkcast(type);
783         } else {
784             checkcast(t);
785             invoke_virtual(t, sig);
786         }
787     }
788
789     /**
790      * Allocates and fills an Object[] array with the arguments to the
791      * current method. Primitive values are inserted as their boxed
792      * (Object) equivalents.
793      */

794     public void create_arg_array() {
795         /* generates:
796            Object[] args = new Object[]{ arg1, new Integer(arg2) };
797          */

798
799         push(state.argumentTypes.length);
800         newarray();
801         for (int i = 0; i < state.argumentTypes.length; i++) {
802             dup();
803             push(i);
804             load_arg(i);
805             box(state.argumentTypes[i]);
806             aastore();
807         }
808     }
809
810
811     /**
812      * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise.
813      */

814     public void zero_or_null(Type type) {
815         if (TypeUtils.isPrimitive(type)) {
816             switch (type.getSort()) {
817             case Type.DOUBLE:
818                 push(0d);
819                 break;
820             case Type.LONG:
821                 push(0L);
822                 break;
823             case Type.FLOAT:
824                 push(0f);
825                 break;
826             case Type.VOID:
827                 aconst_null();
828             default:
829                 push(0);
830             }
831         } else {
832             aconst_null();
833         }
834     }
835
836     /**
837      * Unboxes the object on the top of the stack. If the object is null, the
838      * unboxed primitive value becomes zero.
839      */

840     public void unbox_or_zero(Type type) {
841         if (TypeUtils.isPrimitive(type)) {
842             if (type != Type.VOID_TYPE) {
843                 Label nonNull = make_label();
844                 Label end = make_label();
845                 dup();
846                 ifnonnull(nonNull);
847                 pop();
848                 zero_or_null(type);
849                 goTo(end);
850                 mark(nonNull);
851                 unbox(type);
852                 mark(end);
853             }
854         } else {
855             checkcast(type);
856         }
857     }
858
859     public void visitMaxs(int maxStack, int maxLocals) {
860         if (!TypeUtils.isAbstract(state.access)) {
861             cv.visitMaxs(0, 0);
862         }
863     }
864
865     public void invoke(Method JavaDoc method) {
866         Class JavaDoc declaring = method.getDeclaringClass();
867         Type owner = Type.getType(declaring);
868         Signature sig = TypeUtils.getSignature(method);
869         if (declaring.isInterface()) {
870             invoke_interface(owner, sig);
871         } else if (TypeUtils.isStatic(method.getModifiers())) {
872             invoke_static(owner, sig);
873         } else {
874             invoke_virtual(owner, sig);
875         }
876     }
877
878     public void define_attribute(Attribute attrs) {
879         cv.visitAttribute(attrs);
880     }
881 }
882
Popular Tags