Example usage for org.objectweb.asm Opcodes ARETURN

List of usage examples for org.objectweb.asm Opcodes ARETURN

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes ARETURN.

Prototype

int ARETURN

To view the source code for org.objectweb.asm Opcodes ARETURN.

Click Source Link

Usage

From source file:org.gradle.api.internal.model.NamedObjectInstantiator.java

License:Apache License

private ClassGeneratingLoader loaderFor(Class<?> publicClass) {
    ////from w  w  w  .j  a v  a2  s  . com
    // Generate implementation class
    //

    FormattingValidationProblemCollector problemCollector = new FormattingValidationProblemCollector(
            "Named implementation class", ModelType.of(publicClass));
    visitFields(publicClass, problemCollector);
    if (problemCollector.hasProblems()) {
        throw new GradleException(problemCollector.format());
    }

    AsmClassGenerator generator = new AsmClassGenerator(publicClass, "$Impl");
    Type implementationType = generator.getGeneratedType();
    ClassWriter visitor = generator.getVisitor();
    Type publicType = Type.getType(publicClass);

    Type superClass;
    String[] interfaces;
    if (publicClass.isInterface()) {
        superClass = OBJECT;
        interfaces = new String[] { publicType.getInternalName(), MANAGED.getInternalName() };
    } else {
        superClass = publicType;
        interfaces = INTERFACES_FOR_ABSTRACT_CLASS;
    }

    visitor.visit(V1_5, ACC_PUBLIC | ACC_SYNTHETIC, implementationType.getInternalName(), null,
            superClass.getInternalName(), interfaces);

    //
    // Add name field
    //

    visitor.visitField(ACC_PRIVATE, NAME_FIELD, STRING.getDescriptor(), null, null);

    //
    // Add constructor
    //

    MethodVisitor methodVisitor = visitor.visitMethod(ACC_PUBLIC, CONSTRUCTOR_NAME, RETURN_VOID_FROM_STRING,
            null, EMPTY_STRINGS);
    methodVisitor.visitCode();
    // Call this.super()
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superClass.getInternalName(), CONSTRUCTOR_NAME,
            RETURN_VOID, false);
    // Set this.name = param1
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
    methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, implementationType.getInternalName(), NAME_FIELD,
            STRING.getDescriptor());
    // Done
    methodVisitor.visitInsn(Opcodes.RETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    //
    // Add `getName()`
    //

    methodVisitor = visitor.visitMethod(ACC_PUBLIC, "getName", RETURN_STRING, null, EMPTY_STRINGS);
    methodVisitor.visitCode();
    // return this.name
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitFieldInsn(Opcodes.GETFIELD, implementationType.getInternalName(), NAME_FIELD,
            STRING.getDescriptor());
    methodVisitor.visitInsn(Opcodes.ARETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    //
    // Add `toString()`
    //

    methodVisitor = visitor.visitMethod(ACC_PUBLIC, "toString", RETURN_STRING, null, EMPTY_STRINGS);
    methodVisitor.visitCode();
    // return this.name
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitFieldInsn(Opcodes.GETFIELD, implementationType.getInternalName(), NAME_FIELD,
            STRING.getDescriptor());
    methodVisitor.visitInsn(Opcodes.ARETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    visitor.visitEnd();
    generator.define();

    //
    // Generate factory class
    //

    generator = new AsmClassGenerator(publicClass, "$Factory");
    visitor = generator.getVisitor();
    visitor.visit(V1_5, ACC_PUBLIC | ACC_SYNTHETIC, generator.getGeneratedType().getInternalName(), null,
            CLASS_GENERATING_LOADER.getInternalName(), EMPTY_STRINGS);

    //
    // Add constructor
    //

    methodVisitor = visitor.visitMethod(ACC_PUBLIC, CONSTRUCTOR_NAME, RETURN_VOID, null, EMPTY_STRINGS);
    methodVisitor.visitCode();
    // Call this.super()
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_GENERATING_LOADER.getInternalName(),
            CONSTRUCTOR_NAME, RETURN_VOID, false);
    // Done
    methodVisitor.visitInsn(Opcodes.RETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    //
    // Add factory method
    //

    methodVisitor = visitor.visitMethod(ACC_PUBLIC, "load", RETURN_OBJECT_FROM_STRING, null, EMPTY_STRINGS);
    methodVisitor.visitCode();
    // Call return new <implClass>(param1)
    methodVisitor.visitTypeInsn(Opcodes.NEW, implementationType.getInternalName());
    methodVisitor.visitInsn(Opcodes.DUP);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, implementationType.getInternalName(), CONSTRUCTOR_NAME,
            RETURN_VOID_FROM_STRING, false);
    methodVisitor.visitInsn(Opcodes.ARETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    visitor.visitEnd();
    Class<Object> factoryClass = generator.define();
    try {
        return (ClassGeneratingLoader) factoryClass.getConstructor().newInstance();
    } catch (Exception e) {
        throw UncheckedException.throwAsUncheckedException(e);
    }
}

From source file:org.gradle.groovy.scripts.AsmBackedEmptyScriptGenerator.java

License:Apache License

private <T extends Script> Class<? extends T> generateEmptyScriptClass(Class<T> type) {
    ClassWriter visitor = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    String typeName = type.getName() + "_Decorated";
    Type generatedType = Type.getType("L" + typeName.replaceAll("\\.", "/") + ";");
    Type superclassType = Type.getType(type);
    visitor.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, generatedType.getInternalName(), null,
            superclassType.getInternalName(), new String[0]);

    // Constructor

    String constructorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]);
    MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructorDescriptor, null,
            new String[0]);
    methodVisitor.visitCode();//  w  w w .ja  va2 s.  com

    // super()
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superclassType.getInternalName(), "<init>",
            constructorDescriptor);

    methodVisitor.visitInsn(Opcodes.RETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    // run() method

    String runDesciptor = Type.getMethodDescriptor(Type.getType(Object.class), new Type[0]);
    methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, "run", runDesciptor, null, new String[0]);
    methodVisitor.visitCode();

    // return null
    methodVisitor.visitInsn(Opcodes.ACONST_NULL);

    methodVisitor.visitInsn(Opcodes.ARETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    visitor.visitEnd();

    byte[] bytecode = visitor.toByteArray();
    return (Class<T>) ReflectionUtil.invoke(type.getClassLoader(), "defineClass",
            new Object[] { typeName, bytecode, 0, bytecode.length });
}

