Search in sources :

Example 16 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project jacoco by jacoco.

the class TryWithResourcesEcjFilter method filter.

public void filter(final MethodNode methodNode, final IFilterContext context, final IFilterOutput output) {
    if (methodNode.tryCatchBlocks.isEmpty()) {
        return;
    }
    final Matcher matcher = new Matcher(output);
    for (final TryCatchBlockNode t : methodNode.tryCatchBlocks) {
        if (t.type == null) {
            matcher.start(t.handler);
            if (!matcher.matchEcj()) {
                matcher.start(t.handler);
                matcher.matchEcjNoFlowOut();
            }
        }
    }
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode)

Example 17 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project jacoco by jacoco.

the class FinallyFilter method filter.

private static void filter(final IFilterOutput output, final List<TryCatchBlockNode> tryCatchBlocks, final TryCatchBlockNode catchAnyBlock) {
    final AbstractInsnNode e = next(catchAnyBlock.handler);
    final int size = size(e);
    if (size <= 0) {
        return;
    }
    // Determine instructions inside regions
    final Set<AbstractInsnNode> inside = new HashSet<AbstractInsnNode>();
    for (final TryCatchBlockNode t : tryCatchBlocks) {
        if (t.handler == catchAnyBlock.handler) {
            AbstractInsnNode i = t.start;
            while (i != t.end) {
                inside.add(i);
                i = i.getNext();
            }
        }
    }
    // Find and merge duplicates at exits of regions
    for (final TryCatchBlockNode t : tryCatchBlocks) {
        if (t.handler == catchAnyBlock.handler) {
            boolean continues = false;
            AbstractInsnNode i = t.start;
            while (i != t.end) {
                switch(i.getType()) {
                    case AbstractInsnNode.FRAME:
                    case AbstractInsnNode.LINE:
                    case AbstractInsnNode.LABEL:
                        break;
                    case AbstractInsnNode.JUMP_INSN:
                        final AbstractInsnNode jumpTarget = next(((JumpInsnNode) i).label);
                        if (!inside.contains(jumpTarget)) {
                            merge(output, size, e, jumpTarget);
                        }
                        continues = i.getOpcode() != Opcodes.GOTO;
                        break;
                    default:
                        switch(i.getOpcode()) {
                            case Opcodes.IRETURN:
                            case Opcodes.LRETURN:
                            case Opcodes.FRETURN:
                            case Opcodes.DRETURN:
                            case Opcodes.ARETURN:
                            case Opcodes.RETURN:
                            case Opcodes.ATHROW:
                                continues = false;
                                break;
                            default:
                                continues = true;
                                break;
                        }
                        break;
                }
                i = i.getNext();
            }
            i = next(i);
            if (continues && !inside.contains(i)) {
                merge(output, size, e, i);
            }
        }
        if (t != catchAnyBlock && t.start == catchAnyBlock.start && t.end == catchAnyBlock.end) {
            final AbstractInsnNode i = next(next(t.handler));
            if (!inside.contains(i)) {
                // javac's empty catch - merge after ASTORE
                merge(output, size, e, i);
            }
        }
    }
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) HashSet(java.util.HashSet)

Example 18 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project jacoco by jacoco.

the class MethodAnalyzerTest method setup.

@Before
public void setup() {
    nextProbeId = 0;
    method = new MethodNode();
    method.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
    probes = new boolean[32];
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) MethodNode(org.objectweb.asm.tree.MethodNode) Before(org.junit.Before)

Example 19 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project jacoco by jacoco.

the class StructuredLockingTest method assertStructuredLocking.

