Example usage for org.objectweb.asm Opcodes NOP

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

Introduction

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

Prototype

int NOP

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

Click Source Link

Usage

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

License:Open Source License

@Test
public void setCovered_should_mark_branch_in_predecessor() {
    final Instruction i = new Instruction(new InsnNode(Opcodes.NOP), 122);
    i.setCovered(2);//from w  w w.ja  v  a  2  s .  co  m
    assertEquals(1, i.getCoveredBranches());
    assertEquals("{2}", i.toString());

    final Instruction s1 = new Instruction(new InsnNode(Opcodes.NOP), 123);
    s1.setPredecessor(i, 1);
    s1.setCovered(0);
    assertEquals("{0}", s1.toString());
    assertEquals(1, s1.getCoveredBranches());
    assertEquals("{1, 2}", i.toString());
    assertEquals(2, i.getCoveredBranches());

    final Instruction s2 = new Instruction(new InsnNode(Opcodes.NOP), 124);
    s2.setPredecessor(i, 0);
    s2.setCovered(1);
    assertEquals("{0}", s1.toString());
    assertEquals(1, s2.getCoveredBranches());
    assertEquals("{0, 1, 2}", i.toString());
    assertEquals(3, i.getCoveredBranches());
}

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

License:Open Source License

@Test
public void merge_should_add_covered_branches_from_another_instruction() {
    final Instruction i1 = new Instruction(new InsnNode(Opcodes.NOP), 123);
    i1.setCovered(0);/*from  www . j a va  2  s .c  om*/
    final Instruction i2 = new Instruction(new InsnNode(Opcodes.NOP), 123);
    i2.setCovered(1);
    i1.merge(i2);
    assertEquals("{0, 1}", i1.toString());
    assertEquals(2, i1.getCoveredBranches());
    assertEquals("{1}", i2.toString());
}

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

License:Open Source License

@Test
public void testSetCoveredOnLongSequence() {
    final Instruction first = new Instruction(new InsnNode(Opcodes.NOP), 0);
    Instruction next = first;//from   ww w .ja  v a2 s. co m
    for (int i = 0; i < 0x10000; i++) {
        final Instruction insn = new Instruction(new InsnNode(Opcodes.NOP), i);
        insn.setPredecessor(next, 0);
        next = insn;
    }

    // The implementation must not cause an StackOverflowError even on very
    // long sequences:
    next.setCovered(0);
    assertEquals(1, first.getCoveredBranches());
}

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

License:Open Source License

@Test
public void testFlowScenario09() {
    analyzer.visitInsn(Opcodes.NOP);
    analyzer.visitLabel(label);//w  w w . j  a  v  a2  s .  c  om
    analyzer.visitLabel(label);
    assertFalse(LabelInfo.isMultiTarget(label));
    assertTrue(LabelInfo.isSuccessor(label));
}

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

License:Open Source License

@Test
public void testInsn() {
    testInstructionBetweenFrames(new InsnNode(Opcodes.NOP));
}

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  va  2  s  .c o  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.internal.instr.MethodInstrumenterTest.java

License:Open Source License

@Test(expected = IllegalArgumentException.class)
public void testVisitJumpInsnWithProbe_InvalidOpcode() {
    testVisitJumpInsnWithProbe(Opcodes.NOP, Opcodes.NOP);
}

From source file:org.jacoco.core.test.validation.ResizeInstructionsTest.java

License:Open Source License

/**
 * Test of ASM bug/*w  w  w  .j ava2s  .  com*/
 * <a href="https://gitlab.ow2.org/asm/asm/issues/317792">#317792</a>.
 */
