Search in sources :

Example 6 with ArrayVisitor

use of lucee.transformer.bytecode.visitor.ArrayVisitor in project Lucee by lucee.

the class NamedArgument method _writeOut.

@Override
public Type _writeOut(BytecodeContext bc, int mode) throws TransformerException {
    int form = VALUE;
    int type = STRING;
    if (name instanceof Variable && !((Variable) name).fromHash()) {
        GeneratorAdapter adapter = bc.getAdapter();
        String[] arr = VariableString.variableToStringArray((Variable) name, true);
        if (arr.length > 1) {
            form = ARRAY;
            ArrayVisitor av = new ArrayVisitor();
            av.visitBegin(adapter, Types.STRING, arr.length);
            for (int y = 0; y < arr.length; y++) {
                av.visitBeginItem(adapter, y);
                adapter.push(varKeyUpperCase ? arr[y].toUpperCase() : arr[y]);
                av.visitEndItem(bc.getAdapter());
            }
            av.visitEnd();
        } else {
            // VariableString.toExprString(name).writeOut(bc, MODE_REF);
            String str = VariableString.variableToString((Variable) name, true);
            name = bc.getFactory().createLitString(varKeyUpperCase ? str.toUpperCase() : str);
            getFactory().registerKey(bc, VariableString.toExprString(name), false);
            type = KEY;
        }
    } else {
        getFactory().registerKey(bc, name.getFactory().toExprString(name), false);
        type = KEY;
    }
    // name.writeOut(bc, MODE_REF);
    super._writeOut(bc, MODE_REF);
    // bc.getAdapter().push(variableString);
    bc.getAdapter().invokeStatic(Types.FUNCTION_VALUE_IMPL, NEW_INSTANCE[type][form]);
    return Types.FUNCTION_VALUE;
}
Also used : Variable(lucee.transformer.expression.var.Variable) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ArrayVisitor(lucee.transformer.bytecode.visitor.ArrayVisitor)

Example 7 with ArrayVisitor

use of lucee.transformer.bytecode.visitor.ArrayVisitor in project Lucee by lucee.

the class OPUnary method _writeOut.

