Example usage for org.objectweb.asm Opcodes IFEQ

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

Introduction

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

Prototype

int IFEQ

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

Click Source Link

Usage

From source file:org.jboss.byteman.rule.expression.LogicalExpression.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);

    Expression oper0 = getOperand(0);
    Expression oper1 = getOperand(1);

    int currentStack = compileContext.getStackCount();

    // compile the first expression and make sure it is a boolean -- adds 1 to stack height
    oper0.compile(mv, compileContext);/*from w  w  w.  ja  v  a2s.c o m*/
    if (oper0.getType() == Type.BOOLEAN) {
        compileBooleanConversion(Type.BOOLEAN, type.Z, mv, compileContext);
    }
    // plant a test and branch
    Label nextLabel = new Label();
    Label endLabel = new Label();
    if (oper == AND) {
        // only try next if we got true here
        mv.visitJumpInsn(Opcodes.IFNE, nextLabel);
        // ok, the first branch was false so stack a false for the result and skip to the end
        mv.visitLdcInsn(false);
        mv.visitJumpInsn(Opcodes.GOTO, endLabel);
    } else {
        // only try next if we got false here
        mv.visitJumpInsn(Opcodes.IFEQ, nextLabel);
        // ok, the first branch was true so stack a true for the result and skip to the end
        mv.visitLdcInsn(true);
        mv.visitJumpInsn(Opcodes.GOTO, endLabel);
    }
    // in either case if we get here the if test removed 1 from the stack
    compileContext.addStackCount(-1);
    // the else branch -- adds 1 to stack height
    mv.visitLabel(nextLabel);
    oper1.compile(mv, compileContext);
    if (oper0.getType() == Type.BOOLEAN) {
        compileBooleanConversion(Type.BOOLEAN, type.Z, mv, compileContext);
    }
    // the final result is the result of the second oper which is on the stack already
    // This is the end, my beau-tiful friend
    mv.visitLabel(endLabel);
    // in either case if we get here we should have one extra value on the stack
    // check stack height
    if (compileContext.getStackCount() != currentStack + 1) {
        throw new CompileException("LogicalExpression.compile : invalid stack height "
                + compileContext.getStackCount() + " expecting " + (currentStack + 1));
    }
}

From source file:org.jtsan.InstrumentCalls.java

License:Apache License

private void genTryCatchBlock(MethodMapping.HandlerInfo target, Label startExceptionRegion,
        Label endExceptionRegion) {
    Label startCatchRegion = new Label();
    Label labelSkip = new Label();
    Label labelAfter = new Label();

    boolean isStatic = (opcode == Opcodes.INVOKESTATIC);

    gen.visitJumpInsn(Opcodes.GOTO, labelAfter);

    gen.visitLabel(startCatchRegion);//from w w w.  j a  v a2  s .c  o m

    // TODO(vors): Handle static method exceptions incorrectly: we don't check class
    if (!isStatic) {
        // Skip the event if 'this' is not a child of the base class.
        saverThis.loadStack();
        gen.instanceOf(Type.getObjectType(target.getWatchedClass()));
        gen.visitJumpInsn(Opcodes.IFEQ, labelSkip);
    }

    // Restore stack to invoke exception handler.
    // dup() exception object.
    gen.dup();
    if (!isStatic) {
        saverThis.loadStack();
        gen.swap();
    }
    gen.push(cb.codePosition());

    cb.listenerCall(target.getHandler(),
            (isStatic ? "(" : ("(L" + target.getWatchedClass()) + ";") + "Ljava/lang/Throwable;J)V");

    gen.visitLabel(labelSkip);
    // throw exception object to next handler in exception table.
    gen.throwException();

    gen.visitLabel(labelAfter);

    // Mark try catch region with highest priority to all Exceptions.
    cb.topVisitTryCatchBlock(startExceptionRegion, endExceptionRegion, startCatchRegion, "java/lang/Throwable");

}

From source file:org.jtsan.InstrumentCalls.java

License:Apache License