@Test
public void should_not_loose_InnerClasses_attribute() throws Exception {
    // FIXME fails without COMPUTE_FRAMES because of
    // https://gitlab.ow2.org/asm/asm/issues/317800
    final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
    final ClassReader cr = new ClassReader(TargetLoader.getClassDataAsBytes(Inner.class));
    cr.accept(new ClassVisitor(InstrSupport.ASM_API_VERSION, cw) {
        @Override
        public void visitEnd() {
            final MethodVisitor mv = cv.visitMethod(0, "m", "()V", null, null);
            mv.visitCode();
            addCauseOfResizeInstructions(mv);
            mv.visitInsn(Opcodes.NOP);
            mv.visitMaxs(2, 1);
            mv.visitEnd();
            super.visitEnd();
        }
    }, 0);
    final byte[] bytes = instrumenter.instrument(cw.toByteArray(), "");

    final TargetLoader targetLoader = new TargetLoader();
    final Class<?> outer = targetLoader.add(ResizeInstructionsTest.class,
            TargetLoader.getClassDataAsBytes(ResizeInstructionsTest.class));
    final Class<?> inner = targetLoader.add(Inner.class, bytes);
    assertSame(outer, inner.getEnclosingClass());
    assertNotNull(inner.getEnclosingClass());
    assertSame(outer, inner.getDeclaringClass());
    assertNotNull(inner.getDeclaringClass());
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Encodes the Java code for a given Java operator expression.
 *   /* w  w w .j a va 2  s  .  c  o  m*/
 * @param operatorExpr the java operator expression  
 * @param context
 * @return JavaTypeName
 * @throws JavaGenerationException
 */
private static JavaTypeName encodeOperatorExpr(JavaExpression.OperatorExpression operatorExpr,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    JavaOperator operator = operatorExpr.getJavaOperator();
    String symbol = operator.getSymbol();
    JavaTypeName valueType = operator.getValueType();

    // Now carry out the operation according to its type.
    if (operator.isArithmeticOp()) {

        // Add the instructions to evaluate the first argument.
        JavaTypeName arg1Type = encodeExpr(operatorExpr.getArgument(0), context);

        if (operatorExpr instanceof OperatorExpression.Unary) {

            if (symbol.equals("-")) { // number negation

                mv.visitInsn(getNegateOpCode(arg1Type));
                return arg1Type;
            }

            throw new JavaGenerationException("Unknown unary arithmetic operator " + symbol + ".");
        }

        // Add an instruction to widen the argument if necessary.
        int wideningOpCode = getWideningOpCode(arg1Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        // Add the instructions to evaluate the second argument.
        JavaTypeName arg2Type = encodeExpr(operatorExpr.getArgument(1), context);

        // Add an instruction to widen the argument if necessary.
        wideningOpCode = getWideningOpCode(arg2Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        // Evaluate.
        mv.visitInsn(getArithmeticBinaryOpCode(symbol, valueType));

        return valueType;
    }

    if (operator.isBitOp()) {
        // Add the instructions to evaluate the first argument.
        JavaTypeName arg1Type = encodeExpr(operatorExpr.getArgument(0), context);

        // Add an instruction to widen the argument if necessary.
        int wideningOpCode = getWideningOpCode(arg1Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        if (operatorExpr instanceof OperatorExpression.Unary) {
            if (symbol.equals("~")) { // number negation
                if (valueType == JavaTypeName.INT) {
                    mv.visitInsn(Opcodes.ICONST_M1);
                    mv.visitInsn(Opcodes.IXOR);
                    return valueType;
                } else if (valueType == JavaTypeName.LONG) {
                    encodePushLongValue(new Long(-1), context);
                    mv.visitInsn(Opcodes.LXOR);
                    return valueType;
                }
            }

            throw new JavaGenerationException("Unknown unary arithmetic operator " + symbol + ".");
        }

        // Add the instructions to evaluate the second argument.
        JavaTypeName arg2Type = encodeExpr(operatorExpr.getArgument(1), context);

        // If this is >>, >>>, or << we may need to narrow the second argument to an int
        if (symbol.equals(">>") || symbol.equals(">>>") || symbol.equals("<<")) {
            if (arg2Type == JavaTypeName.LONG) {
                mv.visitInsn(Opcodes.L2I);
            }
        } else {
            // Add an instruction to widen the argument if necessary.
            wideningOpCode = getWideningOpCode(arg2Type, valueType);
            if (wideningOpCode != Opcodes.NOP) {
                mv.visitInsn(wideningOpCode);
            }
        }

        // Evaluate.
        mv.visitInsn(getArithmeticBinaryOpCode(symbol, valueType));

        return valueType;

    }

    if (operator.isLogicalOp() || operator.isRelationalOp()) {

        // Logical op:    {"!", "&&", "||"}
        // Relational op: {">", ">=", "<", "<=", "==", "!="}

        Label trueContinuation = new Label();
        Label falseContinuation = new Label();

        encodeBooleanValuedOperatorHelper(operatorExpr, context, trueContinuation, falseContinuation);
        return encodeThenTrueElseFalse(trueContinuation, falseContinuation, context);
    }

    if (operator == JavaOperator.STRING_CONCATENATION) {

        // Create an uninitialized StringBuilder, duplicate the reference (so we can invoke the initializer).
        mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
        mv.visitInsn(Opcodes.DUP);

        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");

        // append the first arg.
        JavaTypeName firstArgType = encodeExpr(operatorExpr.getArgument(0), context);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                getAppendJVMDescriptor(firstArgType));

        // Append the results of evaluation of the second arg.
        // Note that, conveniently, StringBuilder has an append() method for all the different types.
        JavaTypeName secondArgType = encodeExpr(operatorExpr.getArgument(1), context);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                getAppendJVMDescriptor(secondArgType));

        // Call toString() on the result.           
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                "()Ljava/lang/String;");

        return JavaTypeName.STRING;
    }

    return encodeTernaryOperatorExpr((OperatorExpression.Ternary) operatorExpr, context);
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**  
 * Boolean valued operators (!, &&, ||, ==, !=, <, <=, > and >=) are highly optimized during compilation to bytecode.
 * Here is a quick outline of the optimizations used:
 * -not (e1 && e2) is compiled as a single notAnd operator
 * -not (e1 || e2) is compiled as a single notOr operator
 * -not (not e) is optimized out.//from   w  w  w. j av  a  2  s. c om
 * -not (x < y) is compiled as x >= y for integral comparisons. A similar thing is done for not (double <), but it is not quite double >= because
 *  of NaN. However, there is special java bytecode support for treatment of this.
 * -Comparisons where the right-hand-side is an int 0 are treated more efficiently i.e. x > 0.
 * -Comparisons to null are treated specially i.e. x != null, x == null.  
 * -if the result of a boolean valued operator is used by the condition part of an if-then-else statement (or ternary operator) then
 *  the resulting true or false value is not pushed onto the stack and then tested. Rather we directly branch to the appropriate
 *  continuation.
 * -the most complicated optimization is that "trees" of boolean valued operators are effectively compiled as a single operator. 
 *  What this means is that the resulting "true" and "false" values are not popped onto the stack and consumed by subsequent operators
 *  but rather a "continuation style" is employed where we just jump to the correct next comparison.
 *  This saves an extra comparison per operator, as well as unecessary pushes of trues and falses compared to the naive compilation scheme. 
 *  The precise bytecode instructions used in the compilation schemes varies depending on context (see the endsWithTrueForm argument).
 * 
 * @param operatorExpr
 * @param context
 * @param trueContinuation label to jump to if the expression has a true value
 * @param falseContinuation label to jump to if the expression has a false value 
 * @param endsWithTrueForm operators are encoded as a series of tests with jumps where if none of the jumps are taken the operator slips
 *    through to the default case. This is usually "true" but if the "endsWithTrueForm" flag is set to false, then the default case will
 *    be false. For example, this is useful when encoding a boolean-valued operator that is the left argument of the || operator. 
 *    In that case we want the default case to proceed to evaluation of the second argument of ||.
 * @throws JavaGenerationException
 */
private static void encodeBooleanValuedOperatorHelper(JavaExpression.OperatorExpression operatorExpr,
        GenerationContext context, Label trueContinuation, Label falseContinuation, boolean endsWithTrueForm)
        throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    JavaOperator operator = operatorExpr.getJavaOperator();
    String symbol = operator.getSymbol();
    JavaTypeName valueType = operator.getValueType();

    if (operator.isLogicalOp()) {

        // Logical op:    {"!", "&&", "||"}
        // Note: conditional statements should not be handled here..
        //   eg. "if" conditional evaluation happens during "if" source generation.
        //   We can get here if, eg. printing the result of a conditional.            

        // boolean negation
        if (symbol.equals("!")) {

            JavaExpression arg0Expr = operatorExpr.getArgument(0);

            //attempt to optimize a variety of cases where not is composed with another boolean valued operator.

            if (arg0Expr instanceof JavaExpression.OperatorExpression) {

                if (arg0Expr instanceof JavaExpression.OperatorExpression.Binary) {

                    JavaExpression.OperatorExpression.Binary arg0BinaryOperatorExpr = (JavaExpression.OperatorExpression.Binary) arg0Expr;
                    JavaOperator arg0BinaryOperator = arg0BinaryOperatorExpr.getJavaOperator();

                    //not (expr1 && expr2) is encoded in a special way. Effectively there is a notAnd operator.

                    if (arg0BinaryOperator == JavaOperator.CONDITIONAL_AND) {

                        //x notAnd y                    
                        //is encoded as                    
                        //if x == false then goto trueContinuation
                        //if y == true then goto falseContinuation

                        ////what follows is a sample continuation in the case when a literal value is pushed onto the stack
                        //label trueContinuation:
                        //push true
                        //goto next
                        //label falseContinuation:
                        //push false
                        //next: 

                        JavaExpression andOpArg0Expr = arg0BinaryOperatorExpr.getArgument(0);
                        if (isBooleanValuedOperatorExpr(andOpArg0Expr)) {
                            Label innerTrueContinuation = new Label();
                            encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) andOpArg0Expr,
                                    context, innerTrueContinuation, trueContinuation);
                            mv.visitLabel(innerTrueContinuation);
                        } else {
                            encodeExpr(andOpArg0Expr, context);
                            mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
                        }

                        JavaExpression andOpArg1Expr = arg0BinaryOperatorExpr.getArgument(1);
                        if (isBooleanValuedOperatorExpr(andOpArg1Expr)) {
                            encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) andOpArg1Expr,
                                    context, falseContinuation, trueContinuation, !endsWithTrueForm);
                        } else {
                            encodeExpr(andOpArg1Expr, context);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
                            }
                        }

                        return;
                    }

                    //not (expr1 || expr2) is encoded in a special way. Effectively there is a notOr operator.

                    if (arg0BinaryOperator == JavaOperator.CONDITIONAL_OR) {

                        //x notOr y                    
                        //is encoded as                    
                        //if x == true then goto falseContinuation
                        //if y == true then goto falseContinuation

                        ////what follows is a sample continuation in the case when a literal value is pushed onto the stack                           
                        //label trueContinuation:
                        //push true
                        //goto next
                        //label falseContinuation:
                        //push false
                        //next: 

                        JavaExpression orOpArg0Expr = arg0BinaryOperatorExpr.getArgument(0);
                        if (isBooleanValuedOperatorExpr(orOpArg0Expr)) {
                            Label innerFalseContinuation = new Label();
                            //if x evaluates to false, we want to continue with evaluating y, this is why the "endsWithTrueForm" argument is false here.
                            //if x evaluates to false, then x notOr y returns true without needing to evaluate y. That is why the trueContinuation for x, is
                            //the falseContinuation for the call that encodes x.
                            encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) orOpArg0Expr,
                                    context, falseContinuation, innerFalseContinuation, false);
                            mv.visitLabel(innerFalseContinuation);
                        } else {
                            encodeExpr(orOpArg0Expr, context);
                            mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
                        }

                        JavaExpression orOpArg1Expr = arg0BinaryOperatorExpr.getArgument(1);
                        if (isBooleanValuedOperatorExpr(orOpArg1Expr)) {
                            encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) orOpArg1Expr,
                                    context, falseContinuation, trueContinuation, !endsWithTrueForm);
                        } else {
                            encodeExpr(orOpArg1Expr, context);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
                            }
                        }

                        return;
                    }

                    //try to optimize not composed with a boolean valued operator as a single operation
                    //for example, for int operators, not (x < y) is actually encoded as x >= y.                        

                    JavaExpression.OperatorExpression.Binary notComposedOperatorExpr = arg0BinaryOperatorExpr
                            .getNotComposedOperatorExpr();
                    if (notComposedOperatorExpr != null) {

                        encodeBooleanValuedOperatorHelper(notComposedOperatorExpr, context, trueContinuation,
                                falseContinuation, endsWithTrueForm);
                        return;
                    }

                    //not (x Double.< y) is encoded like x Double.>= y except that the opposite DCMP instruction is used.                           
                    //this is to handle NAN. Similar for the others.

                    if (arg0BinaryOperator == JavaOperator.LESS_THAN_DOUBLE
                            || arg0BinaryOperator == JavaOperator.LESS_THAN_EQUALS_DOUBLE
                            || arg0BinaryOperator == JavaOperator.GREATER_THAN_DOUBLE
                            || arg0BinaryOperator == JavaOperator.GREATER_THAN_EQUALS_DOUBLE) {

                        //encode the first argument
                        JavaTypeName firstArgType = encodeExpr(arg0BinaryOperatorExpr.getArgument(0), context);

                        // Add instructions to widen the first argument if necessary.
                        int wideningOpCode = getWideningOpCode(firstArgType, JavaTypeName.DOUBLE);
                        if (wideningOpCode != Opcodes.NOP) {
                            mv.visitInsn(wideningOpCode);
                        }

                        //endcode the second argument
                        JavaExpression secondArgExpr = arg0BinaryOperatorExpr.getArgument(1);
                        JavaTypeName secondArgType = encodeExpr(secondArgExpr, context);
                        wideningOpCode = getWideningOpCode(secondArgType, JavaTypeName.DOUBLE);
                        if (wideningOpCode != Opcodes.NOP) {
                            mv.visitInsn(wideningOpCode);
                        }

                        if (arg0BinaryOperator == JavaOperator.LESS_THAN_DOUBLE) {

                            mv.visitInsn(Opcodes.DCMPG);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFLT, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFGE, trueContinuation);
                            }

                        } else if (arg0BinaryOperator == JavaOperator.LESS_THAN_EQUALS_DOUBLE) {

                            mv.visitInsn(Opcodes.DCMPG);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFLE, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFGT, trueContinuation);
                            }

                        } else if (arg0BinaryOperator == JavaOperator.GREATER_THAN_DOUBLE) {

                            mv.visitInsn(Opcodes.DCMPL);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFGT, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFLE, trueContinuation);
                            }

                        } else if (arg0BinaryOperator == JavaOperator.GREATER_THAN_EQUALS_DOUBLE) {

                            mv.visitInsn(Opcodes.DCMPL);
                            if (endsWithTrueForm) {
                                mv.visitJumpInsn(Opcodes.IFGE, falseContinuation);
                            } else {
                                mv.visitJumpInsn(Opcodes.IFLT, trueContinuation);
                            }

                        } else {

                            throw new JavaGenerationException(
                                    "Expecting one of the double operators <, >, <= or >=.");
                        }

                        return;
                    }

                    //fall through to the unoptimized case...

                } else if (arg0Expr instanceof JavaExpression.OperatorExpression.Unary) {

                    //"not (not expr)" is encoded as "id expr"

                    JavaExpression.OperatorExpression.Unary arg0UnaryOperatorExpr = (JavaExpression.OperatorExpression.Unary) arg0Expr;
                    if (arg0UnaryOperatorExpr.getJavaOperator() != JavaOperator.LOGICAL_NEGATE) {
                        throw new JavaGenerationException("Unary logical negation expected.");
                    }

                    JavaExpression expr = arg0UnaryOperatorExpr.getArgument(0);
                    if (isBooleanValuedOperatorExpr(expr)) {
                        encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) expr, context,
                                trueContinuation, falseContinuation, endsWithTrueForm);
                    } else {
                        encodeExpr(expr, context);
                        if (endsWithTrueForm) {
                            mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
                        } else {
                            mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
                        }
                    }

                    return;
                }
            }

            //!x 
            //is encoded as
            //if x == true then goto falseContinuation;

            ////what follows is a sample continuation in the case when a literal value is pushed onto the stack
            //push true;
            //goto next;
            //falseContinuation:
            //push false;
            //label next:                                   

            encodeExpr(arg0Expr, context);
            if (endsWithTrueForm) {
                //Note that IFNE consumes a value on the stack.
                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
            }

            return;
        }

        if (symbol.equals("&&")) {

            //x && y                    
            //is encoded as                    
            //if x == false then goto falseContinuation
            //if y == false then goto falseContinuation

            ////what follows is a sample continuation in the case when a literal value is pushed onto the stack
            //push true
            //goto next
            //label falseContinuation:
            //push false
            //label next:

            JavaExpression arg0Expr = operatorExpr.getArgument(0);
            if (isBooleanValuedOperatorExpr(arg0Expr)) {
                Label innerTrueContinuation = new Label();
                encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) arg0Expr, context,
                        innerTrueContinuation, falseContinuation);
                mv.visitLabel(innerTrueContinuation);
            } else {
                encodeExpr(arg0Expr, context);
                mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
            }

            JavaExpression arg1Expr = operatorExpr.getArgument(1);
            if (isBooleanValuedOperatorExpr(arg1Expr)) {
                encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) arg1Expr, context,
                        trueContinuation, falseContinuation, endsWithTrueForm);
            } else {
                encodeExpr(arg1Expr, context);
                if (endsWithTrueForm) {
                    mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
                }
            }

            return;
        }

        if (symbol.equals("||")) {

            //x || y
            //is encoded as
            //if x == true then goto trueContinuation
            //if y == false then goto falseContinuation

            ////what follows is a sample continuation in the case when a literal value is pushed onto the stack
            //push true
            //goto next
            //label falseContinuation:
            //push false
            //label next:

            JavaExpression arg0Expr = operatorExpr.getArgument(0);
            if (isBooleanValuedOperatorExpr(arg0Expr)) {
                Label innerFalseContinuation = new Label();
                //if x evaluates to false, we want to continue with evaluating y, this is why the "endsWithTrueForm" argument is false here.
                encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) arg0Expr, context,
                        trueContinuation, innerFalseContinuation, false);
                mv.visitLabel(innerFalseContinuation);
            } else {
                encodeExpr(arg0Expr, context);
                mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
            }

            JavaExpression arg1Expr = operatorExpr.getArgument(1);
            if (isBooleanValuedOperatorExpr(arg1Expr)) {
                encodeBooleanValuedOperatorHelper((JavaExpression.OperatorExpression) arg1Expr, context,
                        trueContinuation, falseContinuation, endsWithTrueForm);
            } else {
                encodeExpr(arg1Expr, context);
                if (endsWithTrueForm) {
                    mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
                }
            }

            return;
        }

        throw new JavaGenerationException("Unknown logical operator " + symbol + ".");

    } // if(operator.isLogicalOp()) 

    // A relational operator

    //one comment on the bytecode sequences: there is some subtle points here because of the treatment of special values e.g. such
    //as not a number, plus infinity, minus 0 etc in the double and float types. The code below is based on copying what the Java
    //compiler generates for simple functions such as:
    //double foo(double x, double y) {double z = x < y; return z;}

    //encode the first argument
    JavaTypeName firstArgType = encodeExpr(operatorExpr.getArgument(0), context);

    // Add instructions to widen the first argument if necessary.
    int wideningOpCode = getWideningOpCode(firstArgType, valueType);
    if (wideningOpCode != Opcodes.NOP) {
        mv.visitInsn(wideningOpCode);
    }

    //Deal with comparisons to null as a special case. Don't push the second argument, since the null is 
    //implicit in the bytecode instruction.
    JavaExpression secondArgExpr = operatorExpr.getArgument(1);
    final boolean compareToNull = secondArgExpr == LiteralWrapper.NULL;

    //Deal with comparisons to int zero as a special case. There are special 1 argument operators for this case.
    //javac makes use of this optimization. Interestingly, javac does not optimize the case when the first argument
    //is a literal int zero i.e. 0 < x, is not converted to x > 0 which then can make use of the 1 argument comparison.        
    final boolean compareToIntZero = isInternalIntType(valueType) && isLiteralIntZeroExpr(secondArgExpr);

    if (!compareToNull && !compareToIntZero) {
        //endcode the second argument
        JavaTypeName secondArgType = encodeExpr(secondArgExpr, context);
        wideningOpCode = getWideningOpCode(secondArgType, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }
    }

    // relational symbols: {">", ">=", "<", "<=", "==", "!="}
    if (symbol.equals(">")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFLE, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPLE, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFGT, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPGT, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGT, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGT, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGT, trueContinuation);
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM > operator.");
        }

    } else if (symbol.equals(">=")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFLT, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPLT, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFGE, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPGE, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFLT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFGE, trueContinuation);
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM >= operator.");
        }

    } else if (symbol.equals("<")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFGE, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPGE, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFLT, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPLT, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLT, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPG);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLT, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPG);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLT, trueContinuation);
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM < operator.");
        }

    } else if (symbol.equals("<=")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFGT, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPGT, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFLE, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPLE, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPG);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPG);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFGT, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFLE, trueContinuation);
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM <= operator.");
        }

    } else if (symbol.equals("==")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BOOLEAN_TAG:
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPNE, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPEQ, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFNE, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFEQ, trueContinuation);
            }
            break;
        }

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG: {
            if (endsWithTrueForm) {
                if (compareToNull) {
                    mv.visitJumpInsn(Opcodes.IFNONNULL, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ACMPNE, falseContinuation);
                }
            } else {
                if (compareToNull) {
                    mv.visitJumpInsn(Opcodes.IFNULL, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, trueContinuation);
                }
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM == operator.");
        }

    } else if (symbol.equals("!=")) {

        switch (valueType.getTag()) {
        case JavaTypeName.BOOLEAN_TAG:
        case JavaTypeName.BYTE_TAG:
        case JavaTypeName.SHORT_TAG:
        case JavaTypeName.CHAR_TAG:
        case JavaTypeName.INT_TAG: {
            if (endsWithTrueForm) {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPEQ, falseContinuation);
                }
            } else {
                if (compareToIntZero) {
                    mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ICMPNE, trueContinuation);
                }
            }
            break;
        }

        case JavaTypeName.LONG_TAG: {
            mv.visitInsn(Opcodes.LCMP);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.DOUBLE_TAG: {
            mv.visitInsn(Opcodes.DCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.FLOAT_TAG: {
            mv.visitInsn(Opcodes.FCMPL);
            if (endsWithTrueForm) {
                mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);
            } else {
                mv.visitJumpInsn(Opcodes.IFNE, trueContinuation);
            }
            break;
        }

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG: {
            if (endsWithTrueForm) {
                if (compareToNull) {
                    mv.visitJumpInsn(Opcodes.IFNULL, falseContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ACMPEQ, falseContinuation);
                }
            } else {
                if (compareToNull) {
                    mv.visitJumpInsn(Opcodes.IFNONNULL, trueContinuation);
                } else {
                    mv.visitJumpInsn(Opcodes.IF_ACMPNE, trueContinuation);
                }
            }
            break;
        }

        default:
            throw new IllegalArgumentException("Unsupported operand type for JVM != operator.");
        }

    } else {
        throw new JavaGenerationException("Unknown relational operator " + symbol + ".");
    }
}