@Override
public Type _writeOut(BytecodeContext bc, int mode) throws TransformerException {
    GeneratorAdapter adapter = bc.getAdapter();
    // convert value
    if (operation == CONCAT)
        value = CastString.toExprString(value);
    else
        value = CastDouble.toExprDouble(value);
    List<Member> members = var.getMembers();
    int size = members.size();
    String scope = VariableInterpreter.scopeInt2String(var.getScope());
    /*
		 *  (susi.sorglos++ or variables.susi++)
		 */
    if ((scope == null && size > 1) || (scope != null && size > 0)) {
        Member last = var.removeMember(members.size() - 1);
        if (!(last instanceof DataMember))
            throw new TransformerException("you cannot use a unary operator with a function " + last.getClass().getName(), getStart());
        // write the variable
        var.setAsCollection(Boolean.TRUE);
        var.writeOut(bc, mode);
        // write out last Key
        getFactory().registerKey(bc, ((DataMember) last).getName(), false);
        // write out value
        value.writeOut(bc, MODE_VALUE);
        if (type == POST) {
            if (operation != OpDouble.PLUS && operation != OpDouble.MINUS)
                throw new TransformerException("Post only possible with plus or minus " + operation, value.getStart());
            if (operation == PLUS)
                adapter.invokeStatic(Types.OPERATOR, UNARY_POST_PLUS2);
            else if (operation == MINUS)
                adapter.invokeStatic(Types.OPERATOR, UNARY_POST_MINUS2);
        } else if (type == PRE) {
            if (operation == PLUS)
                adapter.invokeStatic(Types.OPERATOR, UNARY_PRE_PLUS2);
            else if (operation == MINUS)
                adapter.invokeStatic(Types.OPERATOR, UNARY_PRE_MINUS2);
            else if (operation == DIVIDE)
                adapter.invokeStatic(Types.OPERATOR, UNARY_PRE_DIVIDE2);
            else if (operation == MULTIPLY)
                adapter.invokeStatic(Types.OPERATOR, UNARY_PRE_MULTIPLY2);
            else if (operation == CONCAT)
                adapter.invokeStatic(Types.OPERATOR, UNARY_PRE_CONCAT2);
        }
        if (operation == CONCAT)
            return Types.STRING;
        // convert from Double to double (if necessary)
        if (mode == MODE_REF) {
            adapter.invokeStatic(Types.CASTER, Methods.METHOD_TO_DOUBLE_FROM_DOUBLE);
            return Types.DOUBLE;
        }
        return Types.DOUBLE_VALUE;
    }
    /*
		 *  undefined scope only with one key (susi++;)
		 */
    // PageContext instance
    adapter.loadArg(0);
    // Collection key Array
    int arrSize = scope != null ? members.size() + 1 : members.size();
    boolean useArray = arrSize > 1 || scope != null;
    if (useArray) {
        ArrayVisitor av = new ArrayVisitor();
        int index = 0;
        av.visitBegin(adapter, Types.COLLECTION_KEY, arrSize);
        Iterator<Member> it = members.iterator();
        Member m;
        DataMember dm;
        if (scope != null) {
            av.visitBeginItem(adapter, index++);
            getFactory().registerKey(bc, getFactory().createLitString(scope), false);
            av.visitEndItem(adapter);
        }
        while (it.hasNext()) {
            av.visitBeginItem(adapter, index++);
            m = it.next();
            if (!(m instanceof DataMember))
                throw new TransformerException("you cannot use a unary operator with a function " + m.getClass().getName(), getStart());
            getFactory().registerKey(bc, ((DataMember) m).getName(), false);
            av.visitEndItem(adapter);
        }
        av.visitEnd();
    } else {
        Member m = members.iterator().next();
        if (!(m instanceof DataMember))
            throw new TransformerException("you cannot use a unary operator with a function " + m.getClass().getName(), getStart());
        getFactory().registerKey(bc, ((DataMember) m).getName(), false);
    }
    if (type == POST) {
        if (operation != OpDouble.PLUS && operation != OpDouble.MINUS)
            throw new TransformerException("Post only possible with plus or minus " + operation, value.getStart());
        value.writeOut(bc, MODE_VALUE);
        if (operation == PLUS)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_POST_PLUS_N : UNARY_POST_PLUS_1);
        else if (operation == MINUS)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_POST_MINUS_N : UNARY_POST_MINUS_1);
    } else if (type == PRE) {
        value.writeOut(bc, MODE_VALUE);
        if (operation == PLUS)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_PRE_PLUS_N : UNARY_PRE_PLUS_1);
        else if (operation == MINUS)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_PRE_MINUS_N : UNARY_PRE_MINUS_1);
        else if (operation == DIVIDE)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_PRE_DIVIDE_N : UNARY_PRE_DIVIDE_1);
        else if (operation == MULTIPLY)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_PRE_MULTIPLY_N : UNARY_PRE_MULTIPLY_1);
        else if (operation == CONCAT)
            adapter.invokeStatic(Types.OPERATOR, useArray ? UNARY_PRE_CONCAT_N : UNARY_PRE_CONCAT_1);
    }
    if (operation == CONCAT)
        return Types.STRING;
    // convert from double to Double (if necessary)
    if (mode == MODE_REF) {
        adapter.invokeStatic(Types.CASTER, Methods.METHOD_TO_DOUBLE_FROM_DOUBLE);
        return Types.DOUBLE;
    }
    return Types.DOUBLE_VALUE;
}
Also used : DataMember(lucee.transformer.expression.var.DataMember) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) CastString(lucee.transformer.bytecode.cast.CastString) ArrayVisitor(lucee.transformer.bytecode.visitor.ArrayVisitor) DataMember(lucee.transformer.expression.var.DataMember) Member(lucee.transformer.expression.var.Member) TransformerException(lucee.transformer.TransformerException)

Example 8 with ArrayVisitor

use of lucee.transformer.bytecode.visitor.ArrayVisitor in project Lucee by lucee.

the class OpElvis method _writeOutPureDataMember.

