Example usage for org.objectweb.asm Opcodes GOTO

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

Introduction

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

Prototype

int GOTO

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

Click Source Link

Usage

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

License:Open Source License

@Test
public void ecj_try_catch_finally() {
    final Label tryStart = new Label();
    final Label tryEnd = new Label();
    final Label catchStart = new Label();
    final Label catchEnd = new Label();
    final Label finallyStart = new Label();
    final Label finallyEnd = new Label();
    final Label after = new Label();

    m.visitTryCatchBlock(tryStart, tryEnd, catchStart, "java/lang/Exception");
    m.visitTryCatchBlock(tryStart, catchEnd, finallyStart, null);

    m.visitLabel(tryStart);/*from w ww .j  ava 2s  .  c o m*/
    m.visitInsn(Opcodes.NOP); // try body
    m.visitLabel(tryEnd);
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);

    m.visitLabel(catchStart);
    m.visitInsn(Opcodes.POP);
    m.visitInsn(Opcodes.NOP); // catch body
    m.visitLabel(catchEnd);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, after);
    shouldIgnoreLast();

    m.visitLabel(finallyStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitVarInsn(Opcodes.ALOAD, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.ATHROW);
    shouldIgnoreLast();
    m.visitLabel(finallyEnd);

    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitLabel(after);
    m.visitInsn(Opcodes.NOP);

    execute();
}

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

License:Open Source License

/**
 * javac 1.5 - 1.7/*from   w w w  . j a v a  2  s  .co m*/
 */
@Test
public void javac_empty_catch() {
    final Label tryStart = new Label();
    final Label tryEnd = new Label();
    final Label catchStart = new Label();
    final Label catchEnd = new Label();
    final Label finallyStart = new Label();
    final Label finallyEnd = new Label();

    m.visitTryCatchBlock(tryStart, tryEnd, catchStart, "java/lang/Exception");
    m.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
    m.visitTryCatchBlock(catchStart, catchEnd, finallyStart, null);
    // actually one more useless TryCatchBlock for ASTORE in finally

    m.visitLabel(tryStart);
    m.visitInsn(Opcodes.NOP); // try body
    m.visitLabel(tryEnd);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);
    shouldIgnoreLast();

    m.visitLabel(catchStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    m.visitLabel(catchEnd);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);
    shouldIgnoreLast();

    m.visitLabel(finallyStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitVarInsn(Opcodes.ALOAD, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.ATHROW);
    shouldIgnoreLast();
    m.visitLabel(finallyEnd);

    m.visitInsn(Opcodes.NOP);

    execute();
}

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

License:Open Source License

/**
 * javac >= 1.8/*ww  w  . ja  v  a 2 s.  c  o m*/
 *
 * Probably related to https://bugs.openjdk.java.net/browse/JDK-7093325
 */
@Test
public void javac_8_empty_catch() throws Exception {
    final Label tryStart = new Label();
    final Label tryEnd = new Label();
    final Label catchStart = new Label();
    final Label finallyStart = new Label();
    final Label finallyEnd = new Label();

    m.visitTryCatchBlock(tryStart, tryEnd, catchStart, "java/lang/Exception");
    m.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);

    m.visitLabel(tryStart);
    m.visitInsn(Opcodes.NOP); // try body
    m.visitLabel(tryEnd);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);
    shouldIgnoreLast();
    shouldIgnoreLast();

    m.visitLabel(catchStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);
    shouldIgnoreLast();

    m.visitLabel(finallyStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitVarInsn(Opcodes.ALOAD, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.ATHROW);
    shouldIgnoreLast();
    m.visitLabel(finallyEnd);

    execute();
}

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

License:Open Source License