From source file:org.gradle.initialization.ExceptionDecoratingClassGenerator.java

License:Apache License

private <T> Class<? extends T> doGenerate(Class<T> type) {
    ClassWriter visitor = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    String typeName = StringUtils.substringBeforeLast(type.getName(), ".") + ".LocationAware"
            + type.getSimpleName();/*from   w  ww. j a  v a2  s .c  o m*/
    Type generatedType = Type.getType("L" + typeName.replaceAll("\\.", "/") + ";");
    Type superclassType = Type.getType(type);

    visitor.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, generatedType.getInternalName(), null,
            superclassType.getInternalName(),
            new String[] { Type.getType(LocationAwareException.class).getInternalName() });

    Type helperType = Type.getType(ExceptionHelper.class);
    Type throwableType = Type.getType(Throwable.class);
    Type scriptSourceType = Type.getType(ScriptSource.class);
    Type integerType = Type.getType(Integer.class);

    // GENERATE private ExceptionHelper helper;
    visitor.visitField(Opcodes.ACC_PRIVATE, "helper", helperType.getDescriptor(), null, null);

    // GENERATE <init>(<type> target, ScriptSource source, Integer lineNumber)

    String methodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE,
            new Type[] { superclassType, scriptSourceType, integerType });
    MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, "<init>", methodDescriptor, null,
            new String[0]);
    methodVisitor.visitCode();

    boolean noArgsConstructor;
    try {
        type.getConstructor(type);
        noArgsConstructor = false;
    } catch (NoSuchMethodException e) {
        try {
            type.getConstructor();
            noArgsConstructor = true;
        } catch (NoSuchMethodException e1) {
            throw new IllegalArgumentException(String.format(
                    "Cannot create subtype for exception '%s'. It needs a zero-args or copy constructor.",
                    type.getName()));
        }
    }

    if (noArgsConstructor) {
        // GENERATE super()
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superclassType.getInternalName(), "<init>",
                Type.getMethodDescriptor(Type.VOID_TYPE, new Type[0]));
        // END super()
    } else {
        // GENERATE super(target)
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superclassType.getInternalName(), "<init>",
                Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] { superclassType }));
        // END super(target)
    }

    // GENERATE helper = new ExceptionHelper(this, target, source, lineNumber)
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);

    methodVisitor.visitTypeInsn(Opcodes.NEW, helperType.getInternalName());
    methodVisitor.visitInsn(Opcodes.DUP);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 2);
    methodVisitor.visitVarInsn(Opcodes.ALOAD, 3);
    methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, helperType.getInternalName(), "<init>",
            Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { throwableType, throwableType, scriptSourceType, integerType }));

    methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, generatedType.getInternalName(), "helper",
            helperType.getDescriptor());

    // END helper = new ExceptionHelper(target)

    methodVisitor.visitInsn(Opcodes.RETURN);
    methodVisitor.visitMaxs(0, 0);
    methodVisitor.visitEnd();

    // END <init>(<type> target, ScriptSource source, Integer lineNumber)

    for (Method method : ExceptionHelper.class.getDeclaredMethods()) {
        // GENERATE public <type> <method>() { return helper.<method>(); }
        methodDescriptor = Type.getMethodDescriptor(Type.getType(method.getReturnType()), new Type[0]);
        methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methodDescriptor, null,
                new String[0]);
        methodVisitor.visitCode();

        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), "helper",
                helperType.getDescriptor());
        methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, helperType.getInternalName(), method.getName(),
                methodDescriptor);

        methodVisitor.visitInsn(Opcodes.ARETURN);
        methodVisitor.visitMaxs(0, 0);
        methodVisitor.visitEnd();
        // END public <type> <method>() { return helper.<method>(); }
    }

    visitor.visitEnd();

    byte[] bytecode = visitor.toByteArray();
    return (Class<T>) ReflectionUtil.invoke(type.getClassLoader(), "defineClass",
            new Object[] { typeName, bytecode, 0, bytecode.length });
}

