Search in sources :

Example 46 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class CompileStack method applyBlockRecorder.

private void applyBlockRecorder(List<BlockRecorder> blocks) {
    if (blocks.isEmpty() || blocks.size() == visitedBlocks.size())
        return;
    MethodVisitor mv = controller.getMethodVisitor();
    for (BlockRecorder fb : blocks) {
        if (visitedBlocks.contains(fb))
            continue;
        Label end = new Label();
        mv.visitInsn(NOP);
        mv.visitLabel(end);
        fb.closeRange(end);
        // we exclude the finally block from the exception table
        // here to avoid double visiting of finally statements
        fb.excludedStatement.run();
        Label newStart = new Label();
        fb.startRange(newStart);
        mv.visitInsn(NOP);
        mv.visitLabel(newStart);
    }
}
Also used : Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 47 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class CompileStack method defineVariable.

public BytecodeVariable defineVariable(Variable v, ClassNode variableType, boolean initFromStack) {
    String name = v.getName();
    BytecodeVariable answer = defineVar(name, variableType, v.isClosureSharedVariable(), v.isClosureSharedVariable());
    stackVariables.put(name, answer);
    MethodVisitor mv = controller.getMethodVisitor();
    Label startLabel = new Label();
    answer.setStartLabel(startLabel);
    ClassNode type = answer.getType().redirect();
    OperandStack operandStack = controller.getOperandStack();
    if (!initFromStack) {
        if (ClassHelper.isPrimitiveType(v.getOriginType()) && ClassHelper.getWrapper(v.getOriginType()) == variableType) {
            pushInitValue(v.getOriginType(), mv);
            operandStack.push(v.getOriginType());
            operandStack.box();
            operandStack.remove(1);
        } else {
            pushInitValue(type, mv);
        }
    }
    operandStack.push(answer.getType());
    if (answer.isHolder()) {
        operandStack.box();
        operandStack.remove(1);
        createReference(answer);
    } else {
        operandStack.storeVar(answer);
    }
    mv.visitLabel(startLabel);
    return answer;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) Label(org.objectweb.asm.Label) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 48 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class Verifier method addGroovyObjectInterfaceAndMethods.

protected void addGroovyObjectInterfaceAndMethods(ClassNode node, final String classInternalName) {
    if (!node.isDerivedFromGroovyObject())
        node.addInterface(ClassHelper.make(GroovyObject.class));
    FieldNode metaClassField = getMetaClassField(node);
    if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        addMethod(node, !isAbstract(node.getModifiers()), "getMetaClass", ACC_PUBLIC, ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                Label nullLabel = new Label();
                /**
                             *  the code is:
                             *  if (this.metaClass==null) {
                             *      this.metaClass = this.$getStaticMetaClass
                             *      return this.metaClass
                             *  } else {
                             *      return this.metaClass
                             *  }
                             *  with the optimization that the result of the
                             *  first this.metaClass is duped on the operand
                             *  stack and reused for the return in the else part
                             */
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(DUP);
                mv.visitJumpInsn(IFNULL, nullLabel);
                mv.visitInsn(ARETURN);
                mv.visitLabel(nullLabel);
                mv.visitInsn(POP);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitVarInsn(ALOAD, 0);
                mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                mv.visitInsn(ARETURN);
            }
        }));
    }
    Parameter[] parameters = new Parameter[] { new Parameter(ClassHelper.METACLASS_TYPE, "mc") };
    if (!node.hasMethod("setMetaClass", parameters)) {
        metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
        Statement setMetaClassCode;
        if (isFinal(metaClassField.getModifiers())) {
            ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
            ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
            setMetaClassCode = new ExpressionStatement(cce);
        } else {
            List list = new ArrayList();
            list.add(new BytecodeInstruction() {

                public void visit(MethodVisitor mv) {
                    /**
                         * the code is (meta class is stored in 1):
                         * this.metaClass = <1>
                         */
                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(ALOAD, 1);
                    mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                    mv.visitInsn(RETURN);
                }
            });
            setMetaClassCode = new BytecodeSequence(list);
        }
        addMethod(node, !isAbstract(node.getModifiers()), "setMetaClass", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
    }
    if (!node.hasMethod("invokeMethod", INVOKE_METHOD_PARAMS)) {
        VariableExpression vMethods = new VariableExpression("method");
        VariableExpression vArguments = new VariableExpression("arguments");
        VariableScope blockScope = new VariableScope();
        blockScope.putReferencedLocalVariable(vMethods);
        blockScope.putReferencedLocalVariable(vArguments);
        addMethod(node, !isAbstract(node.getModifiers()), "invokeMethod", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, INVOKE_METHOD_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "invokeMethod", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", true);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    if (!node.hasMethod("getProperty", GET_PROPERTY_PARAMS)) {
        addMethod(node, !isAbstract(node.getModifiers()), "getProperty", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, GET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "getProperty", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", true);
                mv.visitInsn(ARETURN);
            }
        }));
    }
    if (!node.hasMethod("setProperty", SET_PROPERTY_PARAMS)) {
        addMethod(node, !isAbstract(node.getModifiers()), "setProperty", ACC_PUBLIC, ClassHelper.VOID_TYPE, SET_PROPERTY_PARAMS, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

            public void visit(MethodVisitor mv) {
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitVarInsn(ALOAD, 2);
                mv.visitMethodInsn(INVOKEINTERFACE, "groovy/lang/MetaClass", "setProperty", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", true);
                mv.visitInsn(RETURN);
            }
        }));
    }
}
Also used : BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Label(org.objectweb.asm.Label) ArrayList(java.util.ArrayList) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) MethodVisitor(org.objectweb.asm.MethodVisitor) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) List(java.util.List) ArrayList(java.util.ArrayList)