private void genListenerCalls(List<MethodMapping.HandlerInfo> targets, boolean saveRet) {
    boolean returns = false;
    if (saveRet && saver.hasReturnValue()) {
        returns = true;/*  w  w w.  j a v a2 s .c om*/
    }
    if (returns) {
        saver.saveReturnValue();
    }
    for (MethodMapping.HandlerInfo target : targets) {
        Label labelSkip = new Label();
        Label labelAfter = new Label();
        boolean exact = target.isExact();
        boolean callGenerated = false;
        boolean listenStatic = (opcode == Opcodes.INVOKESTATIC);
        if (!listenStatic) {
            saverThis.loadStack();
        }
        // Shape the listener method's descriptor.
        String tailReplacement = "J)V";
        int idx = desc.indexOf(")");
        if (returns) {
            String retType = desc.substring(idx + 1, desc.length());
            tailReplacement = retType + tailReplacement;
        }
        String actualDesc = desc.substring(0, idx) + tailReplacement;
        if (!listenStatic) {
            actualDesc = addClassAsFirstArgument(target.getWatchedClass(), actualDesc);
        }

        // Insert type match checking and the listener call.
        if (!exact && !listenStatic) {
            // Skip the event if 'this' is not a child of the base class.
            gen.dup();
            gen.instanceOf(Type.getObjectType(target.getWatchedClass()));
            gen.visitJumpInsn(Opcodes.IFEQ, labelSkip);
            gen.checkCast(Type.getObjectType(target.getWatchedClass()));
        }
        if (!exact || target.getWatchedClass().equals(owner)) {
            saver.loadStack();
            if (returns) {
                saver.loadReturnValue();
            }
            gen.push(cb.codePosition());
            cb.listenerCall(target.getHandler(), actualDesc);
            callGenerated = true;
        }
        if (callGenerated && !listenStatic) {
            gen.visitJumpInsn(Opcodes.GOTO, labelAfter);
            gen.visitLabel(labelSkip);
            gen.pop();
            gen.visitLabel(labelAfter);
        }
    }
    if (returns) {
        saver.loadReturnValue();
    }
}

From source file:org.kantega.dogmaticmvc.mutation.MutationMethodVisitor.java

License:Apache License

private int getMutatedJumpInsn(int i) {
    switch (i) {//from   ww  w .  j  ava2  s.  c  o m
    case Opcodes.IFEQ:
        return Opcodes.IFNE;
    case Opcodes.IFNE:
        return Opcodes.IFEQ;
    case Opcodes.IFLT:
        return Opcodes.IFGE;
    case Opcodes.IFGE:
        return Opcodes.IFLT;
    case Opcodes.IFGT:
        return Opcodes.IFLE;
    case Opcodes.IFLE:
        return Opcodes.IFGT;
    case Opcodes.IF_ICMPEQ:
        return Opcodes.IF_ICMPNE;
    case Opcodes.IF_ICMPNE:
        return Opcodes.IF_ICMPEQ;
    case Opcodes.IF_ICMPLT:
        return Opcodes.IF_ICMPGE;
    case Opcodes.IF_ICMPGE:
        return Opcodes.IF_ICMPLT;
    case Opcodes.IF_ICMPGT:
        return Opcodes.IF_ICMPLE;
    case Opcodes.IF_ICMPLE:
        return Opcodes.IF_ICMPGT;
    case Opcodes.IF_ACMPEQ:
        return Opcodes.IF_ACMPNE;
    case Opcodes.IF_ACMPNE:
        return Opcodes.IF_ACMPEQ;
    case Opcodes.IFNULL:
        return Opcodes.IFNONNULL;
    case Opcodes.IFNONNULL:
        return Opcodes.IFNULL;

    default:
        return i;
    }
}

From source file:org.lambdamatic.analyzer.ast.LambdaExpressionReader.java

License:Open Source License

/**
 * Extracts the comparison {@link CompoundExpressionOperator} from the given {@link JumpInsnNode}.
 * /* ww w  .  j a v a2s.com*/
 * @param currentInstruction the comparison instruction
 * @return the corresponding {@link CompoundExpressionOperator}
 */