private void assertStructuredLocking(String owner, MethodNode mn) throws Exception {
    Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(new BasicInterpreter()) {

        @Override
        protected Frame<BasicValue> newFrame(int nLocals, int nStack) {
            return new LockFrame(nLocals, nStack);
        }

        @Override
        protected Frame<BasicValue> newFrame(Frame<? extends BasicValue> src) {
            return new LockFrame(src);
        }
    };
    Frame<BasicValue>[] frames = analyzer.analyze(owner, mn);
    // Make sure no locks are left when method exits:
    for (int i = 0; i < frames.length; i++) {
        AbstractInsnNode insn = mn.instructions.get(i);
        switch(insn.getOpcode()) {
            case Opcodes.IRETURN:
            case Opcodes.LRETURN:
            case Opcodes.FRETURN:
            case Opcodes.DRETURN:
            case Opcodes.ARETURN:
            case Opcodes.RETURN:
                ((LockFrame) frames[i]).assertNoLock("Exit with lock");
                break;
            case Opcodes.ATHROW:
                List<TryCatchBlockNode> handlers = analyzer.getHandlers(i);
                if (handlers == null || handlers.isEmpty()) {
                    ((LockFrame) frames[i]).assertNoLock("Exit with lock");
                }
                break;
        }
    }
    // Only instructions protected by a catch-all handler can hold locks:
    for (int i = 0; i < frames.length; i++) {
        AbstractInsnNode insn = mn.instructions.get(i);
        if (insn.getOpcode() > 0) {
            boolean catchAll = false;
            List<TryCatchBlockNode> handlers = analyzer.getHandlers(i);
            if (handlers != null) {
                for (TryCatchBlockNode node : handlers) {
                    catchAll |= node.type == null;
                }
            }
            if (!catchAll) {
                ((LockFrame) frames[i]).assertNoLock("No handlers for insn with lock");
            }
        }
    }
}
Also used : TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) Frame(org.objectweb.asm.tree.analysis.Frame) BasicInterpreter(org.objectweb.asm.tree.analysis.BasicInterpreter) Analyzer(org.objectweb.asm.tree.analysis.Analyzer) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) BasicValue(org.objectweb.asm.tree.analysis.BasicValue)

Example 20 with TryCatchBlockNode

use of org.objectweb.asm.tree.TryCatchBlockNode in project evosuite by EvoSuite.

the class Instrumenter method wrapMethod.

/**
 * 	public int myMethod(int i)
 *		{
 *			try
 *			{
 *				return _sw_prototype_original_myMethod(i)
 *			}
 *			finally
 *			{
 *				Capturer.enable();
 *			}
 *		}
 *
 * @param classNode
 * @param className
 * @param methodNode
 */