public Type _writeOutPureDataMember(BytecodeContext bc, int mode) throws TransformerException {
    // TODO use function isNull for this
    GeneratorAdapter adapter = bc.getAdapter();
    Label yes = new Label();
    Label end = new Label();
    List<Member> members = left.getMembers();
    // to array
    Iterator<Member> it = members.iterator();
    List<DataMember> list = new ArrayList<DataMember>();
    while (it.hasNext()) {
        list.add((DataMember) it.next());
    }
    DataMember[] arr = list.toArray(new DataMember[members.size()]);
    ExpressionUtil.visitLine(bc, left.getStart());
    // public static boolean call(PageContext pc , double scope,String[] varNames)
    // pc
    adapter.loadArg(0);
    // scope
    adapter.push((double) left.getScope());
    // varNames
    // all literal string?
    boolean allLiteral = true;
    for (int i = 0; i < arr.length; i++) {
        if (!(arr[i].getName() instanceof Literal))
            allLiteral = false;
    }
    ArrayVisitor av = new ArrayVisitor();
    if (!allLiteral) {
        // String Array
        av.visitBegin(adapter, Types.STRING, arr.length);
        for (int i = 0; i < arr.length; i++) {
            av.visitBeginItem(adapter, i);
            arr[i].getName().writeOut(bc, MODE_REF);
            av.visitEndItem(adapter);
        }
    } else {
        // Collection.Key Array
        av.visitBegin(adapter, Types.COLLECTION_KEY, arr.length);
        for (int i = 0; i < arr.length; i++) {
            av.visitBeginItem(adapter, i);
            getFactory().registerKey(bc, arr[i].getName(), false);
            av.visitEndItem(adapter);
        }
    }
    av.visitEnd();
    // allowNull
    // adapter.push(false);
    // ASMConstants.NULL(adapter);
    // call IsDefined.invoke
    adapter.invokeStatic(ELVIS, allLiteral ? INVOKE_KEY : INVOKE_STR);
    ExpressionUtil.visitLine(bc, left.getEnd());
    adapter.visitJumpInsn(Opcodes.IFEQ, yes);
    // left
    ExpressionUtil.visitLine(bc, left.getStart());
    left.writeOut(bc, MODE_REF);
    ExpressionUtil.visitLine(bc, left.getEnd());
    adapter.visitJumpInsn(Opcodes.GOTO, end);
    // right
    ExpressionUtil.visitLine(bc, right.getStart());
    adapter.visitLabel(yes);
    right.writeOut(bc, MODE_REF);
    ExpressionUtil.visitLine(bc, right.getEnd());
    adapter.visitLabel(end);
    return Types.OBJECT;
}
Also used : Label(org.objectweb.asm.Label) ArrayList(java.util.ArrayList) Literal(lucee.transformer.expression.literal.Literal) DataMember(lucee.transformer.expression.var.DataMember) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ArrayVisitor(lucee.transformer.bytecode.visitor.ArrayVisitor) DataMember(lucee.transformer.expression.var.DataMember) Member(lucee.transformer.expression.var.Member)

Example 9 with ArrayVisitor

use of lucee.transformer.bytecode.visitor.ArrayVisitor in project Lucee by lucee.

the class JavaProxyFactory method _createMethod.

