Example usage for org.objectweb.asm Opcodes ACONST_NULL

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

Introduction

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

Prototype

int ACONST_NULL

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

Click Source Link

Usage

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

License:Open Source License

/**
 * ECJ for/*from   w w  w.  j  a  v  a  2 s .c o  m*/
 *
 * <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/*  w w w  .j  ava  2  s .co  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);
}

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

License:Open Source License

/**
 * javac 7 and 8 for//from   w  w  w.  ja  va  2s. c o  m
 *
 * <pre>
 *     try (r0 = ...; r1 = ...) {
 *         return ...
 *     } finally {
 *         ...
 *     }
 * </pre>
 *
 * generate
 *
 * <pre>
 *     ...
 *     ASTORE r0
 *     ACONST_NULL
 *     ASTORE primaryExc0
 *
 *     ...
 *     ASTORE r1
 *     ACONST_NULL
 *     ASTORE primaryExc1
 *
 *     ... // body
 *
 *     ALOAD r1
 *     IFNULL n
 *     ALOAD primaryExc1
 *     IFNULL c
 *     ALOAD r1
 *     INVOKEINTERFACE close:()V
 *     GOTO n
 *     ASTORE t
 *     ALOAD primaryExc1
 *     ALOAD t
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     GOTO n
 *     c:
 *     ALOAD r1
 *     INVOKEINTERFACE close:()V
 *     n:
 *
 *     ALOAD r0
 *     IFNULL n
 *     ALOAD primaryExc0
 *     IFNULL c
 *     ALOAD r0
 *     INVOKEVIRTUAL close:()V
 *     GOTO n
 *     ASTORE t
 *     ALOAD primaryExc0
 *     ALOAD t
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     GOTO n
 *     c:
 *     ALOAD r0
 *     INVOKEVIRTUAL close:()V
 *     n:
 *
 *     ... // finally on normal path
 *     ARETURN
 *
 *     ASTORE t
 *     ALOAD t
 *     ASTORE primaryExc1
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t1
 *     ALOAD r1
 *     IFNULL e
 *     ALOAD primaryExc1
 *     IFNULL c
 *     ALOAD r1
 *     INVOKEINTERFACE close:()V
 *     GOTO e
 *     ASTORE t2
 *     ALOAD primaryExc1
 *     ALOAD t2
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     GOTO e
 *     c:
 *     ALOAD r1
 *     INVOKEINTERFACE close:()V
 *     e:
 *     ALOAD t1
 *     ATHROW
 *
 *     ASTORE t
 *     ALOAD t
 *     ASTORE primaryExc0
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t1
 *     ALOAD r0
 *     IFNULL e
 *     ALOAD primaryExc0
 *     IFNULL c
 *     ALOAD r0
 *     INVOKEVIRTUAL close:()V
 *     GOTO e
 *     ASTORE t2
 *     ALOAD primaryExc0
 *     ALOAD t2
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     GOTO e
 *     c:
 *     ALOAD r0
 *     INVOKEVIRTUAL close:()V
 *     e:
 *     ALOAD t1
 *     ATHROW
 *
 *     ... // additional handlers for catch blocks and finally on exceptional path
 * </pre>
 */