@SuppressWarnings("unchecked")
private MethodNode wrapMethod(final ClassNode classNode, final String className, final MethodNode methodNode) {
    methodNode.maxStack += 4;
    // create wrapper for original method
    final MethodNode wrappingMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, (String[]) methodNode.exceptions.toArray(new String[methodNode.exceptions.size()]));
    wrappingMethodNode.maxStack = methodNode.maxStack;
    // assign annotations to wrapping method
    wrappingMethodNode.visibleAnnotations = methodNode.visibleAnnotations;
    wrappingMethodNode.visibleParameterAnnotations = methodNode.visibleParameterAnnotations;
    // remove annotations from wrapped method to avoid wrong behavior controlled by annotations
    methodNode.visibleAnnotations = null;
    methodNode.visibleParameterAnnotations = null;
    // rename original method
    methodNode.access = TransformerUtil.modifyVisibility(methodNode.access, Opcodes.ACC_PRIVATE);
    final LabelNode l0 = new LabelNode();
    final LabelNode l1 = new LabelNode();
    final LabelNode l2 = new LabelNode();
    final InsnList wInstructions = wrappingMethodNode.instructions;
    if ("<init>".equals(methodNode.name)) {
        // wrap a constructor
        methodNode.name = WRAP_NAME_PREFIX + "init" + WRAP_NAME_PREFIX;
        // move call to other constructors to new method
        AbstractInsnNode ins = null;
        ListIterator<AbstractInsnNode> iter = methodNode.instructions.iterator();
        // number of invokespecial calls before actual constructor call
        int numInvokeSpecials = 0;
        while (iter.hasNext()) {
            ins = iter.next();
            iter.remove();
            wInstructions.add(ins);
            if (ins instanceof MethodInsnNode) {
                MethodInsnNode mins = (MethodInsnNode) ins;
                if (ins.getOpcode() == Opcodes.INVOKESPECIAL) {
                    if (mins.name.startsWith("<init>")) {
                        if (numInvokeSpecials == 0) {
                            break;
                        } else {
                            numInvokeSpecials--;
                        }
                    }
                }
            } else if (ins instanceof TypeInsnNode) {
                TypeInsnNode typeIns = (TypeInsnNode) ins;
                if (typeIns.getOpcode() == Opcodes.NEW || typeIns.getOpcode() == Opcodes.NEWARRAY) {
                    numInvokeSpecials++;
                }
            }
        }
    } else {
        methodNode.name = WRAP_NAME_PREFIX + methodNode.name;
    }
    int varReturnValue = 0;
    final Type returnType = Type.getReturnType(methodNode.desc);
    if (returnType.equals(Type.VOID_TYPE)) {
        wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l1, "java/lang/Throwable"));
    } else {
        wrappingMethodNode.tryCatchBlocks.add(new TryCatchBlockNode(l0, l1, l2, "java/lang/Throwable"));
        if (!TransformerUtil.isStatic(methodNode.access)) {
            // load "this"
            varReturnValue++;
        }
        // consider method arguments to find right variable index
        final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
        for (int i = 0; i < argTypes.length; i++) {
            varReturnValue++;
            // long/double take two registers
            if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
                varReturnValue++;
            }
        }
        // push NULL on the stack and initialize variable for return value for it
        wInstructions.add(new InsnNode(Opcodes.ACONST_NULL));
        wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
    }
    int var = 0;
    // --- L0
    wInstructions.add(l0);
    wInstructions.add(this.addCaptureCall(TransformerUtil.isStatic(methodNode.access), className, wrappingMethodNode.name, wrappingMethodNode.desc, Type.getArgumentTypes(methodNode.desc)));
    if (!TransformerUtil.isStatic(methodNode.access)) {
        // load "this" to call method
        wInstructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
        var++;
    }
    final Type[] argTypes = Type.getArgumentTypes(methodNode.desc);
    for (int i = 0; i < argTypes.length; i++) {
        this.addLoadInsn(wInstructions, argTypes[i], var++);
        // long/double take two registers
        if (argTypes[i].equals(Type.LONG_TYPE) || argTypes[i].equals(Type.DOUBLE_TYPE)) {
            var++;
        }
    }
    if (TransformerUtil.isStatic(methodNode.access)) {
        wInstructions.add(new MethodInsnNode(Opcodes.INVOKESTATIC, classNode.name, methodNode.name, methodNode.desc));
    } else {
        wInstructions.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, classNode.name, methodNode.name, methodNode.desc));
    }
    var++;
    if (returnType.equals(Type.VOID_TYPE)) {
        wInstructions.add(new JumpInsnNode(Opcodes.GOTO, l2));
        // --- L1
        wInstructions.add(l1);
        wInstructions.add(new FrameNode(Opcodes.F_SAME1, 0, null, 1, new Object[] { "java/lang/Throwable" }));
        wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
        this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
        wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
        wInstructions.add(new InsnNode(Opcodes.ATHROW));
        // FIXME <--- DUPLICATE CODE
        // --- L2
        wInstructions.add(l2);
        wInstructions.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null));
        this.addCaptureEnableStatement(className, methodNode, wInstructions, -1);
        wInstructions.add(new InsnNode(Opcodes.RETURN));
    } else {
        // construct store of the wrapped method call's result
        this.addBoxingStmt(wInstructions, returnType);
        wInstructions.add(new VarInsnNode(Opcodes.ASTORE, varReturnValue));
        wInstructions.add(new VarInsnNode(Opcodes.ALOAD, varReturnValue));
        this.addUnBoxingStmt(wInstructions, returnType);
        final int storeOpcode = returnType.getOpcode(Opcodes.ISTORE);
        // might be only var
        wInstructions.add(new VarInsnNode(storeOpcode, ++var));
        // --- L1
        wInstructions.add(l1);
        this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
        // construct load of the wrapped method call's result
        int loadOpcode = returnType.getOpcode(Opcodes.ILOAD);
        wInstructions.add(new VarInsnNode(loadOpcode, var));
        // construct return of the wrapped method call's result
        this.addReturnInsn(wInstructions, returnType);
        // ---- L2
        wInstructions.add(l2);
        wInstructions.add(new FrameNode(Opcodes.F_FULL, 2, new Object[] { className, this.getInternalName(returnType) }, 1, new Object[] { "java/lang/Throwable" }));
        wInstructions.add(new VarInsnNode(Opcodes.ASTORE, --var));
        this.addCaptureEnableStatement(className, methodNode, wInstructions, varReturnValue);
        wInstructions.add(new VarInsnNode(Opcodes.ALOAD, var));
        wInstructions.add(new InsnNode(Opcodes.ATHROW));
    }
    transformWrapperCalls(methodNode);
    return wrappingMethodNode;
}
Also used : LabelNode(org.objectweb.asm.tree.LabelNode) TryCatchBlockNode(org.objectweb.asm.tree.TryCatchBlockNode) FrameNode(org.objectweb.asm.tree.FrameNode) TypeInsnNode(org.objectweb.asm.tree.TypeInsnNode) InsnList(org.objectweb.asm.tree.InsnList) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) FieldInsnNode(org.objectweb.asm.tree.FieldInsnNode) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) IntInsnNode(org.objectweb.asm.tree.IntInsnNode) TypeInsnNode(org.objectweb.asm.tree.TypeInsnNode) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) LdcInsnNode(org.objectweb.asm.tree.LdcInsnNode) AbstractInsnNode(org.objectweb.asm.tree.AbstractInsnNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode) InsnNode(org.objectweb.asm.tree.InsnNode) Type(org.objectweb.asm.Type) MethodNode(org.objectweb.asm.tree.MethodNode) MethodInsnNode(org.objectweb.asm.tree.MethodInsnNode) JumpInsnNode(org.objectweb.asm.tree.JumpInsnNode) VarInsnNode(org.objectweb.asm.tree.VarInsnNode)