From source file:org.jacoco.core.internal.analysis.AC_MethodAnalyzerTest.java

License:Open Source License

private void createIfBranch() {
    final Label l0 = new Label();
    method.visitLabel(l0);//from  w  w  w  . j  a v a  2  s  .  co m
    method.visitLineNumber(1001, l0);
    method.visitVarInsn(Opcodes.ILOAD, 1);
    Label l1 = new Label();
    method.visitJumpInsn(Opcodes.IFEQ, l1);
    final Label l2 = new Label();
    method.visitLabel(l2);
    method.visitLineNumber(1002, l2);
    method.visitLdcInsn("a");
    method.visitInsn(Opcodes.ARETURN);
    method.visitLabel(l1);
    method.visitLineNumber(1003, l1);
    method.visitLdcInsn("b");
    method.visitInsn(Opcodes.ARETURN);
}

From source file:org.jacoco.core.internal.analysis.filter.FinallyFilter.java

License:Open Source License

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;/*  w  w w  .  j  av  a  2s.c  o m*/
    }

    // 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);
            }
        }
    }
}

From source file:org.jacoco.core.internal.analysis.filter.KotlinCoroutineFilterTest.java

License:Open Source License

@Test
public void should_filter_suspending_lambdas_generated_by_Kotlin_1_3_30() {
    final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "invokeSuspend",
            "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
    context.classAnnotations.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);

    m.visitLabel(new Label());
    final Range range1 = new Range();
    range1.fromInclusive = m.instructions.getLast();
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/coroutines/intrinsics/IntrinsicsKt",
            "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
    m.visitVarInsn(Opcodes.ASTORE, 4);//from  w w w  . ja v a2s.c  om

    m.visitVarInsn(Opcodes.ALOAD, 0);
    // line of "runBlocking"
    m.visitFieldInsn(Opcodes.GETFIELD, "Target", "label", "I");
    final Label dflt = new Label();
    final Label state0 = new Label();
    final Label state1 = new Label();
    m.visitTableSwitchInsn(0, 1, dflt, state0, state1);

    m.visitLabel(state0);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V",
                false);
        range1.toInclusive = m.instructions.getLast();
    }

    // line before "suspendingFunction"
    m.visitInsn(Opcodes.NOP);

    // line of "suspendingFunction"
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
            "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);

    m.visitInsn(Opcodes.DUP);
    final Range range2 = new Range();
    range2.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ALOAD, 4);
    final Label continuationLabelAfterLoadedResult = new Label();
    m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
    // line of "runBlocking"
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(state1);

    m.visitVarInsn(Opcodes.ALOAD, 0);
    m.visitFieldInsn(Opcodes.GETFIELD, "Target", "I$0", "I");
    m.visitVarInsn(Opcodes.ISTORE, 3);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/ResultKt", "throwOnFailure", "(Ljava/lang/Object;)V",
                false);
    }
    m.visitVarInsn(Opcodes.ALOAD, 1);
    range2.toInclusive = m.instructions.getLast();
    m.visitLabel(continuationLabelAfterLoadedResult);

    // line after "suspendingFunction"
    m.visitInsn(Opcodes.NOP);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(dflt);
    final Range range0 = new Range();
    range0.fromInclusive = m.instructions.getLast();
    m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
    m.visitInsn(Opcodes.DUP);
    m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
    m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
            "(Ljava/lang/String;)V", false);
    m.visitInsn(Opcodes.ATHROW);
    range0.toInclusive = m.instructions.getLast();

    filter.filter(m, context, output);

    assertIgnored(range0, range1, range2);
}