private static void _createMethod(ClassWriter cw, Map<String, Class> mDone, Method src, String className) throws IOException {
    final Class<?>[] classArgs = src.getParameterTypes();
    final Class<?> classRtn = src.getReturnType();
    String str = src.getName() + "(" + Reflector.getDspMethods(classArgs) + ")";
    Class rtnClass = mDone.get(str);
    if (rtnClass != null) {
        if (rtnClass != classRtn)
            throw new IOException("there is a conflict with method [" + str + "], this method is declared more than once with different return types.");
        return;
    }
    mDone.put(str, classRtn);
    Type[] typeArgs = ASMUtil.toTypes(classArgs);
    Type typeRtn = Type.getType(classRtn);
    org.objectweb.asm.commons.Method method = new org.objectweb.asm.commons.Method(src.getName(), typeRtn, typeArgs);
    GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, method, null, null, cw);
    // BytecodeContext bc = new BytecodeContext(statConstr,constr,null,null,keys,cw,className,adapter,method,writeLog);
    Label start = adapter.newLabel();
    adapter.visitLabel(start);
    // if the result of "call" need castring, we have to do this here
    if (needCastring(classRtn)) {
        adapter.invokeStatic(CFML_ENGINE_FACTORY, GET_INSTANCE);
        adapter.invokeInterface(CFML_ENGINE, GET_JAVA_PROXY_UTIL);
        adapter.checkCast(JAVA_PROXY_UTIL);
    }
    adapter.invokeStatic(CFML_ENGINE_FACTORY, GET_INSTANCE);
    adapter.invokeInterface(CFML_ENGINE, GET_JAVA_PROXY_UTIL);
    adapter.checkCast(JAVA_PROXY_UTIL);
    // Java Proxy.call(cfc,"add",new Object[]{arg0})
    // config (first argument)
    adapter.visitVarInsn(Opcodes.ALOAD, 0);
    adapter.visitFieldInsn(Opcodes.GETFIELD, className, "config", CONFIG_WEB_NAME);
    // cfc (second argument)
    adapter.visitVarInsn(Opcodes.ALOAD, 0);
    adapter.visitFieldInsn(Opcodes.GETFIELD, className, "cfc", COMPONENT_NAME);
    // name (3th argument)
    adapter.push(src.getName());
    // arguments (4th argument)
    ArrayVisitor av = new ArrayVisitor();
    av.visitBegin(adapter, Types.OBJECT, typeArgs.length);
    for (int y = 0; y < typeArgs.length; y++) {
        av.visitBeginItem(adapter, y);
        adapter.invokeStatic(CFML_ENGINE_FACTORY, GET_INSTANCE);
        adapter.invokeInterface(CFML_ENGINE, GET_JAVA_PROXY_UTIL);
        adapter.checkCast(JAVA_PROXY_UTIL);
        adapter.loadArg(y);
        if (classArgs[y] == boolean.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _BOOLEAN);
        else if (classArgs[y] == byte.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _BYTE);
        else if (classArgs[y] == char.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _CHAR);
        else if (classArgs[y] == double.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _DOUBLE);
        else if (classArgs[y] == float.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _FLOAT);
        else if (classArgs[y] == int.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _INT);
        else if (classArgs[y] == long.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _LONG);
        else if (classArgs[y] == short.class)
            adapter.invokeInterface(JAVA_PROXY_UTIL, _SHORT);
        else
            adapter.invokeInterface(JAVA_PROXY_UTIL, _OBJECT);
        av.visitEndItem(adapter);
    }
    av.visitEnd();
    adapter.invokeInterface(JAVA_PROXY_UTIL, CALL);
    // CFMLEngineFactory.getInstance().getCastUtil().toBooleanValue(o);
    // Java Proxy.to...(...);
    int rtn = Opcodes.IRETURN;
    if (classRtn == boolean.class)
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_BOOLEAN);
    else if (classRtn == byte.class)
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_BYTE);
    else if (classRtn == char.class)
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_CHAR);
    else if (classRtn == double.class) {
        rtn = Opcodes.DRETURN;
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_DOUBLE);
    } else if (classRtn == float.class) {
        rtn = Opcodes.FRETURN;
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_FLOAT);
    } else if (classRtn == int.class)
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_INT);
    else if (classRtn == long.class) {
        rtn = Opcodes.LRETURN;
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_LONG);
    } else if (classRtn == short.class)
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_SHORT);
    else if (classRtn == void.class) {
        rtn = Opcodes.RETURN;
        adapter.pop();
    } else if (classRtn == String.class) {
        rtn = Opcodes.ARETURN;
        adapter.invokeInterface(JAVA_PROXY_UTIL, TO_STRING);
    } else {
        rtn = Opcodes.ARETURN;
        adapter.checkCast(typeRtn);
    }
    adapter.visitInsn(rtn);
    adapter.endMethod();
}
Also used : Label(org.objectweb.asm.Label) IOException(java.io.IOException) Method(java.lang.reflect.Method) Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ArrayVisitor(lucee.transformer.bytecode.visitor.ArrayVisitor)

Example 10 with ArrayVisitor

use of lucee.transformer.bytecode.visitor.ArrayVisitor in project Lucee by lucee.

the class SourceLastModifiedClassAdapter method execute.

/**
 * convert the Page Object to java bytecode
 * @param className name of the genrated class (only necessary when Page object has no PageSource reference)
 * @return
 * @throws TransformerException
 */