@Test
public void javac_7_8() {
    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");

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

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

    // r2 = ...
    m.visitVarInsn(Opcodes.ASTORE, 3);
    // primaryExc2 = 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);

    final Label l15 = new Label();
    // if (r2 != null)
    m.visitVarInsn(Opcodes.ALOAD, 3);
    range0.fromInclusive = m.instructions.getLast();
    m.visitJumpInsn(Opcodes.IFNULL, l15);
    // if (primaryExc2 != null)
    m.visitVarInsn(Opcodes.ALOAD, 4);
    final Label l26 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l26);
    // r2.close
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Fun$Resource2", "close", "()V", false);
    m.visitJumpInsn(Opcodes.GOTO, l15);

    m.visitVarInsn(Opcodes.ASTORE, 6);
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitVarInsn(Opcodes.ALOAD, 6);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed", "(Ljava/lang/Throwable;)V",
            false);
    m.visitJumpInsn(Opcodes.GOTO, l15);

    m.visitLabel(l26);

    // r2.close
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Fun$Resource2", "close", "()V", false);
    range0.toInclusive = m.instructions.getLast();
    m.visitLabel(l15);

    // if (r1 != null)
    m.visitVarInsn(Opcodes.ALOAD, 1);
    range2.fromInclusive = m.instructions.getLast();
    final Label l23 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l23);
    // if (primaryExc1 != null)
    m.visitVarInsn(Opcodes.ALOAD, 2);
    final Label l27 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l27);
    // r1.close
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource1", "close", "()V", false);
    m.visitJumpInsn(Opcodes.GOTO, l23);

    m.visitVarInsn(Opcodes.ASTORE, 6);
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitVarInsn(Opcodes.ALOAD, 6);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed", "(Ljava/lang/Throwable;)V",
            false);
    m.visitJumpInsn(Opcodes.GOTO, l23);

    m.visitLabel(l27);
    // r1.close
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource1", "close", "()V", false);
    range2.toInclusive = m.instructions.getLast();
    m.visitLabel(l23);

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

    // catch (Throwable t)
    m.visitLabel(handler1);
    range1.fromInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ASTORE, 5);
    // primaryExc2 = 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, 7);
    // if (r2 != null)
    m.visitVarInsn(Opcodes.ALOAD, 3);
    final Label l28 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l28);
    // if (primaryExc2 != null)
    m.visitVarInsn(Opcodes.ALOAD, 4);
    final Label l29 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l29);
    // r2.close
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Fun$Resource2", "close", "()V", false);
    m.visitJumpInsn(Opcodes.GOTO, l28);

    m.visitVarInsn(Opcodes.ASTORE, 8);
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitVarInsn(Opcodes.ALOAD, 8);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed", "(Ljava/lang/Throwable;)V",
            false);
    m.visitJumpInsn(Opcodes.GOTO, l28);

    m.visitLabel(l29);
    // r2.close
    m.visitVarInsn(Opcodes.ALOAD, 3);
    m.visitMethodInsn(Opcodes.INVOKEINTERFACE, "Fun$Resource2", "close", "()V", false);
    m.visitLabel(l28);
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 7);
    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);
    // primaryExc2 = 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, 9);
    // if (r1 != null)
    m.visitVarInsn(Opcodes.ALOAD, 1);
    final Label l30 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l30);
    // if (primaryExc1 != null)
    m.visitVarInsn(Opcodes.ALOAD, 2);
    final Label l31 = new Label();
    m.visitJumpInsn(Opcodes.IFNULL, l31);
    // r1.close
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource1", "close", "()V", false);
    m.visitJumpInsn(Opcodes.GOTO, l30);

    m.visitVarInsn(Opcodes.ASTORE, 10);
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitVarInsn(Opcodes.ALOAD, 10);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed", "(Ljava/lang/Throwable;)V",
            false);
    m.visitJumpInsn(Opcodes.GOTO, l30);

    m.visitLabel(l31);
    // r1.close
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Fun$Resource1", "close", "()V", false);
    m.visitLabel(l30);
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 9);
    m.visitInsn(Opcodes.ATHROW);
    range3.toInclusive = m.instructions.getLast();

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

    filter.filter(m, context, output);

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

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

License:Open Source License