Aggregations

TryCatchBlockNode (org.objectweb.asm.tree.TryCatchBlockNode)27 AbstractInsnNode (org.objectweb.asm.tree.AbstractInsnNode)11 InsnNode (org.objectweb.asm.tree.InsnNode)5 LabelNode (org.objectweb.asm.tree.LabelNode)5 MethodInsnNode (org.objectweb.asm.tree.MethodInsnNode)5 MethodNode (org.objectweb.asm.tree.MethodNode)5 Label (org.objectweb.asm.Label)4 LdcInsnNode (org.objectweb.asm.tree.LdcInsnNode)4 Frame (org.objectweb.asm.tree.analysis.Frame)4 ArrayList (java.util.ArrayList)3 Type (org.objectweb.asm.Type)3 FrameNode (org.objectweb.asm.tree.FrameNode)3 InsnList (org.objectweb.asm.tree.InsnList)3 IntInsnNode (org.objectweb.asm.tree.IntInsnNode)3 JumpInsnNode (org.objectweb.asm.tree.JumpInsnNode)3 HashSet (java.util.HashSet)2 List (java.util.List)2 Analyzer (org.objectweb.asm.tree.analysis.Analyzer)2 Textifier (org.objectweb.asm.util.Textifier)2 TraceMethodVisitor (org.objectweb.asm.util.TraceMethodVisitor)2