@Test
public void ecj_empty_catch() {
    final Label tryStart = new Label();
    final Label tryEnd = new Label();
    final Label catchStart = new Label();
    final Label catchEnd = new Label();
    final Label finallyStart = new Label();
    final Label finallyEnd = new Label();
    final Label after = new Label();

    m.visitTryCatchBlock(tryStart, tryEnd, catchStart, "java/lang/Exception");
    m.visitTryCatchBlock(tryStart, catchEnd, finallyStart, null);

    m.visitLabel(tryStart);/*from  w ww  .  j  a va2s . com*/
    m.visitInsn(Opcodes.NOP); // try body
    m.visitLabel(tryEnd);
    m.visitJumpInsn(Opcodes.GOTO, finallyEnd);

    m.visitLabel(catchStart);
    m.visitInsn(Opcodes.POP);
    m.visitLabel(catchEnd);
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitJumpInsn(Opcodes.GOTO, after);
    shouldIgnoreLast();

    m.visitLabel(finallyStart);
    m.visitVarInsn(Opcodes.ASTORE, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitVarInsn(Opcodes.ALOAD, 1);
    shouldIgnoreLast();
    m.visitInsn(Opcodes.ATHROW);
    shouldIgnoreLast();
    m.visitLabel(finallyEnd);

    m.visitInsn(Opcodes.NOP); // finally body
    shouldMergeLast();
    m.visitLabel(after);
    m.visitInsn(Opcodes.NOP);

    execute();
}

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

License:Open Source License

@Test
public void ecj_always_completes_abruptly() {
    final Label tryStart = new Label();
    final Label tryEnd = new Label();
    final Label finallyStart = new Label();

    m.visitTryCatchBlock(tryStart, tryEnd, tryEnd, null);

    m.visitLabel(tryStart);/*from   w ww  . ja  v  a 2 s . c  o  m*/
    m.visitInsn(Opcodes.NOP); // try body
    m.visitJumpInsn(Opcodes.GOTO, finallyStart);
    m.visitLabel(tryEnd);

    m.visitInsn(Opcodes.POP);
    m.visitLabel(finallyStart);
    m.visitInsn(Opcodes.RETURN); // finally body

    execute();
}

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

License:Open Source License

/**
 * <pre>/*from  ww  w . j av a2s  .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.KotlinWhenFilterTest.java

License:Open Source License

@Test
public void should_filter_implicit_default() {
    final Label case1 = new Label();
    final Label caseDefault = new Label();
    final Label after = new Label();

    m.visitInsn(Opcodes.NOP);//from ww w. j  a  v  a 2  s. c  o m

    m.visitTableSwitchInsn(0, 0, caseDefault, case1);
    final AbstractInsnNode switchNode = m.instructions.getLast();
    final Set<AbstractInsnNode> newTargets = new HashSet<AbstractInsnNode>();

    m.visitLabel(case1);
    m.visitInsn(Opcodes.ICONST_1);
    newTargets.add(m.instructions.getLast());
    m.visitJumpInsn(Opcodes.GOTO, after);

    final Range range1 = new Range();
    m.visitLabel(caseDefault);
    range1.fromInclusive = m.instructions.getLast();
    m.visitTypeInsn(Opcodes.NEW, "kotlin/NoWhenBranchMatchedException");
    m.visitInsn(Opcodes.DUP);
    m.visitMethodInsn(Opcodes.INVOKESPECIAL, "kotlin/NoWhenBranchMatchedException", "<init>", "()V", false);
    m.visitInsn(Opcodes.ATHROW);
    range1.toInclusive = m.instructions.getLast();

    m.visitLabel(after);

    filter.filter(m, context, output);

    assertIgnored(range1);
    assertReplacedBranches(switchNode, newTargets);
}

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

License:Open Source License

@Test
public void should_filter() {
    final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>();

    final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "name", "()V", null, null);

    final Label h1 = new Label();
    final Label sameHash = new Label();
    final Label h2 = new Label();
    final Label case1 = new Label();
    final Label case2 = new Label();
    final Label case3 = new Label();
    final Label defaultCase = new Label();

    // filter should not remember this unrelated slot
    m.visitLdcInsn("");
    m.visitVarInsn(Opcodes.ASTORE, 1);/*w  w w.ja v a  2  s .c  o  m*/
    m.visitVarInsn(Opcodes.ALOAD, 1);

    // switch (...)
    m.visitVarInsn(Opcodes.ASTORE, 2);
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    m.visitTableSwitchInsn(97, 98, defaultCase, h1, h2);

    // case "a"
    m.visitLabel(h1);
    final AbstractInsnNode expectedFromInclusive = m.instructions.getLast();

    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    m.visitJumpInsn(Opcodes.IFEQ, sameHash);
    m.visitJumpInsn(Opcodes.GOTO, case1);

    // case "\u0000a"
    m.visitLabel(sameHash);
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("\u0000a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
    m.visitJumpInsn(Opcodes.GOTO, case2);

    // case "b"
    m.visitLabel(h2);
    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("\u0000a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    m.visitJumpInsn(Opcodes.IFEQ, defaultCase);
    m.visitJumpInsn(Opcodes.GOTO, case3);
    final AbstractInsnNode expectedToInclusive = m.instructions.getLast();

    m.visitLabel(case1);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(case2);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(case3);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(defaultCase);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());

    filter.filter(m, context, output);

    assertReplacedBranches(expectedFromInclusive.getPrevious(), expectedNewTargets);
    assertIgnored(new Range(expectedFromInclusive, expectedToInclusive));
}

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

License:Open Source License

@Test
public void should_filter() {
    final Set<AbstractInsnNode> expectedNewTargets = new HashSet<AbstractInsnNode>();

    final MethodNode m = new MethodNode(InstrSupport.ASM_API_VERSION, 0, "name", "()V", null, null);

    final Label case1 = new Label();
    final Label case2 = new Label();
    final Label case3 = new Label();
    final Label caseDefault = new Label();
    final Label h1 = new Label();
    final Label h2 = new Label();

    // filter should not remember this unrelated slot
    m.visitLdcInsn("");
    m.visitVarInsn(Opcodes.ASTORE, 1);/* w  ww  .  j a va 2s. c  o m*/
    m.visitVarInsn(Opcodes.ALOAD, 1);

    // switch (...)
    m.visitInsn(Opcodes.DUP);
    m.visitVarInsn(Opcodes.ASTORE, 2);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    m.visitTableSwitchInsn(97, 98, caseDefault, h1, h2);
    final AbstractInsnNode switchNode = m.instructions.getLast();

    m.visitLabel(h1);

    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if equal "a", then goto its case
    m.visitJumpInsn(Opcodes.IFNE, case1);

    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("\0a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if equal "\0a", then goto its case
    m.visitJumpInsn(Opcodes.IFNE, case2);

    // goto default case
    m.visitJumpInsn(Opcodes.GOTO, caseDefault);

    m.visitLabel(h2);

    m.visitVarInsn(Opcodes.ALOAD, 2);
    m.visitLdcInsn("b");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if equal "b", then goto its case
    m.visitJumpInsn(Opcodes.IFNE, case3);

    // goto default case
    m.visitJumpInsn(Opcodes.GOTO, caseDefault);
    final AbstractInsnNode expectedToInclusive = m.instructions.getLast();

    m.visitLabel(case1);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(case2);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(case3);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());
    m.visitLabel(caseDefault);
    m.visitInsn(Opcodes.RETURN);
    expectedNewTargets.add(m.instructions.getLast());

    filter.filter(m, context, output);

    assertReplacedBranches(switchNode, expectedNewTargets);
    assertIgnored(new Range(switchNode.getNext(), expectedToInclusive));
}

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

License:Open Source License

private void createFirstSwitch() {
    final Label h1 = new Label();
    final Label h1_2 = new Label();
    final Label h2 = new Label();
    final Label secondSwitch = new Label();

    m.visitInsn(Opcodes.ICONST_M1);/*from  www .  j  a va  2 s  .  c  o m*/
    m.visitVarInsn(Opcodes.ISTORE, 2);

    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    m.visitLookupSwitchInsn(secondSwitch, new int[] { 97, 98 }, new Label[] { h1, h2 });
    expectedFromInclusive = m.instructions.getLast();

    m.visitLabel(h1);
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitLdcInsn("a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if not equal "a", then goto next comparison
    m.visitJumpInsn(Opcodes.IFEQ, h1_2);
    m.visitInsn(Opcodes.ICONST_0);
    m.visitVarInsn(Opcodes.ISTORE, 2);

    // goto secondSwitch
    m.visitJumpInsn(Opcodes.GOTO, secondSwitch);

    m.visitLabel(h1_2);
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitLdcInsn("\0a");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if not equal "\0a", then goto second switch
    m.visitJumpInsn(Opcodes.IFEQ, secondSwitch);
    m.visitInsn(Opcodes.ICONST_1);
    m.visitVarInsn(Opcodes.ISTORE, 2);

    // goto secondSwitch
    m.visitJumpInsn(Opcodes.GOTO, secondSwitch);

    m.visitLabel(h2);
    m.visitVarInsn(Opcodes.ALOAD, 1);
    m.visitLdcInsn("b");
    m.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
    // if not equal "b", then goto second switch
    m.visitJumpInsn(Opcodes.IFEQ, secondSwitch);
    m.visitInsn(Opcodes.ICONST_2);
    m.visitVarInsn(Opcodes.ISTORE, 2);

    m.visitLabel(secondSwitch);
    expectedToInclusive = m.instructions.getLast();
    m.visitVarInsn(Opcodes.ILOAD, 2);
}