From source file:org.jacoco.core.internal.analysis.filter.KotlinCoroutineFilterTest.java

License:Open Source License

/**
 * <pre>//from  w  w w .ja v a2 s  .  c  o m
 *     runBlocking {
 *         val x = 42
 *         nop(x)
 *         suspendingFunction()
 *         nop(x)
 *     }
 * </pre>
 */
@Test
public void should_filter_suspending_lambdas() {
    final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "invokeSuspend",
            "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
    context.classAnnotations.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);

    m.visitLabel(new Label());
    final Range range1 = new Range();
    range1.fromInclusive = m.instructions.getLast();
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/coroutines/intrinsics/IntrinsicsKt",
            "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);
    m.visitVarInsn(Opcodes.ASTORE, 4);

    m.visitVarInsn(Opcodes.ALOAD, 0);
    // line of "runBlocking"
    m.visitFieldInsn(Opcodes.GETFIELD, "Target", "label", "I");
    final Label dflt = new Label();
    final Label state0 = new Label();
    final Label state1 = new Label();
    m.visitTableSwitchInsn(0, 1, dflt, state0, state1);

    m.visitLabel(state0);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.DUP);
        m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
        Label label = new Label();
        m.visitJumpInsn(Opcodes.IFEQ, label);
        m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
        m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure", "exception", "Ljava/lang/Throwable");
        m.visitInsn(Opcodes.ATHROW);
        m.visitInsn(Opcodes.POP);
        range1.toInclusive = m.instructions.getLast();
        m.visitLabel(label);
    }

    // line before "suspendingFunction"
    m.visitInsn(Opcodes.NOP);

    // line of "suspendingFunction"
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
            "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);

    m.visitInsn(Opcodes.DUP);
    final Range range2 = new Range();
    range2.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ALOAD, 4);
    final Label continuationLabelAfterLoadedResult = new Label();
    m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
    // line of "runBlocking"
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(state1);

    m.visitVarInsn(Opcodes.ALOAD, 0);
    m.visitFieldInsn(Opcodes.GETFIELD, "Target", "I$0", "I");
    m.visitVarInsn(Opcodes.ISTORE, 3);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.DUP);
        m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
        final Label label = new Label();
        m.visitJumpInsn(Opcodes.IFEQ, label);
        m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
        m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure", "exception", "Ljava/lang/Throwable");
        m.visitInsn(Opcodes.ATHROW);
        m.visitInsn(Opcodes.POP);
        m.visitLabel(label);
    }
    m.visitVarInsn(Opcodes.ALOAD, 1);
    range2.toInclusive = m.instructions.getLast();
    m.visitLabel(continuationLabelAfterLoadedResult);

    // line after "suspendingFunction"
    m.visitInsn(Opcodes.NOP);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(dflt);
    final Range range0 = new Range();
    range0.fromInclusive = m.instructions.getLast();
    m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
    m.visitInsn(Opcodes.DUP);
    m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
    m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
            "(Ljava/lang/String;)V", false);
    m.visitInsn(Opcodes.ATHROW);
    range0.toInclusive = m.instructions.getLast();

    filter.filter(m, context, output);

    assertIgnored(range0, range1, range2);
}

From source file:org.jacoco.core.internal.analysis.filter.KotlinCoroutineFilterTest.java

License:Open Source License

/**
 * <pre>//from ww w .j  a  v  a2  s  .com
 *     suspend fun example() {
 *         suspendingFunction()
 *         nop()
 *     }
 * </pre>
 */
