@Override
public void generateCode(MethodVisitor mv, CodeFlow cf) {
String leftDesc = getLeftOperand().exitTypeDescriptor;
String rightDesc = getRightOperand().exitTypeDescriptor;
Label elseTarget = new Label();
Label endOfIf = new Label();
boolean leftPrim = CodeFlow.isPrimitive(leftDesc);
boolean rightPrim = CodeFlow.isPrimitive(rightDesc);
DescriptorComparison dc = DescriptorComparison.checkNumericCompatibility(leftDesc, rightDesc,
this.leftActualDescriptor, this.rightActualDescriptor);
if (dc.areNumbers && dc.areCompatible) {
char targetType = dc.compatibleType;
getLeftOperand().generateCode(mv, cf);
if (!leftPrim) {
CodeFlow.insertUnboxInsns(mv, targetType, leftDesc);
}
cf.enterCompilationScope();
getRightOperand().generateCode(mv, cf);
cf.exitCompilationScope();
if (!rightPrim) {
CodeFlow.insertUnboxInsns(mv, targetType, rightDesc);
}
// assert: SpelCompiler.boxingCompatible(leftDesc, rightDesc)
if (targetType=='D') {
mv.visitInsn(DCMPL);
mv.visitJumpInsn(IFNE, elseTarget);
}
else if (targetType=='F') {
mv.visitInsn(FCMPL);
mv.visitJumpInsn(IFNE, elseTarget);
}
else if (targetType=='J') {
mv.visitInsn(LCMP);
mv.visitJumpInsn(IFNE, elseTarget);
}
else if (targetType=='I' || targetType=='Z') {
mv.visitJumpInsn(IF_ICMPNE, elseTarget);
}
else {
throw new IllegalStateException("Unexpected descriptor "+leftDesc);
}
}
else {
getLeftOperand().generateCode(mv, cf);
getRightOperand().generateCode(mv, cf);
Label leftNotNull = new Label();
mv.visitInsn(DUP_X1); // Dup right on the top of the stack
mv.visitJumpInsn(IFNONNULL,leftNotNull);
// Right is null!
mv.visitInsn(SWAP);
mv.visitInsn(POP); // remove it
Label rightNotNull = new Label();
mv.visitJumpInsn(IFNONNULL, rightNotNull);
// Left is null too
mv.visitInsn(ICONST_1);
mv.visitJumpInsn(GOTO, endOfIf);
mv.visitLabel(rightNotNull);