Source Code Cross Referenced for GeneratorAdapter.java in  » Rule-Engine » drolls-Rule-Engine » org » drools » asm » commons » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Rule Engine » drolls Rule Engine » org.drools.asm.commons 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /***
0002:         * ASM: a very small and fast Java bytecode manipulation framework
0003:         * Copyright (c) 2000-2005 INRIA, France Telecom
0004:         * All rights reserved.
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         * 1. Redistributions of source code must retain the above copyright
0010:         *    notice, this list of conditions and the following disclaimer.
0011:         * 2. Redistributions in binary form must reproduce the above copyright
0012:         *    notice, this list of conditions and the following disclaimer in the
0013:         *    documentation and/or other materials provided with the distribution.
0014:         * 3. Neither the name of the copyright holders nor the names of its
0015:         *    contributors may be used to endorse or promote products derived from
0016:         *    this software without specific prior written permission.
0017:         *
0018:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0019:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0020:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0021:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0022:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0023:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0024:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0025:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0026:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0027:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
0028:         * THE POSSIBILITY OF SUCH DAMAGE.
0029:         */package org.drools.asm.commons;
0030:
0031:        import java.util.ArrayList;
0032:        import java.util.Arrays;
0033:        import java.util.List;
0034:
0035:        import org.drools.asm.ClassVisitor;
0036:        import org.drools.asm.Label;
0037:        import org.drools.asm.MethodVisitor;
0038:        import org.drools.asm.Opcodes;
0039:        import org.drools.asm.Type;
0040:
0041:        /**
0042:         * A {@link org.drools.asm.MethodAdapter} with convenient methods to generate
0043:         * code. For example, using this adapter, the class below
0044:         * 
0045:         * <pre>
0046:         * public class Example {
0047:         *     public static void main(String[] args) {
0048:         *         System.out.println(&quot;Hello world!&quot;);
0049:         *     }
0050:         * }
0051:         * </pre>
0052:         * 
0053:         * can be generated as follows:
0054:         * 
0055:         * <pre>
0056:         * ClassWriter cw = new ClassWriter(true);
0057:         * cw.visit(V1_1, ACC_PUBLIC, &quot;Example&quot;, null, &quot;java/lang/Object&quot;, null);
0058:         * 
0059:         * Method m = Method.getMethod(&quot;void &lt;init&gt; ()&quot;);
0060:         * GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw);
0061:         * mg.loadThis();
0062:         * mg.invokeConstructor(Type.getType(Object.class), m);
0063:         * mg.returnValue();
0064:         * mg.endMethod();
0065:         * 
0066:         * m = Method.getMethod(&quot;void main (String[])&quot;);
0067:         * mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw);
0068:         * mg.getStatic(Type.getType(System.class), &quot;out&quot;, Type.getType(PrintStream.class));
0069:         * mg.push(&quot;Hello world!&quot;);
0070:         * mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod(&quot;void println (String)&quot;));
0071:         * mg.returnValue();
0072:         * mg.endMethod();
0073:         * 
0074:         * cw.visitEnd();
0075:         * </pre>
0076:         * 
0077:         * @author Juozas Baliuka
0078:         * @author Chris Nokleberg
0079:         * @author Eric Bruneton
0080:         */
0081:        public class GeneratorAdapter extends LocalVariablesSorter {
0082:
0083:            private final static Type BYTE_TYPE = Type
0084:                    .getType("Ljava/lang/Byte;");
0085:
0086:            private final static Type BOOLEAN_TYPE = Type
0087:                    .getType("Ljava/lang/Boolean;");
0088:
0089:            private final static Type SHORT_TYPE = Type
0090:                    .getType("Ljava/lang/Short;");
0091:
0092:            private final static Type CHARACTER_TYPE = Type
0093:                    .getType("Ljava/lang/Character;");
0094:
0095:            private final static Type INTEGER_TYPE = Type
0096:                    .getType("Ljava/lang/Integer;");
0097:
0098:            private final static Type FLOAT_TYPE = Type
0099:                    .getType("Ljava/lang/Float;");
0100:
0101:            private final static Type LONG_TYPE = Type
0102:                    .getType("Ljava/lang/Long;");
0103:
0104:            private final static Type DOUBLE_TYPE = Type
0105:                    .getType("Ljava/lang/Double;");
0106:
0107:            private final static Type NUMBER_TYPE = Type
0108:                    .getType("Ljava/lang/Number;");
0109:
0110:            private final static Type OBJECT_TYPE = Type
0111:                    .getType("Ljava/lang/Object;");
0112:
0113:            private final static Method BOOLEAN_VALUE = Method
0114:                    .getMethod("boolean booleanValue()");
0115:
0116:            private final static Method CHAR_VALUE = Method
0117:                    .getMethod("char charValue()");
0118:
0119:            private final static Method INT_VALUE = Method
0120:                    .getMethod("int intValue()");
0121:
0122:            private final static Method FLOAT_VALUE = Method
0123:                    .getMethod("float floatValue()");
0124:
0125:            private final static Method LONG_VALUE = Method
0126:                    .getMethod("long longValue()");
0127:
0128:            private final static Method DOUBLE_VALUE = Method
0129:                    .getMethod("double doubleValue()");
0130:
0131:            /**
0132:             * Constant for the {@link #math math} method.
0133:             */
0134:            public final static int ADD = Opcodes.IADD;
0135:
0136:            /**
0137:             * Constant for the {@link #math math} method.
0138:             */
0139:            public final static int SUB = Opcodes.ISUB;
0140:
0141:            /**
0142:             * Constant for the {@link #math math} method.
0143:             */
0144:            public final static int MUL = Opcodes.IMUL;
0145:
0146:            /**
0147:             * Constant for the {@link #math math} method.
0148:             */
0149:            public final static int DIV = Opcodes.IDIV;
0150:
0151:            /**
0152:             * Constant for the {@link #math math} method.
0153:             */
0154:            public final static int REM = Opcodes.IREM;
0155:
0156:            /**
0157:             * Constant for the {@link #math math} method.
0158:             */
0159:            public final static int NEG = Opcodes.INEG;
0160:
0161:            /**
0162:             * Constant for the {@link #math math} method.
0163:             */
0164:            public final static int SHL = Opcodes.ISHL;
0165:
0166:            /**
0167:             * Constant for the {@link #math math} method.
0168:             */
0169:            public final static int SHR = Opcodes.ISHR;
0170:
0171:            /**
0172:             * Constant for the {@link #math math} method.
0173:             */
0174:            public final static int USHR = Opcodes.IUSHR;
0175:
0176:            /**
0177:             * Constant for the {@link #math math} method.
0178:             */
0179:            public final static int AND = Opcodes.IAND;
0180:
0181:            /**
0182:             * Constant for the {@link #math math} method.
0183:             */
0184:            public final static int OR = Opcodes.IOR;
0185:
0186:            /**
0187:             * Constant for the {@link #math math} method.
0188:             */
0189:            public final static int XOR = Opcodes.IXOR;
0190:
0191:            /**
0192:             * Constant for the {@link #ifCmp ifCmp} method.
0193:             */
0194:            public final static int EQ = Opcodes.IFEQ;
0195:
0196:            /**
0197:             * Constant for the {@link #ifCmp ifCmp} method.
0198:             */
0199:            public final static int NE = Opcodes.IFNE;
0200:
0201:            /**
0202:             * Constant for the {@link #ifCmp ifCmp} method.
0203:             */
0204:            public final static int LT = Opcodes.IFLT;
0205:
0206:            /**
0207:             * Constant for the {@link #ifCmp ifCmp} method.
0208:             */
0209:            public final static int GE = Opcodes.IFGE;
0210:
0211:            /**
0212:             * Constant for the {@link #ifCmp ifCmp} method.
0213:             */
0214:            public final static int GT = Opcodes.IFGT;
0215:
0216:            /**
0217:             * Constant for the {@link #ifCmp ifCmp} method.
0218:             */
0219:            public final static int LE = Opcodes.IFLE;
0220:
0221:            /**
0222:             * Access flags of the method visited by this adapter.
0223:             */
0224:            private final int access;
0225:
0226:            /**
0227:             * Return type of the method visited by this adapter.
0228:             */
0229:            private final Type returnType;
0230:
0231:            /**
0232:             * Argument types of the method visited by this adapter.
0233:             */
0234:            private final Type[] argumentTypes;
0235:
0236:            /**
0237:             * Types of the local variables of the method visited by this adapter.
0238:             */
0239:            private final List localTypes;
0240:
0241:            /**
0242:             * Creates a new {@link GeneratorAdapter}.
0243:             * 
0244:             * @param mv the method visitor to which this adapter delegates calls.
0245:             * @param access the method's access flags (see {@link Opcodes}).
0246:             * @param name the method's name.
0247:             * @param desc the method's descriptor (see {@link Type Type}).
0248:             */
0249:            public GeneratorAdapter(final MethodVisitor mv, final int access,
0250:                    final String name, final String desc) {
0251:                super (access, desc, mv);
0252:                this .access = access;
0253:                this .returnType = Type.getReturnType(desc);
0254:                this .argumentTypes = Type.getArgumentTypes(desc);
0255:                this .localTypes = new ArrayList();
0256:            }
0257:
0258:            /**
0259:             * Creates a new {@link GeneratorAdapter}.
0260:             * 
0261:             * @param access access flags of the adapted method.
0262:             * @param method the adapted method.
0263:             * @param mv the method visitor to which this adapter delegates calls.
0264:             */
0265:            public GeneratorAdapter(final int access, final Method method,
0266:                    final MethodVisitor mv) {
0267:                super (access, method.getDescriptor(), mv);
0268:                this .access = access;
0269:                this .returnType = method.getReturnType();
0270:                this .argumentTypes = method.getArgumentTypes();
0271:                this .localTypes = new ArrayList();
0272:            }
0273:
0274:            /**
0275:             * Creates a new {@link GeneratorAdapter}.
0276:             * 
0277:             * @param access access flags of the adapted method.
0278:             * @param method the adapted method.
0279:             * @param signature the signature of the adapted method (may be
0280:             *        <tt>null</tt>).
0281:             * @param exceptions the exceptions thrown by the adapted method (may be
0282:             *        <tt>null</tt>).
0283:             * @param cv the class visitor to which this adapter delegates calls.
0284:             */
0285:            public GeneratorAdapter(final int access, final Method method,
0286:                    final String signature, final Type[] exceptions,
0287:                    final ClassVisitor cv) {
0288:                this (access, method, cv.visitMethod(access, method.getName(),
0289:                        method.getDescriptor(), signature,
0290:                        getInternalNames(exceptions)));
0291:            }
0292:
0293:            /**
0294:             * Returns the internal names of the given types.
0295:             * 
0296:             * @param types a set of types.
0297:             * @return the internal names of the given types.
0298:             */
0299:            private static String[] getInternalNames(final Type[] types) {
0300:                if (types == null) {
0301:                    return null;
0302:                }
0303:                final String[] names = new String[types.length];
0304:                for (int i = 0; i < names.length; ++i) {
0305:                    names[i] = types[i].getInternalName();
0306:                }
0307:                return names;
0308:            }
0309:
0310:            // ------------------------------------------------------------------------
0311:            // Instructions to push constants on the stack
0312:            // ------------------------------------------------------------------------
0313:
0314:            /**
0315:             * Generates the instruction to push the given value on the stack.
0316:             * 
0317:             * @param value the value to be pushed on the stack.
0318:             */
0319:            public void push(final boolean value) {
0320:                push(value ? 1 : 0);
0321:            }
0322:
0323:            /**
0324:             * Generates the instruction to push the given value on the stack.
0325:             * 
0326:             * @param value the value to be pushed on the stack.
0327:             */
0328:            public void push(final int value) {
0329:                if (value >= -1 && value <= 5) {
0330:                    this .mv.visitInsn(Opcodes.ICONST_0 + value);
0331:                } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
0332:                    this .mv.visitIntInsn(Opcodes.BIPUSH, value);
0333:                } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
0334:                    this .mv.visitIntInsn(Opcodes.SIPUSH, value);
0335:                } else {
0336:                    this .mv.visitLdcInsn(new Integer(value));
0337:                }
0338:            }
0339:
0340:            /**
0341:             * Generates the instruction to push the given value on the stack.
0342:             * 
0343:             * @param value the value to be pushed on the stack.
0344:             */
0345:            public void push(final long value) {
0346:                if (value == 0L || value == 1L) {
0347:                    this .mv.visitInsn(Opcodes.LCONST_0 + (int) value);
0348:                } else {
0349:                    this .mv.visitLdcInsn(new Long(value));
0350:                }
0351:            }
0352:
0353:            /**
0354:             * Generates the instruction to push the given value on the stack.
0355:             * 
0356:             * @param value the value to be pushed on the stack.
0357:             */
0358:            public void push(final float value) {
0359:                final int bits = Float.floatToIntBits(value);
0360:                if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
0361:                    this .mv.visitInsn(Opcodes.FCONST_0 + (int) value);
0362:                } else {
0363:                    this .mv.visitLdcInsn(new Float(value));
0364:                }
0365:            }
0366:
0367:            /**
0368:             * Generates the instruction to push the given value on the stack.
0369:             * 
0370:             * @param value the value to be pushed on the stack.
0371:             */
0372:            public void push(final double value) {
0373:                final long bits = Double.doubleToLongBits(value);
0374:                if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
0375:                    this .mv.visitInsn(Opcodes.DCONST_0 + (int) value);
0376:                } else {
0377:                    this .mv.visitLdcInsn(new Double(value));
0378:                }
0379:            }
0380:
0381:            /**
0382:             * Generates the instruction to push the given value on the stack.
0383:             * 
0384:             * @param value the value to be pushed on the stack. May be <tt>null</tt>.
0385:             */
0386:            public void push(final String value) {
0387:                if (value == null) {
0388:                    this .mv.visitInsn(Opcodes.ACONST_NULL);
0389:                } else {
0390:                    this .mv.visitLdcInsn(value);
0391:                }
0392:            }
0393:
0394:            /**
0395:             * Generates the instruction to push the given value on the stack.
0396:             * 
0397:             * @param value the value to be pushed on the stack.
0398:             */
0399:            public void push(final Type value) {
0400:                if (value == null) {
0401:                    this .mv.visitInsn(Opcodes.ACONST_NULL);
0402:                } else {
0403:                    this .mv.visitLdcInsn(value);
0404:                }
0405:            }
0406:
0407:            // ------------------------------------------------------------------------
0408:            // Instructions to load and store method arguments
0409:            // ------------------------------------------------------------------------
0410:
0411:            /**
0412:             * Returns the index of the given method argument in the frame's local
0413:             * variables array.
0414:             * 
0415:             * @param arg the index of a method argument.
0416:             * @return the index of the given method argument in the frame's local
0417:             *         variables array.
0418:             */
0419:            private int getArgIndex(final int arg) {
0420:                int index = ((this .access & Opcodes.ACC_STATIC) == 0 ? 1 : 0);
0421:                for (int i = 0; i < arg; i++) {
0422:                    index += this .argumentTypes[i].getSize();
0423:                }
0424:                return index;
0425:            }
0426:
0427:            /**
0428:             * Generates the instruction to push a local variable on the stack.
0429:             * 
0430:             * @param type the type of the local variable to be loaded.
0431:             * @param index an index in the frame's local variables array.
0432:             */
0433:            private void loadInsn(final Type type, final int index) {
0434:                this .mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), index);
0435:            }
0436:
0437:            /**
0438:             * Generates the instruction to store the top stack value in a local
0439:             * variable.
0440:             * 
0441:             * @param type the type of the local variable to be stored.
0442:             * @param index an index in the frame's local variables array.
0443:             */
0444:            private void storeInsn(final Type type, final int index) {
0445:                this .mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), index);
0446:            }
0447:
0448:            /**
0449:             * Generates the instruction to load 'this' on the stack.
0450:             */
0451:            public void loadThis() {
0452:                if ((this .access & Opcodes.ACC_STATIC) != 0) {
0453:                    throw new IllegalStateException(
0454:                            "no 'this' pointer within static method");
0455:                }
0456:                this .mv.visitVarInsn(Opcodes.ALOAD, 0);
0457:            }
0458:
0459:            /**
0460:             * Generates the instruction to load the given method argument on the stack.
0461:             * 
0462:             * @param arg the index of a method argument.
0463:             */
0464:            public void loadArg(final int arg) {
0465:                loadInsn(this .argumentTypes[arg], getArgIndex(arg));
0466:            }
0467:
0468:            /**
0469:             * Generates the instructions to load the given method arguments on the
0470:             * stack.
0471:             * 
0472:             * @param arg the index of the first method argument to be loaded.
0473:             * @param count the number of method arguments to be loaded.
0474:             */
0475:            public void loadArgs(final int arg, final int count) {
0476:                int index = getArgIndex(arg);
0477:                for (int i = 0; i < count; ++i) {
0478:                    final Type t = this .argumentTypes[arg + i];
0479:                    loadInsn(t, index);
0480:                    index += t.getSize();
0481:                }
0482:            }
0483:
0484:            /**
0485:             * Generates the instructions to load all the method arguments on the stack.
0486:             */
0487:            public void loadArgs() {
0488:                loadArgs(0, this .argumentTypes.length);
0489:            }
0490:
0491:            /**
0492:             * Generates the instructions to load all the method arguments on the stack,
0493:             * as a single object array.
0494:             */
0495:            public void loadArgArray() {
0496:                push(this .argumentTypes.length);
0497:                newArray(GeneratorAdapter.OBJECT_TYPE);
0498:                for (int i = 0; i < this .argumentTypes.length; i++) {
0499:                    dup();
0500:                    push(i);
0501:                    loadArg(i);
0502:                    box(this .argumentTypes[i]);
0503:                    arrayStore(GeneratorAdapter.OBJECT_TYPE);
0504:                }
0505:            }
0506:
0507:            /**
0508:             * Generates the instruction to store the top stack value in the given
0509:             * method argument.
0510:             * 
0511:             * @param arg the index of a method argument.
0512:             */
0513:            public void storeArg(final int arg) {
0514:                storeInsn(this .argumentTypes[arg], getArgIndex(arg));
0515:            }
0516:
0517:            // ------------------------------------------------------------------------
0518:            // Instructions to load and store local variables
0519:            // ------------------------------------------------------------------------
0520:
0521:            /**
0522:             * Creates a new local variable of the given type.
0523:             * 
0524:             * @param type the type of the local variable to be created.
0525:             * @return the identifier of the newly created local variable.
0526:             */
0527:            public int newLocal(final Type type) {
0528:                final int local = super .newLocal(type.getSize());
0529:                setLocalType(local, type);
0530:                return local;
0531:            }
0532:
0533:            /**
0534:             * Returns the type of the given local variable.
0535:             * 
0536:             * @param local a local variable identifier, as returned by {@link #newLocal
0537:             *        newLocal}.
0538:             * @return the type of the given local variable.
0539:             */
0540:            public Type getLocalType(final int local) {
0541:                return (Type) this .localTypes.get(local - this .firstLocal);
0542:            }
0543:
0544:            /**
0545:             * Sets the current type of the given local variable.
0546:             * 
0547:             * @param local a local variable identifier, as returned by {@link #newLocal
0548:             *        newLocal}.
0549:             * @param type the type of the value being stored in the local variable
0550:             */
0551:            private void setLocalType(final int local, final Type type) {
0552:                final int index = local - this .firstLocal;
0553:                while (this .localTypes.size() < index + 1) {
0554:                    this .localTypes.add(null);
0555:                }
0556:                this .localTypes.set(index, type);
0557:            }
0558:
0559:            /**
0560:             * Generates the instruction to load the given local variable on the stack.
0561:             * 
0562:             * @param local a local variable identifier, as returned by {@link #newLocal
0563:             *        newLocal}.
0564:             */
0565:            public void loadLocal(final int local) {
0566:                loadInsn(getLocalType(local), local);
0567:            }
0568:
0569:            /**
0570:             * Generates the instruction to load the given local variable on the stack.
0571:             * 
0572:             * @param local a local variable identifier, as returned by {@link #newLocal
0573:             *        newLocal}.
0574:             * @param type the type of this local variable.
0575:             */
0576:            public void loadLocal(final int local, final Type type) {
0577:                setLocalType(local, type);
0578:                loadInsn(type, local);
0579:            }
0580:
0581:            /**
0582:             * Generates the instruction to store the top stack value in the given local
0583:             * variable.
0584:             * 
0585:             * @param local a local variable identifier, as returned by {@link #newLocal
0586:             *        newLocal}.
0587:             */
0588:            public void storeLocal(final int local) {
0589:                storeInsn(getLocalType(local), local);
0590:            }
0591:
0592:            /**
0593:             * Generates the instruction to store the top stack value in the given local
0594:             * variable.
0595:             * 
0596:             * @param local a local variable identifier, as returned by {@link #newLocal
0597:             *        newLocal}.
0598:             * @param type the type of this local variable.
0599:             */
0600:            public void storeLocal(final int local, final Type type) {
0601:                setLocalType(local, type);
0602:                storeInsn(type, local);
0603:            }
0604:
0605:            /**
0606:             * Generates the instruction to load an element from an array.
0607:             * 
0608:             * @param type the type of the array element to be loaded.
0609:             */
0610:            public void arrayLoad(final Type type) {
0611:                this .mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
0612:            }
0613:
0614:            /**
0615:             * Generates the instruction to store an element in an array.
0616:             * 
0617:             * @param type the type of the array element to be stored.
0618:             */
0619:            public void arrayStore(final Type type) {
0620:                this .mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
0621:            }
0622:
0623:            // ------------------------------------------------------------------------
0624:            // Instructions to manage the stack
0625:            // ------------------------------------------------------------------------
0626:
0627:            /**
0628:             * Generates a POP instruction.
0629:             */
0630:            public void pop() {
0631:                this .mv.visitInsn(Opcodes.POP);
0632:            }
0633:
0634:            /**
0635:             * Generates a POP2 instruction.
0636:             */
0637:            public void pop2() {
0638:                this .mv.visitInsn(Opcodes.POP2);
0639:            }
0640:
0641:            /**
0642:             * Generates a DUP instruction.
0643:             */
0644:            public void dup() {
0645:                this .mv.visitInsn(Opcodes.DUP);
0646:            }
0647:
0648:            /**
0649:             * Generates a DUP2 instruction.
0650:             */
0651:            public void dup2() {
0652:                this .mv.visitInsn(Opcodes.DUP2);
0653:            }
0654:
0655:            /**
0656:             * Generates a DUP_X1 instruction.
0657:             */
0658:            public void dupX1() {
0659:                this .mv.visitInsn(Opcodes.DUP_X1);
0660:            }
0661:
0662:            /**
0663:             * Generates a DUP_X2 instruction.
0664:             */
0665:            public void dupX2() {
0666:                this .mv.visitInsn(Opcodes.DUP_X2);
0667:            }
0668:
0669:            /**
0670:             * Generates a DUP2_X1 instruction.
0671:             */
0672:            public void dup2X1() {
0673:                this .mv.visitInsn(Opcodes.DUP2_X1);
0674:            }
0675:
0676:            /**
0677:             * Generates a DUP2_X2 instruction.
0678:             */
0679:            public void dup2X2() {
0680:                this .mv.visitInsn(Opcodes.DUP2_X2);
0681:            }
0682:
0683:            /**
0684:             * Generates a SWAP instruction.
0685:             */
0686:            public void swap() {
0687:                this .mv.visitInsn(Opcodes.SWAP);
0688:            }
0689:
0690:            /**
0691:             * Generates the instructions to swap the top two stack values.
0692:             * 
0693:             * @param prev type of the top - 1 stack value.
0694:             * @param type type of the top stack value.
0695:             */
0696:            public void swap(final Type prev, final Type type) {
0697:                if (type.getSize() == 1) {
0698:                    if (prev.getSize() == 1) {
0699:                        swap(); // same as dupX1(), pop();
0700:                    } else {
0701:                        dupX2();
0702:                        pop();
0703:                    }
0704:                } else {
0705:                    if (prev.getSize() == 1) {
0706:                        dup2X1();
0707:                        pop2();
0708:                    } else {
0709:                        dup2X2();
0710:                        pop2();
0711:                    }
0712:                }
0713:            }
0714:
0715:            // ------------------------------------------------------------------------
0716:            // Instructions to do mathematical and logical operations
0717:            // ------------------------------------------------------------------------
0718:
0719:            /**
0720:             * Generates the instruction to do the specified mathematical or logical
0721:             * operation.
0722:             * 
0723:             * @param op a mathematical or logical operation. Must be one of ADD, SUB,
0724:             *        MUL, DIV, REM, NEG, SHL, SHR, USHR, AND, OR, XOR.
0725:             * @param type the type of the operand(s) for this operation.
0726:             */
0727:            public void math(final int op, final Type type) {
0728:                this .mv.visitInsn(type.getOpcode(op));
0729:            }
0730:
0731:            /**
0732:             * Generates the instructions to compute the bitwise negation of the top
0733:             * stack value.
0734:             */
0735:            public void not() {
0736:                this .mv.visitInsn(Opcodes.ICONST_1);
0737:                this .mv.visitInsn(Opcodes.IXOR);
0738:            }
0739:
0740:            /**
0741:             * Generates the instruction to increment the given local variable.
0742:             * 
0743:             * @param local the local variable to be incremented.
0744:             * @param amount the amount by which the local variable must be incremented.
0745:             */
0746:            public void iinc(final int local, final int amount) {
0747:                this .mv.visitIincInsn(local, amount);
0748:            }
0749:
0750:            /**
0751:             * Generates the instructions to cast a numerical value from one type to
0752:             * another.
0753:             * 
0754:             * @param from the type of the top stack value
0755:             * @param to the type into which this value must be cast.
0756:             */
0757:            public void cast(final Type from, final Type to) {
0758:                if (from != to) {
0759:                    if (from == Type.DOUBLE_TYPE) {
0760:                        if (to == Type.FLOAT_TYPE) {
0761:                            this .mv.visitInsn(Opcodes.D2F);
0762:                        } else if (to == Type.LONG_TYPE) {
0763:                            this .mv.visitInsn(Opcodes.D2L);
0764:                        } else {
0765:                            this .mv.visitInsn(Opcodes.D2I);
0766:                            cast(Type.INT_TYPE, to);
0767:                        }
0768:                    } else if (from == Type.FLOAT_TYPE) {
0769:                        if (to == Type.DOUBLE_TYPE) {
0770:                            this .mv.visitInsn(Opcodes.F2D);
0771:                        } else if (to == Type.LONG_TYPE) {
0772:                            this .mv.visitInsn(Opcodes.F2L);
0773:                        } else {
0774:                            this .mv.visitInsn(Opcodes.F2I);
0775:                            cast(Type.INT_TYPE, to);
0776:                        }
0777:                    } else if (from == Type.LONG_TYPE) {
0778:                        if (to == Type.DOUBLE_TYPE) {
0779:                            this .mv.visitInsn(Opcodes.L2D);
0780:                        } else if (to == Type.FLOAT_TYPE) {
0781:                            this .mv.visitInsn(Opcodes.L2F);
0782:                        } else {
0783:                            this .mv.visitInsn(Opcodes.L2I);
0784:                            cast(Type.INT_TYPE, to);
0785:                        }
0786:                    } else {
0787:                        if (to == Type.BYTE_TYPE) {
0788:                            this .mv.visitInsn(Opcodes.I2B);
0789:                        } else if (to == Type.CHAR_TYPE) {
0790:                            this .mv.visitInsn(Opcodes.I2C);
0791:                        } else if (to == Type.DOUBLE_TYPE) {
0792:                            this .mv.visitInsn(Opcodes.I2D);
0793:                        } else if (to == Type.FLOAT_TYPE) {
0794:                            this .mv.visitInsn(Opcodes.I2F);
0795:                        } else if (to == Type.LONG_TYPE) {
0796:                            this .mv.visitInsn(Opcodes.I2L);
0797:                        } else if (to == Type.SHORT_TYPE) {
0798:                            this .mv.visitInsn(Opcodes.I2S);
0799:                        }
0800:                    }
0801:                }
0802:            }
0803:
0804:            // ------------------------------------------------------------------------
0805:            // Instructions to do boxing and unboxing operations
0806:            // ------------------------------------------------------------------------
0807:
0808:            /**
0809:             * Generates the instructions to box the top stack value. This value is
0810:             * replaced by its boxed equivalent on top of the stack.
0811:             * 
0812:             * @param type the type of the top stack value.
0813:             */
0814:            public void box(final Type type) {
0815:                if (type.getSort() == Type.OBJECT
0816:                        || type.getSort() == Type.ARRAY) {
0817:                    return;
0818:                }
0819:                if (type == Type.VOID_TYPE) {
0820:                    push((String) null);
0821:                } else {
0822:                    Type boxed = type;
0823:                    switch (type.getSort()) {
0824:                    case Type.BYTE:
0825:                        boxed = GeneratorAdapter.BYTE_TYPE;
0826:                        break;
0827:                    case Type.BOOLEAN:
0828:                        boxed = GeneratorAdapter.BOOLEAN_TYPE;
0829:                        break;
0830:                    case Type.SHORT:
0831:                        boxed = GeneratorAdapter.SHORT_TYPE;
0832:                        break;
0833:                    case Type.CHAR:
0834:                        boxed = GeneratorAdapter.CHARACTER_TYPE;
0835:                        break;
0836:                    case Type.INT:
0837:                        boxed = GeneratorAdapter.INTEGER_TYPE;
0838:                        break;
0839:                    case Type.FLOAT:
0840:                        boxed = GeneratorAdapter.FLOAT_TYPE;
0841:                        break;
0842:                    case Type.LONG:
0843:                        boxed = GeneratorAdapter.LONG_TYPE;
0844:                        break;
0845:                    case Type.DOUBLE:
0846:                        boxed = GeneratorAdapter.DOUBLE_TYPE;
0847:                        break;
0848:                    }
0849:                    newInstance(boxed);
0850:                    if (type.getSize() == 2) {
0851:                        // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
0852:                        dupX2();
0853:                        dupX2();
0854:                        pop();
0855:                    } else {
0856:                        // p -> po -> opo -> oop -> o
0857:                        dupX1();
0858:                        swap();
0859:                    }
0860:                    invokeConstructor(boxed, new Method("<init>",
0861:                            Type.VOID_TYPE, new Type[] { type }));
0862:                }
0863:            }
0864:
0865:            /**
0866:             * Generates the instructions to unbox the top stack value. This value is
0867:             * replaced by its unboxed equivalent on top of the stack.
0868:             * 
0869:             * @param type the type of the top stack value.
0870:             */
0871:            public void unbox(final Type type) {
0872:                Type t = GeneratorAdapter.NUMBER_TYPE;
0873:                Method sig = null;
0874:                switch (type.getSort()) {
0875:                case Type.VOID:
0876:                    return;
0877:                case Type.CHAR:
0878:                    t = GeneratorAdapter.CHARACTER_TYPE;
0879:                    sig = GeneratorAdapter.CHAR_VALUE;
0880:                    break;
0881:                case Type.BOOLEAN:
0882:                    t = GeneratorAdapter.BOOLEAN_TYPE;
0883:                    sig = GeneratorAdapter.BOOLEAN_VALUE;
0884:                    break;
0885:                case Type.DOUBLE:
0886:                    sig = GeneratorAdapter.DOUBLE_VALUE;
0887:                    break;
0888:                case Type.FLOAT:
0889:                    sig = GeneratorAdapter.FLOAT_VALUE;
0890:                    break;
0891:                case Type.LONG:
0892:                    sig = GeneratorAdapter.LONG_VALUE;
0893:                    break;
0894:                case Type.INT:
0895:                case Type.SHORT:
0896:                case Type.BYTE:
0897:                    sig = GeneratorAdapter.INT_VALUE;
0898:                }
0899:                if (sig == null) {
0900:                    checkCast(type);
0901:                } else {
0902:                    checkCast(t);
0903:                    invokeVirtual(t, sig);
0904:                }
0905:            }
0906:
0907:            // ------------------------------------------------------------------------
0908:            // Instructions to jump to other instructions
0909:            // ------------------------------------------------------------------------
0910:
0911:            /**
0912:             * Creates a new {@link Label}.
0913:             * 
0914:             * @return a new {@link Label}.
0915:             */
0916:            public Label newLabel() {
0917:                return new Label();
0918:            }
0919:
0920:            /**
0921:             * Marks the current code position with the given label.
0922:             * 
0923:             * @param label a label.
0924:             */
0925:            public void mark(final Label label) {
0926:                this .mv.visitLabel(label);
0927:            }
0928:
0929:            /**
0930:             * Marks the current code position with a new label.
0931:             * 
0932:             * @return the label that was created to mark the current code position.
0933:             */
0934:            public Label mark() {
0935:                final Label label = new Label();
0936:                this .mv.visitLabel(label);
0937:                return label;
0938:            }
0939:
0940:            /**
0941:             * Generates the instructions to jump to a label based on the comparison of
0942:             * the top two stack values.
0943:             * 
0944:             * @param type the type of the top two stack values.
0945:             * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
0946:             *        LE.
0947:             * @param label where to jump if the comparison result is <tt>true</tt>.
0948:             */
0949:            public void ifCmp(final Type type, final int mode, final Label label) {
0950:                int intOp = -1;
0951:                int jumpMode = mode;
0952:                switch (mode) {
0953:                case GE:
0954:                    jumpMode = GeneratorAdapter.LT;
0955:                    break;
0956:                case LE:
0957:                    jumpMode = GeneratorAdapter.GT;
0958:                    break;
0959:                }
0960:                switch (type.getSort()) {
0961:                case Type.LONG:
0962:                    this .mv.visitInsn(Opcodes.LCMP);
0963:                    break;
0964:                case Type.DOUBLE:
0965:                    this .mv.visitInsn(Opcodes.DCMPG);
0966:                    break;
0967:                case Type.FLOAT:
0968:                    this .mv.visitInsn(Opcodes.FCMPG);
0969:                    break;
0970:                case Type.ARRAY:
0971:                case Type.OBJECT:
0972:                    switch (mode) {
0973:                    case EQ:
0974:                        this .mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
0975:                        return;
0976:                    case NE:
0977:                        this .mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
0978:                        return;
0979:                    }
0980:                    throw new IllegalArgumentException(
0981:                            "Bad comparison for type " + type);
0982:                default:
0983:                    switch (mode) {
0984:                    case EQ:
0985:                        intOp = Opcodes.IF_ICMPEQ;
0986:                        break;
0987:                    case NE:
0988:                        intOp = Opcodes.IF_ICMPNE;
0989:                        break;
0990:                    case GE:
0991:                        intOp = Opcodes.IF_ICMPGE;
0992:                        break;
0993:                    case LT:
0994:                        intOp = Opcodes.IF_ICMPLT;
0995:                        break;
0996:                    case LE:
0997:                        intOp = Opcodes.IF_ICMPLE;
0998:                        break;
0999:                    case GT:
1000:                        intOp = Opcodes.IF_ICMPGT;
1001:                        break;
1002:                    }
1003:                    this .mv.visitJumpInsn(intOp, label);
1004:                    return;
1005:                }
1006:                this .mv.visitJumpInsn(jumpMode, label);
1007:            }
1008:
1009:            /**
1010:             * Generates the instructions to jump to a label based on the comparison of
1011:             * the top two integer stack values.
1012:             * 
1013:             * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
1014:             *        LE.
1015:             * @param label where to jump if the comparison result is <tt>true</tt>.
1016:             */
1017:            public void ifICmp(final int mode, final Label label) {
1018:                ifCmp(Type.INT_TYPE, mode, label);
1019:            }
1020:
1021:            /**
1022:             * Generates the instructions to jump to a label based on the comparison of
1023:             * the top integer stack value with zero.
1024:             * 
1025:             * @param mode how these values must be compared. One of EQ, NE, LT, GE, GT,
1026:             *        LE.
1027:             * @param label where to jump if the comparison result is <tt>true</tt>.
1028:             */
1029:            public void ifZCmp(final int mode, final Label label) {
1030:                this .mv.visitJumpInsn(mode, label);
1031:            }
1032:
1033:            /**
1034:             * Generates the instruction to jump to the given label if the top stack
1035:             * value is null.
1036:             * 
1037:             * @param label where to jump if the condition is <tt>true</tt>.
1038:             */
1039:            public void ifNull(final Label label) {
1040:                this .mv.visitJumpInsn(Opcodes.IFNULL, label);
1041:            }
1042:
1043:            /**
1044:             * Generates the instruction to jump to the given label if the top stack
1045:             * value is not null.
1046:             * 
1047:             * @param label where to jump if the condition is <tt>true</tt>.
1048:             */
1049:            public void ifNonNull(final Label label) {
1050:                this .mv.visitJumpInsn(Opcodes.IFNONNULL, label);
1051:            }
1052:
1053:            /**
1054:             * Generates the instruction to jump to the given label.
1055:             * 
1056:             * @param label where to jump if the condition is <tt>true</tt>.
1057:             */
1058:            public void goTo(final Label label) {
1059:                this .mv.visitJumpInsn(Opcodes.GOTO, label);
1060:            }
1061:
1062:            /**
1063:             * Generates a RET instruction.
1064:             * 
1065:             * @param local a local variable identifier, as returned by {@link #newLocal
1066:             *        newLocal}.
1067:             */
1068:            public void ret(final int local) {
1069:                this .mv.visitVarInsn(Opcodes.RET, local);
1070:            }
1071:
1072:            /**
1073:             * Generates the instructions for a switch statement.
1074:             * 
1075:             * @param keys the switch case keys.
1076:             * @param generator a generator to generate the code for the switch cases.
1077:             */
1078:            public void tableSwitch(final int[] keys,
1079:                    final TableSwitchGenerator generator) {
1080:                float density;
1081:                if (keys.length == 0) {
1082:                    density = 0;
1083:                } else {
1084:                    density = (float) keys.length
1085:                            / (keys[keys.length - 1] - keys[0] + 1);
1086:                }
1087:                tableSwitch(keys, generator, density >= 0.5f);
1088:            }
1089:
1090:            /**
1091:             * Generates the instructions for a switch statement.
1092:             * 
1093:             * @param keys the switch case keys.
1094:             * @param generator a generator to generate the code for the switch cases.
1095:             * @param useTable <tt>true</tt> to use a TABLESWITCH instruction, or
1096:             *        <tt>false</tt> to use a LOOKUPSWITCH instruction.
1097:             */
1098:            public void tableSwitch(final int[] keys,
1099:                    final TableSwitchGenerator generator, final boolean useTable) {
1100:                for (int i = 1; i < keys.length; ++i) {
1101:                    if (keys[i] < keys[i - 1]) {
1102:                        throw new IllegalArgumentException(
1103:                                "keys must be sorted ascending");
1104:                    }
1105:                }
1106:                final Label def = newLabel();
1107:                final Label end = newLabel();
1108:                if (keys.length > 0) {
1109:                    final int len = keys.length;
1110:                    final int min = keys[0];
1111:                    final int max = keys[len - 1];
1112:                    final int range = max - min + 1;
1113:                    if (useTable) {
1114:                        final Label[] labels = new Label[range];
1115:                        Arrays.fill(labels, def);
1116:                        for (int i = 0; i < len; ++i) {
1117:                            labels[keys[i] - min] = newLabel();
1118:                        }
1119:                        this .mv.visitTableSwitchInsn(min, max, def, labels);
1120:                        for (int i = 0; i < range; ++i) {
1121:                            final Label label = labels[i];
1122:                            if (label != def) {
1123:                                mark(label);
1124:                                generator.generateCase(i + min, end);
1125:                            }
1126:                        }
1127:                    } else {
1128:                        final Label[] labels = new Label[len];
1129:                        for (int i = 0; i < len; ++i) {
1130:                            labels[i] = newLabel();
1131:                        }
1132:                        this .mv.visitLookupSwitchInsn(def, keys, labels);
1133:                        for (int i = 0; i < len; ++i) {
1134:                            mark(labels[i]);
1135:                            generator.generateCase(keys[i], end);
1136:                        }
1137:                    }
1138:                }
1139:                mark(def);
1140:                generator.generateDefault();
1141:                mark(end);
1142:            }
1143:
1144:            /**
1145:             * Generates the instruction to return the top stack value to the caller.
1146:             */
1147:            public void returnValue() {
1148:                this .mv.visitInsn(this .returnType.getOpcode(Opcodes.IRETURN));
1149:            }
1150:
1151:            // ------------------------------------------------------------------------
1152:            // Instructions to load and store fields
1153:            // ------------------------------------------------------------------------
1154:
1155:            /**
1156:             * Generates a get field or set field instruction.
1157:             * 
1158:             * @param opcode the instruction's opcode.
1159:             * @param ownerType the class in which the field is defined.
1160:             * @param name the name of the field.
1161:             * @param fieldType the type of the field.
1162:             */
1163:            private void fieldInsn(final int opcode, final Type ownerType,
1164:                    final String name, final Type fieldType) {
1165:                this .mv.visitFieldInsn(opcode, ownerType.getInternalName(),
1166:                        name, fieldType.getDescriptor());
1167:            }
1168:
1169:            /**
1170:             * Generates the instruction to push the value of a static field on the
1171:             * stack.
1172:             * 
1173:             * @param owner the class in which the field is defined.
1174:             * @param name the name of the field.
1175:             * @param type the type of the field.
1176:             */
1177:            public void getStatic(final Type owner, final String name,
1178:                    final Type type) {
1179:                fieldInsn(Opcodes.GETSTATIC, owner, name, type);
1180:            }
1181:
1182:            /**
1183:             * Generates the instruction to store the top stack value in a static field.
1184:             * 
1185:             * @param owner the class in which the field is defined.
1186:             * @param name the name of the field.
1187:             * @param type the type of the field.
1188:             */
1189:            public void putStatic(final Type owner, final String name,
1190:                    final Type type) {
1191:                fieldInsn(Opcodes.PUTSTATIC, owner, name, type);
1192:            }
1193:
1194:            /**
1195:             * Generates the instruction to push the value of a non static field on the
1196:             * stack.
1197:             * 
1198:             * @param owner the class in which the field is defined.
1199:             * @param name the name of the field.
1200:             * @param type the type of the field.
1201:             */
1202:            public void getField(final Type owner, final String name,
1203:                    final Type type) {
1204:                fieldInsn(Opcodes.GETFIELD, owner, name, type);
1205:            }
1206:
1207:            /**
1208:             * Generates the instruction to store the top stack value in a non static
1209:             * field.
1210:             * 
1211:             * @param owner the class in which the field is defined.
1212:             * @param name the name of the field.
1213:             * @param type the type of the field.
1214:             */
1215:            public void putField(final Type owner, final String name,
1216:                    final Type type) {
1217:                fieldInsn(Opcodes.PUTFIELD, owner, name, type);
1218:            }
1219:
1220:            // ------------------------------------------------------------------------
1221:            // Instructions to invoke methods
1222:            // ------------------------------------------------------------------------
1223:
1224:            /**
1225:             * Generates an invoke method instruction.
1226:             * 
1227:             * @param opcode the instruction's opcode.
1228:             * @param type the class in which the method is defined.
1229:             * @param method the method to be invoked.
1230:             */
1231:            private void invokeInsn(final int opcode, final Type type,
1232:                    final Method method) {
1233:                final String owner = type.getSort() == Type.ARRAY ? type
1234:                        .getDescriptor() : type.getInternalName();
1235:                this .mv.visitMethodInsn(opcode, owner, method.getName(), method
1236:                        .getDescriptor());
1237:            }
1238:
1239:            /**
1240:             * Generates the instruction to invoke a normal method.
1241:             * 
1242:             * @param owner the class in which the method is defined.
1243:             * @param method the method to be invoked.
1244:             */
1245:            public void invokeVirtual(final Type owner, final Method method) {
1246:                invokeInsn(Opcodes.INVOKEVIRTUAL, owner, method);
1247:            }
1248:
1249:            /**
1250:             * Generates the instruction to invoke a constructor.
1251:             * 
1252:             * @param type the class in which the constructor is defined.
1253:             * @param method the constructor to be invoked.
1254:             */
1255:            public void invokeConstructor(final Type type, final Method method) {
1256:                invokeInsn(Opcodes.INVOKESPECIAL, type, method);
1257:            }
1258:
1259:            /**
1260:             * Generates the instruction to invoke a static method.
1261:             * 
1262:             * @param owner the class in which the method is defined.
1263:             * @param method the method to be invoked.
1264:             */
1265:            public void invokeStatic(final Type owner, final Method method) {
1266:                invokeInsn(Opcodes.INVOKESTATIC, owner, method);
1267:            }
1268:
1269:            /**
1270:             * Generates the instruction to invoke an interface method.
1271:             * 
1272:             * @param owner the class in which the method is defined.
1273:             * @param method the method to be invoked.
1274:             */
1275:            public void invokeInterface(final Type owner, final Method method) {
1276:                invokeInsn(Opcodes.INVOKEINTERFACE, owner, method);
1277:            }
1278:
1279:            // ------------------------------------------------------------------------
1280:            // Instructions to create objects and arrays
1281:            // ------------------------------------------------------------------------
1282:
1283:            /**
1284:             * Generates a type dependent instruction.
1285:             * 
1286:             * @param opcode the instruction's opcode.
1287:             * @param type the instruction's operand.
1288:             */
1289:            private void typeInsn(final int opcode, final Type type) {
1290:                String desc;
1291:                if (type.getSort() == Type.ARRAY) {
1292:                    desc = type.getDescriptor();
1293:                } else {
1294:                    desc = type.getInternalName();
1295:                }
1296:                this .mv.visitTypeInsn(opcode, desc);
1297:            }
1298:
1299:            /**
1300:             * Generates the instruction to create a new object.
1301:             * 
1302:             * @param type the class of the object to be created.
1303:             */
1304:            public void newInstance(final Type type) {
1305:                typeInsn(Opcodes.NEW, type);
1306:            }
1307:
1308:            /**
1309:             * Generates the instruction to create a new array.
1310:             * 
1311:             * @param type the type of the array elements.
1312:             */
1313:            public void newArray(final Type type) {
1314:                int typ;
1315:                switch (type.getSort()) {
1316:                case Type.BOOLEAN:
1317:                    typ = Opcodes.T_BOOLEAN;
1318:                    break;
1319:                case Type.CHAR:
1320:                    typ = Opcodes.T_CHAR;
1321:                    break;
1322:                case Type.BYTE:
1323:                    typ = Opcodes.T_BYTE;
1324:                    break;
1325:                case Type.SHORT:
1326:                    typ = Opcodes.T_SHORT;
1327:                    break;
1328:                case Type.INT:
1329:                    typ = Opcodes.T_INT;
1330:                    break;
1331:                case Type.FLOAT:
1332:                    typ = Opcodes.T_FLOAT;
1333:                    break;
1334:                case Type.LONG:
1335:                    typ = Opcodes.T_LONG;
1336:                    break;
1337:                case Type.DOUBLE:
1338:                    typ = Opcodes.T_DOUBLE;
1339:                    break;
1340:                default:
1341:                    typeInsn(Opcodes.ANEWARRAY, type);
1342:                    return;
1343:                }
1344:                this .mv.visitIntInsn(Opcodes.NEWARRAY, typ);
1345:            }
1346:
1347:            // ------------------------------------------------------------------------
1348:            // Miscelaneous instructions
1349:            // ------------------------------------------------------------------------
1350:
1351:            /**
1352:             * Generates the instruction to compute the length of an array.
1353:             */
1354:            public void arrayLength() {
1355:                this .mv.visitInsn(Opcodes.ARRAYLENGTH);
1356:            }
1357:
1358:            /**
1359:             * Generates the instruction to throw an exception.
1360:             */
1361:            public void throwException() {
1362:                this .mv.visitInsn(Opcodes.ATHROW);
1363:            }
1364:
1365:            /**
1366:             * Generates the instructions to create and throw an exception. The
1367:             * exception class must have a constructor with a single String argument.
1368:             * 
1369:             * @param type the class of the exception to be thrown.
1370:             * @param msg the detailed message of the exception.
1371:             */
1372:            public void throwException(final Type type, final String msg) {
1373:                newInstance(type);
1374:                dup();
1375:                push(msg);
1376:                invokeConstructor(type, Method
1377:                        .getMethod("void <init> (String)"));
1378:                throwException();
1379:            }
1380:
1381:            /**
1382:             * Generates the instruction to check that the top stack value is of the
1383:             * given type.
1384:             * 
1385:             * @param type a class or interface type.
1386:             */
1387:            public void checkCast(final Type type) {
1388:                if (!type.equals(GeneratorAdapter.OBJECT_TYPE)) {
1389:                    typeInsn(Opcodes.CHECKCAST, type);
1390:                }
1391:            }
1392:
1393:            /**
1394:             * Generates the instruction to test if the top stack value is of the given
1395:             * type.
1396:             * 
1397:             * @param type a class or interface type.
1398:             */
1399:            public void instanceOf(final Type type) {
1400:                typeInsn(Opcodes.INSTANCEOF, type);
1401:            }
1402:
1403:            /**
1404:             * Generates the instruction to get the monitor of the top stack value.
1405:             */
1406:            public void monitorEnter() {
1407:                this .mv.visitInsn(Opcodes.MONITORENTER);
1408:            }
1409:
1410:            /**
1411:             * Generates the instruction to release the monitor of the top stack value.
1412:             */
1413:            public void monitorExit() {
1414:                this .mv.visitInsn(Opcodes.MONITOREXIT);
1415:            }
1416:
1417:            // ------------------------------------------------------------------------
1418:            // Non instructions
1419:            // ------------------------------------------------------------------------
1420:
1421:            /**
1422:             * Marks the end of the visited method.
1423:             */
1424:            public void endMethod() {
1425:                if ((this .access & Opcodes.ACC_ABSTRACT) == 0) {
1426:                    this .mv.visitMaxs(0, 0);
1427:                }
1428:            }
1429:
1430:            /**
1431:             * Marks the start of an exception handler.
1432:             * 
1433:             * @param start beginning of the exception handler's scope (inclusive).
1434:             * @param end end of the exception handler's scope (exclusive).
1435:             * @param exception internal name of the type of exceptions handled by the
1436:             *        handler.
1437:             */
1438:            public void catchException(final Label start, final Label end,
1439:                    final Type exception) {
1440:                this.mv.visitTryCatchBlock(start, end, mark(), exception
1441:                        .getInternalName());
1442:            }
1443:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.