@Test
public void should_filter_suspending_functions() {
    final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, Opcodes.ACC_STATIC, "example",
            "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", null, null);
    context.classAnnotations.add(KotlinGeneratedFilter.KOTLIN_METADATA_DESC);

    final int continuationArgumentIndex = 0;
    final int continuationIndex = 2;

    m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
    final Range range1 = new Range();
    range1.fromInclusive = m.instructions.getLast();
    m.visitTypeInsn(Opcodes.INSTANCEOF, "ExampleKt$example$1");
    final Label createStateInstance = new Label();
    m.visitJumpInsn(Opcodes.IFEQ, createStateInstance);

    m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
    m.visitTypeInsn(Opcodes.CHECKCAST, "ExampleKt$example$1");
    m.visitVarInsn(Opcodes.ASTORE, continuationIndex);

    m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
    m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");

    m.visitLdcInsn(Integer.valueOf(Integer.MIN_VALUE));
    m.visitInsn(Opcodes.IAND);
    m.visitJumpInsn(Opcodes.IFEQ, createStateInstance);

    m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
    m.visitInsn(Opcodes.DUP);
    m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");

    m.visitLdcInsn(Integer.valueOf(Integer.MIN_VALUE));
    m.visitInsn(Opcodes.ISUB);
    m.visitFieldInsn(Opcodes.PUTFIELD, "ExampleKt$example$1", "label", "I");

    final Label afterCoroutineStateCreated = new Label();
    m.visitJumpInsn(Opcodes.GOTO, afterCoroutineStateCreated);

    m.visitLabel(createStateInstance);

    m.visitTypeInsn(Opcodes.NEW, "ExampleKt$example$1");
    m.visitInsn(Opcodes.DUP);
    m.visitVarInsn(Opcodes.ALOAD, continuationArgumentIndex);
    m.visitMethodInsn(Opcodes.INVOKESPECIAL, "ExampleKt$example$1", "<init>",
            "(Lkotlin/coroutines/Continuation;)V", false);

    m.visitVarInsn(Opcodes.ASTORE, continuationIndex);

    m.visitLabel(afterCoroutineStateCreated);

    m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
    m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "result", "Ljava/lang/Object;");
    m.visitVarInsn(Opcodes.ASTORE, 1);

    m.visitMethodInsn(Opcodes.INVOKESTATIC, "kotlin/coroutines/intrinsics/IntrinsicsKt",
            "getCOROUTINE_SUSPENDED", "()Ljava/lang/Object;", false);

    // line of "fun"
    m.visitVarInsn(Opcodes.ASTORE, 3);

    m.visitVarInsn(Opcodes.ALOAD, continuationIndex);
    m.visitFieldInsn(Opcodes.GETFIELD, "ExampleKt$example$1", "label", "I");
    final Label dflt = new Label();
    final Label state0 = new Label();
    final Label state1 = new Label();
    m.visitTableSwitchInsn(0, 1, dflt, state0, state1);

    m.visitLabel(state0);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.DUP);
        m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
        Label label = new Label();
        m.visitJumpInsn(Opcodes.IFEQ, label);
        m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
        m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure", "exception", "Ljava/lang/Throwable");
        m.visitInsn(Opcodes.ATHROW);
        m.visitInsn(Opcodes.POP);
        range1.toInclusive = m.instructions.getLast();
        m.visitLabel(label);
    }

    // line of "suspendingFunction"
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "suspendingFunction",
            "(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", false);

    m.visitInsn(Opcodes.DUP);
    final Range range2 = new Range();
    range2.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ALOAD, 3);
    final Label continuationLabelAfterLoadedResult = new Label();
    m.visitJumpInsn(Opcodes.IF_ACMPNE, continuationLabelAfterLoadedResult);
    // line of "fun"
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(state1);

    {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.DUP);
        m.visitTypeInsn(Opcodes.INSTANCEOF, "kotlin/Result$Failure");
        final Label label = new Label();
        m.visitJumpInsn(Opcodes.IFEQ, label);
        m.visitTypeInsn(Opcodes.CHECKCAST, "kotlin/Result$Failure");
        m.visitFieldInsn(Opcodes.GETFIELD, "kotlin/Result$Failure", "exception", "Ljava/lang/Throwable");
        m.visitInsn(Opcodes.ATHROW);
        m.visitInsn(Opcodes.POP);
        m.visitLabel(label);
    }
    m.visitVarInsn(Opcodes.ALOAD, 1);
    range2.toInclusive = m.instructions.getLast();
    m.visitLabel(continuationLabelAfterLoadedResult);

    // line after "suspendingFunction"
    m.visitInsn(Opcodes.NOP);
    m.visitInsn(Opcodes.ARETURN);

    m.visitLabel(dflt);
    final Range range0 = new Range();
    range0.fromInclusive = m.instructions.getLast();
    m.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalStateException");
    m.visitInsn(Opcodes.DUP);
    m.visitLdcInsn("call to 'resume' before 'invoke' with coroutine");
    m.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/IllegalStateException", "<init>",
            "(Ljava/lang/String;)V", false);
    m.visitInsn(Opcodes.ATHROW);
    range0.toInclusive = m.instructions.getLast();

    filter.filter(m, context, output);

    assertIgnored(range0, range1, range2);
}