Example 49 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class Verifier method addStaticMetaClassField.

private void addStaticMetaClassField(final ClassNode node, final String classInternalName) {
    String _staticClassInfoFieldName = "$staticClassInfo";
    while (node.getDeclaredField(_staticClassInfoFieldName) != null) _staticClassInfoFieldName = _staticClassInfoFieldName + "$";
    final String staticMetaClassFieldName = _staticClassInfoFieldName;
    FieldNode staticMetaClassField = node.addField(staticMetaClassFieldName, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.make(ClassInfo.class, false), null);
    staticMetaClassField.setSynthetic(true);
    node.addSyntheticMethod("$getStaticMetaClass", ACC_PROTECTED, ClassHelper.make(MetaClass.class), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new BytecodeSequence(new BytecodeInstruction() {

        public void visit(MethodVisitor mv) {
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
            if (BytecodeHelper.isClassLiteralPossible(node) || BytecodeHelper.isSameCompilationUnit(classNode, node)) {
                BytecodeHelper.visitClassLiteral(mv, node);
            } else {
                mv.visitMethodInsn(INVOKESTATIC, classInternalName, "$get$$class$" + classInternalName.replaceAll("\\/", "\\$"), "()Ljava/lang/Class;", false);
            }
            Label l1 = new Label();
            mv.visitJumpInsn(IF_ACMPEQ, l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/runtime/ScriptBytecodeAdapter", "initMetaClass", "(Ljava/lang/Object;)Lgroovy/lang/MetaClass;", false);
            mv.visitInsn(ARETURN);
            mv.visitLabel(l1);
            mv.visitFieldInsn(GETSTATIC, classInternalName, staticMetaClassFieldName, "Lorg/codehaus/groovy/reflection/ClassInfo;");
            mv.visitVarInsn(ASTORE, 1);
            mv.visitVarInsn(ALOAD, 1);
            Label l0 = new Label();
            mv.visitJumpInsn(IFNONNULL, l0);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
            mv.visitMethodInsn(INVOKESTATIC, "org/codehaus/groovy/reflection/ClassInfo", "getClassInfo", "(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;", false);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ASTORE, 1);
            mv.visitFieldInsn(PUTSTATIC, classInternalName, staticMetaClassFieldName, "Lorg/codehaus/groovy/reflection/ClassInfo;");
            mv.visitLabel(l0);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, "org/codehaus/groovy/reflection/ClassInfo", "getMetaClass", "()Lgroovy/lang/MetaClass;", false);
            mv.visitInsn(ARETURN);
        }
    }));
}
Also used : MetaClass(groovy.lang.MetaClass) Label(org.objectweb.asm.Label) ClassInfo(org.codehaus.groovy.reflection.ClassInfo) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 50 with MethodVisitor

use of org.objectweb.asm.MethodVisitor in project groovy by apache.

the class Verifier method getCovariantImplementation.