public byte[] execute(String className) throws TransformerException {
    // not exists in any case, so every usage must have a plan b for not existence
    PageSource optionalPS = sourceCode instanceof PageSourceCode ? ((PageSourceCode) sourceCode).getPageSource() : null;
    List<LitString> keys = new ArrayList<LitString>();
    ClassWriter cw = ASMUtil.getClassWriter();
    ArrayList<String> imports = new ArrayList<String>();
    getImports(imports, this);
    // look for component if necessary
    TagCIObject comp = getTagCFObject(null);
    // in case we have a sub component
    if (className == null) {
        if (optionalPS == null)
            throw new IllegalArgumentException("when Page object has no PageSource, a className is necessary");
        className = optionalPS.getClassName();
    }
    if (comp != null)
        className = createSubClass(className, comp.getName(), sourceCode.getDialect());
    className = className.replace('.', '/');
    this.className = className;
    // parent
    // "lucee/runtime/Page";
    String parent = PageImpl.class.getName();
    if (// "lucee/runtime/ComponentPage";
    isComponent(comp))
        // "lucee/runtime/ComponentPage";
        parent = ComponentPageImpl.class.getName();
    else // "lucee/runtime/InterfacePage";
    if (isInterface(comp))
        parent = InterfacePageImpl.class.getName();
    parent = parent.replace('.', '/');
    cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, className, null, parent, null);
    if (optionalPS != null) {
        // we use full path  when FD is enabled
        String path = config.allowRequestTimeout() ? optionalPS.getRealpathWithVirtual() : optionalPS.getPhyscalFile().getAbsolutePath();
        // when adding more use ; as delimiter
        cw.visitSource(path, null);
    // cw.visitSource(optionalPS.getPhyscalFile().getAbsolutePath(),
    // "rel:"+optionalPS.getRealpathWithVirtual()); // when adding more use ; as delimiter
    } else {
    // cw.visitSource("","rel:");
    }
    // static constructor
    // GeneratorAdapter statConstrAdapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC,STATIC_CONSTRUCTOR,null,null,cw);
    // StaticConstrBytecodeContext statConstr = null;//new BytecodeContext(null,null,this,externalizer,keys,cw,name,statConstrAdapter,STATIC_CONSTRUCTOR,writeLog(),suppressWSbeforeArg);
    // constructor
    GeneratorAdapter constrAdapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, CONSTRUCTOR_PS, null, null, cw);
    ConstrBytecodeContext constr = new ConstrBytecodeContext(optionalPS, this, keys, cw, className, constrAdapter, CONSTRUCTOR_PS, writeLog(), suppressWSbeforeArg, output, returnValue);
    constrAdapter.loadThis();
    Type t;
    if (isComponent(comp)) {
        t = Types.COMPONENT_PAGE_IMPL;
        // extends
        // Attribute attr = comp.getAttribute("extends");
        // if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),constr, Expression.MODE_REF);
        // else constrAdapter.push("");
        constrAdapter.invokeConstructor(t, CONSTRUCTOR);
    } else if (isInterface(comp)) {
        t = Types.INTERFACE_PAGE_IMPL;
        constrAdapter.invokeConstructor(t, CONSTRUCTOR);
    } else {
        t = Types.PAGE_IMPL;
        constrAdapter.invokeConstructor(t, CONSTRUCTOR);
    }
    // call _init()
    constrAdapter.visitVarInsn(Opcodes.ALOAD, 0);
    constrAdapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, constr.getClassName(), "initKeys", "()V");
    // private static  ImportDefintion[] test=new ImportDefintion[]{...};
    {
        FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "imports", "[Llucee/runtime/component/ImportDefintion;", null, null);
        fv.visitEnd();
        constrAdapter.visitVarInsn(Opcodes.ALOAD, 0);
        ArrayVisitor av = new ArrayVisitor();
        av.visitBegin(constrAdapter, Types.IMPORT_DEFINITIONS, imports.size());
        int index = 0;
        Iterator<String> it = imports.iterator();
        while (it.hasNext()) {
            av.visitBeginItem(constrAdapter, index++);
            constrAdapter.push(it.next());
            ASMConstants.NULL(constrAdapter);
            constrAdapter.invokeStatic(Types.IMPORT_DEFINITIONS_IMPL, ID_GET_INSTANCE);
            av.visitEndItem(constrAdapter);
        }
        av.visitEnd();
        constrAdapter.visitFieldInsn(Opcodes.PUTFIELD, className, "imports", "[Llucee/runtime/component/ImportDefintion;");
    }
    // getVersion
    GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, VERSION, null, null, cw);
    adapter.push(version);
    adapter.returnValue();
    adapter.endMethod();
    // public ImportDefintion[] getImportDefintions()
    if (imports.size() > 0) {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, GET_IMPORT_DEFINITIONS, null, null, cw);
        adapter.visitVarInsn(Opcodes.ALOAD, 0);
        adapter.visitFieldInsn(Opcodes.GETFIELD, className, "imports", "[Llucee/runtime/component/ImportDefintion;");
        adapter.returnValue();
        adapter.endMethod();
    } else {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, GET_IMPORT_DEFINITIONS, null, null, cw);
        adapter.visitInsn(Opcodes.ICONST_0);
        adapter.visitTypeInsn(Opcodes.ANEWARRAY, "lucee/runtime/component/ImportDefintion");
        adapter.returnValue();
        adapter.endMethod();
    }
    // getSourceLastModified
    adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, LAST_MOD, null, null, cw);
    adapter.push(lastModifed);
    adapter.returnValue();
    adapter.endMethod();
    // getSourceLength
    adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, LENGTH, null, null, cw);
    adapter.push(length);
    adapter.returnValue();
    adapter.endMethod();
    // getCompileTime
    adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, COMPILE_TIME, null, null, cw);
    adapter.push(System.currentTimeMillis());
    adapter.returnValue();
    adapter.endMethod();
    // getHash
    adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, HASH, null, null, cw);
    adapter.push(hash);
    adapter.returnValue();
    adapter.endMethod();
    if (comp != null) {
        writeOutStaticConstructor(constr, keys, cw, comp, className);
    }
    // newInstance/initComponent/call
    if (isComponent()) {
        writeOutNewComponent(constr, keys, cw, comp, className);
        writeOutInitComponent(constr, keys, cw, comp, className);
    } else if (isInterface()) {
        writeOutNewInterface(constr, keys, cw, comp, className);
        writeOutInitInterface(constr, keys, cw, comp, className);
    } else {
        writeOutCall(constr, keys, cw, className);
    }
    // write UDFProperties to constructor
    // writeUDFProperties(bc,funcs,pageType);
    // udfCall
    Function[] functions = getFunctions();
    ConditionVisitor cv;
    DecisionIntVisitor div;
    // less/equal than 10 functions
    if (isInterface()) {
    } else if (functions.length <= 10) {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, UDF_CALL, null, new Type[] { Types.THROWABLE }, cw);
        BytecodeContext bc = new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, UDF_CALL, writeLog(), suppressWSbeforeArg, output, returnValue);
        if (functions.length == 0) {
        } else if (functions.length == 1) {
            ExpressionUtil.visitLine(bc, functions[0].getStart());
            functions[0].getBody().writeOut(bc);
            ExpressionUtil.visitLine(bc, functions[0].getEnd());
        } else
            writeOutUdfCallInner(bc, functions, 0, functions.length);
        adapter.visitInsn(Opcodes.ACONST_NULL);
        adapter.returnValue();
        adapter.endMethod();
    } else // more than 10 functions
    {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, UDF_CALL, null, new Type[] { Types.THROWABLE }, cw);
        BytecodeContext bc = new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, UDF_CALL, writeLog(), suppressWSbeforeArg, output, returnValue);
        cv = new ConditionVisitor();
        cv.visitBefore();
        int count = 0;
        for (int i = 0; i < functions.length; i += 10) {
            cv.visitWhenBeforeExpr();
            div = new DecisionIntVisitor();
            div.visitBegin();
            adapter.loadArg(2);
            div.visitLT();
            adapter.push(i + 10);
            div.visitEnd(bc);
            cv.visitWhenAfterExprBeforeBody(bc);
            adapter.visitVarInsn(Opcodes.ALOAD, 0);
            adapter.visitVarInsn(Opcodes.ALOAD, 1);
            adapter.visitVarInsn(Opcodes.ALOAD, 2);
            adapter.visitVarInsn(Opcodes.ILOAD, 3);
            adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, createFunctionName(++count), "(Llucee/runtime/PageContext;Llucee/runtime/type/UDF;I)Ljava/lang/Object;");
            // adapter.returnValue();
            adapter.visitInsn(Opcodes.ARETURN);
            cv.visitWhenAfterBody(bc);
        }
        cv.visitAfter(bc);
        adapter.visitInsn(Opcodes.ACONST_NULL);
        adapter.returnValue();
        adapter.endMethod();
        count = 0;
        Method innerCall;
        for (int i = 0; i < functions.length; i += 10) {
            innerCall = new Method(createFunctionName(++count), Types.OBJECT, new Type[] { Types.PAGE_CONTEXT, USER_DEFINED_FUNCTION, Types.INT_VALUE });
            adapter = new GeneratorAdapter(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, innerCall, null, new Type[] { Types.THROWABLE }, cw);
            writeOutUdfCallInner(new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, innerCall, writeLog(), suppressWSbeforeArg, output, returnValue), functions, i, i + 10 > functions.length ? functions.length : i + 10);
            adapter.visitInsn(Opcodes.ACONST_NULL);
            adapter.returnValue();
            adapter.endMethod();
        }
    }
    // threadCall
    TagThread[] threads = getThreads();
    if (true) {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, THREAD_CALL, null, new Type[] { Types.THROWABLE }, cw);
        if (threads.length > 0)
            writeOutThreadCallInner(new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, THREAD_CALL, writeLog(), suppressWSbeforeArg, output, returnValue), threads, 0, threads.length);
        // adapter.visitInsn(Opcodes.ACONST_NULL);
        adapter.returnValue();
        adapter.endMethod();
    }
    // less/equal than 10 functions
    if (isInterface()) {
    } else if (functions.length <= 10) {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, UDF_DEFAULT_VALUE, null, new Type[] { Types.PAGE_EXCEPTION }, cw);
        if (functions.length > 0)
            writeUdfDefaultValueInner(new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, UDF_DEFAULT_VALUE, writeLog(), suppressWSbeforeArg, output, returnValue), functions, 0, functions.length);
        adapter.loadArg(DEFAULT_VALUE);
        adapter.returnValue();
        adapter.endMethod();
    } else {
        adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL, UDF_DEFAULT_VALUE, null, new Type[] { Types.PAGE_EXCEPTION }, cw);
        BytecodeContext bc = new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, UDF_DEFAULT_VALUE, writeLog(), suppressWSbeforeArg, output, returnValue);
        cv = new ConditionVisitor();
        cv.visitBefore();
        int count = 0;
        for (int i = 0; i < functions.length; i += 10) {
            cv.visitWhenBeforeExpr();
            div = new DecisionIntVisitor();
            div.visitBegin();
            adapter.loadArg(1);
            div.visitLT();
            adapter.push(i + 10);
            div.visitEnd(bc);
            cv.visitWhenAfterExprBeforeBody(bc);
            adapter.visitVarInsn(Opcodes.ALOAD, 0);
            adapter.visitVarInsn(Opcodes.ALOAD, 1);
            adapter.visitVarInsn(Opcodes.ILOAD, 2);
            adapter.visitVarInsn(Opcodes.ILOAD, 3);
            adapter.visitVarInsn(Opcodes.ALOAD, 4);
            adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "udfDefaultValue" + (++count), "(Llucee/runtime/PageContext;IILjava/lang/Object;)Ljava/lang/Object;");
            // adapter.returnValue();
            adapter.visitInsn(Opcodes.ARETURN);
            cv.visitWhenAfterBody(bc);
        }
        cv.visitAfter(bc);
        adapter.visitInsn(Opcodes.ACONST_NULL);
        adapter.returnValue();
        adapter.endMethod();
        count = 0;
        Method innerDefaultValue;
        for (int i = 0; i < functions.length; i += 10) {
            innerDefaultValue = new Method("udfDefaultValue" + (++count), Types.OBJECT, new Type[] { Types.PAGE_CONTEXT, Types.INT_VALUE, Types.INT_VALUE, Types.OBJECT });
            adapter = new GeneratorAdapter(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, innerDefaultValue, null, new Type[] { Types.PAGE_EXCEPTION }, cw);
            writeUdfDefaultValueInner(new BytecodeContext(optionalPS, constr, this, keys, cw, className, adapter, innerDefaultValue, writeLog(), suppressWSbeforeArg, output, returnValue), functions, i, i + 10 > functions.length ? functions.length : i + 10);
            adapter.loadArg(DEFAULT_VALUE);
            // adapter.visitInsn(Opcodes.ACONST_NULL);
            adapter.returnValue();
            adapter.endMethod();
        }
    }
    // CONSTRUCTOR
    List<Data> udfProperties = constr.getUDFProperties();
    Iterator<Data> it = udfProperties.iterator();
    String udfpropsClassName = Types.UDF_PROPERTIES_ARRAY.toString();
    // new UDFProperties Array
    constrAdapter.visitVarInsn(Opcodes.ALOAD, 0);
    constrAdapter.push(udfProperties.size());
    constrAdapter.newArray(Types.UDF_PROPERTIES);
    constrAdapter.visitFieldInsn(Opcodes.PUTFIELD, getClassName(), "udfs", udfpropsClassName);
    // set item
    Data data;
    while (it.hasNext()) {
        data = it.next();
        constrAdapter.visitVarInsn(Opcodes.ALOAD, 0);
        constrAdapter.visitFieldInsn(Opcodes.GETFIELD, constr.getClassName(), "udfs", Types.UDF_PROPERTIES_ARRAY.toString());
        constrAdapter.push(data.arrayIndex);
        data.function.createUDFProperties(constr, data.valueIndex, data.type);
        constrAdapter.visitInsn(Opcodes.AASTORE);
    }
    // setPageSource(pageSource);
    constrAdapter.visitVarInsn(Opcodes.ALOAD, 0);
    constrAdapter.visitVarInsn(Opcodes.ALOAD, 1);
    constrAdapter.invokeVirtual(t, SET_PAGE_SOURCE);
    constrAdapter.returnValue();
    constrAdapter.endMethod();
    // INIT KEYS
    {
        GeneratorAdapter aInit = new GeneratorAdapter(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, INIT_KEYS, null, null, cw);
        BytecodeContext bcInit = new BytecodeContext(optionalPS, constr, this, keys, cw, className, aInit, INIT_KEYS, writeLog(), suppressWSbeforeArg, output, returnValue);
        registerFields(bcInit, keys);
        aInit.returnValue();
        aInit.endMethod();
    }
    // set field subs
    FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, "subs", "[Llucee/runtime/CIPage;", null, null);
    fv.visitEnd();
    // create sub components/interfaces
    if (comp != null && comp.isMain()) {
        List<TagCIObject> subs = getSubs(null);
        if (!ArrayUtil.isEmpty(subs)) {
            Iterator<TagCIObject> _it = subs.iterator();
            TagCIObject tc;
            while (_it.hasNext()) {
                tc = _it.next();
                tc.writeOut(this);
            }
            writeGetSubPages(cw, className, subs, sourceCode.getDialect());
        }
    }
    return cw.toByteArray();
}
Also used : InterfacePageImpl(lucee.runtime.InterfacePageImpl) PageSourceCode(lucee.transformer.util.PageSourceCode) ArrayList(java.util.ArrayList) TagThread(lucee.transformer.bytecode.statement.tag.TagThread) LitString(lucee.transformer.expression.literal.LitString) FieldVisitor(org.objectweb.asm.FieldVisitor) LitString(lucee.transformer.expression.literal.LitString) Function(lucee.transformer.bytecode.statement.udf.Function) IFunction(lucee.transformer.bytecode.statement.IFunction) ConditionVisitor(lucee.transformer.bytecode.visitor.ConditionVisitor) Iterator(java.util.Iterator) DecisionIntVisitor(lucee.transformer.bytecode.visitor.DecisionIntVisitor) TagCIObject(lucee.transformer.bytecode.statement.tag.TagCIObject) Data(lucee.transformer.bytecode.ConstrBytecodeContext.Data) Method(org.objectweb.asm.commons.Method) ClassWriter(org.objectweb.asm.ClassWriter) PageSource(lucee.runtime.PageSource) Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) ArrayVisitor(lucee.transformer.bytecode.visitor.ArrayVisitor)

Aggregations

ArrayVisitor (lucee.transformer.bytecode.visitor.ArrayVisitor)11 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)11 Label (org.objectweb.asm.Label)5 Type (org.objectweb.asm.Type)4 DataMember (lucee.transformer.expression.var.DataMember)3 Member (lucee.transformer.expression.var.Member)3 ArrayList (java.util.ArrayList)2 TransformerException (lucee.transformer.TransformerException)2 BytecodeContext (lucee.transformer.bytecode.BytecodeContext)2 TagCIObject (lucee.transformer.bytecode.statement.tag.TagCIObject)2 LitString (lucee.transformer.expression.literal.LitString)2 Method (org.objectweb.asm.commons.Method)2 IOException (java.io.IOException)1 Method (java.lang.reflect.Method)1 Iterator (java.util.Iterator)1 ClassException (lucee.commons.lang.ClassException)1 RefInteger (lucee.commons.lang.types.RefInteger)1 RefIntegerImpl (lucee.commons.lang.types.RefIntegerImpl)1 InterfacePageImpl (lucee.runtime.InterfacePageImpl)1 PageSource (lucee.runtime.PageSource)1