From source file:org.jacoco.core.internal.analysis.filter.TryWithResourcesEcjFilterTest.java

License:Open Source License

/**
 * ECJ for//from   w  ww.j  av  a  2s  .  c  om
 *
 * <pre>
 *     try (r1 = ...; r2 = ...; r3 = ...) {
 *         return ...
 *     } finally {
 *         ...
 *     }
 * </pre>
 *
 * generates
 *
 * <pre>
 *     ACONST_NULL
 *     astore primaryExc
 *     ACONST_NULL
 *     astore suppressedExc
 *
 *     ...
 *     ASTORE r1
 *     ...
 *     ASTORE r2
 *     ...
 *     ASTORE r3
 *
 *     ... // body
 *
 *     ALOAD r3
 *     IFNULL n
 *     ALOAD r3
 *     INVOKEVIRTUAL close:()V
 *     n:
 *     ALOAD r2
 *     IFNULL n
 *     ALOAD r2
 *     INVOKEVIRTUAL close:()V
 *     n:
 *     ALOAD r1
 *     IFNULL n
 *     ALOAD r1
 *     INVOKEVIRTUAL close:()V
 *     n:
 *
 *     ... // finally on normal path
 *     ARETURN
 *
 *     ASTORE primaryExc
 *     ALOAD r3
 *     IFNULL n
 *     ALOAD r3
 *     INVOKEVIRTUAL close:()V
 *     n:
 *     ALOAD primaryExc
 *     ATHROW
 *
 *     ASTORE suppressedExc
 *     ALOAD primaryExc
 *     IFNONNULL s
 *     ALOAD suppressedExc
 *     ASTORE primaryExc
 *     GOTO  e
 *     s:
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     IF_ACMPEQ  e
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     e:
 *
 *     ALOAD r2
 *     IFNULL n
 *     ALOAD r2
 *     INVOKEVIRTUAL close:()V
 *     n:
 *     ALOAD primaryExc
 *     ATHROW
 *
 *     ASTORE suppressedExc
 *     ALOAD primaryExc
 *     IFNONNULL s
 *     ALOAD suppressedExc
 *     ASTORE primaryExc
 *     GOTO e
 *     s:
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     IF_ACMPEQ e
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     e:
 *
 *     ALOAD r1
 *     IFNULL n
 *     ALOAD r1
 *     INVOKEVIRTUAL close:()V
 *     n:
 *     ALOAD primaryExc
 *     ATHROW
 *
 *     ASTORE suppressedExc
 *     ALOAD primaryExc
 *     IFNONNULL s
 *     ALOAD suppressedExc
 *     ASTORE primaryExc
 *     GOTO e
 *     s:
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     IF_ACMPEQ e
 *     ALOAD primaryExc
 *     ALOAD suppressedExc
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     e:
 *
 *     ALOAD primaryExc
 *     ATHROW
 *
 *     ... // additional handlers for catch blocks and finally on exceptional path
 * </pre>
 */
