Example usage for org.objectweb.asm Opcodes IFGE

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

Introduction

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

Prototype

int IFGE

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

Click Source Link

Usage

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

License:Open Source License

@Test
public void testVisitJumpInsnWithProbe_IFGE() {
    testVisitJumpInsnWithProbe(Opcodes.IFGE, Opcodes.IFLT);
}

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

License:Open Source License

@Test
public void testVisitJumpInsnWithProbe_IFLT() {
    testVisitJumpInsnWithProbe(Opcodes.IFLT, Opcodes.IFGE);
}

From source file:org.jboss.byteman.agent.adapter.cfg.BBlock.java

License:Open Source License

/**
 * write a string represenattion of this block to the buffer
 * @param buf the buffer to be written to
 * @return//  w  w w . ja va  2  s.co  m
 */
void printTo(StringBuffer buf) {
    int blockIdx = this.getBlockIdx();
    buf.append(this.getLabel().getOffset());
    buf.append(": BB ");
    buf.append(blockIdx);
    buf.append("\n");
    FanOut containsFanOut = cfg.getContains(this);
    Iterator<Label> containsIter;
    Label containedLabel;
    int containedPosition;
    if (containsFanOut != null) {
        containsIter = containsFanOut.iterator();
        if (containsIter.hasNext()) {
            containedLabel = containsIter.next();
            containedPosition = cfg.getBlockInstructionIdx(containedLabel);
        } else {
            containedLabel = null;
            containedPosition = -1;
        }
    } else {
        containsIter = null;
        containedLabel = null;
        containedPosition = -1;
    }

    int instructionCount = this.getInstructionCount();
    for (int i = 0; i < instructionCount; i++) {
        // we will never enter this if containedPosition is -1 which safeguards us when containsIter
        // is null or containedLabel is null
        while (containedPosition == i) {
            buf.append(containedLabel.getOffset());
            buf.append(": ");
            buf.append(containedLabel);
            buf.append(" +");
            buf.append(containedPosition);
            if (cfg.tryCatchStart(containedLabel)) {
                List<TryCatchDetails> detailsList = cfg.tryCatchStartDetails(containedLabel);
                int detailsCount = detailsList.size();
                for (int j = 0; j < detailsCount; j++) {
                    TryCatchDetails details = detailsList.get(j);
                    Label handlerLabel = details.getHandler();
                    CodeLocation handlerLocation = cfg.getLocation(handlerLabel);
                    buf.append(" try ");
                    buf.append(details.getType());
                    buf.append(" ");
                    if (handlerLocation != null) {
                        buf.append(handlerLabel.getOffset());
                    } else {
                        buf.append("??");
                    }
                    buf.append(" ");
                    buf.append(handlerLabel);
                }
            }
            if (cfg.tryCatchEnd(containedLabel)) {
                List<TryCatchDetails> detailsList = cfg.tryCatchEndDetails(containedLabel);
                int detailsCount = detailsList.size();
                for (int j = 0; j < detailsCount; j++) {
                    TryCatchDetails details = detailsList.get(j);
                    Label handlerLabel = details.getHandler();
                    CodeLocation handlerLocation = cfg.getLocation(handlerLabel);
                    buf.append(" catch ");
                    buf.append(details.getType());
                    buf.append(" ");
                    if (handlerLocation != null) {
                        buf.append(handlerLabel.getOffset());
                    } else {
                        buf.append("??");
                    }
                    buf.append(" ");
                    buf.append(handlerLabel);
                }
            }
            if (cfg.tryCatchHandlerStart(containedLabel)) {
                List<TryCatchDetails> detailsList = cfg.tryCatchHandlerStartDetails(containedLabel);
                int detailsCount = detailsList.size();
                for (int j = 0; j < detailsCount; j++) {
                    TryCatchDetails details = detailsList.get(j);
                    buf.append(" handle ");
                    buf.append(details.getType());
                    buf.append(" ");
                    buf.append(details.getStart().getOffset());
                    buf.append(" ");
                    buf.append(details.getEnd().getOffset());
                }
            }
            if (cfg.triggerStart(containedLabel)) {
                buf.append(" trigger start");
                TriggerDetails details = cfg.triggerStartDetails(containedLabel);
            }
            if (cfg.triggerEnd(containedLabel)) {
                buf.append(" trigger end");
            }
            buf.append("\n");
            List<CodeLocation> openEnters = cfg.getOpenMonitorEnters(containedLabel);
            if (openEnters != null) {
                int openCount = openEnters.size();
                if (openCount > 0) {
                    buf.append("open monitors: ");
                    for (int j = 0; j < openCount; j++) {
                        CodeLocation l = openEnters.get(j);
                        buf.append(" BB");
                        buf.append(l.getBlock().getBlockIdx());
                        buf.append(".");
                        buf.append(l.getInstructionIdx());
                    }
                    buf.append('\n');
                }
            }
            containedLabel = (containsIter.hasNext() ? containsIter.next() : null);
            containedPosition = (containedLabel != null ? cfg.getBlockInstructionIdx(containedLabel) : -1);
        }
        // buf.append("   ");
        buf.append(blockIdx);
        buf.append(".");
        buf.append(i);
        buf.append(": ");
        int opcode = this.getInstruction(i);
        switch (OpcodesHelper.insnType(opcode)) {
        case OpcodesHelper.INSN_NONE: {
            // print the instruction name
            buf.append(OpcodesHelper.insnName(opcode));
            if (opcode == Opcodes.MONITOREXIT) {
                CodeLocation exit = new CodeLocation(this, i);
                CodeLocation enter = cfg.getPairedEnter(exit);
                // print the corresponding open instruction
                buf.append(" (enter: ");
                buf.append(enter);
                buf.append(")");
            }
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_INT: {
            // just print the instruction name and one integer argument
            int intValue = this.getInstructionArg(i, 0);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(intValue);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_LDC: {
            // print the instruction and one constant argument
            int nameIdx = this.getInstructionArg(i, 0);
            String name = cfg.getName(nameIdx);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(name);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_VAR: {
            // print the instruction and the var idx
            int varIdx = this.getInstructionArg(i, 0);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(varIdx);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_IINC: {
            // print the instruction and the var idx
            int increment = this.getInstructionArg(i, 0);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(increment);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_JUMP: {
            // note that we may not have generated the code for the jump target yet
            Label targetLabel = this.firstOut();
            CodeLocation targetLocation = cfg.getLocation(targetLabel);
            int targetPos = (targetLocation != null ? targetLabel.getOffset() : -1);
            switch (opcode) {
            case Opcodes.IFEQ:
                buf.append("IFEQ ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFNE:
                buf.append("IFNE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFLT:
                buf.append("IFLT ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFGE:
                buf.append("IFGE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFGT:
                buf.append("IFGT ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFLE:
                buf.append("IFLE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPEQ:
                buf.append("IF_ICMPEQ ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPNE:
                buf.append("IF_ICMPNE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPLT:
                buf.append("IF_ICMPLT ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPGE:
                buf.append("IF_ICMPGE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPGT:
                buf.append("IF_ICMPGT ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ICMPLE:
                buf.append("IF_ICMPLE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ACMPEQ:
                buf.append("IF_ACMPEQ ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IF_ACMPNE:
                buf.append("IF_ACMPNE ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.GOTO:
                buf.append("GOTO ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.JSR:
                buf.append("JSR ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFNULL:
                buf.append("IFNULL ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            case Opcodes.IFNONNULL:
                buf.append("IFNONNULL ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
                buf.append("\n");
                break;
            }
        }
            break;
        case OpcodesHelper.INSN_TSWITCH: {
            Label targetLabel;
            CodeLocation targetLocation;
            int targetPos;
            // print the instruction followed by the jump table discriminant min and max and then
            // the jump labels
            int min = this.getInstructionArg(i, 0);
            int max = this.getInstructionArg(i, 1);
            int count = (max + 1 - min);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(min);
            buf.append(" ");
            buf.append(max);
            buf.append("\n");
            for (int j = 1; j <= count; j++) {
                // note that we may not have generated the code for the jump target yet
                targetLabel = this.nthOut(j);
                targetLocation = cfg.getLocation(targetLabel);
                targetPos = (targetLocation != null ? targetLabel.getOffset() : -1);
                buf.append("    ");
                buf.append(min + j);
                buf.append(" : ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
            }
            targetLabel = this.firstOut();
            targetLocation = cfg.getLocation(targetLabel);
            targetPos = (targetLocation != null ? targetLabel.getOffset() : -1);
            buf.append("    dflt : ");
            if (targetPos >= 0) {
                buf.append(targetPos);
                buf.append(" BB ");
                buf.append(targetLocation.getBlock().getBlockIdx());
                buf.append(" ");
                buf.append(targetLabel);
            } else {
                buf.append("??  ");
                buf.append(targetLabel);
            }
        }
            break;
        case OpcodesHelper.INSN_LOOKUP: {
            Label targetLabel;
            CodeLocation targetLocation;
            int targetPos;
            // print the instruction followed by each jump table discriminant and label
            int count = this.getInstructionArg(i, 0);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append("\n");
            for (int j = 1; j <= count; j++) {
                // note that we may not have generated the code for the jump target yet
                targetLabel = this.nthOut(j);
                targetLocation = cfg.getLocation(targetLabel);
                targetPos = (targetLocation != null ? targetLabel.getOffset() : -1);
                buf.append("    ");
                buf.append(this.getInstructionArg(i, j));
                buf.append(" : ");
                if (targetPos >= 0) {
                    buf.append(targetPos);
                    buf.append(" BB ");
                    buf.append(targetLocation.getBlock().getBlockIdx());
                    buf.append(" ");
                    buf.append(targetLabel);
                } else {
                    buf.append("??  ");
                    buf.append(targetLabel);
                }
            }
            targetLabel = this.firstOut();
            targetLocation = cfg.getLocation(targetLabel);
            targetPos = (targetLocation != null ? targetLabel.getOffset() : -1);
            buf.append("    dflt : ");
            if (targetPos >= 0) {
                buf.append(targetPos);
                buf.append(" BB ");
                buf.append(targetLocation.getBlock().getBlockIdx());
                buf.append(" ");
                buf.append(targetLabel);
            } else {
                buf.append("??  ");
                buf.append(targetLabel);
            }
        }
            break;
        case OpcodesHelper.INSN_FIELD:
        case OpcodesHelper.INSN_METHOD: {
            // print the instruction with the owner, name and descriptor
            int idx1 = this.getInstructionArg(i, 0);
            int idx2 = this.getInstructionArg(i, 1);
            int idx3 = this.getInstructionArg(i, 2);
            String owner = cfg.getName(idx1);
            String name = cfg.getName(idx2);
            String desc = cfg.getName(idx3);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(owner);
            buf.append(" ");
            buf.append(name);
            buf.append(" ");
            buf.append(desc);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_TYPE: {
            // print the instruction with the type name
            int idx = this.getInstructionArg(i, 0);
            String name = cfg.getName(idx);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(name);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_MULTIANEWARRAY: {
            // print the instruction with the typename and the dimension count
            int idx = this.getInstructionArg(i, 0);
            int dims = this.getInstructionArg(i, 1);
            String name = cfg.getName(idx);
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append(" ");
            buf.append(name);
            buf.append(" ");
            buf.append(dims);
            buf.append("\n");
        }
            break;
        case OpcodesHelper.INSN_UNUSED: {
            // print the instruction
            buf.append(OpcodesHelper.insnName(opcode));
            buf.append("!!!\n");
        }
            break;
        }
    }
    // print the active starts for this block
    if (activeTryStarts != null) {
        Iterator<TryCatchDetails> activeStartsIter = activeTryStarts.iterator();
        while (activeStartsIter.hasNext()) {
            TryCatchDetails details = activeStartsIter.next();
            Label label = details.getStart();
            BBlock block = cfg.getBlock(label);
            buf.append("try: ");
            if (block != null) {
                buf.append(label.getOffset());
                buf.append(" ");
                buf.append(block.getBlockIdx());
                buf.append(".");
                buf.append(cfg.getBlockInstructionIdx(label));
            } else {
                buf.append(label);
            }
            buf.append(" catch: ");
            label = details.getEnd();
            block = cfg.getBlock(label);
            if (block != null) {
                buf.append(label.getOffset());
                buf.append(" ");
                buf.append(block.getBlockIdx());
                buf.append(".");
                buf.append(cfg.getBlockInstructionIdx(label));
            } else {
                buf.append(label);
            }
            buf.append(" handle: ");
            label = details.getHandler();
            block = cfg.getBlock(label);
            if (block != null) {
                buf.append(label.getOffset());
                buf.append(" ");
                buf.append(block.getBlockIdx());
                buf.append(".");
                buf.append(cfg.getBlockInstructionIdx(label));
            } else {
                buf.append(label);
            }
            buf.append(" ");
            buf.append(details.getType());
            buf.append("\n");
        }
    }
}

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

License:Open Source License

@Override
public void visitJumpInsn(int opcode, Label label) {
    super.visitJumpInsn(opcode, label);
    switch (opcode) {
    case Opcodes.IFEQ:
    case Opcodes.IFNE:
    case Opcodes.IFLT:
    case Opcodes.IFGE:
    case Opcodes.IFGT:
    case Opcodes.IFLE:
    case Opcodes.IF_ICMPEQ:
    case Opcodes.IF_ICMPNE:
    case Opcodes.IF_ICMPLT:
    case Opcodes.IF_ICMPGE:
    case Opcodes.IF_ICMPGT:
    case Opcodes.IF_ICMPLE:
    case Opcodes.IF_ACMPEQ:
    case Opcodes.IF_ACMPNE: {
        // create a new current block and add the label supplied in the call as the
        // first out of the old current block and the label of the new current block as
        // the second out
        cfg.add(opcode);// ww  w.  j  a v a 2  s . c  o m
        Label newStart = super.newLabel();
        // must call split before visiting the label
        cfg.split(newStart, label, newStart);
        visitLabel(newStart);
    }
        break;
    case Opcodes.GOTO: {
        // create a new current block and  add the label supplied in the call as the
        // first out of the old current block
        cfg.add(opcode);
        Label newStart = super.newLabel();
        // must call split before visiting the label
        cfg.split(newStart, label);
        visitLabel(newStart);
    }
        break;
    case Opcodes.JSR: {
        // create a new current block and add the label supplied in the call as the first out
        // of the current block -- the new current block is a potential return point from the
        // JSR but we cannot represent that statically
        cfg.add(opcode);
        Label newStart = super.newLabel();
        // must call split before visiting the label
        cfg.split(newStart, label, newStart);
        visitLabel(newStart);
    }
        break;
    case Opcodes.IFNULL:
    case Opcodes.IFNONNULL: {
        // create a new current block and add the label supplied in the call as the
        // first out of the old current block and the label of the new current block as
        // the second out
        cfg.add(opcode);
        Label newStart = super.newLabel();
        // must call split before visiting the label
        cfg.split(newStart, label, newStart);
        visitLabel(newStart);
    }
        break;
    }
}

From source file:org.jboss.byteman.rule.expression.ComparisonExpression.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 removed = 0;

    // evaluate the operands and ensure the reuslt is of the correct type for comparison adds 2
    oper0.compile(mv, compileContext);/* w  ww . j  av  a 2s  . c om*/
    compileTypeConversion(oper0.getType(), comparisonType, mv, compileContext);
    oper1.compile(mv, compileContext);
    compileTypeConversion(oper1.getType(), comparisonType, mv, compileContext);

    // now do the appropriate type of comparison
    if (comparisonType == type.B || comparisonType == type.S || comparisonType == type.S
            || comparisonType == type.I) {
        Label elsetarget = new Label();
        Label endtarget = new Label();
        // we remove 2 words from the stack and then add 1 back
        removed = 2;
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IF_ICMPGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IF_ICMPGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IF_ICMPLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IF_ICMPLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case EQ:
            mv.visitJumpInsn(Opcodes.IF_ICMPNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IF_ICMPEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        }
    } else if (comparisonType == type.J || comparisonType == type.F || comparisonType == type.D) {
        if (comparisonType == type.J) {
            mv.visitInsn(Opcodes.LCMP);
            // we remove four words from the stack and add 1 back
            removed = 4;
        } else if (comparisonType == type.F) {
            // we remove two words from the stack and add 1 back
            removed = 2;
            mv.visitInsn(Opcodes.FCMPG);
        } else if (comparisonType == type.D) {
            // we remove four words from the stack and add 1 back
            removed = 4;
            mv.visitInsn(Opcodes.DCMPG);
        }
        Label elsetarget = new Label();
        Label endtarget = new Label();
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IFGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IFGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IFLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IFLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case EQ:
            mv.visitJumpInsn(Opcodes.IFNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        }
    } else if (comparable) {
        // we add a further two words setting up the relevant test then remove them
        // and also remove the original two words replacing them with a single word
        removed = 4;
        compileContext.addStackCount(2);
        // we need to deal with null values correctly
        // if op1 == null || op2 == null
        // then
        //   EQ:
        //   push value1 == value2
        //   NE:
        //   push value1 != value2
        //   ow:
        //   push false
        // else
        //   execute compareTo or equals and test for the desired outcome
        // end if
        Label splittarget = new Label(); // else
        Label jointarget = new Label(); // end if
        mv.visitInsn(Opcodes.DUP2); // [... op1, op2 ] ==> [... op1, op2, op1,  op2]
        mv.visitInsn(Opcodes.POP); // [... op1, op2, op1, op2 ] ==> [... op1, op2, op1]
        // if op1 == null
        mv.visitJumpInsn(Opcodes.IFNULL, splittarget); // [... op1, op2, op1] ==> [... op1, op2]
        mv.visitInsn(Opcodes.DUP); // [... op1, op2 ] ==> [... op1, op2, op2]
        // || op2 == null
        mv.visitJumpInsn(Opcodes.IFNULL, splittarget); // [... op1, op2, op2] ==> [... op1, op2]
        // so, it is ok to call compareTo leaving an int or equals leaving a boolean
        if (oper != EQ && oper != NE) {
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Comparable", "compareTo",
                    "(Ljava/lang/Object;)I");
        } else {
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z");
        }
        // now if we did a compareTo we need to generate the required boolean
        Label elsetarget = new Label();
        Label endtarget = new Label();
        // if needed the convert the compareTo result to the required boolean outcome
        switch (oper) {
        case LT:
            mv.visitJumpInsn(Opcodes.IFGE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case LE:
            mv.visitJumpInsn(Opcodes.IFGT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GT:
            mv.visitJumpInsn(Opcodes.IFLE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case GE:
            mv.visitJumpInsn(Opcodes.IFLT, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
            break;
        case NE:
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
            break;
        }
        // skip to the join point
        mv.visitJumpInsn(Opcodes.GOTO, jointarget);
        // label the split point
        mv.visitLabel(splittarget);
        if (oper == EQ) {
            elsetarget = new Label();
            endtarget = new Label();
            mv.visitJumpInsn(Opcodes.IF_ACMPEQ, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
        } else if (oper == NE) {
            elsetarget = new Label();
            endtarget = new Label();
            mv.visitJumpInsn(Opcodes.IF_ACMPNE, elsetarget);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(true);
            mv.visitLabel(endtarget);
        } else {
            // pop the operands and stack false
            mv.visitInsn(Opcodes.POP2);
            mv.visitLdcInsn(false);
        }
        // label the join point
        mv.visitLabel(jointarget);
    } else if (comparisonType == Type.Z) {
        // unboxed booleans need special treatment
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
        // on this branch for EQ the stacked value is what we need and for NE
        // the stacked value needs flipping
        if (oper == NE) {
            Label elsetarget2 = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget2);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget2);
            mv.visitLdcInsn(true);
        }
        mv.visitJumpInsn(Opcodes.GOTO, endtarget);
        mv.visitLabel(elsetarget);
        // on this branch for NE the stacked value is what we need and for EQ
        // the stacked value needs flipping
        if (oper == EQ) {
            Label elsetarget2 = new Label();
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget2);
            mv.visitLdcInsn(false);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget2);
            mv.visitLdcInsn(true);
        }
        mv.visitLabel(endtarget);

    } else if (comparisonType == Type.BOOLEAN) {
        // boxed booleans need special treatment
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java.lang.Boolean", "equals", "(Ljava/lang/Boolean;)Z");
        if (oper == NE) {
            mv.visitJumpInsn(Opcodes.IFEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        }
    } else {
        // we remove two words replacing them with a single word
        removed = 2;
        Label elsetarget = new Label();
        Label endtarget = new Label();
        if (oper == EQ) {
            mv.visitJumpInsn(Opcodes.IF_ACMPNE, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        } else {
            mv.visitJumpInsn(Opcodes.IF_ACMPEQ, elsetarget);
            mv.visitLdcInsn(true);
            mv.visitJumpInsn(Opcodes.GOTO, endtarget);
            mv.visitLabel(elsetarget);
            mv.visitLdcInsn(false);
            mv.visitLabel(endtarget);
        }
    }
    compileContext.addStackCount(1 - removed);
}

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

License:Apache License

private int getMutatedJumpInsn(int i) {
    switch (i) {//from   w ww  .  jav a2  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}.
 * /*from w ww  . j av a  2  s . c  o m*/
 * @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 www .  jav  a2 s  . com*/
 * 
 * @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.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.// w  ww.j  a v  a2  s  .  com
 * -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 + ".");
    }
}

From source file:org.sonar.java.bytecode.se.BytecodeEGWalkerExecuteTest.java

License:Open Source License

@Test
public void test_compare_with_zero() {
    SymbolicValue sv = new SymbolicValue();
    int[] opcodes = { Opcodes.IFEQ, Opcodes.IFNE, Opcodes.IFLT, Opcodes.IFGE };
    for (int opcode : opcodes) {
        ProgramState programState = walker.branchingState(new Instruction(opcode),
                ProgramState.EMPTY_STATE.stackValue(sv));
        RelationalSymbolicValue relSV = (RelationalSymbolicValue) programState.peekValue();
        assertThat(relSV.getLeftOp()).isSameAs(sv);
        assertThat(relSV.getRightOp()).isNotSameAs(sv);
        assertThat(programState.getConstraints(relSV.getRightOp())
                .hasConstraint(DivisionByZeroCheck.ZeroConstraint.ZERO)).isTrue();
    }//from   www . ja  v a  2s.  c o m

    // these opcodes inverse operator and swap operands
    int[] swapOperandsOpcodes = { Opcodes.IFLE, Opcodes.IFGT };
    for (int opcode : swapOperandsOpcodes) {
        ProgramState programState = walker.branchingState(new Instruction(opcode),
                ProgramState.EMPTY_STATE.stackValue(sv));
        RelationalSymbolicValue relSV = (RelationalSymbolicValue) programState.peekValue();
        assertThat(relSV.getRightOp()).isSameAs(sv);
        assertThat(relSV.getLeftOp()).isNotSameAs(sv);
        assertThat(programState.getConstraints(relSV.getLeftOp())
                .hasConstraint(DivisionByZeroCheck.ZeroConstraint.ZERO)).isTrue();
    }
}