/**
 * javac 9 for/*from  w ww  .  j  a  v a  2 s  .co  m*/
 *
 * <pre>
 *     try (r = new ...) {
 *         ...
 *     } finally {
 *         ...
 *     }
 * </pre>
 *
 * generates
 *
 * <pre>
 *     ...
 *     ASTORE r
 *     ACONST_NULL
 *     ASTORE primaryExc
 *
 *     ... // body
 *
 *     ALOAD primaryExc
 *     IFNULL c
 *     ALOAD r
 *     INVOKEVIRTUAL close:()V
 *     GOTO f
 *     ASTORE t
 *     ALOAD primaryExc
 *     ALOAD t
 *     NVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     GOTO f
 *     c:
 *     ALOAD r
 *     INVOKEVIRTUAL close:()V
 *     GOTO f
 *
 *     ASTORE t
 *     ALOAD t
 *     ASTORE primaryExc
 *     ALOAD t
 *     ATHROW
 *
 *     ASTORE t
 *     ALOAD primaryExc
 *     IFNULL c
 *     ALOAD r
 *     INVOKEVIRTUAL close:()V
 *     GOTO L78
 *     ASTORE t2
 *     ALOAD primaryExc
 *     ALOAD t2
 *     INVOKEVIRTUAL java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
 *     goto e
 *     c:
 *     ALOAD r
 *     INVOKEVIRTUAL close:()V
 *     e:
 *     ALOAD t
 *     ATHROW
 *
 *     f:
 *     ... // finally on normal path
 *     ... // additional handlers for catch blocks and finally on exceptional path
 *     ...
 * </pre>
 */
@Test
public void javac9_omitted_null_check() {
    final Range range0 = new Range();
    final Range range1 = new Range();

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

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

    // r = new ...
    m.visitInsn(Opcodes.NOP);

    final Label end = new Label();
    // "finally" on a normal path
    {
        // if (primaryExc != null)
        m.visitVarInsn(Opcodes.ALOAD, 2);
        range0.fromInclusive = m.instructions.getLast();
        final Label closeLabel = new Label();
        m.visitJumpInsn(Opcodes.IFNULL, closeLabel);
        // r.close
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Resource", "close", "()V", false);
        m.visitJumpInsn(Opcodes.GOTO, end);

        // catch (Throwable t)
        m.visitVarInsn(Opcodes.ASTORE, 3);
        // primaryExc.addSuppressed(t)
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitVarInsn(Opcodes.ALOAD, 3);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed",
                "(Ljava/lang/Throwable;)V", false);
        m.visitJumpInsn(Opcodes.GOTO, end);

        m.visitLabel(closeLabel);
        // r.close()
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Resource", "close", "()V", false);
    }
    m.visitJumpInsn(Opcodes.GOTO, end);
    range0.toInclusive = m.instructions.getLast();
    // catch (Throwable t)
    m.visitLabel(handler);
    {
        range1.fromInclusive = m.instructions.getLast();
        m.visitVarInsn(Opcodes.ASTORE, 3);
        // primaryExc = 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, 4);
    // "finally" on exceptional path
    {
        // if (primaryExc != null)
        m.visitVarInsn(Opcodes.ALOAD, 2);
        final Label closeLabel = new Label();
        m.visitJumpInsn(Opcodes.IFNULL, closeLabel);
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Resource", "close", "()V", false);
        final Label finallyEndLabel = new Label();
        m.visitJumpInsn(Opcodes.GOTO, finallyEndLabel);

        // catch (Throwable t)
        m.visitVarInsn(Opcodes.ASTORE, 5);
        // primaryExc.addSuppressed(t)
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitVarInsn(Opcodes.ALOAD, 5);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "addSuppressed",
                "(Ljava/lang/Throwable;)V", false);
        m.visitJumpInsn(Opcodes.GOTO, finallyEndLabel);

        m.visitLabel(closeLabel);
        // r.close()
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "Resource", "close", "()V", false);
        m.visitLabel(finallyEndLabel);
    }
    // throw t
    m.visitVarInsn(Opcodes.ALOAD, 4);
    m.visitInsn(Opcodes.ATHROW);
    range1.toInclusive = m.instructions.getLast();

    m.visitLabel(end);

    filter.filter(m, context, output);

    assertIgnored(range0, range1);
}

From source file:org.jacoco.core.internal.flow.FrameSnapshotTest.java

License:Open Source License