@Test
public void ecj_noFlowOut() {
    final Range range0 = new Range();
    final Range range1 = new Range();

    final Label handler = new Label();
    m.visitTryCatchBlock(handler, handler, handler, null);

    // primaryExc = null
    m.visitInsn(Opcodes.ACONST_NULL);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    // suppressedExc = null
    m.visitInsn(Opcodes.ACONST_NULL);
    m.visitVarInsn(Opcodes.ASTORE, 2);

    // body
    m.visitInsn(Opcodes.NOP);

    { // nextIsEcjClose("r0")
        final Label label = new Label();
        m.visitVarInsn(Opcodes.ALOAD, 5);
        range0.fromInclusive = m.instructions.getLast();
        m.visitJumpInsn(Opcodes.IFNULL, label);
        m.visitVarInsn(Opcodes.ALOAD, 5);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        m.visitLabel(label);
    }
    { // nextIsEcjClose("r1")
        final Label label = new Label();
        m.visitVarInsn(Opcodes.ALOAD, 4);
        m.visitJumpInsn(Opcodes.IFNULL, label);
        m.visitVarInsn(Opcodes.ALOAD, 4);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        m.visitLabel(label);
    }
    { // nextIsEcjClose("r2")
        final Label label = new Label();
        m.visitVarInsn(Opcodes.ALOAD, 3);
        m.visitJumpInsn(Opcodes.IFNULL, label);
        m.visitVarInsn(Opcodes.ALOAD, 3);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        range0.toInclusive = m.instructions.getLast();
        m.visitLabel(label);
    }

    // finally
    m.visitInsn(Opcodes.NOP);
    m.visitInsn(Opcodes.ARETURN);

    // catch (any primaryExc)
    m.visitLabel(handler);
    range1.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ASTORE, 1);
    { // nextIsEcjCloseAndThrow("r0")
        m.visitVarInsn(Opcodes.ALOAD, 5);
        final Label throwLabel = new Label();
        m.visitJumpInsn(Opcodes.IFNULL, throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 5);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        m.visitLabel(throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.ATHROW);
    }
    { // nextIsEcjSuppress
        m.visitVarInsn(Opcodes.ASTORE, 2);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        final Label suppressStart = new Label();
        m.visitJumpInsn(Opcodes.IFNONNULL, suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitVarInsn(Opcodes.ASTORE, 1);
        final Label suppressEnd = new Label();
        m.visitJumpInsn(Opcodes.GOTO, suppressEnd);
        m.visitLabel(suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitJumpInsn(Opcodes.IF_ACMPEQ, suppressEnd);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed",
                "(Ljava/lang/Throwable;)V", false);
        m.visitLabel(suppressEnd);
    }
    { // nextIsEcjCloseAndThrow("r1")
        m.visitVarInsn(Opcodes.ALOAD, 4);
        final Label throwLabel = new Label();
        m.visitJumpInsn(Opcodes.IFNULL, throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 4);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        m.visitLabel(throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.ATHROW);
    }
    { // nextIsEcjSuppress
        m.visitVarInsn(Opcodes.ASTORE, 2);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        final Label suppressStart = new Label();
        m.visitJumpInsn(Opcodes.IFNONNULL, suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitVarInsn(Opcodes.ASTORE, 1);
        final Label suppressEnd = new Label();
        m.visitJumpInsn(Opcodes.GOTO, suppressEnd);
        m.visitLabel(suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitJumpInsn(Opcodes.IF_ACMPEQ, suppressEnd);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed",
                "(Ljava/lang/Throwable;)V", false);
        m.visitLabel(suppressEnd);
    }
    { // nextIsEcjCloseAndThrow("r2")
        m.visitVarInsn(Opcodes.ALOAD, 3);
        final Label throwLabel = new Label();
        m.visitJumpInsn(Opcodes.IFNULL, throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 3);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource", "close", "()V", false);
        m.visitLabel(throwLabel);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitInsn(Opcodes.ATHROW);
    }
    { // nextIsEcjSuppress
        m.visitVarInsn(Opcodes.ASTORE, 2);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        final Label suppressStart = new Label();
        m.visitJumpInsn(Opcodes.IFNONNULL, suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitVarInsn(Opcodes.ASTORE, 1);
        final Label suppressEnd = new Label();
        m.visitJumpInsn(Opcodes.GOTO, suppressEnd);
        m.visitLabel(suppressStart);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitJumpInsn(Opcodes.IF_ACMPEQ, suppressEnd);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed",
                "(Ljava/lang/Throwable;)V", false);
        m.visitLabel(suppressEnd);
    }
    // throw primaryExc
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitInsn(Opcodes.ATHROW);
    range1.toInclusive = m.instructions.getLast();

    // additional handlers
    m.visitInsn(Opcodes.NOP);

    filter.filter(m, context, output);

    assertIgnored(range0, range1);
}

From source file:org.jacoco.core.internal.analysis.filter.TryWithResourcesJavacFilterTest.java

License:Open Source License

/**
 * javac 9 for//from  w  w  w.j  a va  2  s .c  o  m
 *
 * <pre>
 *     try (r0 = open(...); r1 = new ...) {
 *         return ...
 *     } finally {
 *         ...
 *     }
 * </pre>
 *
 * generates
 *
 * <pre>
 *     ...
 *     ASTORE r0
 *     ACONST_NULL
 *     ASTORE primaryExc0
 *
 *     ...
 *     ASTORE r1
 *     ACONST_NULL
 *     ASTORE primaryExc1
 *
 *     ... // body
 *
 *     ALOAD primaryExc1
 *     ALOAD r1
 *     INVOKESTATIC $closeResource:(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
 *
 *     ALOAD r0
 *     IFNULL n
 *     ALOAD primaryExc0
 *     ALOAD r0
 *     INVOKESTATIC $closeResource:(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
 *     n:
 *
 *     ... // finally on normal path
 *     ARETURN
 *
 *     ASTORE t
 *     ALOAD t
 *     ASTORE primaryExc1
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t
 *     ALOAD primaryExc1
 *     ALOAD r1
 *     INVOKESTATIC  $closeResource:(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t
 *     ALOAD t
 *     ASTORE primaryExc0
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t
 *     ALOAD r0
 *     IFNULL n
 *     ALOAD primaryExc0
 *     ALOAD r0
 *     INVOKESTATIC  $closeResource:(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V
 *     n:
 *     ALOAD t
 *     ATHROW
 *
 *     ... // additional handlers for catch blocks and finally on exceptional path
 * </pre>
 */
@Test
public void javac9() {
    final Range range0 = new Range();
    final Range range1 = new Range();
    final Range range2 = new Range();
    final Range range3 = new Range();

    final Label handler1 = new Label();
    m.visitTryCatchBlock(handler1, handler1, handler1, "java/lang/Throwable");

    final Label handler2 = new Label();
    m.visitTryCatchBlock(handler2, handler2, handler2, "java/lang/Throwable");

    // r0 = open(...)
    m.visitVarInsn(Opcodes.ASTORE, 1);

    // primaryExc0 = null
    m.visitInsn(Opcodes.ACONST_NULL);
    m.visitVarInsn(Opcodes.ASTORE, 2);

    // r1 = new ..
    m.visitVarInsn(Opcodes.ASTORE, 3);

    // primaryExc1 = null
    m.visitInsn(Opcodes.ACONST_NULL);
    m.visitVarInsn(Opcodes.ASTORE, 4);

    // body
    m.visitInsn(Opcodes.NOP);
    m.visitInsn(Opcodes.ACONST_NULL);
    m.visitVarInsn(Opcodes.ASTORE, 5);

    // $closeResource(primaryExc1, r1)
    m.visitVarInsn(Opcodes.ALOAD, 4);
    range0.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "Fun", "$closeResource",
            "(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V", false);
    range0.toInclusive = m.instructions.getLast();

    // if (r0 != null)
    m.visitVarInsn(Opcodes.ALOAD, 1);
    range2.fromInclusive = m.instructions.getLast();
    final Label l11 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l11);
    // $closeResource(primaryExc0, r0)
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "Fun", "$closeResource",
            "(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V", false);
    range2.toInclusive = m.instructions.getLast();
    m.visitLabel(l11);

    // finally
    m.visitInsn(Opcodes.NOP);
    m.visitVarInsn(Opcodes.ALOAD, 5);
    m.visitInsn(Opcodes.ARETURN);

    // catch (Throwable t)
    m.visitLabel(handler1);
    range1.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ASTORE, 5);
    // primaryExc1 = t
    m.visitVarInsn(Opcodes.ALOAD, 5);
    m.visitVarInsn(Opcodes.ASTORE, 4);
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 5);
    m.visitInsn(Opcodes.ATHROW);

    // catch (any t)
    m.visitVarInsn(Opcodes.ASTORE, 6);
    // $closeResource(primaryExc1, r1)
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "Fun", "$closeResource",
            "(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V", false);
    m.visitVarInsn(Opcodes.ALOAD, 6);
    m.visitInsn(Opcodes.ATHROW);
    range1.toInclusive = m.instructions.getLast();

    // catch (Throwable t)
    m.visitLabel(handler2);
    range3.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ASTORE, 3);
    // primaryExc0 = t
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitVarInsn(Opcodes.ASTORE, 2);
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitInsn(Opcodes.ATHROW);

    // catch (any t)
    m.visitVarInsn(Opcodes.ASTORE, 7);
    // if (r0 != null)
    m.visitVarInsn(Opcodes.ALOAD, 1);
    final Label l14 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l14);
    // $closeResource(primaryExc0, r0)
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKESTATIC, "Fun", "$closeResource",
            "(Ljava/lang/Throwable;Ljava/lang/AutoCloseable;)V", false);
    m.visitLabel(l14);
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 7);
    m.visitInsn(Opcodes.ATHROW);
    range3.toInclusive = m.instructions.getLast();

    m.visitVarInsn(Opcodes.ASTORE, 8);
    // finally
    m.visitInsn(Opcodes.NOP);
    m.visitVarInsn(Opcodes.ALOAD, 8);
    m.visitInsn(Opcodes.ATHROW);

    filter.filter(m, context, output);

    assertIgnored(range0, range1, range2, range3);
}