private static CompoundExpressionOperator extractComparisonOperator(final AbstractInsnNode currentInstruction) {
    switch (currentInstruction.getOpcode()) {
    case Opcodes.IF_ACMPNE:
    case Opcodes.IF_ICMPNE:
    case Opcodes.IFNE:
        return CompoundExpressionOperator.NOT_EQUALS;
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IFEQ:
        return CompoundExpressionOperator.EQUALS;
    case Opcodes.IF_ICMPLE:
    case Opcodes.IFLE:
        return CompoundExpressionOperator.LESS_EQUALS;
    case Opcodes.IF_ICMPLT:
    case Opcodes.IFLT:
        return CompoundExpressionOperator.LESS;
    case Opcodes.IF_ICMPGE:
    case Opcodes.IFGE:
        return CompoundExpressionOperator.GREATER_EQUALS;
    case Opcodes.IF_ICMPGT:
    case Opcodes.IFGT:
        return CompoundExpressionOperator.GREATER;
    default:
        throw new AnalyzeException(
                "Failed to retrieve the operator for the current comparison instruction (opcode: "
                        + currentInstruction.getOpcode() + ")");
    }
}

From source file:org.lambdamatic.analyzer.ast.LambdaExpressionReader.java

License:Open Source License

/**
 * The {@link AbstractInsnNode#getOpcode()} value should be one of {@code IFEQ}, {@code IFNE},
 * {@code IFLT}, {@code IFGE}, {@code IFGT}, {@code IFLE}, {@code IFLT}, {@code IFGE},
 * {@code IFGT},{@code IF_ICMPEQ}, {@code IF_ICMPNE}, {@code IF_ICMPLT}, {@code IF_ICMPGE},
 * {@code IF_ICMPGT}, {@code IF_ICMPLE}, {@code IF_ACMPEQ}, {@code IF_ACMPNE}, {@code GOTO},
 * {@code JSR}, {@code IFNULL} or {@code IFNONNULL}.
 * /*from   w w  w.jav a2s .co  m*/
 * 
 * @param instructionCursor the cursor for the current instruction to read
 * @param expressionStack the stack of Expressions
 * @param capturedArguments the captured arguments
 * @param localVariables the local variables
 * @return the list of statements read from the jump instruction
 */
private List<Statement> readJumpInstruction(final InsnCursor instructionCursor,
        final Stack<Expression> expressionStack, final List<CapturedArgument> capturedArguments,
        final LocalVariables localVariables) {
    final JumpInsnNode jumpInsnNode = (JumpInsnNode) instructionCursor.getCurrent();
    final LabelNode jumpLabel = jumpInsnNode.label;
    // FIXME: add support for LCMP:
    // Takes two two-word long integers off the stack and compares them. If
    // the two integers are the same, the int 0 is pushed onto the stack. If
    // value2 is greater than value1, the int 1 is pushed onto the stack. If
    // value1 is greater than value2, the int -1 is pushed onto the stack.
    switch (jumpInsnNode.getOpcode()) {
    case Opcodes.IFEQ:
    case Opcodes.IFNE:
    case Opcodes.IFLE:
    case Opcodes.IFLT:
    case Opcodes.IFGE:
    case Opcodes.IFGT:
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ICMPNE:
    case Opcodes.IF_ICMPLE:
    case Opcodes.IF_ICMPLT:
    case Opcodes.IF_ICMPGE:
    case Opcodes.IF_ICMPGT:
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ACMPNE:
        return Arrays.asList(buildControlFlowStatement(instructionCursor, expressionStack, capturedArguments,
                localVariables));
    case Opcodes.GOTO:
        final InsnCursor jumpInstructionCursor = instructionCursor.duplicate();
        jumpInstructionCursor.move(jumpLabel.getLabel());
        return readStatements(jumpInstructionCursor, expressionStack, capturedArguments, localVariables);
    default:
        throw new AnalyzeException("Unexpected JumpInsnNode OpCode: " + jumpInsnNode.getOpcode());
    }
}