/**
 * Test of <a href="https://gitlab.ow2.org/asm/asm/issues/317793">ASM
 * bug</a>: according to <a href=
 * "https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.10.1.9.aaload">JVMS
 * "4.10.1.9 Type Checking Instructions, AALOAD"</a> resulting type on the
 * operand stack should be null if the input array is null.
 *///w  w w .ja  v a2  s .  c o m
@Test
public void after_aaload_stack_should_contain_null_when_input_array_is_null() {
    analyzer.visitInsn(Opcodes.ACONST_NULL);
    analyzer.visitInsn(Opcodes.ICONST_0);
    analyzer.visitInsn(Opcodes.AALOAD);
    frame = FrameSnapshot.create(analyzer, 0);

    final Object[] stack = arr(Opcodes.NULL);
    expectedVisitor.visitFrame(Opcodes.F_FULL, 1, arr("Foo"), 1, stack);
}

From source file:org.jacoco.core.internal.instr.FrameTracker.java

License:Open Source License

@Override
public void visitInsn(final int opcode) {
    final Object t1, t2, t3, t4;
    switch (opcode) {
    case Opcodes.NOP:
    case Opcodes.RETURN:
        break;//w w  w .j a v  a2s  . co m
    case Opcodes.ARETURN:
    case Opcodes.ATHROW:
    case Opcodes.FRETURN:
    case Opcodes.IRETURN:
    case Opcodes.MONITORENTER:
    case Opcodes.MONITOREXIT:
    case Opcodes.POP:
        pop(1);
        break;
    case Opcodes.DRETURN:
    case Opcodes.LRETURN:
    case Opcodes.POP2:
        pop(2);
        break;
    case Opcodes.AASTORE:
    case Opcodes.BASTORE:
    case Opcodes.CASTORE:
    case Opcodes.FASTORE:
    case Opcodes.IASTORE:
    case Opcodes.SASTORE:
        pop(3);
        break;
    case Opcodes.LASTORE:
    case Opcodes.DASTORE:
        pop(4);
        break;
    case Opcodes.ICONST_M1:
    case Opcodes.ICONST_0:
    case Opcodes.ICONST_1:
    case Opcodes.ICONST_2:
    case Opcodes.ICONST_3:
    case Opcodes.ICONST_4:
    case Opcodes.ICONST_5:
        push(Opcodes.INTEGER);
        break;
    case Opcodes.ARRAYLENGTH:
    case Opcodes.F2I:
    case Opcodes.I2B:
    case Opcodes.I2C:
    case Opcodes.I2S:
    case Opcodes.INEG:
        pop(1);
        push(Opcodes.INTEGER);
        break;
    case Opcodes.BALOAD:
    case Opcodes.CALOAD:
    case Opcodes.D2I:
    case Opcodes.FCMPG:
    case Opcodes.FCMPL:
    case Opcodes.IADD:
    case Opcodes.IALOAD:
    case Opcodes.IAND:
    case Opcodes.IDIV:
    case Opcodes.IMUL:
    case Opcodes.IOR:
    case Opcodes.IREM:
    case Opcodes.ISHL:
    case Opcodes.ISHR:
    case Opcodes.ISUB:
    case Opcodes.IUSHR:
    case Opcodes.IXOR:
    case Opcodes.L2I:
    case Opcodes.SALOAD:
        pop(2);
        push(Opcodes.INTEGER);
        break;
    case Opcodes.DCMPG:
    case Opcodes.DCMPL:
    case Opcodes.LCMP:
        pop(4);
        push(Opcodes.INTEGER);
        break;
    case Opcodes.FCONST_0:
    case Opcodes.FCONST_1:
    case Opcodes.FCONST_2:
        push(Opcodes.FLOAT);
        break;
    case Opcodes.FNEG:
    case Opcodes.I2F:
        pop(1);
        push(Opcodes.FLOAT);
        break;
    case Opcodes.D2F:
    case Opcodes.FADD:
    case Opcodes.FALOAD:
    case Opcodes.FDIV:
    case Opcodes.FMUL:
    case Opcodes.FREM:
    case Opcodes.FSUB:
    case Opcodes.L2F:
        pop(2);
        push(Opcodes.FLOAT);
        break;
    case Opcodes.LCONST_0:
    case Opcodes.LCONST_1:
        push(Opcodes.LONG);
        push(Opcodes.TOP);
        break;
    case Opcodes.F2L:
    case Opcodes.I2L:
        pop(1);
        push(Opcodes.LONG);
        push(Opcodes.TOP);
        break;
    case Opcodes.D2L:
    case Opcodes.LALOAD:
    case Opcodes.LNEG:
        pop(2);
        push(Opcodes.LONG);
        push(Opcodes.TOP);
        break;
    case Opcodes.LSHL:
    case Opcodes.LSHR:
    case Opcodes.LUSHR:
        pop(3);
        push(Opcodes.LONG);
        push(Opcodes.TOP);
        break;
    case Opcodes.LADD:
    case Opcodes.LAND:
    case Opcodes.LDIV:
    case Opcodes.LMUL:
    case Opcodes.LOR:
    case Opcodes.LREM:
    case Opcodes.LSUB:
    case Opcodes.LXOR:
        pop(4);
        push(Opcodes.LONG);
        push(Opcodes.TOP);
        break;
    case Opcodes.DCONST_0:
    case Opcodes.DCONST_1:
        push(Opcodes.DOUBLE);
        push(Opcodes.TOP);
        break;
    case Opcodes.F2D:
    case Opcodes.I2D:
        pop(1);
        push(Opcodes.DOUBLE);
        push(Opcodes.TOP);
        break;
    case Opcodes.DALOAD:
    case Opcodes.DNEG:
    case Opcodes.L2D:
        pop(2);
        push(Opcodes.DOUBLE);
        push(Opcodes.TOP);
        break;
    case Opcodes.DADD:
    case Opcodes.DDIV:
    case Opcodes.DMUL:
    case Opcodes.DREM:
    case Opcodes.DSUB:
        pop(4);
        push(Opcodes.DOUBLE);
        push(Opcodes.TOP);
        break;
    case Opcodes.ACONST_NULL:
        push(Opcodes.NULL);
        break;
    case Opcodes.AALOAD:
        pop(1);
        t1 = pop();
        push(Type.getType(((String) t1).substring(1)));
        break;
    case Opcodes.DUP:
        t1 = pop();
        push(t1);
        push(t1);
        break;
    case Opcodes.DUP_X1:
        t1 = pop();
        t2 = pop();
        push(t1);
        push(t2);
        push(t1);
        break;
    case Opcodes.DUP_X2:
        t1 = pop();
        t2 = pop();
        t3 = pop();
        push(t1);
        push(t3);
        push(t2);
        push(t1);
        break;
    case Opcodes.DUP2:
        t1 = pop();
        t2 = pop();
        push(t2);
        push(t1);
        push(t2);
        push(t1);
        break;
    case Opcodes.DUP2_X1:
        t1 = pop();
        t2 = pop();
        t3 = pop();
        push(t2);
        push(t1);
        push(t3);
        push(t2);
        push(t1);
        break;
    case Opcodes.DUP2_X2:
        t1 = pop();
        t2 = pop();
        t3 = pop();
        t4 = pop();
        push(t2);
        push(t1);
        push(t4);
        push(t3);
        push(t2);
        push(t1);
        break;
    case Opcodes.SWAP:
        t1 = pop();
        t2 = pop();
        push(t1);
        push(t2);
        break;
    default:
        throw new IllegalArgumentException();
    }
    mv.visitInsn(opcode);
}