private MethodNode getCovariantImplementation(final MethodNode oldMethod, final MethodNode overridingMethod, Map genericsSpec, boolean ignoreError) {
    // method name
    if (!oldMethod.getName().equals(overridingMethod.getName()))
        return null;
    if ((overridingMethod.getModifiers() & ACC_BRIDGE) != 0)
        return null;
    if (oldMethod.isPrivate())
        return null;
    // parameters
    boolean normalEqualParameters = equalParametersNormal(overridingMethod, oldMethod);
    boolean genericEqualParameters = equalParametersWithGenerics(overridingMethod, oldMethod, genericsSpec);
    if (!normalEqualParameters && !genericEqualParameters)
        return null;
    //correct to method level generics for the overriding method
    genericsSpec = GenericsUtils.addMethodGenerics(overridingMethod, genericsSpec);
    // return type
    ClassNode mr = overridingMethod.getReturnType();
    ClassNode omr = oldMethod.getReturnType();
    boolean equalReturnType = mr.equals(omr);
    ClassNode testmr = correctToGenericsSpec(genericsSpec, omr);
    if (!isAssignable(mr, testmr)) {
        if (ignoreError)
            return null;
        throw new RuntimeParserException("The return type of " + overridingMethod.getTypeDescriptor() + " in " + overridingMethod.getDeclaringClass().getName() + " is incompatible with " + testmr.getName() + " in " + oldMethod.getDeclaringClass().getName(), overridingMethod);
    }
    if (equalReturnType && normalEqualParameters)
        return null;
    if ((oldMethod.getModifiers() & ACC_FINAL) != 0) {
        throw new RuntimeParserException("Cannot override final method " + oldMethod.getTypeDescriptor() + " in " + oldMethod.getDeclaringClass().getName(), overridingMethod);
    }
    if (oldMethod.isStatic() != overridingMethod.isStatic()) {
        throw new RuntimeParserException("Cannot override method " + oldMethod.getTypeDescriptor() + " in " + oldMethod.getDeclaringClass().getName() + " with disparate static modifier", overridingMethod);
    }
    if (!equalReturnType) {
        boolean oldM = ClassHelper.isPrimitiveType(oldMethod.getReturnType());
        boolean newM = ClassHelper.isPrimitiveType(overridingMethod.getReturnType());
        if (oldM || newM) {
            String message = "";
            if (oldM && newM) {
                message = " with old and new method having different primitive return types";
            } else if (newM) {
                message = " with new method having a primitive return type and old method not";
            } else /* oldM */
            {
                message = " with old method having a primitive return type and new method not";
            }
            throw new RuntimeParserException("Cannot override method " + oldMethod.getTypeDescriptor() + " in " + oldMethod.getDeclaringClass().getName() + message, overridingMethod);
        }
    }
    // if we reach this point we have at least one parameter or return type, that
    // is different in its specified form. That means we have to create a bridge method!
    MethodNode newMethod = new MethodNode(oldMethod.getName(), overridingMethod.getModifiers() | ACC_SYNTHETIC | ACC_BRIDGE, oldMethod.getReturnType().getPlainNodeReference(), cleanParameters(oldMethod.getParameters()), oldMethod.getExceptions(), null);
    List instructions = new ArrayList(1);
    instructions.add(new BytecodeInstruction() {

        public void visit(MethodVisitor mv) {
            mv.visitVarInsn(ALOAD, 0);
            Parameter[] para = oldMethod.getParameters();
            Parameter[] goal = overridingMethod.getParameters();
            int doubleSlotOffset = 0;
            for (int i = 0; i < para.length; i++) {
                ClassNode type = para[i].getType();
                BytecodeHelper.load(mv, type, i + 1 + doubleSlotOffset);
                if (type.redirect() == ClassHelper.double_TYPE || type.redirect() == ClassHelper.long_TYPE) {
                    doubleSlotOffset++;
                }
                if (!type.equals(goal[i].getType())) {
                    BytecodeHelper.doCast(mv, goal[i].getType());
                }
            }
            mv.visitMethodInsn(INVOKEVIRTUAL, BytecodeHelper.getClassInternalName(classNode), overridingMethod.getName(), BytecodeHelper.getMethodDescriptor(overridingMethod.getReturnType(), overridingMethod.getParameters()), false);
            BytecodeHelper.doReturn(mv, oldMethod.getReturnType());
        }
    });
    newMethod.setCode(new BytecodeSequence(instructions));
    return newMethod;
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) RuntimeParserException(org.codehaus.groovy.syntax.RuntimeParserException) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

MethodVisitor (org.objectweb.asm.MethodVisitor)630 Label (org.objectweb.asm.Label)186 ClassWriter (org.objectweb.asm.ClassWriter)116 Type (org.objectweb.asm.Type)59 ClassNode (org.codehaus.groovy.ast.ClassNode)57 FieldVisitor (org.objectweb.asm.FieldVisitor)56 ClassVisitor (org.objectweb.asm.ClassVisitor)47 ClassReader (org.objectweb.asm.ClassReader)43 ArrayList (java.util.ArrayList)32 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)30 Test (org.junit.Test)29 AnnotationVisitor (org.objectweb.asm.AnnotationVisitor)29 List (java.util.List)23 LinkedList (java.util.LinkedList)22 Parameter (org.codehaus.groovy.ast.Parameter)22 InterfaceHelperClassNode (org.codehaus.groovy.ast.InterfaceHelperClassNode)18 AsmClassGenerator (org.codehaus.groovy.classgen.AsmClassGenerator)18 BytecodeExpression (org.codehaus.groovy.classgen.BytecodeExpression)18 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)17 Method (java.lang.reflect.Method)16