Source Code Cross Referenced for ASMAccessorOptimizer.java in  » Scripting » mvel » org » mvel » optimizers » impl » asm » 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 » Scripting » mvel » org.mvel.optimizers.impl.asm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * MVEL (The MVFLEX Expression Language)
0003:         *
0004:         * Copyright (C) 2007 Christopher Brock, MVFLEX/Valhalla Project and the Codehaus
0005:         *
0006:         * Licensed under the Apache License, Version 2.0 (the "License");
0007:         * you may not use this file except in compliance with the License.
0008:         * You may obtain a copy of the License at
0009:         *
0010:         *     http://www.apache.org/licenses/LICENSE-2.0
0011:         *
0012:         * Unless required by applicable law or agreed to in writing, software
0013:         * distributed under the License is distributed on an "AS IS" BASIS,
0014:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:         * See the License for the specific language governing permissions and
0016:         * limitations under the License.
0017:         *
0018:         */package org.mvel.optimizers.impl.asm;
0019:
0020:        import org.mvel.*;
0021:        import static org.mvel.DataConversion.canConvert;
0022:        import static org.mvel.DataConversion.convert;
0023:        import static org.mvel.MVEL.isAdvancedDebugging;
0024:        import org.mvel.asm.ClassWriter;
0025:        import org.mvel.asm.Label;
0026:        import org.mvel.asm.MethodVisitor;
0027:        import org.mvel.asm.Opcodes;
0028:        import static org.mvel.asm.Opcodes.*;
0029:        import static org.mvel.asm.Type.*;
0030:        import org.mvel.ast.Function;
0031:        import org.mvel.compiler.Accessor;
0032:        import org.mvel.compiler.ExecutableLiteral;
0033:        import org.mvel.compiler.ExecutableStatement;
0034:        import org.mvel.integration.VariableResolverFactory;
0035:        import org.mvel.optimizers.AbstractOptimizer;
0036:        import org.mvel.optimizers.AccessorOptimizer;
0037:        import org.mvel.optimizers.OptimizationNotSupported;
0038:        import org.mvel.optimizers.impl.refl.Union;
0039:        import static org.mvel.util.ArrayTools.findFirst;
0040:        import org.mvel.util.*;
0041:        import static org.mvel.util.ParseTools.*;
0042:
0043:        import java.io.FileWriter;
0044:        import java.io.IOException;
0045:        import static java.lang.System.getProperty;
0046:        import static java.lang.reflect.Array.getLength;
0047:        import java.lang.reflect.*;
0048:        import java.util.ArrayList;
0049:        import java.util.Arrays;
0050:        import java.util.List;
0051:        import java.util.Map;
0052:
0053:        /**
0054:         * Implementation of the MVEL Just-in-Time (JIT) compiler for Property Accessors using the ASM bytecode
0055:         * engineering library.
0056:         * <p/>
0057:         * TODO: This class needs serious re-factoring.
0058:         */
0059:        @SuppressWarnings({"TypeParameterExplicitlyExtendsObject","unchecked","UnusedDeclaration"})
0060:        public class ASMAccessorOptimizer extends AbstractOptimizer implements 
0061:                AccessorOptimizer {
0062:            private static final String MAP_IMPL = "java/util/HashMap";
0063:            private static final String LIST_IMPL = "org/mvel/util/FastList";
0064:
0065:            private static final int OPCODES_VERSION;
0066:
0067:            static {
0068:                final String javaVersion = getProperty("java.version");
0069:                if (javaVersion.startsWith("1.4"))
0070:                    OPCODES_VERSION = Opcodes.V1_4;
0071:                else if (javaVersion.startsWith("1.5"))
0072:                    OPCODES_VERSION = Opcodes.V1_5;
0073:                else if (javaVersion.startsWith("1.6")
0074:                        || javaVersion.startsWith("1.7"))
0075:                    OPCODES_VERSION = Opcodes.V1_6;
0076:                else
0077:                    OPCODES_VERSION = Opcodes.V1_2;
0078:            }
0079:
0080:            private Object ctx;
0081:            private Object this Ref;
0082:
0083:            private VariableResolverFactory variableFactory;
0084:
0085:            private static final Object[] EMPTYARG = new Object[0];
0086:            private static final Class[] EMPTYCLS = new Class[0];
0087:
0088:            private boolean first = true;
0089:            private boolean deferFinish = false;
0090:            private boolean literal = false;
0091:
0092:            private String className;
0093:            private ClassWriter cw;
0094:            private MethodVisitor mv;
0095:
0096:            private Object val;
0097:            private int stacksize = 1;
0098:            private int maxlocals = 1;
0099:            private long time;
0100:
0101:            private ArrayList<ExecutableStatement> compiledInputs;
0102:
0103:            private Class returnType;
0104:
0105:            @SuppressWarnings({"StringBufferField"})
0106:            private StringAppender buildLog;
0107:
0108:            public ASMAccessorOptimizer() {
0109:                //do this to confirm we're running the correct version
0110:                //otherwise should create a verification error in VM
0111:                new ClassWriter(ClassWriter.COMPUTE_MAXS);
0112:            }
0113:
0114:            /**
0115:             * Does all the boilerplate for initiating the JIT.
0116:             */
0117:            private void _initJIT() {
0118:                if (isAdvancedDebugging()) {
0119:                    buildLog = new StringAppender();
0120:                }
0121:
0122:                cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
0123:                        + ClassWriter.COMPUTE_FRAMES);
0124:
0125:                synchronized (Runtime.getRuntime()) {
0126:                    int r = (int) Math.random() * 100;
0127:                    cw.visit(OPCODES_VERSION, Opcodes.ACC_PUBLIC
0128:                            + Opcodes.ACC_SUPER, className = "ASMAccessorImpl_"
0129:                            + String.valueOf(cw.hashCode()).replaceAll("\\-",
0130:                                    "_") + (System.currentTimeMillis() / 10)
0131:                            + r, null, "java/lang/Object",
0132:                            new String[] { "org/mvel/compiler/Accessor" });
0133:                }
0134:
0135:                MethodVisitor m = cw.visitMethod(ACC_PUBLIC, "<init>", "()V",
0136:                        null, null);
0137:                m.visitCode();
0138:                m.visitVarInsn(Opcodes.ALOAD, 0);
0139:                m.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>",
0140:                        "()V");
0141:                m.visitInsn(RETURN);
0142:
0143:                m.visitMaxs(1, 1);
0144:                m.visitEnd();
0145:
0146:                mv = cw
0147:                        .visitMethod(
0148:                                ACC_PUBLIC,
0149:                                "getValue",
0150:                                "(Ljava/lang/Object;Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;)Ljava/lang/Object;",
0151:                                null, null);
0152:                mv.visitCode();
0153:            }
0154:
0155:            public Accessor optimizeAccessor(char[] property,
0156:                    Object staticContext, Object this Ref,
0157:                    VariableResolverFactory factory, boolean root) {
0158:                time = System.currentTimeMillis();
0159:
0160:                //inputs = 0;
0161:                compiledInputs = new ArrayList<ExecutableStatement>();
0162:
0163:                start = cursor = 0;
0164:
0165:                this .first = true;
0166:                this .val = null;
0167:
0168:                this .length = property.length;
0169:                this .expr = property;
0170:                this .ctx = staticContext;
0171:                this .this Ref = this Ref;
0172:                this .variableFactory = factory;
0173:
0174:                _initJIT();
0175:
0176:                return compileAccessor();
0177:            }
0178:
0179:            public SetAccessor optimizeSetAccessor(char[] property, Object ctx,
0180:                    Object this Ref, VariableResolverFactory factory,
0181:                    boolean rootThisRef, Object value) {
0182:                throw new RuntimeException("not implemented");
0183:            }
0184:
0185:            private void _finishJIT() {
0186:                if (!deferFinish) {
0187:
0188:                    if (returnType != null && returnType.isPrimitive()) {
0189:                        //noinspection unchecked
0190:                        wrapPrimitive(returnType);
0191:                    }
0192:
0193:                    if (returnType == void.class) {
0194:                        assert debug("ACONST_NULL");
0195:                        mv.visitInsn(ACONST_NULL);
0196:                    }
0197:
0198:                    assert debug("ARETURN");
0199:
0200:                    mv.visitInsn(ARETURN);
0201:                }
0202:
0203:                assert debug("\n{METHOD STATS (maxstack=" + stacksize + ")}\n");
0204:                mv.visitMaxs(stacksize, maxlocals);
0205:
0206:                mv.visitEnd();
0207:
0208:                buildInputs();
0209:
0210:                cw.visitEnd();
0211:
0212:                dumpAdvancedDebugging(); // dump advanced debugging if necessary
0213:            }
0214:
0215:            private Accessor _initializeAccessor() throws Exception {
0216:
0217:                /**
0218:                 * Hot load the class we just generated.
0219:                 */
0220:                Class cls = loadClass(className, cw.toByteArray());
0221:
0222:                assert debug("[MVEL JIT Completed Optimization <<"
0223:                        + new String(expr) + ">>]::" + cls + " (time: "
0224:                        + (System.currentTimeMillis() - time) + "ms)");
0225:
0226:                Object o;
0227:
0228:                try {
0229:                    if (compiledInputs.size() == 0) {
0230:                        o = cls.newInstance();
0231:                    } else {
0232:                        Class[] parms = new Class[compiledInputs.size()];
0233:                        for (int i = 0; i < compiledInputs.size(); i++) {
0234:                            parms[i] = ExecutableStatement.class;
0235:                        }
0236:                        o = cls
0237:                                .getConstructor(parms)
0238:                                .newInstance(
0239:                                        compiledInputs
0240:                                                .toArray(new ExecutableStatement[compiledInputs
0241:                                                        .size()]));
0242:                    }
0243:                } catch (VerifyError e) {
0244:                    System.out
0245:                            .println("**** COMPILER BUG! REPORT THIS IMMEDIATELY AT http://jira.codehaus.org/browse/mvel");
0246:                    System.out.println("Expression: " + new String(expr));
0247:                    throw e;
0248:                }
0249:
0250:                if (!(o instanceof  Accessor)) {
0251:                    dumpAdvancedDebugging();
0252:                    throw new RuntimeException(
0253:                            "Classloader problem detected. JIT Class is not subclass of org.mvel.compiler.Accessor.");
0254:                }
0255:
0256:                return (Accessor) o;
0257:            }
0258:
0259:            private Accessor compileAccessor() {
0260:                assert debug("<<INITIATE COMPILE>>");
0261:
0262:                Object curr = ctx;
0263:
0264:                try {
0265:                    while (cursor < length) {
0266:                        switch (nextSubToken()) {
0267:                        case BEAN:
0268:                            curr = getBeanProperty(curr, capture());
0269:                            break;
0270:                        case METH:
0271:                            curr = getMethod(curr, capture());
0272:                            break;
0273:                        case COL:
0274:                            curr = getCollectionProperty(curr, capture());
0275:                            break;
0276:                        }
0277:
0278:                        // check to see if a null safety is enabled on this property.
0279:                        if (fields == -1) {
0280:                            if (curr == null) {
0281:                                break;
0282:                            } else {
0283:                                fields = 0;
0284:                            }
0285:                        }
0286:
0287:                        first = false;
0288:                    }
0289:
0290:                    val = curr;
0291:
0292:                    _finishJIT();
0293:
0294:                    return _initializeAccessor();
0295:                } catch (InvocationTargetException e) {
0296:                    throw new PropertyAccessException(new String(expr), e);
0297:                } catch (IllegalAccessException e) {
0298:                    throw new PropertyAccessException(new String(expr), e);
0299:                } catch (IndexOutOfBoundsException e) {
0300:                    throw new PropertyAccessException(new String(expr), e);
0301:                } catch (PropertyAccessException e) {
0302:                    //    throw new PropertyAccessException(e.getMessage(), e);
0303:                    throw new CompileException(e.getMessage(), e);
0304:                } catch (CompileException e) {
0305:                    throw e;
0306:                } catch (NullPointerException e) {
0307:                    throw new PropertyAccessException(new String(expr), e);
0308:                } catch (OptimizationNotSupported e) {
0309:                    throw e;
0310:                } catch (Exception e) {
0311:                    //  throw new PropertyAccessException(new String(expr), e);
0312:                    throw new CompileException(e.getMessage(), e);
0313:                }
0314:            }
0315:
0316:            private Object getBeanProperty(Object ctx, String property)
0317:                    throws IllegalAccessException, InvocationTargetException {
0318:
0319:                assert debug("\n  **  ENTER -> {bean: " + property + "; ctx="
0320:                        + ctx + "}");
0321:
0322:                if (returnType != null && returnType.isPrimitive()) {
0323:                    //noinspection unchecked
0324:                    wrapPrimitive(returnType);
0325:                }
0326:
0327:                Class cls = (ctx instanceof  Class ? ((Class) ctx)
0328:                        : ctx != null ? ctx.getClass() : null);
0329:                Member member = cls != null ? PropertyTools.getFieldOrAccessor(
0330:                        cls, property) : null;
0331:
0332:                if (first) {
0333:                    if ("this".equals(property)) {
0334:                        assert debug("ALOAD 2");
0335:                        mv.visitVarInsn(ALOAD, 2);
0336:                        return this Ref;
0337:                    } else if (variableFactory != null
0338:                            && variableFactory.isResolveable(property)) {
0339:                        if (variableFactory.isIndexedFactory()
0340:                                && variableFactory.isTarget(property)) {
0341:                            int idx;
0342:                            try {
0343:                                loadVariableByIndex(idx = variableFactory
0344:                                        .variableIndexOf(property));
0345:                            } catch (Exception e) {
0346:                                throw new OptimizationFailure(property);
0347:                            }
0348:
0349:                            return variableFactory.getIndexedVariableResolver(
0350:                                    idx).getValue();
0351:                        } else {
0352:                            try {
0353:                                loadVariableByName(property);
0354:                            } catch (Exception e) {
0355:                                throw new OptimizationFailure(
0356:                                        "critical error in JIT", e);
0357:                            }
0358:
0359:                            return variableFactory
0360:                                    .getVariableResolver(property).getValue();
0361:                        }
0362:                    } else {
0363:                        assert debug("ALOAD 1");
0364:                        mv.visitVarInsn(ALOAD, 1);
0365:                    }
0366:                }
0367:
0368:                if (member instanceof  Field) {
0369:                    Object o = ((Field) member).get(ctx);
0370:
0371:                    if (first) {
0372:                        assert debug("ALOAD 1 (A)");
0373:                        mv.visitVarInsn(ALOAD, 1);
0374:                    }
0375:
0376:                    if (((member.getModifiers() & Modifier.STATIC) != 0)) {
0377:                        assert debug("GETSTATIC "
0378:                                + getDescriptor(member.getDeclaringClass())
0379:                                + "." + member.getName() + "::"
0380:                                + getDescriptor(((Field) member).getType()));
0381:
0382:                        mv.visitFieldInsn(GETSTATIC, getInternalName(member
0383:                                .getDeclaringClass()), member.getName(),
0384:                                getDescriptor(returnType = ((Field) member)
0385:                                        .getType()));
0386:                    } else {
0387:                        assert debug("CHECKCAST " + getInternalName(cls));
0388:                        mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
0389:
0390:                        assert debug("GETFIELD " + property + ":"
0391:                                + getDescriptor(((Field) member).getType()));
0392:                        mv.visitFieldInsn(GETFIELD, getInternalName(cls),
0393:                                property,
0394:                                getDescriptor(returnType = ((Field) member)
0395:                                        .getType()));
0396:                    }
0397:
0398:                    returnType = ((Field) member).getType();
0399:
0400:                    return o;
0401:                } else if (member != null) {
0402:                    Object o;
0403:
0404:                    if (first) {
0405:                        assert debug("ALOAD 1 (B)");
0406:                        mv.visitVarInsn(ALOAD, 1);
0407:                    }
0408:
0409:                    try {
0410:                        o = ((Method) member).invoke(ctx, EMPTYARG);
0411:
0412:                        if (returnType != member.getDeclaringClass()) {
0413:                            assert debug("CHECKCAST "
0414:                                    + getInternalName(member
0415:                                            .getDeclaringClass()));
0416:                            mv.visitTypeInsn(CHECKCAST, getInternalName(member
0417:                                    .getDeclaringClass()));
0418:                        }
0419:
0420:                        returnType = ((Method) member).getReturnType();
0421:
0422:                        assert debug("INVOKEVIRTUAL " + member.getName() + ":"
0423:                                + returnType);
0424:                        mv.visitMethodInsn(INVOKEVIRTUAL,
0425:                                getInternalName(member.getDeclaringClass()),
0426:                                member.getName(),
0427:                                getMethodDescriptor((Method) member));
0428:                    } catch (IllegalAccessException e) {
0429:                        Method iFaceMeth = determineActualTargetMethod((Method) member);
0430:
0431:                        assert debug("CHECKCAST "
0432:                                + getInternalName(iFaceMeth.getDeclaringClass()));
0433:                        mv.visitTypeInsn(CHECKCAST, getInternalName(iFaceMeth
0434:                                .getDeclaringClass()));
0435:
0436:                        returnType = iFaceMeth.getReturnType();
0437:
0438:                        assert debug("INVOKEINTERFACE " + member.getName()
0439:                                + ":" + returnType);
0440:                        mv.visitMethodInsn(INVOKEINTERFACE,
0441:                                getInternalName(iFaceMeth.getDeclaringClass()),
0442:                                member.getName(),
0443:                                getMethodDescriptor((Method) member));
0444:
0445:                        o = iFaceMeth.invoke(ctx, EMPTYARG);
0446:                    }
0447:                    return o;
0448:
0449:                } else if (ctx instanceof  Map
0450:                        && ((Map) ctx).containsKey(property)) {
0451:                    assert debug("CHECKCAST java/util/Map");
0452:                    mv.visitTypeInsn(CHECKCAST, "java/util/Map");
0453:
0454:                    assert debug("LDC: \"" + property + "\"");
0455:                    mv.visitLdcInsn(property);
0456:
0457:                    assert debug("INVOKEINTERFACE: get");
0458:                    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get",
0459:                            "(Ljava/lang/Object;)Ljava/lang/Object;");
0460:                    return ((Map) ctx).get(property);
0461:                } else if (first && "this".equals(property)) {
0462:                    assert debug("ALOAD 2");
0463:                    mv.visitVarInsn(ALOAD, 2); // load the thisRef value.
0464:
0465:                    return this .this Ref;
0466:                } else if ("length".equals(property)
0467:                        && ctx.getClass().isArray()) {
0468:                    anyArrayCheck(ctx.getClass());
0469:
0470:                    assert debug("ARRAYLENGTH");
0471:                    mv.visitInsn(ARRAYLENGTH);
0472:
0473:                    wrapPrimitive(int.class);
0474:                    return getLength(ctx);
0475:                } else if (LITERALS.containsKey(property)) {
0476:                    Object lit = LITERALS.get(property);
0477:
0478:                    if (lit instanceof  Class) {
0479:                        ldcClassConstant((Class) lit);
0480:                    }
0481:
0482:                    return LITERALS.get(property);
0483:                } else if (ctx == null) {
0484:                    throw new NullPointerException("parent field of '"
0485:                            + property + "' is null in: " + new String(expr));
0486:                } else {
0487:                    Object ts = tryStaticAccess();
0488:
0489:                    if (ts != null) {
0490:                        if (ts instanceof  Class) {
0491:                            ldcClassConstant((Class) ts);
0492:                            return ts;
0493:                        } else if (ts instanceof  Method) {
0494:                            writeFunctionPointerStub(((Method) ts)
0495:                                    .getDeclaringClass(), (Method) ts);
0496:                            return ts;
0497:                        } else {
0498:                            assert debug("GETSTATIC "
0499:                                    + getDescriptor(((Field) ts)
0500:                                            .getDeclaringClass()) + "."
0501:                                    + ((Field) ts).getName() + "::"
0502:                                    + getDescriptor(((Field) ts).getType()));
0503:
0504:                            mv.visitFieldInsn(GETSTATIC,
0505:                                    getDescriptor(((Field) ts)
0506:                                            .getDeclaringClass()), ((Field) ts)
0507:                                            .getName(),
0508:                                    getDescriptor(returnType = ((Field) ts)
0509:                                            .getType()));
0510:
0511:                            return ((Field) ts).get(null);
0512:                        }
0513:                    } else if (ctx instanceof  Class) {
0514:                        /**
0515:                         * This is our ugly support for function pointers.  This works but needs to be re-thought out at some
0516:                         * point.
0517:                         */
0518:                        Class c = (Class) ctx;
0519:                        for (Method m : c.getMethods()) {
0520:                            if (property.equals(m.getName())) {
0521:                                writeFunctionPointerStub(c, m);
0522:                                return m;
0523:                            }
0524:                        }
0525:                    }
0526:
0527:                    throw new PropertyAccessException(property);
0528:                }
0529:            }
0530:
0531:            private void writeFunctionPointerStub(Class c, Method m) {
0532:                ldcClassConstant(c);
0533:
0534:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
0535:                        "getMethods", "()[Ljava/lang/reflect/Method;");
0536:                mv.visitVarInsn(ASTORE, 7);
0537:                mv.visitInsn(ICONST_0);
0538:                mv.visitVarInsn(ISTORE, 5);
0539:                mv.visitVarInsn(ALOAD, 7);
0540:                mv.visitInsn(ARRAYLENGTH);
0541:                mv.visitVarInsn(ISTORE, 6);
0542:                Label l1 = new Label();
0543:                mv.visitJumpInsn(GOTO, l1);
0544:                Label l2 = new Label();
0545:                mv.visitLabel(l2);
0546:                mv.visitVarInsn(ALOAD, 7);
0547:                mv.visitVarInsn(ILOAD, 5);
0548:                mv.visitInsn(AALOAD);
0549:                mv.visitVarInsn(ASTORE, 4);
0550:                Label l3 = new Label();
0551:                mv.visitLabel(l3);
0552:                mv.visitLdcInsn(m.getName());
0553:                mv.visitVarInsn(ALOAD, 4);
0554:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Method",
0555:                        "getName", "()Ljava/lang/String;");
0556:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals",
0557:                        "(Ljava/lang/Object;)Z");
0558:                Label l4 = new Label();
0559:                mv.visitJumpInsn(IFEQ, l4);
0560:                Label l5 = new Label();
0561:                mv.visitLabel(l5);
0562:                mv.visitVarInsn(ALOAD, 4);
0563:                mv.visitInsn(ARETURN);
0564:                mv.visitLabel(l4);
0565:                mv.visitIincInsn(5, 1);
0566:                mv.visitLabel(l1);
0567:                mv.visitVarInsn(ILOAD, 5);
0568:                mv.visitVarInsn(ILOAD, 6);
0569:                mv.visitJumpInsn(IF_ICMPLT, l2);
0570:                Label l6 = new Label();
0571:                mv.visitLabel(l6);
0572:                mv.visitInsn(ACONST_NULL);
0573:                mv.visitInsn(ARETURN);
0574:
0575:                deferFinish = true;
0576:            }
0577:
0578:            private Object getCollectionProperty(Object ctx, String prop)
0579:                    throws IllegalAccessException, InvocationTargetException {
0580:                if (prop.length() > 0)
0581:                    ctx = getBeanProperty(ctx, prop);
0582:
0583:                assert debug("\n  **  ENTER -> {collections: " + prop
0584:                        + "; ctx=" + ctx + "}");
0585:
0586:                int start = ++cursor;
0587:
0588:                whiteSpaceSkip();
0589:
0590:                if (cursor == length)
0591:                    throw new CompileException("unterminated '['");
0592:
0593:                if (!scanTo(']'))
0594:                    throw new CompileException("unterminated '['");
0595:
0596:                String tk = new String(expr, start, cursor - start);
0597:
0598:                assert debug("{collection token:<<" + tk + ">>}");
0599:
0600:                ExecutableStatement compiled = (ExecutableStatement) subCompileExpression(tk);
0601:                Object item = compiled.getValue(ctx, variableFactory);
0602:
0603:                ++cursor;
0604:
0605:                if (ctx instanceof  Map) {
0606:                    assert debug("CHECKCAST java/util/Map");
0607:                    mv.visitTypeInsn(CHECKCAST, "java/util/Map");
0608:
0609:                    Class c = writeLiteralOrSubexpression(compiled);
0610:                    if (c != null && c.isPrimitive()) {
0611:                        wrapPrimitive(c);
0612:                    }
0613:
0614:                    assert debug("INVOKEINTERFACE: get");
0615:                    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get",
0616:                            "(Ljava/lang/Object;)Ljava/lang/Object;");
0617:
0618:                    return ((Map) ctx).get(item);
0619:                } else if (ctx instanceof  List) {
0620:                    assert debug("CHECKCAST java/util/List");
0621:                    mv.visitTypeInsn(CHECKCAST, "java/util/List");
0622:
0623:                    writeLiteralOrSubexpression(compiled, int.class);
0624:
0625:                    assert debug("INVOKEINTERFACE: java/util/List.get");
0626:                    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List",
0627:                            "get", "(I)Ljava/lang/Object;");
0628:
0629:                    return ((List) ctx).get(convert(item, Integer.class));
0630:
0631:                } else if (ctx instanceof  Object[]) {
0632:                    assert debug("CHECKCAST [Ljava/lang/Object;");
0633:                    mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
0634:
0635:                    writeLiteralOrSubexpression(compiled, int.class, item
0636:                            .getClass());
0637:
0638:                    assert debug("AALOAD");
0639:                    mv.visitInsn(AALOAD);
0640:
0641:                    return ((Object[]) ctx)[convert(item, Integer.class)];
0642:                } else if (ctx instanceof  CharSequence) {
0643:
0644:                    assert debug("CHECKCAST java/lang/CharSequence");
0645:                    mv.visitTypeInsn(CHECKCAST, "java/lang/CharSequence");
0646:
0647:                    if (item instanceof  Integer) {
0648:                        intPush((Integer) item);
0649:
0650:                        assert debug("INVOKEINTERFACE java/lang/CharSequence.charAt");
0651:                        mv.visitMethodInsn(INVOKEINTERFACE,
0652:                                "java/lang/CharSequence", "charAt", "(I)C");
0653:
0654:                        wrapPrimitive(char.class);
0655:
0656:                        return ((CharSequence) ctx).charAt((Integer) item);
0657:                    } else {
0658:                        writeLiteralOrSubexpression(compiled, Integer.class);
0659:                        unwrapPrimitive(int.class);
0660:
0661:                        assert debug("INVOKEINTERFACE java/lang/CharSequence.charAt");
0662:                        mv.visitMethodInsn(INVOKEINTERFACE,
0663:                                "java/lang/CharSequence", "charAt", "(I)C");
0664:
0665:                        wrapPrimitive(char.class);
0666:
0667:                        return ((CharSequence) ctx).charAt(convert(item,
0668:                                Integer.class));
0669:
0670:                    }
0671:                } else {
0672:                    throw new CompileException(
0673:                            "illegal use of []: unknown type: "
0674:                                    + (ctx == null ? null : ctx.getClass()
0675:                                            .getName()));
0676:                }
0677:            }
0678:
0679:            @SuppressWarnings({"unchecked"})
0680:            private Object getMethod(Object ctx, String name)
0681:                    throws IllegalAccessException, InvocationTargetException {
0682:                assert debug("\n  **  {method: " + name + "}");
0683:
0684:                int st = cursor;
0685:                String tk = ((cursor = ParseTools.balancedCapture(expr, cursor,
0686:                        '(')) - st) > 1 ? new String(expr, st + 1, cursor - st
0687:                        - 1) : "";
0688:                cursor++;
0689:
0690:                Object[] preConvArgs;
0691:                Object[] args;
0692:                ExecutableStatement[] es;
0693:
0694:                if (tk.length() == 0) {
0695:                    //noinspection ZeroLengthArrayAllocation
0696:                    args = new Object[0];
0697:
0698:                    //noinspection ZeroLengthArrayAllocation
0699:                    preConvArgs = new Object[0];
0700:                    es = null;
0701:                } else {
0702:                    String[] subtokens = parseParameterList(tk.toCharArray(),
0703:                            0, -1);
0704:
0705:                    es = new ExecutableStatement[subtokens.length];
0706:                    args = new Object[subtokens.length];
0707:                    preConvArgs = new Object[es.length];
0708:
0709:                    for (int i = 0; i < subtokens.length; i++) {
0710:                        preConvArgs[i] = args[i] = (es[i] = (ExecutableStatement) subCompileExpression(subtokens[i]))
0711:                                .getValue(this .ctx, this .this Ref,
0712:                                        variableFactory);
0713:                    }
0714:                }
0715:
0716:                if (first && variableFactory != null
0717:                        && variableFactory.isResolveable(name)) {
0718:                    Object ptr = variableFactory.getVariableResolver(name)
0719:                            .getValue();
0720:
0721:                    if (ptr instanceof  Method) {
0722:                        ctx = ((Method) ptr).getDeclaringClass();
0723:                        name = ((Method) ptr).getName();
0724:                    } else if (ptr instanceof  MethodStub) {
0725:                        ctx = ((MethodStub) ptr).getClassReference();
0726:                        name = ((MethodStub) ptr).getMethodName();
0727:                    } else if (ptr instanceof  Function) {
0728:
0729:                        if (es != null && es.length != 0) {
0730:                            compiledInputs.addAll(Arrays.asList(es));
0731:
0732:                            intPush(es.length);
0733:
0734:                            assert debug("ANEWARRAY [" + es.length + "]");
0735:                            mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
0736:
0737:                            assert debug("ASTORE 4");
0738:                            mv.visitVarInsn(ASTORE, 4);
0739:
0740:                            for (int i = 0; i < es.length; i++) {
0741:                                assert debug("ALOAD 4");
0742:                                mv.visitVarInsn(ALOAD, 4);
0743:                                intPush(i);
0744:                                loadField(i);
0745:
0746:                                assert debug("ALOAD 1");
0747:                                mv.visitVarInsn(ALOAD, 1);
0748:
0749:                                assert debug("ALOAD 3");
0750:                                mv.visitIntInsn(ALOAD, 3);
0751:
0752:                                assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
0753:                                mv
0754:                                        .visitMethodInsn(
0755:                                                INVOKEINTERFACE,
0756:                                                "org/mvel/compiler/ExecutableStatement",
0757:                                                "getValue",
0758:                                                "(Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;)Ljava/lang/Object;");
0759:
0760:                                assert debug("AASTORE");
0761:                                mv.visitInsn(AASTORE);
0762:                            }
0763:
0764:                        } else {
0765:                            assert debug("ACONST_NULL");
0766:                            mv.visitInsn(ACONST_NULL);
0767:
0768:                            assert debug("CHECKCAST java/lang/Object");
0769:                            mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
0770:
0771:                            assert debug("ASTORE 4");
0772:                            mv.visitVarInsn(ASTORE, 4);
0773:                        }
0774:
0775:                        if (variableFactory.isIndexedFactory()
0776:                                && variableFactory.isTarget(name)) {
0777:                            loadVariableByIndex(variableFactory
0778:                                    .variableIndexOf(name));
0779:                        } else {
0780:                            loadVariableByName(name);
0781:                        }
0782:
0783:                        checkcast(Function.class);
0784:
0785:                        assert debug("ALOAD 1");
0786:                        mv.visitVarInsn(ALOAD, 1);
0787:
0788:                        assert debug("ALOAD 2");
0789:                        mv.visitVarInsn(ALOAD, 2);
0790:
0791:                        assert debug("ALOAD 3");
0792:                        mv.visitVarInsn(ALOAD, 3);
0793:
0794:                        assert debug("ALOAD 4");
0795:                        mv.visitVarInsn(ALOAD, 4);
0796:
0797:                        assert debug("INVOKEVIRTUAL Function.call");
0798:                        mv
0799:                                .visitMethodInsn(
0800:                                        INVOKEVIRTUAL,
0801:                                        getInternalName(Function.class),
0802:                                        "call",
0803:                                        "(Ljava/lang/Object;Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;[Ljava/lang/Object;)Ljava/lang/Object;");
0804:
0805:                        Object[] parm = null;
0806:
0807:                        if (es != null) {
0808:                            parm = new Object[es.length];
0809:                            for (int i = 0; i < es.length; i++) {
0810:                                parm[i] = es[i].getValue(ctx, this Ref,
0811:                                        variableFactory);
0812:                            }
0813:                        }
0814:
0815:                        return ((Function) ptr).call(ctx, this Ref,
0816:                                variableFactory, parm);
0817:                    } else {
0818:                        throw new OptimizationFailure(
0819:                                "attempt to optimize a method call for a reference that does not point to a method: "
0820:                                        + name
0821:                                        + " (reference is type: "
0822:                                        + (ctx != null ? ctx.getClass()
0823:                                                .getName() : null) + ")");
0824:                    }
0825:
0826:                    first = false;
0827:                } else if (returnType != null && returnType.isPrimitive()) {
0828:                    //noinspection unchecked
0829:                    wrapPrimitive(returnType);
0830:                }
0831:
0832:                int inputsOffset = compiledInputs.size();
0833:
0834:                if (es != null) {
0835:                    for (ExecutableStatement e : es) {
0836:                        if (e instanceof  ExecutableLiteral) {
0837:                            continue;
0838:                        }
0839:
0840:                        compiledInputs.add(e);
0841:                    }
0842:                }
0843:
0844:                if (first) {
0845:                    assert debug("ALOAD 1 (D) ");
0846:                    mv.visitVarInsn(ALOAD, 1);
0847:                }
0848:
0849:                /**
0850:                 * If the target object is an instance of java.lang.Class itself then do not
0851:                 * adjust the Class scope target.
0852:                 */
0853:                Class cls = ctx instanceof  Class ? (Class) ctx : ctx.getClass();
0854:
0855:                Method m;
0856:                Class[] parameterTypes = null;
0857:
0858:                /**
0859:                 * Try to find an instance method from the class target.
0860:                 */
0861:                if ((m = getBestCandidate(args, name, cls, cls.getMethods())) != null) {
0862:                    parameterTypes = m.getParameterTypes();
0863:                }
0864:
0865:                if (m == null) {
0866:                    /**
0867:                     * If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
0868:                     */
0869:                    if ((m = getBestCandidate(args, name, cls, cls.getClass()
0870:                            .getDeclaredMethods())) != null) {
0871:                        parameterTypes = m.getParameterTypes();
0872:                    }
0873:                }
0874:
0875:                if (m == null) {
0876:                    StringAppender errorBuild = new StringAppender();
0877:
0878:                    if (parameterTypes != null) {
0879:                        for (int i = 0; i < args.length; i++) {
0880:                            errorBuild
0881:                                    .append(parameterTypes[i] != null ? parameterTypes[i]
0882:                                            .getClass().getName()
0883:                                            : null);
0884:                            if (i < args.length - 1)
0885:                                errorBuild.append(", ");
0886:                        }
0887:                    }
0888:
0889:                    if ("size".equals(name) && args.length == 0
0890:                            && cls.isArray()) {
0891:                        anyArrayCheck(cls);
0892:
0893:                        assert debug("ARRAYLENGTH");
0894:                        mv.visitInsn(ARRAYLENGTH);
0895:
0896:                        wrapPrimitive(int.class);
0897:                        return getLength(ctx);
0898:                    }
0899:
0900:                    throw new CompileException("unable to resolve method: "
0901:                            + cls.getName() + "." + name + "("
0902:                            + errorBuild.toString() + ") [arglength="
0903:                            + args.length + "]");
0904:                } else {
0905:                    m = getWidenedTarget(m);
0906:
0907:                    if (es != null) {
0908:                        ExecutableStatement cExpr;
0909:                        for (int i = 0; i < es.length; i++) {
0910:                            if ((cExpr = es[i]).getKnownIngressType() == null) {
0911:                                cExpr.setKnownIngressType(parameterTypes[i]);
0912:                                cExpr.computeTypeConversionRule();
0913:                            }
0914:                            if (!cExpr.isConvertableIngressEgress()) {
0915:                                args[i] = convert(args[i], parameterTypes[i]);
0916:                            }
0917:                        }
0918:                    } else {
0919:                        /**
0920:                         * Coerce any types if required.
0921:                         */
0922:                        for (int i = 0; i < args.length; i++) {
0923:                            args[i] = convert(args[i], parameterTypes[i]);
0924:                        }
0925:                    }
0926:
0927:                    if (m.getParameterTypes().length == 0) {
0928:                        if ((m.getModifiers() & Modifier.STATIC) != 0) {
0929:                            assert debug("INVOKESTATIC " + m.getName());
0930:                            mv.visitMethodInsn(INVOKESTATIC, getInternalName(m
0931:                                    .getDeclaringClass()), m.getName(),
0932:                                    getMethodDescriptor(m));
0933:                        } else {
0934:                            assert debug("CHECKCAST "
0935:                                    + getInternalName(m.getDeclaringClass()));
0936:                            mv.visitTypeInsn(CHECKCAST, getInternalName(m
0937:                                    .getDeclaringClass()));
0938:
0939:                            if (m.getDeclaringClass().isInterface()) {
0940:                                assert debug("INVOKEINTERFACE " + m.getName());
0941:                                mv.visitMethodInsn(INVOKEINTERFACE,
0942:                                        getInternalName(m.getDeclaringClass()),
0943:                                        m.getName(), getMethodDescriptor(m));
0944:
0945:                            } else {
0946:                                assert debug("INVOKEVIRTUAL " + m.getName());
0947:                                mv.visitMethodInsn(INVOKEVIRTUAL,
0948:                                        getInternalName(m.getDeclaringClass()),
0949:                                        m.getName(), getMethodDescriptor(m));
0950:                            }
0951:                        }
0952:
0953:                        returnType = m.getReturnType();
0954:
0955:                        stacksize++;
0956:                    } else {
0957:                        if ((m.getModifiers() & Modifier.STATIC) == 0) {
0958:                            assert debug("CHECKCAST " + getInternalName(cls));
0959:                            mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
0960:                        }
0961:
0962:                        for (int i = 0; i < es.length; i++) {
0963:                            if (es[i] instanceof  ExecutableLiteral) {
0964:                                ExecutableLiteral literal = (ExecutableLiteral) es[i];
0965:
0966:                                if (literal.getLiteral() == null) {
0967:                                    assert debug("ICONST_NULL");
0968:                                    mv.visitInsn(ACONST_NULL);
0969:                                    continue;
0970:                                } else if (parameterTypes[i] == int.class
0971:                                        && literal.intOptimized()) {
0972:                                    intPush(literal.getInteger32());
0973:                                    continue;
0974:                                } else if (parameterTypes[i] == int.class
0975:                                        && preConvArgs[i] instanceof  Integer) {
0976:                                    intPush((Integer) preConvArgs[i]);
0977:                                    continue;
0978:                                } else if (parameterTypes[i] == boolean.class) {
0979:                                    boolean bool = DataConversion
0980:                                            .convert(literal.getLiteral(),
0981:                                                    Boolean.class);
0982:                                    assert debug(bool ? "ICONST_1" : "ICONST_0");
0983:                                    mv.visitInsn(bool ? ICONST_1 : ICONST_0);
0984:                                    continue;
0985:                                } else {
0986:                                    Object lit = literal.getLiteral();
0987:
0988:                                    if (parameterTypes[i] == Object.class) {
0989:                                        if (isPrimitiveWrapper(lit.getClass())) {
0990:                                            if (lit.getClass() == Integer.class) {
0991:                                                intPush((Integer) lit);
0992:                                            } else {
0993:                                                assert debug("LDC " + lit);
0994:                                                mv.visitLdcInsn(lit);
0995:                                            }
0996:
0997:                                            wrapPrimitive(lit.getClass());
0998:                                        } else if (lit instanceof  String) {
0999:                                            mv.visitLdcInsn(lit);
1000:                                            checkcast(Object.class);
1001:                                        }
1002:                                        continue;
1003:                                    } else if (canConvert(parameterTypes[i],
1004:                                            lit.getClass())) {
1005:                                        assert debug("LDC " + lit + " ("
1006:                                                + lit.getClass().getName()
1007:                                                + ")");
1008:                                        mv.visitLdcInsn(convert(lit,
1009:                                                parameterTypes[i]));
1010:                                        continue;
1011:                                    }
1012:                                }
1013:                            }
1014:
1015:                            assert debug("ALOAD 0");
1016:                            mv.visitVarInsn(ALOAD, 0);
1017:
1018:                            assert debug("GETFIELD p" + inputsOffset);
1019:                            mv.visitFieldInsn(GETFIELD, className, "p"
1020:                                    + inputsOffset,
1021:                                    "Lorg/mvel/compiler/ExecutableStatement;");
1022:
1023:                            inputsOffset++;
1024:
1025:                            assert debug("ALOAD 2");
1026:                            mv.visitVarInsn(ALOAD, 2);
1027:
1028:                            assert debug("ALOAD 3");
1029:                            mv.visitVarInsn(ALOAD, 3);
1030:
1031:                            assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
1032:                            mv
1033:                                    .visitMethodInsn(
1034:                                            INVOKEINTERFACE,
1035:                                            getInternalName(ExecutableStatement.class),
1036:                                            "getValue",
1037:                                            "(Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;)Ljava/lang/Object;");
1038:
1039:                            if (parameterTypes[i].isPrimitive()) {
1040:                                if (preConvArgs[i] == null
1041:                                        || (parameterTypes[i] != String.class && !parameterTypes[i]
1042:                                                .isAssignableFrom(preConvArgs[i]
1043:                                                        .getClass()))) {
1044:
1045:                                    ldcClassConstant(getWrapperClass(parameterTypes[i]));
1046:
1047:                                    assert debug("INVOKESTATIC DataConversion.convert");
1048:                                    mv
1049:                                            .visitMethodInsn(INVOKESTATIC,
1050:                                                    "org/mvel/DataConversion",
1051:                                                    "convert",
1052:                                                    "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
1053:
1054:                                    unwrapPrimitive(parameterTypes[i]);
1055:                                }
1056:
1057:                                else {
1058:                                    unwrapPrimitive(parameterTypes[i]);
1059:                                }
1060:
1061:                            } else if (preConvArgs[i] == null
1062:                                    || (parameterTypes[i] != String.class && !parameterTypes[i]
1063:                                            .isAssignableFrom(preConvArgs[i]
1064:                                                    .getClass()))) {
1065:
1066:                                ldcClassConstant(parameterTypes[i]);
1067:
1068:                                assert debug("INVOKESTATIC DataConversion.convert");
1069:                                mv
1070:                                        .visitMethodInsn(INVOKESTATIC,
1071:                                                "org/mvel/DataConversion",
1072:                                                "convert",
1073:                                                "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
1074:
1075:                                assert debug("CHECKCAST "
1076:                                        + getInternalName(parameterTypes[i]));
1077:                                mv.visitTypeInsn(CHECKCAST,
1078:                                        getInternalName(parameterTypes[i]));
1079:                            } else if (parameterTypes[i] == String.class) {
1080:                                assert debug("<<<DYNAMIC TYPE OPTIMIZATION STRING>>");
1081:                                mv
1082:                                        .visitMethodInsn(INVOKESTATIC,
1083:                                                "java/lang/String", "valueOf",
1084:                                                "(Ljava/lang/Object;)Ljava/lang/String;");
1085:                            } else {
1086:                                assert debug("<<<DYNAMIC TYPING BYPASS>>>");
1087:                                assert debug("<<<OPT. JUSTIFICATION "
1088:                                        + parameterTypes[i] + "="
1089:                                        + preConvArgs[i].getClass() + ">>>");
1090:
1091:                                assert debug("CHECKCAST "
1092:                                        + getInternalName(parameterTypes[i]));
1093:                                mv.visitTypeInsn(CHECKCAST,
1094:                                        getInternalName(parameterTypes[i]));
1095:                            }
1096:
1097:                        }
1098:
1099:                        if ((m.getModifiers() & Modifier.STATIC) != 0) {
1100:                            assert debug("INVOKESTATIC: " + m.getName());
1101:                            mv.visitMethodInsn(INVOKESTATIC, getInternalName(m
1102:                                    .getDeclaringClass()), m.getName(),
1103:                                    getMethodDescriptor(m));
1104:                        } else {
1105:                            if (m.getDeclaringClass() != cls
1106:                                    && m.getDeclaringClass().isInterface()) {
1107:                                assert debug("INVOKEINTERFACE: "
1108:                                        + getInternalName(m.getDeclaringClass())
1109:                                        + "." + m.getName());
1110:                                mv.visitMethodInsn(INVOKEINTERFACE,
1111:                                        getInternalName(m.getDeclaringClass()),
1112:                                        m.getName(), getMethodDescriptor(m));
1113:                            } else {
1114:                                assert debug("INVOKEVIRTUAL: "
1115:                                        + getInternalName(cls) + "."
1116:                                        + m.getName());
1117:                                mv.visitMethodInsn(INVOKEVIRTUAL,
1118:                                        getInternalName(cls), m.getName(),
1119:                                        getMethodDescriptor(m));
1120:                            }
1121:                        }
1122:
1123:                        returnType = m.getReturnType();
1124:
1125:                        stacksize++;
1126:                    }
1127:
1128:                    return m.invoke(ctx, args);
1129:                }
1130:            }
1131:
1132:            private void dataConversion(Class target) {
1133:                ldcClassConstant(target);
1134:                assert debug("INVOKESTATIC org/mvel/DataConversion.convert");
1135:                mv
1136:                        .visitMethodInsn(INVOKESTATIC,
1137:                                "org/mvel/DataConversion", "convert",
1138:                                "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
1139:            }
1140:
1141:            private static final ClassLoader classLoader;
1142:            private static final Method defineClass;
1143:
1144:            static {
1145:                try {
1146:                    classLoader = Thread.currentThread()
1147:                            .getContextClassLoader();
1148:                    //noinspection RedundantArrayCreation
1149:                    defineClass = ClassLoader.class.getDeclaredMethod(
1150:                            "defineClass", new Class[] { String.class,
1151:                                    byte[].class, int.class, int.class });
1152:                } catch (Exception e) {
1153:                    throw new RuntimeException(e);
1154:                }
1155:            }
1156:
1157:            private java.lang.Class loadClass(String className, byte[] b)
1158:                    throws Exception {
1159:                /**
1160:                 * This must be synchronized.  Two classes cannot be simultaneously deployed in the JVM.
1161:                 */
1162:                synchronized (defineClass) {
1163:                    defineClass.setAccessible(true);
1164:                    try {
1165:                        //noinspection RedundantArrayCreation
1166:                        return (Class) defineClass.invoke(classLoader,
1167:                                new Object[] { className, b, 0, (b.length) });
1168:                    } catch (Exception t) {
1169:                        dumpAdvancedDebugging();
1170:                        throw t;
1171:                    } finally {
1172:                        defineClass.setAccessible(false);
1173:                    }
1174:                }
1175:            }
1176:
1177:            private boolean debug(String instruction) {
1178:                // assert ParseTools.debug(instruction);
1179:                if (buildLog != null) {
1180:                    buildLog.append(instruction).append("\n");
1181:                }
1182:                return true;
1183:            }
1184:
1185:            @SuppressWarnings({"SameReturnValue"})
1186:            public String getName() {
1187:                return "ASM";
1188:            }
1189:
1190:            public Object getResultOptPass() {
1191:                return val;
1192:            }
1193:
1194:            private Class getWrapperClass(Class cls) {
1195:                if (cls == boolean.class) {
1196:                    return Boolean.class;
1197:                } else if (cls == int.class) {
1198:                    return Integer.class;
1199:                } else if (cls == float.class) {
1200:                    return Float.class;
1201:                } else if (cls == double.class) {
1202:                    return Double.class;
1203:                } else if (cls == short.class) {
1204:                    return Short.class;
1205:                } else if (cls == long.class) {
1206:                    return Long.class;
1207:                } else if (cls == byte.class) {
1208:                    return Byte.class;
1209:                } else if (cls == char.class) {
1210:                    return Character.class;
1211:                }
1212:
1213:                return null;
1214:            }
1215:
1216:            private void unwrapPrimitive(Class cls) {
1217:                if (cls == boolean.class) {
1218:                    assert debug("CHECKCAST java/lang/Boolean");
1219:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
1220:                    assert debug("INVOKEVIRTUAL java/lang/Boolean.booleanValue");
1221:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean",
1222:                            "booleanValue", "()Z");
1223:                } else if (cls == int.class) {
1224:                    assert debug("CHECKCAST java/lang/Integer");
1225:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
1226:                    assert debug("INVOKEVIRTUAL java/lang/Integer.intValue");
1227:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer",
1228:                            "intValue", "()I");
1229:                } else if (cls == float.class) {
1230:                    assert debug("CHECKCAST java/lang/Float");
1231:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
1232:                    assert debug("INVOKEVIRTUAL java/lang/Float.floatValue");
1233:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float",
1234:                            "floatValue", "()F");
1235:                } else if (cls == double.class) {
1236:                    assert debug("CHECKCAST java/lang/Double");
1237:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
1238:                    assert debug("INVOKEVIRTUAL java/lang/Double.doubleValue");
1239:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double",
1240:                            "doubleValue", "()D");
1241:                } else if (cls == short.class) {
1242:                    assert debug("CHECKCAST java/lang/Short");
1243:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
1244:                    assert debug("INVOKEVIRTUAL java/lang/Short.shortValue");
1245:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short",
1246:                            "shortValue", "()S");
1247:                } else if (cls == long.class) {
1248:                    assert debug("CHECKCAST java/lang/Long");
1249:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
1250:                    assert debug("INVOKEVIRTUAL java/lang/Long.longValue");
1251:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long",
1252:                            "longValue", "()J");
1253:                } else if (cls == byte.class) {
1254:                    assert debug("CHECKCAST java/lang/Byte");
1255:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
1256:                    assert debug("INVOKEVIRTUAL java/lang/Byte.byteValue");
1257:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte",
1258:                            "byteValue", "()B");
1259:                } else if (cls == char.class) {
1260:                    assert debug("CHECKCAST java/lang/Character");
1261:                    mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
1262:                    assert debug("INVOKEVIRTUAL java/lang/Character.charValue");
1263:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character",
1264:                            "charValue", "()C");
1265:                }
1266:            }
1267:
1268:            private void wrapPrimitive(Class<? extends Object> cls) {
1269:                if (OPCODES_VERSION == Opcodes.V1_4) {
1270:                    /**
1271:                     * JAVA 1.4 SUCKS!  DIE 1.4 DIE!!!
1272:                     */
1273:
1274:                    if (cls == boolean.class || cls == Boolean.class) {
1275:                        assert debug("NEW java/lang/Boolean");
1276:                        mv.visitTypeInsn(NEW, "java/lang/Boolean");
1277:
1278:                        assert debug("DUP X1");
1279:                        mv.visitInsn(DUP_X1);
1280:
1281:                        assert debug("SWAP");
1282:                        mv.visitInsn(SWAP);
1283:
1284:                        assert debug("INVOKESPECIAL java/lang/Boolan.<init>::(Z)V");
1285:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Boolean",
1286:                                "<init>", "(Z)V");
1287:
1288:                        returnType = Boolean.class;
1289:                    } else if (cls == int.class || cls == Integer.class) {
1290:                        assert debug("NEW java/lang/Integer");
1291:                        mv.visitTypeInsn(NEW, "java/lang/Integer");
1292:
1293:                        assert debug("DUP X1");
1294:                        mv.visitInsn(DUP_X1);
1295:
1296:                        assert debug("SWAP");
1297:                        mv.visitInsn(SWAP);
1298:
1299:                        assert debug("INVOKESPECIAL java/lang/Integer.<init>::(I)V");
1300:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Integer",
1301:                                "<init>", "(I)V");
1302:
1303:                        returnType = Integer.class;
1304:                    } else if (cls == float.class || cls == Float.class) {
1305:                        assert debug("NEW java/lang/Float");
1306:                        mv.visitTypeInsn(NEW, "java/lang/Float");
1307:
1308:                        assert debug("DUP X1");
1309:                        mv.visitInsn(DUP_X1);
1310:
1311:                        assert debug("SWAP");
1312:                        mv.visitInsn(SWAP);
1313:
1314:                        assert debug("INVOKESPECIAL java/lang/Float.<init>::(F)V");
1315:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Float",
1316:                                "<init>", "(F)V");
1317:
1318:                        returnType = Float.class;
1319:                    } else if (cls == double.class || cls == Double.class) {
1320:                        assert debug("NEW java/lang/Double");
1321:                        mv.visitTypeInsn(NEW, "java/lang/Double");
1322:
1323:                        assert debug("DUP X1");
1324:                        mv.visitInsn(DUP_X1);
1325:
1326:                        assert debug("SWAP");
1327:                        mv.visitInsn(SWAP);
1328:
1329:                        assert debug("INVOKESPECIAL java/lang/Double.<init>::(D)V");
1330:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Doble",
1331:                                "<init>", "(D)V");
1332:
1333:                        returnType = Double.class;
1334:                    } else if (cls == short.class || cls == Short.class) {
1335:                        assert debug("NEW java/lang/Short");
1336:                        mv.visitTypeInsn(NEW, "java/lang/Short");
1337:
1338:                        assert debug("DUP X1");
1339:                        mv.visitInsn(DUP_X1);
1340:
1341:                        assert debug("SWAP");
1342:                        mv.visitInsn(SWAP);
1343:
1344:                        assert debug("INVOKESPECIAL java/lang/Short.<init>::(S)V");
1345:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Short",
1346:                                "<init>", "(S)V");
1347:
1348:                        returnType = Short.class;
1349:                    } else if (cls == long.class || cls == Long.class) {
1350:                        assert debug("NEW java/lang/Long");
1351:                        mv.visitTypeInsn(NEW, "java/lang/Long");
1352:
1353:                        assert debug("DUP X1");
1354:                        mv.visitInsn(DUP_X1);
1355:
1356:                        assert debug("SWAP");
1357:                        mv.visitInsn(SWAP);
1358:
1359:                        assert debug("INVOKESPECIAL java/lang/Long.<init>::(L)V");
1360:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Float",
1361:                                "<init>", "(L)V");
1362:
1363:                        returnType = Long.class;
1364:                    } else if (cls == byte.class || cls == Byte.class) {
1365:                        assert debug("NEW java/lang/Byte");
1366:                        mv.visitTypeInsn(NEW, "java/lang/Byte");
1367:
1368:                        assert debug("DUP X1");
1369:                        mv.visitInsn(DUP_X1);
1370:
1371:                        assert debug("SWAP");
1372:                        mv.visitInsn(SWAP);
1373:
1374:                        assert debug("INVOKESPECIAL java/lang/Byte.<init>::(B)V");
1375:                        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Byte",
1376:                                "<init>", "(B)V");
1377:
1378:                        returnType = Byte.class;
1379:                    } else if (cls == char.class || cls == Character.class) {
1380:                        assert debug("NEW java/lang/Character");
1381:                        mv.visitTypeInsn(NEW, "java/lang/Character");
1382:
1383:                        assert debug("DUP X1");
1384:                        mv.visitInsn(DUP_X1);
1385:
1386:                        assert debug("SWAP");
1387:                        mv.visitInsn(SWAP);
1388:
1389:                        assert debug("INVOKESPECIAL java/lang/Character.<init>::(C)V");
1390:                        mv.visitMethodInsn(INVOKESPECIAL,
1391:                                "java/lang/Character", "<init>", "(C)V");
1392:
1393:                        returnType = Character.class;
1394:                    }
1395:                } else {
1396:                    if (cls == boolean.class || cls == Boolean.class) {
1397:                        assert debug("INVOKESTATIC java/lang/Boolean.valueOf");
1398:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean",
1399:                                "valueOf", "(Z)Ljava/lang/Boolean;");
1400:                        returnType = Boolean.class;
1401:                    } else if (cls == int.class || cls == Integer.class) {
1402:                        assert debug("INVOKESTATIC java/lang/Integer.valueOf");
1403:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer",
1404:                                "valueOf", "(I)Ljava/lang/Integer;");
1405:                        returnType = Integer.class;
1406:                    } else if (cls == float.class || cls == Float.class) {
1407:                        assert debug("INVOKESTATIC java/lang/Float.valueOf");
1408:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float",
1409:                                "valueOf", "(F)Ljava/lang/Float;");
1410:                        returnType = Float.class;
1411:                    } else if (cls == double.class || cls == Double.class) {
1412:                        assert debug("INVOKESTATIC java/lang/Double.valueOf");
1413:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double",
1414:                                "valueOf", "(D)Ljava/lang/Double;");
1415:                        returnType = Double.class;
1416:                    } else if (cls == short.class || cls == Short.class) {
1417:                        assert debug("INVOKESTATIC java/lang/Short.valueOf");
1418:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short",
1419:                                "valueOf", "(S)Ljava/lang/Short;");
1420:                        returnType = Short.class;
1421:                    } else if (cls == long.class || cls == Long.class) {
1422:                        assert debug("INVOKESTATIC java/lang/Long.valueOf");
1423:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long",
1424:                                "valueOf", "(J)Ljava/lang/Long;");
1425:                        returnType = Long.class;
1426:                    } else if (cls == byte.class || cls == Byte.class) {
1427:                        assert debug("INVOKESTATIC java/lang/Byte.valueOf");
1428:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte",
1429:                                "valueOf", "(B)Ljava/lang/Byte;");
1430:                        returnType = Byte.class;
1431:                    } else if (cls == char.class || cls == Character.class) {
1432:                        assert debug("INVOKESTATIC java/lang/Character.valueOf");
1433:                        mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character",
1434:                                "valueOf", "(C)Ljava/lang/Character;");
1435:                        returnType = Character.class;
1436:                    }
1437:                }
1438:            }
1439:
1440:            private void anyArrayCheck(Class<? extends Object> cls) {
1441:                if (cls == boolean[].class) {
1442:                    assert debug("CHECKCAST [Z");
1443:                    mv.visitTypeInsn(CHECKCAST, "[Z");
1444:                } else if (cls == int[].class) {
1445:                    assert debug("CHECKCAST [I");
1446:                    mv.visitTypeInsn(CHECKCAST, "[I");
1447:                } else if (cls == float[].class) {
1448:                    assert debug("CHECKCAST [F");
1449:                    mv.visitTypeInsn(CHECKCAST, "[F");
1450:                } else if (cls == double[].class) {
1451:                    assert debug("CHECKCAST [D");
1452:                    mv.visitTypeInsn(CHECKCAST, "[D");
1453:                } else if (cls == short[].class) {
1454:                    assert debug("CHECKCAST [S");
1455:                    mv.visitTypeInsn(CHECKCAST, "[S");
1456:                } else if (cls == long[].class) {
1457:                    assert debug("CHECKCAST [J");
1458:                    mv.visitTypeInsn(CHECKCAST, "[J");
1459:                } else if (cls == byte[].class) {
1460:                    assert debug("CHECKCAST [B");
1461:                    mv.visitTypeInsn(CHECKCAST, "[B");
1462:                } else if (cls == char[].class) {
1463:                    assert debug("CHECKCAST [C");
1464:                    mv.visitTypeInsn(CHECKCAST, "[C");
1465:                } else {
1466:                    assert debug("CHECKCAST [Ljava/lang/Object;");
1467:                    mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
1468:                }
1469:            }
1470:
1471:            private void writeOutLiteralWrapped(Object lit) {
1472:                if (lit instanceof  Integer) {
1473:                    intPush((Integer) lit);
1474:                    wrapPrimitive(int.class);
1475:                    return;
1476:                }
1477:
1478:                assert debug("LDC " + lit);
1479:                if (lit instanceof  String) {
1480:                    mv.visitLdcInsn(lit);
1481:                } else if (lit instanceof  Long) {
1482:                    mv.visitLdcInsn(lit);
1483:                    wrapPrimitive(long.class);
1484:                } else if (lit instanceof  Float) {
1485:                    mv.visitLdcInsn(lit);
1486:                    wrapPrimitive(float.class);
1487:                } else if (lit instanceof  Double) {
1488:                    mv.visitLdcInsn(lit);
1489:                    wrapPrimitive(double.class);
1490:                } else if (lit instanceof  Short) {
1491:                    mv.visitLdcInsn(lit);
1492:                    wrapPrimitive(short.class);
1493:                } else if (lit instanceof  Character) {
1494:                    mv.visitLdcInsn(lit);
1495:                    wrapPrimitive(char.class);
1496:                } else if (lit instanceof  Boolean) {
1497:                    mv.visitLdcInsn(lit);
1498:                    wrapPrimitive(boolean.class);
1499:                } else if (lit instanceof  Byte) {
1500:                    mv.visitLdcInsn(lit);
1501:                    wrapPrimitive(byte.class);
1502:                }
1503:            }
1504:
1505:            private void loadVariableByName(String name) {
1506:                assert debug("ALOAD 3");
1507:                mv.visitVarInsn(ALOAD, 3);
1508:
1509:                assert debug("LDC :" + name);
1510:                mv.visitLdcInsn(name);
1511:
1512:                assert debug("INVOKEINTERFACE org/mvel/integration/VariableResolverFactory.getVariableResolver");
1513:                mv
1514:                        .visitMethodInsn(INVOKEINTERFACE,
1515:                                "org/mvel/integration/VariableResolverFactory",
1516:                                "getVariableResolver",
1517:                                "(Ljava/lang/String;)Lorg/mvel/integration/VariableResolver;");
1518:
1519:                assert debug("INVOKEINTERFACE org/mvel/integration/VariableResolver.getValue");
1520:                mv.visitMethodInsn(INVOKEINTERFACE,
1521:                        "org/mvel/integration/VariableResolver", "getValue",
1522:                        "()Ljava/lang/Object;");
1523:
1524:                returnType = Object.class;
1525:            }
1526:
1527:            private void loadVariableByIndex(int pos) {
1528:                assert debug("ALOAD 3");
1529:                mv.visitVarInsn(ALOAD, 3);
1530:
1531:                assert debug("PUSH IDX VAL =" + pos);
1532:                intPush(pos);
1533:
1534:                assert debug("INVOKEINTERFACE org/mvel/integration/VariableResolverFactory.getIndexedVariableResolver");
1535:                mv.visitMethodInsn(INVOKEINTERFACE,
1536:                        "org/mvel/integration/VariableResolverFactory",
1537:                        "getIndexedVariableResolver",
1538:                        "(I)Lorg/mvel/integration/VariableResolver;");
1539:
1540:                assert debug("INVOKEINTERFACE org/mvel/integration/VariableResolver.getValue");
1541:                mv.visitMethodInsn(INVOKEINTERFACE,
1542:                        "org/mvel/integration/VariableResolver", "getValue",
1543:                        "()Ljava/lang/Object;");
1544:
1545:                returnType = Object.class;
1546:            }
1547:
1548:            private void loadField(int number) {
1549:                assert debug("ALOAD 0");
1550:                mv.visitVarInsn(ALOAD, 0);
1551:
1552:                assert debug("GETFIELD p" + number);
1553:                mv.visitFieldInsn(GETFIELD, className, "p" + number,
1554:                        "Lorg/mvel/compiler/ExecutableStatement;");
1555:            }
1556:
1557:            //    private void writeOutLiteral(Object lit) {
1558:            //        if (lit instanceof Integer) {
1559:            //            intPush((Integer) lit);
1560:            //            return;
1561:            //        }
1562:            //
1563:            //
1564:            //        debug("LDC " + lit);
1565:            //        if (lit instanceof String) {
1566:            //            mv.visitLdcInsn(lit);
1567:            //        }
1568:            //        else if (lit instanceof Long) {
1569:            //            mv.visitLdcInsn(lit);
1570:            //        }
1571:            //        else if (lit instanceof Float) {
1572:            //            mv.visitLdcInsn(lit);
1573:            //        }
1574:            //        else if (lit instanceof Double) {
1575:            //            mv.visitLdcInsn(lit);
1576:            //        }
1577:            //        else if (lit instanceof Short) {
1578:            //            mv.visitLdcInsn(lit);
1579:            //        }
1580:            //        else if (lit instanceof Character) {
1581:            //            mv.visitLdcInsn(lit);
1582:            //        }
1583:            //        else if (lit instanceof Boolean) {
1584:            //            mv.visitLdcInsn(lit);
1585:            //        }
1586:            //        else if (lit instanceof Byte) {
1587:            //            mv.visitLdcInsn(lit);
1588:            //        }
1589:            //    }
1590:
1591:            private void ldcClassConstant(Class cls) {
1592:                if (OPCODES_VERSION == Opcodes.V1_4) {
1593:                    assert debug("LDC \"" + cls.getName() + "\"");
1594:                    mv.visitLdcInsn(cls.getName());
1595:                    mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class",
1596:                            "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
1597:                    Label l4 = new Label();
1598:                    mv.visitJumpInsn(GOTO, l4);
1599:                    mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
1600:                    mv.visitInsn(DUP_X1);
1601:                    mv.visitInsn(SWAP);
1602:                    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Throwable",
1603:                            "getMessage", "()Ljava/lang/String;");
1604:                    mv.visitMethodInsn(INVOKESPECIAL,
1605:                            "java/lang/NoClassDefFoundError", "<init>",
1606:                            "(Ljava/lang/String;)V");
1607:                    mv.visitInsn(ATHROW);
1608:                    mv.visitLabel(l4);
1609:
1610:                } else {
1611:                    assert debug("LDC " + getType(cls));
1612:                    mv.visitLdcInsn(getType(cls));
1613:                }
1614:            }
1615:
1616:            private void buildInputs() {
1617:                if (compiledInputs.size() == 0)
1618:                    return;
1619:
1620:                assert debug("\n{SETTING UP MEMBERS...}\n");
1621:
1622:                StringAppender constSig = new StringAppender("(");
1623:                int size = compiledInputs.size();
1624:
1625:                for (int i = 0; i < size; i++) {
1626:                    assert debug("ACC_PRIVATE p" + i);
1627:                    //FieldVisitor fv =
1628:                    cw.visitField(ACC_PRIVATE, "p" + i,
1629:                            "Lorg/mvel/compiler/ExecutableStatement;", null,
1630:                            null).visitEnd();
1631:                    // fv.visitEnd();
1632:
1633:                    constSig.append("Lorg/mvel/compiler/ExecutableStatement;");
1634:                }
1635:                constSig.append(")V");
1636:
1637:                assert debug("\n{CREATING INJECTION CONSTRUCTOR}\n");
1638:
1639:                MethodVisitor cv = cw.visitMethod(ACC_PUBLIC, "<init>",
1640:                        constSig.toString(), null, null);
1641:                cv.visitCode();
1642:                assert debug("ALOAD 0");
1643:                cv.visitVarInsn(ALOAD, 0);
1644:                assert debug("INVOKESPECIAL java/lang/Object.<init>");
1645:                cv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>",
1646:                        "()V");
1647:
1648:                for (int i = 0; i < size; i++) {
1649:                    assert debug("ALOAD 0");
1650:                    cv.visitVarInsn(ALOAD, 0);
1651:                    assert debug("ALOAD " + (i + 1));
1652:                    cv.visitVarInsn(ALOAD, i + 1);
1653:                    assert debug("PUTFIELD p" + i);
1654:                    cv.visitFieldInsn(PUTFIELD, className, "p" + i,
1655:                            "Lorg/mvel/compiler/ExecutableStatement;");
1656:                }
1657:
1658:                assert debug("RETURN");
1659:                cv.visitInsn(RETURN);
1660:                cv.visitMaxs(0, 0);
1661:                cv.visitEnd();
1662:
1663:                assert debug("}");
1664:            }
1665:
1666:            private static final int ARRAY = 0;
1667:            private static final int LIST = 1;
1668:            private static final int MAP = 2;
1669:            private static final int VAL = 3;
1670:
1671:            private int _getAccessor(Object o) {
1672:                if (o instanceof  List) {
1673:                    assert debug("NEW " + LIST_IMPL);
1674:                    mv.visitTypeInsn(NEW, LIST_IMPL);
1675:
1676:                    assert debug("DUP");
1677:                    mv.visitInsn(DUP);
1678:
1679:                    assert debug("DUP");
1680:                    mv.visitInsn(DUP);
1681:
1682:                    intPush(((List) o).size());
1683:                    assert debug("INVOKESPECIAL " + LIST_IMPL + ".<init>");
1684:                    mv.visitMethodInsn(INVOKESPECIAL, LIST_IMPL, "<init>",
1685:                            "(I)V");
1686:
1687:                    for (Object item : (List) o) {
1688:                        if (_getAccessor(item) != VAL) {
1689:                            assert debug("POP");
1690:                            mv.visitInsn(POP);
1691:                        }
1692:
1693:                        assert debug("INVOKEINTERFACE java/util/List.add");
1694:                        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List",
1695:                                "add", "(Ljava/lang/Object;)Z");
1696:
1697:                        assert debug("POP");
1698:                        mv.visitInsn(POP);
1699:
1700:                        assert debug("DUP");
1701:                        mv.visitInsn(DUP);
1702:                    }
1703:
1704:                    return LIST;
1705:                } else if (o instanceof  Map) {
1706:                    assert debug("NEW " + MAP_IMPL);
1707:                    mv.visitTypeInsn(NEW, MAP_IMPL);
1708:
1709:                    assert debug("DUP");
1710:                    mv.visitInsn(DUP);
1711:
1712:                    assert debug("DUP");
1713:                    mv.visitInsn(DUP);
1714:
1715:                    intPush(((Map) o).size());
1716:
1717:                    assert debug("INVOKESPECIAL " + MAP_IMPL + ".<init>");
1718:                    mv.visitMethodInsn(INVOKESPECIAL, MAP_IMPL, "<init>",
1719:                            "(I)V");
1720:
1721:                    for (Object item : ((Map) o).keySet()) {
1722:                        mv.visitTypeInsn(CHECKCAST, "java/util/Map");
1723:
1724:                        if (_getAccessor(item) != VAL) {
1725:                            assert debug("POP");
1726:                            mv.visitInsn(POP);
1727:                        }
1728:                        if (_getAccessor(((Map) o).get(item)) != VAL) {
1729:                            assert debug("POP");
1730:                            mv.visitInsn(POP);
1731:                        }
1732:
1733:                        assert debug("INVOKEINTERFACE java/util/Map.put");
1734:                        mv
1735:                                .visitMethodInsn(INVOKEINTERFACE,
1736:                                        "java/util/Map", "put",
1737:                                        "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
1738:
1739:                        assert debug("POP");
1740:                        mv.visitInsn(POP);
1741:
1742:                        assert debug("DUP");
1743:                        mv.visitInsn(DUP);
1744:                    }
1745:
1746:                    return MAP;
1747:                } else if (o instanceof  Object[]) {
1748:                    intPush(((Object[]) o).length);
1749:
1750:                    assert debug("ANEWARRAY (" + o.hashCode() + ")");
1751:                    mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
1752:
1753:                    assert debug("DUP");
1754:                    mv.visitInsn(DUP);
1755:
1756:                    int i = 0;
1757:                    for (Object item : (Object[]) o) {
1758:                        intPush(i);
1759:
1760:                        if (_getAccessor(item) != VAL) {
1761:                            assert debug("POP");
1762:                            mv.visitInsn(POP);
1763:                        }
1764:
1765:                        assert debug("AASTORE (" + o.hashCode() + ")");
1766:                        mv.visitInsn(AASTORE);
1767:
1768:                        assert debug("DUP");
1769:                        mv.visitInsn(DUP);
1770:
1771:                        i++;
1772:                    }
1773:
1774:                    return ARRAY;
1775:                } else {
1776:                    writeLiteralOrSubexpression(subCompileExpression((String) o));
1777:                    return VAL;
1778:                }
1779:            }
1780:
1781:            private Class writeLiteralOrSubexpression(Object stmt) {
1782:                return writeLiteralOrSubexpression(stmt, null, null);
1783:            }
1784:
1785:            private Class writeLiteralOrSubexpression(Object stmt,
1786:                    Class desiredTarget) {
1787:                return writeLiteralOrSubexpression(stmt, desiredTarget, null);
1788:            }
1789:
1790:            private Class writeLiteralOrSubexpression(Object stmt,
1791:                    Class desiredTarget, Class knownIngressType) {
1792:
1793:                if (stmt instanceof  ExecutableLiteral) {
1794:                    Class type = ((ExecutableLiteral) stmt).getLiteral()
1795:                            .getClass();
1796:
1797:                    assert debug("*** type:" + type + ";desired:"
1798:                            + desiredTarget);
1799:
1800:                    if (type == Integer.class && desiredTarget == int.class) {
1801:                        intPush(((ExecutableLiteral) stmt).getInteger32());
1802:                        type = int.class;
1803:                    } else if (desiredTarget != null && type != desiredTarget) {
1804:                        assert debug("*** Converting because desiredType("
1805:                                + desiredTarget.getClass() + ") is not: "
1806:                                + type);
1807:
1808:                        dataConversion(desiredTarget);
1809:                        writeOutLiteralWrapped(convert(
1810:                                ((ExecutableLiteral) stmt).getLiteral(),
1811:                                desiredTarget));
1812:                    } else {
1813:                        writeOutLiteralWrapped(((ExecutableLiteral) stmt)
1814:                                .getLiteral());
1815:                    }
1816:
1817:                    return type;
1818:                } else {
1819:                    literal = false;
1820:
1821:                    compiledInputs.add((ExecutableStatement) stmt);
1822:
1823:                    assert debug("ALOAD 0");
1824:                    mv.visitVarInsn(ALOAD, 0);
1825:
1826:                    assert debug("GETFIELD p" + (compiledInputs.size() - 1));
1827:                    mv.visitFieldInsn(GETFIELD, className, "p"
1828:                            + (compiledInputs.size() - 1),
1829:                            "Lorg/mvel/compiler/ExecutableStatement;");
1830:
1831:                    assert debug("ALOAD 2");
1832:                    mv.visitVarInsn(ALOAD, 2);
1833:
1834:                    assert debug("ALOAD 3");
1835:                    mv.visitVarInsn(ALOAD, 3);
1836:
1837:                    assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
1838:                    mv
1839:                            .visitMethodInsn(
1840:                                    INVOKEINTERFACE,
1841:                                    getInternalName(ExecutableStatement.class),
1842:                                    "getValue",
1843:                                    "(Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;)Ljava/lang/Object;");
1844:
1845:                    Class type;
1846:                    if (knownIngressType == null) {
1847:                        type = ((ExecutableStatement) stmt)
1848:                                .getKnownEgressType();
1849:                    } else {
1850:                        type = knownIngressType;
1851:                    }
1852:
1853:                    if (desiredTarget != null && type != desiredTarget) {
1854:                        //      dataConversion(desiredTarget);
1855:                        if (desiredTarget.isPrimitive()) {
1856:                            if (type == null)
1857:                                throw new OptimizationFailure(
1858:                                        "cannot optimize expression: "
1859:                                                + new String(expr)
1860:                                                + ": cannot determine ingress type for primitive output");
1861:
1862:                            checkcast(type);
1863:                            unwrapPrimitive(desiredTarget);
1864:                        }
1865:                    }
1866:
1867:                    return type;
1868:                }
1869:
1870:            }
1871:
1872:            private void addPrintOut(String text) {
1873:                mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
1874:                        "Ljava/io/PrintStream;");
1875:                mv.visitLdcInsn(text);
1876:                mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream",
1877:                        "println", "(Ljava/lang/String;)V");
1878:            }
1879:
1880:            public Accessor optimizeCollection(char[] property, Object ctx,
1881:                    Object this Ref, VariableResolverFactory factory) {
1882:                this .cursor = 0;
1883:                this .length = (this .expr = property).length;
1884:                this .compiledInputs = new ArrayList<ExecutableStatement>();
1885:
1886:                this .ctx = ctx;
1887:                this .this Ref = this Ref;
1888:                this .variableFactory = factory;
1889:
1890:                CollectionParser parser = new CollectionParser();
1891:                Object o = ((List) parser.parseCollection(property)).get(0);
1892:
1893:                _initJIT();
1894:
1895:                literal = true;
1896:
1897:                switch (_getAccessor(o)) {
1898:                case LIST:
1899:                    this .returnType = List.class;
1900:                    break;
1901:                case MAP:
1902:                    this .returnType = Map.class;
1903:                    break;
1904:                case ARRAY:
1905:                    this .returnType = Object[].class;
1906:                    break;
1907:                }
1908:
1909:                _finishJIT();
1910:
1911:                int end = parser.getCursor() + 2;
1912:                try {
1913:                    Accessor compiledAccessor = _initializeAccessor();
1914:
1915:                    if (end < property.length) {
1916:                        return new Union(compiledAccessor,
1917:                                subset(property, end));
1918:                    } else {
1919:                        return compiledAccessor;
1920:                    }
1921:
1922:                } catch (Exception e) {
1923:                    throw new OptimizationFailure(
1924:                            "could not optimize collection", e);
1925:                }
1926:            }
1927:
1928:            private void checkcast(Class cls) {
1929:                assert debug("CHECKCAST " + getInternalName(cls));
1930:                mv.visitTypeInsn(CHECKCAST, getInternalName(cls));
1931:            }
1932:
1933:            private void intPush(int index) {
1934:                if (index < 6) {
1935:                    switch (index) {
1936:                    case 0:
1937:                        assert debug("ICONST_0");
1938:                        mv.visitInsn(ICONST_0);
1939:                        break;
1940:                    case 1:
1941:                        assert debug("ICONST_1");
1942:                        mv.visitInsn(ICONST_1);
1943:                        break;
1944:                    case 2:
1945:                        assert debug("ICONST_2");
1946:                        mv.visitInsn(ICONST_2);
1947:                        break;
1948:                    case 3:
1949:                        assert debug("ICONST_3");
1950:                        mv.visitInsn(ICONST_3);
1951:                        break;
1952:                    case 4:
1953:                        assert debug("ICONST_4");
1954:                        mv.visitInsn(ICONST_4);
1955:                        break;
1956:                    case 5:
1957:                        assert debug("ICONST_5");
1958:                        mv.visitInsn(ICONST_5);
1959:                        break;
1960:                    }
1961:                } else if (index < Byte.MAX_VALUE) {
1962:                    assert debug("BIPUSH " + index);
1963:                    mv.visitIntInsn(BIPUSH, index);
1964:                } else {
1965:                    assert debug("SIPUSH " + index);
1966:                    mv.visitIntInsn(SIPUSH, index);
1967:                }
1968:            }
1969:
1970:            public Accessor optimizeObjectCreation(char[] property, Object ctx,
1971:                    Object this Ref, VariableResolverFactory factory) {
1972:                _initJIT();
1973:
1974:                compiledInputs = new ArrayList<ExecutableStatement>();
1975:                this .length = (this .expr = property).length;
1976:                this .ctx = ctx;
1977:                this .this Ref = this Ref;
1978:                this .variableFactory = factory;
1979:
1980:                String[] cnsRes = captureContructorAndResidual(property);
1981:                String[] constructorParms = parseMethodOrConstructor(cnsRes[0]
1982:                        .toCharArray());
1983:
1984:                try {
1985:                    if (constructorParms != null) {
1986:                        for (String constructorParm : constructorParms) {
1987:                            compiledInputs
1988:                                    .add((ExecutableStatement) subCompileExpression(constructorParm));
1989:                        }
1990:
1991:                        Class cls = findClass(factory, new String(subset(
1992:                                property, 0, findFirst('(', property))));
1993:
1994:                        assert debug("NEW " + getInternalName(cls));
1995:                        mv.visitTypeInsn(NEW, getInternalName(cls));
1996:                        assert debug("DUP");
1997:                        mv.visitInsn(DUP);
1998:
1999:                        Object[] parms = new Object[constructorParms.length];
2000:
2001:                        int i = 0;
2002:                        for (ExecutableStatement es : compiledInputs) {
2003:                            parms[i++] = es.getValue(ctx, factory);
2004:                        }
2005:
2006:                        Constructor cns = getBestConstructorCanadidate(parms,
2007:                                cls);
2008:
2009:                        if (cns == null)
2010:                            throw new CompileException(
2011:                                    "unable to find constructor for: "
2012:                                            + cls.getName());
2013:
2014:                        Class tg;
2015:                        for (i = 0; i < constructorParms.length; i++) {
2016:                            assert debug("ALOAD 0");
2017:                            mv.visitVarInsn(ALOAD, 0);
2018:                            assert debug("GETFIELD p" + i);
2019:                            mv.visitFieldInsn(GETFIELD, className, "p" + i,
2020:                                    "Lorg/mvel/compiler/ExecutableStatement;");
2021:                            assert debug("ALOAD 2");
2022:                            mv.visitVarInsn(ALOAD, 2);
2023:                            assert debug("ALOAD 3");
2024:                            mv.visitVarInsn(ALOAD, 3);
2025:                            assert debug("INVOKEINTERFACE org/mvel/compiler/ExecutableStatement.getValue");
2026:                            mv
2027:                                    .visitMethodInsn(
2028:                                            INVOKEINTERFACE,
2029:                                            "org/mvel/compiler/ExecutableStatement",
2030:                                            "getValue",
2031:                                            "(Ljava/lang/Object;Lorg/mvel/integration/VariableResolverFactory;)Ljava/lang/Object;");
2032:
2033:                            tg = cns.getParameterTypes()[i].isPrimitive() ? getWrapperClass(cns
2034:                                    .getParameterTypes()[i])
2035:                                    : cns.getParameterTypes()[i];
2036:
2037:                            if (parms[i] != null
2038:                                    && !parms[i].getClass().isAssignableFrom(
2039:                                            cns.getParameterTypes()[i])) {
2040:                                ldcClassConstant(tg);
2041:
2042:                                assert debug("INVOKESTATIC org/mvel/DataConversion.convert");
2043:                                mv
2044:                                        .visitMethodInsn(INVOKESTATIC,
2045:                                                "org/mvel/DataConversion",
2046:                                                "convert",
2047:                                                "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
2048:
2049:                                if (cns.getParameterTypes()[i].isPrimitive()) {
2050:                                    unwrapPrimitive(cns.getParameterTypes()[i]);
2051:                                } else {
2052:                                    assert debug("CHECKCAST "
2053:                                            + getInternalName(tg));
2054:                                    mv.visitTypeInsn(CHECKCAST,
2055:                                            getInternalName(tg));
2056:                                }
2057:
2058:                            } else {
2059:                                assert debug("CHECKCAST "
2060:                                        + getInternalName(cns
2061:                                                .getParameterTypes()[i]));
2062:                                mv.visitTypeInsn(CHECKCAST, getInternalName(cns
2063:                                        .getParameterTypes()[i]));
2064:                            }
2065:
2066:                        }
2067:
2068:                        assert debug("INVOKESPECIAL " + getInternalName(cls)
2069:                                + ".<init> : " + getConstructorDescriptor(cns));
2070:                        mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls),
2071:                                "<init>", getConstructorDescriptor(cns));
2072:
2073:                        _finishJIT();
2074:
2075:                        Accessor acc = _initializeAccessor();
2076:
2077:                        if (cnsRes.length > 1 && cnsRes[1] != null
2078:                                && !cnsRes[1].trim().equals("")) {
2079:                            return new Union(acc, cnsRes[1].toCharArray());
2080:                        }
2081:
2082:                        return acc;
2083:                    } else {
2084:                        Class cls = findClass(factory, new String(property));
2085:
2086:                        assert debug("NEW " + getInternalName(cls));
2087:                        mv.visitTypeInsn(NEW, getInternalName(cls));
2088:                        assert debug("DUP");
2089:                        mv.visitInsn(DUP);
2090:
2091:                        Constructor cns = cls.getConstructor(EMPTYCLS);
2092:
2093:                        assert debug("INVOKESPECIAL <init>");
2094:
2095:                        mv.visitMethodInsn(INVOKESPECIAL, getInternalName(cls),
2096:                                "<init>", getConstructorDescriptor(cns));
2097:
2098:                        _finishJIT();
2099:                        Accessor acc = _initializeAccessor();
2100:
2101:                        if (cnsRes.length > 1 && cnsRes[1] != null
2102:                                && !cnsRes[1].trim().equals("")) {
2103:                            return new Union(acc, cnsRes[1].toCharArray());
2104:                        }
2105:
2106:                        return acc;
2107:                    }
2108:                } catch (ClassNotFoundException e) {
2109:                    throw new CompileException(
2110:                            "class or class reference not found: "
2111:                                    + new String(property));
2112:                } catch (Exception e) {
2113:                    throw new OptimizationFailure(
2114:                            "could not optimize construtor: "
2115:                                    + new String(property), e);
2116:                }
2117:            }
2118:
2119:            public Accessor optimizeFold(char[] property, Object ctx,
2120:                    Object this Ref, VariableResolverFactory factory) {
2121:                throw new OptimizationNotSupported(
2122:                        "JIT does not yet support fold operations.");
2123:            }
2124:
2125:            public Class getEgressType() {
2126:                return returnType;
2127:            }
2128:
2129:            private void dumpAdvancedDebugging() {
2130:                if (buildLog == null)
2131:                    return;
2132:
2133:                System.out.println("JIT Compiler Dump for: <<"
2134:                        + new String(expr)
2135:                        + ">>\n-------------------------------\n");
2136:                System.out.println(buildLog.toString());
2137:                System.out.println("\n<END OF DUMP>\n");
2138:                if (MVEL.isFileDebugging()) {
2139:                    try {
2140:                        FileWriter writer = ParseTools.getDebugFileWriter();
2141:                        writer.write(buildLog.toString());
2142:                        writer.flush();
2143:                        writer.close();
2144:                    } catch (IOException e) {
2145:                        // --
2146:                    }
2147:                }
2148:            }
2149:
2150:            public boolean isLiteralOnly() {
2151:                return literal;
2152:            }
2153:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.