KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > asm > commons > GASMifierMethodVisitor


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000-2005 INRIA, France Telecom
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the copyright holders nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28  * THE POSSIBILITY OF SUCH DAMAGE.
29  */

30 package org.objectweb.asm.commons;
31
32 import org.objectweb.asm.AnnotationVisitor;
33 import org.objectweb.asm.MethodVisitor;
34 import org.objectweb.asm.Label;
35 import org.objectweb.asm.Opcodes;
36 import org.objectweb.asm.Type;
37 import org.objectweb.asm.util.ASMifierAbstractVisitor;
38 import org.objectweb.asm.util.ASMifierAnnotationVisitor;
39
40 import java.util.ArrayList JavaDoc;
41 import java.util.HashMap JavaDoc;
42 import java.util.List JavaDoc;
43 import java.util.Map JavaDoc;
44
45 /**
46  * A {@link MethodVisitor} that prints the ASM code that generates the methods
47  * it visits.
48  *
49  * @author Eric Bruneton
50  * @author Eugene Kuleshov
51  */

52 public class GASMifierMethodVisitor extends ASMifierAbstractVisitor implements
53         MethodVisitor,
54         Opcodes
55 {
56
57     int access;
58
59     Type[] argumentTypes;
60
61     int firstLocal;
62
63     Map JavaDoc locals;
64
65     List JavaDoc localTypes;
66
67     int lastOpcode = -1;
68
69     HashMap JavaDoc labelNames;
70
71     public GASMifierMethodVisitor(int access, String JavaDoc desc) {
72         super("mg");
73         this.access = access;
74         this.labelNames = new HashMap JavaDoc();
75         this.argumentTypes = Type.getArgumentTypes(desc);
76         int nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
77         for (int i = 0; i < argumentTypes.length; i++) {
78             nextLocal += argumentTypes[i].getSize();
79         }
80         this.firstLocal = nextLocal;
81         this.locals = new HashMap JavaDoc();
82         this.localTypes = new ArrayList JavaDoc();
83     }
84
85     public AnnotationVisitor visitAnnotationDefault() {
86         buf.setLength(0);
87         buf.append("{\n").append("av0 = mg.visitAnnotationDefault();\n");
88         text.add(buf.toString());
89         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
90         text.add(av.getText());
91         text.add("}\n");
92         return av;
93     }
94
95     public AnnotationVisitor visitParameterAnnotation(
96         final int parameter,
97         final String JavaDoc desc,
98         final boolean visible)
99     {
100         buf.setLength(0);
101         buf.append("{\n")
102                 .append("av0 = mg.visitParameterAnnotation(")
103                 .append(parameter)
104                 .append(", \"");
105         buf.append(desc);
106         buf.append("\", ").append(visible).append(");\n");
107         text.add(buf.toString());
108         ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
109         text.add(av.getText());
110         text.add("}\n");
111         return av;
112     }
113
114     public void visitCode() {
115         /* text.add("mg.visitCode();\n"); */
116     }
117
118     public void visitInsn(final int opcode) {
119         buf.setLength(0);
120         switch (opcode) {
121             case IRETURN:
122             case LRETURN:
123             case FRETURN:
124             case DRETURN:
125             case ARETURN:
126             case RETURN:
127                 buf.append("mg.returnValue();\n");
128                 break;
129             case NOP:
130                 break;
131             case ACONST_NULL:
132                 buf.append("mg.push((String)null);\n");
133                 break;
134             case ICONST_M1:
135             case ICONST_0:
136             case ICONST_1:
137             case ICONST_2:
138             case ICONST_3:
139             case ICONST_4:
140             case ICONST_5:
141                 buf.append("mg.push(").append(opcode - ICONST_0).append(");\n");
142                 break;
143             case LCONST_0:
144             case LCONST_1:
145                 buf.append("mg.push(")
146                         .append(opcode - LCONST_0)
147                         .append("L);\n");
148                 break;
149             case FCONST_0:
150             case FCONST_1:
151             case FCONST_2:
152                 buf.append("mg.push(")
153                         .append(opcode - FCONST_0)
154                         .append("f);\n");
155                 break;
156             case DCONST_0:
157             case DCONST_1:
158                 buf.append("mg.push(")
159                         .append(opcode - DCONST_0)
160                         .append("d);\n");
161                 break;
162             case POP:
163                 buf.append("mg.pop();\n");
164                 break;
165             case POP2:
166                 buf.append("mg.pop2();\n");
167                 break;
168             case DUP:
169                 buf.append("mg.dup();\n");
170                 break;
171             case DUP_X1:
172                 buf.append("mg.dupX1();\n");
173                 break;
174             case DUP_X2:
175                 buf.append("mg.dupX2();\n");
176                 break;
177             case DUP2:
178                 buf.append("mg.dup2();\n");
179                 break;
180             case DUP2_X1:
181                 buf.append("mg.dup2X1();\n");
182                 break;
183             case DUP2_X2:
184                 buf.append("mg.dup2X2();\n");
185                 break;
186             case SWAP:
187                 buf.append("mg.swap();\n");
188                 break;
189             case MONITORENTER:
190                 buf.append("mg.monitorEnter();\n");
191                 break;
192             case MONITOREXIT:
193                 buf.append("mg.monitorExit();\n");
194                 break;
195             case ARRAYLENGTH:
196                 buf.append("mg.arrayLength();\n");
197                 break;
198             case IALOAD:
199                 buf.append("mg.arrayLoad(Type.INT_TYPE);\n");
200                 break;
201             case LALOAD:
202                 buf.append("mg.arrayLoad(Type.LONG_TYPE);\n");
203                 break;
204             case FALOAD:
205                 buf.append("mg.arrayLoad(Type.FLOAT_TYPE);\n");
206                 break;
207             case DALOAD:
208                 buf.append("mg.arrayLoad(Type.DOUBLE_TYPE);\n");
209                 break;
210             case AALOAD:
211                 buf.append("mg.arrayLoad(" + getType("java/lang/Object")
212                         + ");\n");
213                 break;
214             case BALOAD:
215                 buf.append("mg.arrayLoad(Type.BYTE_TYPE);\n");
216                 break;
217             case CALOAD:
218                 buf.append("mg.arrayLoad(Type.CHAR_TYPE);\n");
219                 break;
220             case SALOAD:
221                 buf.append("mg.arrayLoad(Type.SHORT_TYPE);\n");
222                 break;
223             case IASTORE:
224                 buf.append("mg.arrayStore(Type.INT_TYPE);\n");
225                 break;
226             case LASTORE:
227                 buf.append("mg.arrayStore(Type.LONG_TYPE);\n");
228                 break;
229             case FASTORE:
230                 buf.append("mg.arrayStore(Type.FLOAT_TYPE);\n");
231                 break;
232             case DASTORE:
233                 buf.append("mg.arrayStore(Type.DOUBLE_TYPE);\n");
234                 break;
235             case AASTORE:
236                 buf.append("mg.arrayStore(" + getType("java/lang/Object")
237                         + ");\n");
238                 break;
239             case BASTORE:
240                 buf.append("mg.arrayStore(Type.BYTE_TYPE);\n");
241                 break;
242             case CASTORE:
243                 buf.append("mg.arrayStore(Type.CHAR_TYPE);\n");
244                 break;
245             case SASTORE:
246                 buf.append("mg.arrayStore(Type.SHORT_TYPE);\n");
247                 break;
248             case IADD:
249                 buf.append("mg.math(GeneratorAdapter.ADD, Type.INT_TYPE);\n");
250                 break;
251             case LADD:
252                 buf.append("mg.math(GeneratorAdapter.ADD, Type.LONG_TYPE);\n");
253                 break;
254             case FADD:
255                 buf.append("mg.math(GeneratorAdapter.ADD, Type.FLOAT_TYPE);\n");
256                 break;
257             case DADD:
258                 buf.append("mg.math(GeneratorAdapter.ADD, Type.DOUBLE_TYPE);\n");
259                 break;
260             case ISUB:
261                 buf.append("mg.math(GeneratorAdapter.SUB, Type.INT_TYPE);\n");
262                 break;
263             case LSUB:
264                 buf.append("mg.math(GeneratorAdapter.SUB, Type.LONG_TYPE);\n");
265                 break;
266             case FSUB:
267                 buf.append("mg.math(GeneratorAdapter.SUB, Type.FLOAT_TYPE);\n");
268                 break;
269             case DSUB:
270                 buf.append("mg.math(GeneratorAdapter.SUB, Type.DOUBLE_TYPE);\n");
271                 break;
272             case IMUL:
273                 buf.append("mg.math(GeneratorAdapter.MUL, Type.INT_TYPE);\n");
274                 break;
275             case LMUL:
276                 buf.append("mg.math(GeneratorAdapter.MUL, Type.LONG_TYPE);\n");
277                 break;
278             case FMUL:
279                 buf.append("mg.math(GeneratorAdapter.MUL, Type.FLOAT_TYPE);\n");
280                 break;
281             case DMUL:
282                 buf.append("mg.math(GeneratorAdapter.MUL, Type.DOUBLE_TYPE);\n");
283                 break;
284             case IDIV:
285                 buf.append("mg.math(GeneratorAdapter.DIV, Type.INT_TYPE);\n");
286                 break;
287             case LDIV:
288                 buf.append("mg.math(GeneratorAdapter.DIV, Type.LONG_TYPE);\n");
289                 break;
290             case FDIV:
291                 buf.append("mg.math(GeneratorAdapter.DIV, Type.FLOAT_TYPE);\n");
292                 break;
293             case DDIV:
294                 buf.append("mg.math(GeneratorAdapter.DIV, Type.DOUBLE_TYPE);\n");
295                 break;
296             case IREM:
297                 buf.append("mg.math(GeneratorAdapter.REM, Type.INT_TYPE);\n");
298                 break;
299             case LREM:
300                 buf.append("mg.math(GeneratorAdapter.REM, Type.LONG_TYPE);\n");
301                 break;
302             case FREM:
303                 buf.append("mg.math(GeneratorAdapter.REM, Type.FLOAT_TYPE);\n");
304                 break;
305             case DREM:
306                 buf.append("mg.math(GeneratorAdapter.REM, Type.DOUBLE_TYPE);\n");
307                 break;
308             case INEG:
309                 buf.append("mg.math(GeneratorAdapter.NEG, Type.INT_TYPE);\n");
310                 break;
311             case LNEG:
312                 buf.append("mg.math(GeneratorAdapter.NEG, Type.LONG_TYPE);\n");
313                 break;
314             case FNEG:
315                 buf.append("mg.math(GeneratorAdapter.NEG, Type.FLOAT_TYPE);\n");
316                 break;
317             case DNEG:
318                 buf.append("mg.math(GeneratorAdapter.NEG, Type.DOUBLE_TYPE);\n");
319                 break;
320             case ISHL:
321                 buf.append("mg.math(GeneratorAdapter.SHL, Type.INT_TYPE);\n");
322                 break;
323             case LSHL:
324                 buf.append("mg.math(GeneratorAdapter.SHL, Type.LONG_TYPE);\n");
325                 break;
326             case ISHR:
327                 buf.append("mg.math(GeneratorAdapter.SHR, Type.INT_TYPE);\n");
328                 break;
329             case LSHR:
330                 buf.append("mg.math(GeneratorAdapter.SHR, Type.LONG_TYPE);\n");
331                 break;
332             case IUSHR:
333                 buf.append("mg.math(GeneratorAdapter.USHR, Type.INT_TYPE);\n");
334                 break;
335             case LUSHR:
336                 buf.append("mg.math(GeneratorAdapter.USHR, Type.LONG_TYPE);\n");
337                 break;
338             case IAND:
339                 buf.append("mg.math(GeneratorAdapter.AND, Type.INT_TYPE);\n");
340                 break;
341             case LAND:
342                 buf.append("mg.math(GeneratorAdapter.AND, Type.LONG_TYPE);\n");
343                 break;
344             case IOR:
345                 buf.append("mg.math(GeneratorAdapter.OR, Type.INT_TYPE);\n");
346                 break;
347             case LOR:
348                 buf.append("mg.math(GeneratorAdapter.OR, Type.LONG_TYPE);\n");
349                 break;
350             case IXOR:
351                 buf.append("mg.math(GeneratorAdapter.XOR, Type.INT_TYPE);\n");
352                 break;
353             case LXOR:
354                 buf.append("mg.math(GeneratorAdapter.XOR, Type.LONG_TYPE);\n");
355                 break;
356             case ATHROW:
357                 buf.append("mg.throwException();\n");
358                 break;
359             case I2L:
360                 buf.append("mg.cast(Type.INT_TYPE, Type.LONG_TYPE);\n");
361                 break;
362             case I2F:
363                 buf.append("mg.cast(Type.INT_TYPE, Type.FLOAT_TYPE);\n");
364                 break;
365             case I2D:
366                 buf.append("mg.cast(Type.INT_TYPE, Type.DOUBLE_TYPE);\n");
367                 break;
368             case L2I:
369                 buf.append("mg.cast(Type.LONG_TYPE, Type.INT_TYPE);\n");
370                 break;
371             case L2F:
372                 buf.append("mg.cast(Type.LONG_TYPE, Type.FLOAT_TYPE);\n");
373                 break;
374             case L2D:
375                 buf.append("mg.cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);\n");
376                 break;
377             case F2I:
378                 buf.append("mg.cast(Type.FLOAT_TYPE, Type.INT_TYPE);\n");
379                 break;
380             case F2L:
381                 buf.append("mg.cast(Type.FLOAT_TYPE, Type.LONG_TYPE);\n");
382                 break;
383             case F2D:
384                 buf.append("mg.cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);\n");
385                 break;
386             case D2I:
387                 buf.append("mg.cast(Type.DOUBLE_TYPE, Type.INT_TYPE);\n");
388                 break;
389             case D2L:
390                 buf.append("mg.cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);\n");
391                 break;
392             case D2F:
393                 buf.append("mg.cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);\n");
394                 break;
395             case I2B:
396                 // TODO detect if previous element in 'text' is a cast,
397
// for possible optimisations (e.g. cast(F,I) cast(I,B) =
398
// cast(F,B))
399
buf.append("mg.cast(Type.INT_TYPE, Type.BYTE_TYPE);\n");
400                 break;
401             case I2C: // idem
402
buf.append("mg.cast(Type.INT_TYPE, Type.CHAR_TYPE);\n");
403                 break;
404             case I2S: // idem
405
buf.append("mg.cast(Type.INT_TYPE, Type.SHORT_TYPE);\n");
406                 break;
407             case LCMP:
408             case FCMPL:
409             case FCMPG:
410             case DCMPL:
411             case DCMPG:
412                 // TODO detect xCMPy IF_ICMP -> ifCmp(..., ..., label)
413
buf.append("mg.visitInsn(")
414                         .append(OPCODES[opcode])
415                         .append(");\n");
416                 break;
417             default:
418                 throw new RuntimeException JavaDoc("unexpected case");
419         }
420         text.add(buf.toString());
421         lastOpcode = opcode;
422     }
423
424     public void visitIntInsn(final int opcode, final int operand) {
425         buf.setLength(0);
426         if (opcode == NEWARRAY) {
427             String JavaDoc type;
428             switch (operand) {
429                 case T_BOOLEAN:
430                     type = "Type.BOOLEAN_TYPE";
431                     break;
432                 case T_CHAR:
433                     type = "Type.CHAR_TYPE";
434                     break;
435                 case T_FLOAT:
436                     type = "Type.FLOAT_TYPE";
437                     break;
438                 case T_DOUBLE:
439                     type = "Type.DOUBLE_TYPE";
440                     break;
441                 case T_BYTE:
442                     type = "Type.BYTE_TYPE";
443                     break;
444                 case T_SHORT:
445                     type = "Type.SHORT_TYPE";
446                     break;
447                 case T_INT:
448                     type = "Type.INT_TYPE";
449                     break;
450                 case T_LONG:
451                     type = "Type.LONG_TYPE";
452                     break;
453                 default:
454                     throw new RuntimeException JavaDoc("unexpected case");
455             }
456             buf.append("mg.newArray(").append(type).append(");\n");
457         } else {
458             buf.append("mg.push(").append(operand).append(");\n");
459         }
460         text.add(buf.toString());
461         lastOpcode = opcode;
462     }
463
464     public void visitVarInsn(final int opcode, int var) {
465         buf.setLength(0);
466         switch (opcode) {
467             case RET:
468                 buf.append("mg.ret(");
469                 if (var < firstLocal) {
470                     buf.append(var);
471                 } else {
472                     int v = generateNewLocal(var, "Type.INT_TYPE");
473                     buf.append("local").append(v);
474                 }
475                 buf.append(");\n");
476                 break;
477
478             case ILOAD:
479                 generateLoadLocal(var, "Type.INT_TYPE");
480                 break;
481             case LLOAD:
482                 generateLoadLocal(var, "Type.LONG_TYPE");
483                 break;
484             case FLOAD:
485                 generateLoadLocal(var, "Type.FLOAT_TYPE");
486                 break;
487             case DLOAD:
488                 generateLoadLocal(var, "Type.DOUBLE_TYPE");
489                 break;
490             case ALOAD:
491                 generateLoadLocal(var, getType("java/lang/Object"));
492                 break;
493
494             case ISTORE:
495                 generateStoreLocal(var, "Type.INT_TYPE");
496                 break;
497             case LSTORE:
498                 generateStoreLocal(var, "Type.LONG_TYPE");
499                 break;
500             case FSTORE:
501                 generateStoreLocal(var, "Type.FLOAT_TYPE");
502                 break;
503             case DSTORE:
504                 generateStoreLocal(var, "Type.DOUBLE_TYPE");
505                 break;
506             case ASTORE:
507                 generateStoreLocal(var, getType("java/lang/Object"));
508                 break;
509
510             default:
511                 throw new RuntimeException JavaDoc("unexpected case");
512         }
513
514         text.add(buf.toString());
515         lastOpcode = opcode;
516     }
517
518     private void generateLoadLocal(int var, String JavaDoc type) {
519         if (var < firstLocal) {
520             if (var == 0 && (access & ACC_STATIC) == 0) {
521                 buf.append("mg.loadThis();\n");
522             } else {
523                 buf.append("mg.loadArg(")
524                         .append(getArgIndex(var))
525                         .append(");\n");
526             }
527         } else {
528             int local = generateNewLocal(var, type);
529             buf.append("mg.loadLocal(local").append(local);
530             if (!type.equals(localTypes.get(local))) {
531                 localTypes.set(local, type);
532                 buf.append(", ").append(type);
533             }
534             buf.append(");\n");
535         }
536     }
537
538     private void generateStoreLocal(int var, String JavaDoc type) {
539         if (var < firstLocal) {
540             buf.append("mg.storeArg(").append(getArgIndex(var)).append(");\n");
541         } else {
542             int local = generateNewLocal(var, type);
543             buf.append("mg.storeLocal(local").append(local);
544             if (!type.equals(localTypes.get(local))) {
545                 localTypes.set(local, type);
546                 buf.append(", ").append(type);
547             }
548             buf.append(");\n");
549         }
550     }
551
552     private int generateNewLocal(int var, String JavaDoc type) {
553         Integer JavaDoc i = (Integer JavaDoc) locals.get(new Integer JavaDoc(var));
554         if (i == null) {
555             int local = locals.size();
556             locals.put(new Integer JavaDoc(var), new Integer JavaDoc(local));
557             localTypes.add(type);
558             buf.append("int local" + local + " = mg.newLocal(" + type + ");\n");
559             return local;
560         }
561         return i.intValue();
562     }
563
564     private int getArgIndex(int var) {
565         int nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
566         int i = 0;
567         while (nextLocal != var) {
568             nextLocal += argumentTypes[i++].getSize();
569         }
570         return i;
571     }
572
573     public void visitTypeInsn(final int opcode, final String JavaDoc desc) {
574         String JavaDoc type;
575         if (desc.charAt(0) == '[') {
576             type = getDescType(desc);
577         } else {
578             type = getType(desc);
579         }
580         buf.setLength(0);
581         if (opcode == NEW) {
582             buf.append("mg.newInstance(").append(type).append(");\n");
583         } else if (opcode == ANEWARRAY) {
584             buf.append("mg.newArray(").append(type).append(");\n");
585         } else if (opcode == CHECKCAST) {
586             buf.append("mg.checkCast(").append(type).append(");\n");
587         } else if (opcode == INSTANCEOF) {
588             buf.append("mg.instanceOf(").append(type).append(");\n");
589         }
590         text.add(buf.toString());
591         lastOpcode = opcode;
592     }
593
594     public void visitFieldInsn(
595         final int opcode,
596         final String JavaDoc owner,
597         final String JavaDoc name,
598         final String JavaDoc desc)
599     {
600         buf.setLength(0);
601         switch (opcode) {
602             case GETFIELD:
603                 buf.append("mg.getField(");
604                 break;
605             case PUTFIELD:
606                 buf.append("mg.putField(");
607                 break;
608             case GETSTATIC:
609                 buf.append("mg.getStatic(");
610                 break;
611             case PUTSTATIC:
612                 buf.append("mg.putStatic(");
613                 break;
614             default:
615                 throw new RuntimeException JavaDoc("unexpected case");
616         }
617         buf.append(getType(owner));
618         buf.append(", \"");
619         buf.append(name);
620         buf.append("\", ");
621         buf.append(getDescType(desc));
622         buf.append(");\n");
623         text.add(buf.toString());
624         lastOpcode = opcode;
625     }
626
627     public void visitMethodInsn(
628         final int opcode,
629         final String JavaDoc owner,
630         final String JavaDoc name,
631         final String JavaDoc desc)
632     {
633         buf.setLength(0);
634         switch (opcode) {
635             case INVOKEVIRTUAL:
636                 buf.append("mg.invokeVirtual(");
637                 break;
638             case INVOKESPECIAL:
639                 buf.append("mg.invokeConstructor(");
640                 break;
641             case INVOKESTATIC:
642                 buf.append("mg.invokeStatic(");
643                 break;
644             case INVOKEINTERFACE:
645                 buf.append("mg.invokeInterface(");
646                 break;
647             default:
648                 throw new RuntimeException JavaDoc("unexpected case");
649         }
650         if (owner.charAt(0) == '[') {
651             buf.append(getDescType(owner));
652         } else {
653             buf.append(getType(owner));
654         }
655         buf.append(", ");
656         buf.append(getMethod(name, desc));
657         buf.append(");\n");
658         text.add(buf.toString());
659         lastOpcode = opcode;
660     }
661
662     public void visitJumpInsn(final int opcode, final Label label) {
663         buf.setLength(0);
664         declareLabel(label);
665         if (opcode == GOTO || opcode == IFNULL || opcode == IFNONNULL) {
666             if (opcode == GOTO)
667                 buf.append("mg.goTo(");
668             if (opcode == IFNULL)
669                 buf.append("mg.ifNull(");
670             if (opcode == IFNONNULL)
671                 buf.append("mg.ifNonNull(");
672             appendLabel(label);
673             buf.append(");\n");
674         } else if (opcode == IF_ICMPEQ) {
675             buf.append("mg.ifICmp(GeneratorAdapter.EQ, ");
676             appendLabel(label);
677             buf.append(");\n");
678         } else if (opcode == IF_ICMPNE) {
679             buf.append("mg.ifICmp(GeneratorAdapter.NE, ");
680             appendLabel(label);
681             buf.append(");\n");
682         } else if (opcode == IF_ICMPLT) {
683             buf.append("mg.ifICmp(GeneratorAdapter.LT, ");
684             appendLabel(label);
685             buf.append(");\n");
686         } else if (opcode == IF_ICMPGE) {
687             buf.append("mg.ifICmp(GeneratorAdapter.GE, ");
688             appendLabel(label);
689             buf.append(");\n");
690         } else if (opcode == IF_ICMPGT) {
691             buf.append("mg.ifICmp(GeneratorAdapter.GT, ");
692             appendLabel(label);
693             buf.append(");\n");
694         } else if (opcode == IF_ICMPLE) {
695             buf.append("mg.ifICmp(GeneratorAdapter.LE, ");
696             appendLabel(label);
697             buf.append(");\n");
698         } else if (opcode == IF_ACMPEQ) {
699             buf.append("mg.ifCmp(");
700             buf.append(getType("java/lang/Object"))
701                     .append(", ")
702                     .append("GeneratorAdapter.EQ, ");
703             appendLabel(label);
704             buf.append(");\n");
705         } else if (opcode == IF_ACMPNE) {
706             buf.append("mg.ifCmp(");
707             buf.append(getType("java/lang/Object"))
708                     .append(", ")
709                     .append("GeneratorAdapter.NE, ");
710             appendLabel(label);
711             buf.append(");\n");
712         } else if (opcode == IFEQ) {
713             buf.append("mg.ifZCmp(GeneratorAdapter.EQ, ");
714             appendLabel(label);
715             buf.append(");\n");
716         } else if (opcode == IFNE) {
717             buf.append("mg.ifZCmp(GeneratorAdapter.NE, ");
718             appendLabel(label);
719             buf.append(");\n");
720         } else if (opcode == IFLT) {
721             buf.append("mg.ifZCmp(GeneratorAdapter.LT, ");
722             appendLabel(label);
723             buf.append(");\n");
724         } else if (opcode == IFGE) {
725             buf.append("mg.ifZCmp(GeneratorAdapter.GE, ");
726             appendLabel(label);
727             buf.append(");\n");
728         } else if (opcode == IFGT) {
729             buf.append("mg.ifZCmp(GeneratorAdapter.GT, ");
730             appendLabel(label);
731             buf.append(");\n");
732         } else if (opcode == IFLE) {
733             buf.append("mg.ifZCmp(GeneratorAdapter.LE, ");
734             appendLabel(label);
735             buf.append(");\n");
736         } else {
737             buf.append("mg.visitJumpInsn(")
738                     .append(OPCODES[opcode])
739                     .append(", ");
740             appendLabel(label);
741             buf.append(");\n");
742         }
743         text.add(buf.toString());
744         lastOpcode = opcode;
745     }
746
747     public void visitLabel(final Label label) {
748         buf.setLength(0);
749         declareLabel(label);
750         buf.append("mg.mark(");
751         appendLabel(label);
752         buf.append(");\n");
753         text.add(buf.toString());
754         lastOpcode = -1;
755     }
756
757     public void visitLdcInsn(final Object JavaDoc cst) {
758         buf.setLength(0);
759         buf.append("mg.push(");
760         if (cst == null) {
761             buf.append("(String)null");
762         } else if (cst instanceof Long JavaDoc) {
763             buf.append(cst + "L");
764         } else if (cst instanceof Float JavaDoc) {
765             float f = ((Float JavaDoc) cst).floatValue();
766             if (Float.isNaN(f)) {
767                 buf.append("Float.NaN");
768             } else if (Float.isInfinite(f)) {
769                 buf.append(f > 0
770                         ? "Float.POSITIVE_INFINITY"
771                         : "Float.NEGATIVE_INFINITY");
772             } else {
773                 buf.append(cst + "f");
774             }
775         } else if (cst instanceof Double JavaDoc) {
776             double d = ((Double JavaDoc) cst).doubleValue();
777             if (Double.isNaN(d)) {
778                 buf.append("Double.NaN");
779             } else if (Double.isInfinite(d)) {
780                 buf.append(d > 0
781                         ? "Double.POSITIVE_INFINITY"
782                         : "Double.NEGATIVE_INFINITY");
783             } else {
784                 buf.append(cst + "d");
785             }
786         } else if (cst instanceof String JavaDoc) {
787             appendString(buf, (String JavaDoc) cst);
788         } else if (cst instanceof Type) {
789             buf.append("Type.getType(\"").append(cst).append("\")");
790         } else {
791             buf.append(cst);
792         }
793         buf.append(");\n");
794         text.add(buf.toString());
795         lastOpcode = LDC;
796     }
797
798     public void visitIincInsn(final int var, final int increment) {
799         buf.setLength(0);
800         if (var < firstLocal) {
801             buf.append("mg.iinc(").append(var);
802         } else {
803             int v = generateNewLocal(var, "Type.INT_TYPE");
804             buf.append("mg.iinc(local").append(v);
805         }
806         buf.append(", ").append(increment).append(");\n");
807         text.add(buf.toString());
808         lastOpcode = IINC;
809     }
810
811     public void visitTableSwitchInsn(
812         final int min,
813         final int max,
814         final Label dflt,
815         final Label labels[])
816     {
817         buf.setLength(0);
818         for (int i = 0; i < labels.length; ++i) {
819             declareLabel(labels[i]);
820         }
821         declareLabel(dflt);
822
823         buf.append("mg.visitTableSwitchInsn(")
824                 .append(min)
825                 .append(", ")
826                 .append(max)
827                 .append(", ");
828         appendLabel(dflt);
829         buf.append(", new Label[] {");
830         for (int i = 0; i < labels.length; ++i) {
831             buf.append(i == 0 ? " " : ", ");
832             appendLabel(labels[i]);
833         }
834         buf.append(" }); // TODO\n");
835         text.add(buf.toString());
836         lastOpcode = TABLESWITCH;
837     }
838
839     public void visitLookupSwitchInsn(
840         final Label dflt,
841         final int keys[],
842         final Label labels[])
843     {
844         buf.setLength(0);
845         for (int i = 0; i < labels.length; ++i) {
846             declareLabel(labels[i]);
847         }
848         declareLabel(dflt);
849
850         buf.append("mg.visitLookupSwitchInsn(");
851         appendLabel(dflt);
852         buf.append(", new int[] {");
853         for (int i = 0; i < keys.length; ++i) {
854             buf.append(i == 0 ? " " : ", ").append(keys[i]);
855         }
856         buf.append(" }, new Label[] {");
857         for (int i = 0; i < labels.length; ++i) {
858             buf.append(i == 0 ? " " : ", ");
859             appendLabel(labels[i]);
860         }
861         buf.append(" }); // TODO\n");
862         text.add(buf.toString());
863         lastOpcode = LOOKUPSWITCH;
864     }
865
866     public void visitMultiANewArrayInsn(final String JavaDoc desc, final int dims) {
867         buf.setLength(0);
868         buf.append("mg.visitMultiANewArrayInsn(\"");
869         buf.append(desc);
870         buf.append("\", ").append(dims).append(");\n");
871         text.add(buf.toString());
872         lastOpcode = MULTIANEWARRAY;
873     }
874
875     public void visitTryCatchBlock(
876         final Label start,
877         final Label end,
878         final Label handler,
879         final String JavaDoc type)
880     {
881         buf.setLength(0);
882         buf.append("mg.visitTryCatchBlock(");
883         appendLabel(start);
884         buf.append(", ");
885         appendLabel(end);
886         buf.append(", ");
887         appendLabel(handler);
888         buf.append(", ");
889         if (type == null) {
890             buf.append("null");
891         } else {
892             buf.append('"').append(type).append('"');
893         }
894         buf.append("); // TODO\n");
895         text.add(buf.toString());
896         lastOpcode = -1;
897     }
898
899     public void visitLocalVariable(
900         final String JavaDoc name,
901         final String JavaDoc desc,
902         final String JavaDoc signature,
903         final Label start,
904         final Label end,
905         final int index)
906     {
907         buf.setLength(0);
908         buf.append("mg.visitLocalVariable(\"");
909         buf.append(name);
910         buf.append("\", \"");
911         buf.append(desc);
912         buf.append("\", ");
913         if (signature == null) {
914             buf.append("null");
915         } else {
916             buf.append('"').append(signature).append('"');
917         }
918         buf.append(", ");
919         appendLabel(start);
920         buf.append(", ");
921         appendLabel(end);
922         buf.append(", ").append(index).append(");\n");
923         text.add(buf.toString());
924         lastOpcode = -1;
925     }
926
927     public void visitLineNumber(final int line, final Label start) {
928         buf.setLength(0);
929         buf.append("mg.visitLineNumber(").append(line).append(", ");
930         appendLabel(start);
931         buf.append(");\n");
932         text.add(buf.toString());
933         lastOpcode = -1;
934     }
935
936     public void visitMaxs(final int maxStack, final int maxLocals) {
937         text.add("mg.endMethod();\n");
938         lastOpcode = -1;
939     }
940
941     public void visitEnd() {
942         // does nothing
943
}
944
945     static String JavaDoc getType(String JavaDoc internalName) {
946         return "Type.getType(\"L" + internalName + ";\")";
947     }
948
949     static String JavaDoc getDescType(String JavaDoc desc) {
950         if (desc.equals("Z"))
951             return "Type.BOOLEAN_TYPE";
952         if (desc.equals("B"))
953             return "Type.BYTE_TYPE";
954         if (desc.equals("C"))
955             return "Type.CHAR_TYPE";
956         if (desc.equals("D"))
957             return "Type.DOUBLE_TYPE";
958         if (desc.equals("F"))
959             return "Type.FLOAT_TYPE";
960         if (desc.equals("I"))
961             return "Type.INT_TYPE";
962         if (desc.equals("J"))
963             return "Type.LONG_TYPE";
964         if (desc.equals("S"))
965             return "Type.SHORT_TYPE";
966         if (desc.equals("V"))
967             return "Type.VOID_TYPE";
968         return "Type.getType(\"" + desc + "\")";
969     }
970
971     static String JavaDoc getMethod(String JavaDoc name, String JavaDoc desc) {
972         Type rt = Type.getReturnType(desc);
973         Type[] argt = Type.getArgumentTypes(desc);
974         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
975         buf.append("Method.getMethod(\"");
976         buf.append(rt.getClassName()).append(" ");
977         buf.append(name).append("(");
978         for (int i = 0; i < argt.length; ++i) {
979             if (i > 0)
980                 buf.append(',');
981             buf.append(argt[i].getClassName());
982         }
983         buf.append(")\")");
984         return buf.toString();
985     }
986
987     /**
988      * Appends a declaration of the given label to {@link #buf buf}. This
989      * declaration is of the form "Label lXXX = new Label();". Does nothing if
990      * the given label has already been declared.
991      *
992      * @param l a label.
993      */

994     private void declareLabel(final Label l) {
995         String JavaDoc name = (String JavaDoc) labelNames.get(l);
996         if (name == null) {
997             name = "label" + labelNames.size();
998             labelNames.put(l, name);
999             buf.append("Label ").append(name).append(" = mg.newLabel();\n");
1000        }
1001    }
1002
1003    /**
1004     * Appends the name of the given label to {@link #buf buf}. The given label
1005     * <i>must</i> already have a name. One way to ensure this is to always
1006     * call {@link #declareLabel declared} before calling this method.
1007     *
1008     * @param l a label.
1009     */

1010    private void appendLabel(final Label l) {
1011        buf.append((String JavaDoc) labelNames.get(l));
1012    }
1013}
1014
Popular Tags