Search in sources :

Example 51 with Method

use of org.objectweb.asm.commons.Method in project Lucee by lucee.

the class ASMUtil method createProperty.

private static void createProperty(ClassWriter cw, String classType, ASMProperty property) throws PageException {
    String name = property.getName();
    Type type = property.getASMType();
    Class clazz = property.getClazz();
    cw.visitField(Opcodes.ACC_PRIVATE, name, type.toString(), null, null).visitEnd();
    int load = loadFor(type);
    // int sizeOf=sizeOf(type);
    // get<PropertyName>():<type>
    Type[] types = new Type[0];
    Method method = new Method((clazz == boolean.class ? "get" : "get") + (name), type, types);
    GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw);
    Label start = new Label();
    adapter.visitLabel(start);
    adapter.visitVarInsn(Opcodes.ALOAD, 0);
    adapter.visitFieldInsn(Opcodes.GETFIELD, classType, name, type.toString());
    adapter.returnValue();
    Label end = new Label();
    adapter.visitLabel(end);
    adapter.visitLocalVariable("this", "L" + classType + ";", null, start, end, 0);
    adapter.visitEnd();
    adapter.endMethod();
    // set<PropertyName>(object):void
    types = new Type[] { type };
    method = new Method("set" + (name), Types.VOID, types);
    adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC, method, null, null, cw);
    start = new Label();
    adapter.visitLabel(start);
    adapter.visitVarInsn(Opcodes.ALOAD, 0);
    adapter.visitVarInsn(load, 1);
    adapter.visitFieldInsn(Opcodes.PUTFIELD, classType, name, type.toString());
    adapter.visitInsn(Opcodes.RETURN);
    end = new Label();
    adapter.visitLabel(end);
    adapter.visitLocalVariable("this", "L" + classType + ";", null, start, end, 0);
    adapter.visitLocalVariable(name, type.toString(), null, start, end, 1);
    // adapter.visitMaxs(0, 0);//.visitMaxs(sizeOf+1, sizeOf+1);// hansx
    adapter.visitEnd();
    adapter.endMethod();
}
Also used : Type(org.objectweb.asm.Type) Label(org.objectweb.asm.Label) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) VariableString(lucee.transformer.bytecode.expression.var.VariableString) LitString(lucee.transformer.expression.literal.LitString) ExprString(lucee.transformer.expression.ExprString) Method(org.objectweb.asm.commons.Method) lucee.aprint(lucee.aprint)

Example 52 with Method

use of org.objectweb.asm.commons.Method 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)

Example 53 with Method

use of org.objectweb.asm.commons.Method in project Lucee by lucee.

the class VT method _writeOutEmpty.

/**
 * outputs a empty Variable, only scope
 * Example: pc.formScope();
 * @param adapter
 * @throws TemplateException
 */
private Type _writeOutEmpty(BytecodeContext bc) throws TransformerException {
    if (ignoredFirstMember && (scope == Scope.SCOPE_LOCAL || scope == Scope.SCOPE_VAR))
        return Types.VOID;
    GeneratorAdapter adapter = bc.getAdapter();
    adapter.loadArg(0);
    Method m;
    Type t = Types.PAGE_CONTEXT;
    if (scope == Scope.SCOPE_ARGUMENTS) {
        getFactory().TRUE().writeOut(bc, MODE_VALUE);
        m = TypeScope.METHOD_ARGUMENT_BIND;
    } else if (scope == Scope.SCOPE_LOCAL) {
        t = Types.PAGE_CONTEXT;
        getFactory().TRUE().writeOut(bc, MODE_VALUE);
        m = TypeScope.METHOD_LOCAL_BIND;
    } else if (scope == Scope.SCOPE_VAR) {
        t = Types.PAGE_CONTEXT;
        getFactory().TRUE().writeOut(bc, MODE_VALUE);
        m = TypeScope.METHOD_VAR_BIND;
    } else
        m = TypeScope.METHODS[scope];
    TypeScope.invokeScope(adapter, m, t);
    return m.getReturnType();
}
Also used : Type(org.objectweb.asm.Type) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) Method(org.objectweb.asm.commons.Method)

Example 54 with Method

use of org.objectweb.asm.commons.Method in project cdap by caskdata.