From source file:org.lanternpowered.server.event.filter.delegate.ExcludeSubtypeFilterDelegate.java

License:MIT License

@Override
public int write(String name, ClassWriter cw, MethodVisitor mv, Method method, int locals) {
    // TODO could do an optimization here to inline a single instanceof if
    // the set would contain only a single member
    mv.visitVarInsn(ALOAD, 0);/*from  w ww .j  a v a  2s.c om*/
    mv.visitFieldInsn(GETFIELD, name, "classes", "Ljava/util/Set;");
    // Loop through the classes set's members
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "iterator", "()Ljava/util/Iterator;", true);
    mv.visitVarInsn(ASTORE, locals);
    Label continueLabel = new Label();
    mv.visitJumpInsn(GOTO, continueLabel);
    Label loopStart = new Label();
    mv.visitLabel(loopStart);
    mv.visitVarInsn(ALOAD, locals);
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);
    mv.visitTypeInsn(CHECKCAST, "java/lang/Class");
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "isInstance", "(Ljava/lang/Object;)Z", false);
    mv.visitJumpInsn(Opcodes.IFEQ, continueLabel);
    mv.visitInsn(ACONST_NULL);
    mv.visitInsn(ARETURN);
    mv.visitLabel(continueLabel);
    mv.visitVarInsn(ALOAD, locals);
    mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);
    mv.visitJumpInsn(IFNE, loopStart);
    return locals + 1;
}

From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java

License:Apache License

/**
 * convert boolean to Boolean//w w w. java  2 s.  c  om
 * @param mv
 */
public void boxBoolean(MethodVisitor mv) {
    Label l0 = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, l0);
    mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "TRUE", "Ljava/lang/Boolean;");
    Label l1 = new Label();
    mv.visitJumpInsn(Opcodes.GOTO, l1);
    mv.visitLabel(l0);
    mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", "FALSE", "Ljava/lang/Boolean;");
    mv.visitLabel(l1);
}

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

License:Open Source License

private static boolean encodeIfThenElseStatement(JavaStatement.IfThenElseStatement iteStatement,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    JavaExpression conditionExpr = iteStatement.getCondition();
    JavaStatement thenStatement = iteStatement.getThenStatement();
    JavaStatement elseStatement = iteStatement.getElseStatement();

    if (conditionExpr instanceof JavaExpression.OperatorExpression) {

        //generate more efficient code in the case of if (boolean-valued-operator)...

        //This case exists to handle the special case where an operator occurs as the child of an if-then-else (or ternary operator)
        //conditional. For example, in the situation:
        ////from w ww  . j  av a  2  s.  c  om
        //if (x != null) {...} else {...}
        // 
        // we do not want to evaluate x != null to a boolean value, push that value on the stack,
        // and then test it prior to selecting the correct branch. Rather, we can combine the evaluation
        // and jump operations into a single step.

        JavaExpression.OperatorExpression operatorExpr = (JavaExpression.OperatorExpression) conditionExpr;
        JavaOperator operator = operatorExpr.getJavaOperator();

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

            Label trueContinuation = new Label();
            context.addStatementJumpLabel(trueContinuation);

            Label falseContinuation = new Label();
            context.addStatementJumpLabel(falseContinuation);

            encodeBooleanValuedOperatorHelper(operatorExpr, context, trueContinuation, falseContinuation);
            return encodeThenStatementElseStatement(trueContinuation, falseContinuation, thenStatement,
                    elseStatement, context);
        }

        throw new JavaGenerationException(
                "Unrecognized boolean-valued conditional operator " + operator.getSymbol() + ".");
    }

    //encode the condition. It will be boolean valued.
    encodeExpr(iteStatement.getCondition(), context);

    //if false, jump to falseContinuation
    Label falseContinuation = new Label();
    mv.visitJumpInsn(Opcodes.IFEQ, falseContinuation);

    return encodeThenStatementElseStatement(null, falseContinuation, thenStatement, elseStatement, 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 ww w  . ja  v a2s.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 + ".");
    }
}