From source file:org.jacoco.core.runtime.URLStreamHandlerRuntime.java

License:Open Source License

public int generateDataAccessor(final long classid, final String classname, final int probecount,
        final MethodVisitor mv) {

    // The data accessor performs the following steps:
    ////from ww  w  . ja  v a2s  .  c  o  m
    // final URL url = new URL(protocol, null, "");
    // final URLConnection connection = url.openConnection();
    // final Object[] args = new Object[3];
    // args[0] = Long.valueOf(classid);
    // args[1] = classname;
    // args[2] = Integer.valueOf(probecount);
    // connection.equals(args);
    // final byte[] probedata = (byte[]) args[0];

    RuntimeData.generateArgumentArray(classid, classname, probecount, mv);
    mv.visitInsn(Opcodes.DUP);

    // Stack[1]: [Ljava/lang/Object;
    // Stack[0]: [Ljava/lang/Object;

    mv.visitTypeInsn(Opcodes.NEW, "java/net/URL");
    mv.visitInsn(Opcodes.DUP);
    mv.visitLdcInsn(protocol);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitLdcInsn("");
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/net/URL", "<init>",
            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");

    // Stack[2]: [Ljava/net/URL;
    // Stack[1]: [Ljava/lang/Object;
    // Stack[0]: [Ljava/lang/Object;

    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/net/URL", "openConnection", "()Ljava/net/URLConnection;");

    // Stack[2]: [Ljava/net/URLConnection;
    // Stack[1]: [Ljava/lang/Object;
    // Stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.SWAP);

    // Stack[2]: [Ljava/lang/Object;
    // Stack[1]: [Ljava/net/URLConnection;
    // Stack[0]: [Ljava/lang/Object;

    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z");

    // Stack[1]: Z;
    // Stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.POP);

    // Stack[0]: [Ljava/lang/Object;

    mv.visitInsn(Opcodes.ICONST_0);
    mv.visitInsn(Opcodes.AALOAD);
    mv.visitTypeInsn(Opcodes.CHECKCAST, InstrSupport.DATAFIELD_DESC);

    return 7;
}