the class SparkClassRewriter method rewritePythonRunner.

/**
 * Rewrites the PythonRunner.main() method to wrap it with call to SparkRuntimeUtils.initSparkMain() method on
 * enter and cancel on exit. Also, wrap the PythonRunner.main() call with a try block to catch the
 * {@code SparkUserAppException} into a {@link RuntimeException} to avoid Spark calling System.exit in
 * {@link SparkSubmit}.
 */
private byte[] rewritePythonRunner(InputStream byteCodeStream) throws IOException {
    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    // Intercept the static void main(String[] args) method.
    final Method mainMethod = new Method("main", Type.VOID_TYPE, new Type[] { Type.getType(String[].class) });
    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            if (!mainMethod.equals(new Method(name, desc)) || !Modifier.isStatic(access)) {
                return mv;
            }
            // }
            return new AdviceAdapter(Opcodes.ASM5, mv, access, name, desc) {

                final Type sparkUserAppExceptionType = Type.getObjectType("org/apache/spark/SparkUserAppException");

                final Type cancellableType = Type.getObjectType("org/apache/twill/common/Cancellable");

                final Label tryLabel = newLabel();

                final Label tryEndLabel = newLabel();

                final Label catchLabel = newLabel();

                final Label finallyLabel = newLabel();

                int cancellable;

                @Override
                protected void onMethodEnter() {
                    cancellable = newLocal(cancellableType);
                    invokeStatic(SPARK_RUNTIME_UTILS_TYPE, new Method("initSparkMain", cancellableType, EMPTY_ARGS));
                    storeLocal(cancellable);
                    // try {
                    visitTryCatchBlock(tryLabel, tryEndLabel, catchLabel, sparkUserAppExceptionType.getInternalName());
                    visitLabel(tryLabel);
                }

                @Override
                protected void onMethodExit(int opcode) {
                    // } catch (SparkUserAppException e) {
                    // throw new RuntimeException(e);
                    visitLabel(tryEndLabel);
                    goTo(finallyLabel);
                    visitLabel(catchLabel);
                    int exception = newLocal(sparkUserAppExceptionType);
                    storeLocal(exception);
                    newInstance(Type.getType(RuntimeException.class));
                    dup();
                    loadLocal(exception);
                    invokeConstructor(Type.getType(RuntimeException.class), Methods.getMethod(void.class, "<init>", Throwable.class));
                    throwException();
                    // } finally {
                    // cancellable.cancel()
                    // }
                    visitLabel(finallyLabel);
                    loadLocal(cancellable);
                    invokeInterface(cancellableType, new Method("cancel", Type.VOID_TYPE, EMPTY_ARGS));
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);
    return cw.toByteArray();
}
Also used : AdviceAdapter(org.objectweb.asm.commons.AdviceAdapter) Type(org.objectweb.asm.Type) Label(org.objectweb.asm.Label) ClassReader(org.objectweb.asm.ClassReader) Method(org.objectweb.asm.commons.Method) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 55 with Method

use of org.objectweb.asm.commons.Method in project cdap by caskdata.

the class SparkClassRewriter method rewriteExecutorClassLoader.

/**
 * Rewrites the ExecutorClassLoader so that it won't use system classloader as parent since CDAP classes
 * are not in system classloader.
 * Also optionally overrides the getResource, getResources and getResourceAsStream methods if they are not
 * defined (for fixing SPARK-11818 for older Spark < 1.6).
 */
private byte[] rewriteExecutorClassLoader(InputStream byteCodeStream) throws IOException {
    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    final Type classloaderType = Type.getType(ClassLoader.class);
    final Type parentClassLoaderType = Type.getObjectType("org/apache/spark/util/ParentClassLoader");
    final Method parentLoaderMethod = new Method("parentLoader", parentClassLoaderType, EMPTY_ARGS);
    // Map from getResource* methods to the method signature
    // (can be null, since only method that has generic has signature)
    final Map<Method, String> resourceMethods = new HashMap<>();
    Method method = new Method("getResource", Type.getType(URL.class), new Type[] { Type.getType(String.class) });
    resourceMethods.put(method, null);
    method = new Method("getResources", Type.getType(Enumeration.class), new Type[] { Type.getType(String.class) });
    resourceMethods.put(method, Signatures.getMethodSignature(method, new TypeToken<Enumeration<URL>>() {
    }, TypeToken.of(String.class)));
    method = new Method("getResourceAsStream", Type.getType(InputStream.class), new Type[] { Type.getType(String.class) });
    resourceMethods.put(method, null);
    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {

        private boolean hasParentLoader;

        private boolean rewriteInit;

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            // Only rewrite `<init>` if the ExecutorClassloader extends from ClassLoader
            if (classloaderType.getInternalName().equals(superName)) {
                rewriteInit = true;
            }
            super.visit(version, access, name, signature, superName, interfaces);
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            // If the resource method is declared, no need to generate at the end.
            Method method = new Method(name, desc);
            resourceMethods.remove(method);
            hasParentLoader = hasParentLoader || parentLoaderMethod.equals(method);
            if (!rewriteInit || !"<init>".equals(name)) {
                return mv;
            }
            return new GeneratorAdapter(Opcodes.ASM5, mv, access, name, desc) {

                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    // If there is a call to `super()`, skip that instruction and have the onMethodEnter generate the call
                    if (opcode == Opcodes.INVOKESPECIAL && Type.getObjectType(owner).equals(classloaderType) && name.equals("<init>") && Type.getArgumentTypes(desc).length == 0 && Type.getReturnType(desc).equals(Type.VOID_TYPE)) {
                        // Generate `super(null)`. The `this` is already in the stack, so no need to `loadThis()`
                        push((Type) null);
                        invokeConstructor(classloaderType, new Method("<init>", Type.VOID_TYPE, new Type[] { classloaderType }));
                    } else {
                        super.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }
            };
        }

        @Override
        public void visitEnd() {
            // All implementations are delegating to the parentLoader
            if (!hasParentLoader) {
                super.visitEnd();
                return;
            }
            for (Map.Entry<Method, String> entry : resourceMethods.entrySet()) {
                // Generate the method.
                // return parentLoader().getResource*(arg)
                Method method = entry.getKey();
                MethodVisitor mv = super.visitMethod(Modifier.PUBLIC, method.getName(), method.getDescriptor(), entry.getValue(), null);
                GeneratorAdapter generator = new GeneratorAdapter(Modifier.PUBLIC, method, mv);
                // call `parentLoader()`
                generator.loadThis();
                generator.invokeVirtual(SPARK_EXECUTOR_CLASSLOADER_TYPE, parentLoaderMethod);
                // Load the argument
                generator.loadArg(0);
                // Call the method on the parent loader.
                generator.invokeVirtual(parentClassLoaderType, method);
                generator.returnValue();
                generator.endMethod();
            }
        }
    }, ClassReader.EXPAND_FRAMES);
    return cw.toByteArray();
}
Also used : HashMap(java.util.HashMap) Method(org.objectweb.asm.commons.Method) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) URL(java.net.URL) MethodVisitor(org.objectweb.asm.MethodVisitor) Type(org.objectweb.asm.Type) TypeToken(com.google.common.reflect.TypeToken) ClassReader(org.objectweb.asm.ClassReader) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter)

Aggregations

Method (org.objectweb.asm.commons.Method)78 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)58 Type (org.objectweb.asm.Type)38 ClassWriter (org.objectweb.asm.ClassWriter)14 Label (org.objectweb.asm.Label)14 MethodVisitor (org.objectweb.asm.MethodVisitor)9 IOException (java.io.IOException)7 ClassReader (org.objectweb.asm.ClassReader)7 TypeInfo (com.google.template.soy.jbcsrc.restricted.TypeInfo)6 MethodNode (org.objectweb.asm.tree.MethodNode)6 ExprString (lucee.transformer.expression.ExprString)5 LitString (lucee.transformer.expression.literal.LitString)5 ClassVisitor (org.objectweb.asm.ClassVisitor)5 Schema (co.cask.cdap.api.data.schema.Schema)4 ArrayList (java.util.ArrayList)4 File (java.io.File)3 Set (java.util.Set)3 Nullable (javax.annotation.Nullable)3 ExprDouble (lucee.transformer.expression.ExprDouble)3 MetricsContext (co.cask.cdap.api.metrics.MetricsContext)2