From source file:org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.java

License:Open Source License

/**
 * Generates the instruction to push the given value on the stack.
 *
 * @param value the value to be pushed on the stack. May be <tt>null</tt>.
 *///from ww  w . j a  v a 2  s  .  c om
public void push(final String value) {
    if (value == null) {
        visitInsn(Opcodes.ACONST_NULL);
    } else {
        visitLdcInsn(value);
    }
}

From source file:org.jboss.byteman.agent.adapter.RuleGeneratorAdapter.java

License:Open Source License

/**
 * Generates the instruction to push the given value on the stack.
 *
 * @param value the value to be pushed on the stack.
 *///w  ww .  ja  va2  s. co m
public void push(final Type value) {
    if (value == null) {
        visitInsn(Opcodes.ACONST_NULL);
    } else {
        visitLdcInsn(value);
    }
}

From source file:org.jboss.byteman.rule.expression.MethodExpression.java

License:Open Source License

public void compile(MethodVisitor mv, CompileContext compileContext) throws CompileException {
    // make sure we are at the right source line
    compileContext.notifySourceLine(line);

    int currentStack = compileContext.getStackCount();
    int extraParams = 0; // space used by stacked args after conversion
    int expected = 0;

    // no need for type conversion as return type was derived from method
    if (type.getNBytes() > 4) {
        expected = 2;/*from  w  w  w.j  a v a  2 s. c  om*/
    } else if (type != Type.VOID) {
        expected = 1;
    } else {
        expected = 0;
    }

    int argCount = arguments.size();

    if (isPublicMethod) {
        // we can just do this as a direct call
        // stack the recipient if necessary then stack the args and then invoke the method
        if (recipient != null) {
            // compile code for recipient
            recipient.compile(mv, compileContext);

            extraParams += 1;
        }

        for (int i = 0; i < argCount; i++) {
            Expression argument = arguments.get(i);
            Type argType = argumentTypes.get(i);
            Type paramType = paramTypes.get(i);
            // compile code to stack argument and type convert if necessary
            argument.compile(mv, compileContext);
            compileTypeConversion(argType, paramType, mv, compileContext);
            // allow for stacked paramType value
            extraParams += (paramType.getNBytes() > 4 ? 2 : 1);
        }

        // enable triggering before we call the method
        // this adds an extra value to the stack so modify the compile context to ensure
        // we increase the maximum height if necessary
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "enableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);

        // ok, now just call the method -- removes extraParams words

        String ownerName = Type.internalName(method.getDeclaringClass());

        if (recipient == null) {
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, ownerName, method.getName(), getDescriptor());
        } else if (method.getDeclaringClass().isInterface()) {
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, ownerName, method.getName(), getDescriptor());
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ownerName, method.getName(), getDescriptor());
        }
        // decrement the stack height to account for stacked param values (removed) and return value (added)
        compileContext.addStackCount(expected - extraParams);

        // now disable triggering again
        // this temporarily adds an extra value to the stack -- n.b. we *must* increment and
        // then decrement the stack height even though we bumped the max before the call. in
        // some cases the stack may be larger after the method call than before e.g. calling
        // a static which returns a value or calling a non-static which returns a long/double

        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "disableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);
    } else {
        // if we are calling a method by reflection then we need to stack the current helper then
        // the recipient or null if there is none and then build an object array on the stack
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        compileContext.addStackCount(1);
        if (recipient != null) {
            // compile code for recipient
            recipient.compile(mv, compileContext);
        } else {
            mv.visitInsn(Opcodes.ACONST_NULL);
            compileContext.addStackCount(1);
        }

        // stack arg count then create a new array
        mv.visitLdcInsn(argCount);
        compileContext.addStackCount(1);
        // this just swaps one word for another
        mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");

        // duplicate the array, stack the index, compile code to generate the arg and the do an array put
        for (int i = 0; i < argCount; i++) {
            mv.visitInsn(Opcodes.DUP);
            mv.visitLdcInsn(i);
            // that was two extra words
            compileContext.addStackCount(2);
            Expression argument = arguments.get(i);
            Type argType = argumentTypes.get(i);
            Type paramType = paramTypes.get(i);
            // compile code to stack argument and type convert/box if necessary
            argument.compile(mv, compileContext);
            compileTypeConversion(argType, paramType, mv, compileContext);
            compileBox(paramType, mv, compileContext);
            // that's 3 extra words which now get removed
            mv.visitInsn(Opcodes.AASTORE);
            compileContext.addStackCount(-3);
        }
        // now stack the method object index
        mv.visitLdcInsn(methodIndex);
        compileContext.addStackCount(1);

        // enable triggering before we call the method
        // this adds an extra value to the stack so modify the compile context to ensure
        // we increase the maximum height if necessary
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "enableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);

        // ok, we  now have the recipient, args array and method index on the stack
        // so we can call the HelperAdapter method  to do the actual reflective invocation
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Type.internalName(HelperAdapter.class),
                "invokeAccessibleMethod", "(Ljava/lang/Object;[Ljava/lang/Object;I)Ljava/lang/Object;");
        // we popped 4 words and left one in its place
        compileContext.addStackCount(-3);
        if (type == Type.VOID) {
            mv.visitInsn(Opcodes.POP);
            compileContext.addStackCount(-1);
        } else {
            // do any necessary casting and/or unboxing
            compileTypeConversion(Type.OBJECT, type, mv, compileContext);
        }

        // now disable triggering again
        // this temporarily adds an extra value to the stack -- n.b. no need to increment and
        // then decrement the stack height here because the previous enable call will already have
        // bumped the max when we had 4 slots on the stack and any return value on the stack will
        // occupy at most 2 slots

        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "org/jboss/byteman/rule/Rule", "disableTriggersInternal",
                "()Z");
        compileContext.addStackCount(1);
        mv.visitInsn(Opcodes.POP);
        compileContext.addStackCount(-1);
    }

    // ensure we have only increased the stack by the return value size
    if (compileContext.getStackCount() != currentStack + expected) {
        throw new CompileException("MethodExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + expected));
    }

    // no need to update max stack since compiling the  recipient or arguments will
    // have done so (and there will be no change if there was no such compile call)
}