private void prepareLeftOperand(
        BooleanOperator operation,
        Class<?> type,
        Class<?> leftType,
        Class<?> rightType,
        Label shortcutEvaluation) {
      if (leftType.isPrimitive()) {
        if (type != null) {
          castOrCoercePrimitive(LEFT_OPERAND, leftType, type);
        }
        return;
      }

      Label notNullLabel =
          jitLeftIsNull(
              type == null || leftType == type
                  ? jitNullSafeOperationStart()
                  : jitNullSafeCoercion(leftType, type));

      if (operation.isEquality() && !rightType.isPrimitive()) {
        // if (left == null) return right == null
        checkNullEquality();
      } else {
        // if (left == null) return false
        mv.visitInsn(ICONST_0);
      }

      mv.visitJumpInsn(GOTO, shortcutEvaluation);
      mv.visitLabel(notNullLabel);
    }
    private void jitObjectBinary(
        SingleCondition singleCondition, Expression left, Expression right, Class<?> type) {
      Class<?> leftType =
          isDeclarationExpression(left) ? convertFromPrimitiveType(left.getType()) : left.getType();
      Class<?> rightType =
          isDeclarationExpression(right)
              ? convertFromPrimitiveType(right.getType())
              : right.getType();

      jitExpression(left, type != null ? type : leftType);
      if (isDeclarationExpression(left) && left.getType().isPrimitive()) {
        castFromPrimitive(left.getType());
      }
      store(LEFT_OPERAND, leftType);

      jitExpression(right, type != null ? type : rightType);
      if (isDeclarationExpression(right) && right.getType().isPrimitive()) {
        castFromPrimitive(right.getType());
      }
      store(RIGHT_OPERAND, rightType);

      Label shortcutEvaluation = new Label();
      BooleanOperator operation = singleCondition.getOperation();
      prepareLeftOperand(operation, type, leftType, rightType, shortcutEvaluation);
      prepareRightOperand(right, type, rightType, shortcutEvaluation);

      load(LEFT_OPERAND);
      load(RIGHT_OPERAND);

      switch (operation) {
        case CONTAINS:
          invokeStatic(
              EvaluatorHelper.class,
              "contains",
              boolean.class,
              Object.class,
              rightType.isPrimitive() ? rightType : Object.class);
          break;
        case MATCHES:
          invokeVirtual(type, "matches", boolean.class, String.class);
          break;
        case SOUNDSLIKE:
          invokeStatic(
              EvaluatorHelper.class, "soundslike", boolean.class, String.class, String.class);
          break;
        default:
          if (operation.isEquality()) {
            if (type.isInterface()) {
              invokeInterface(type, "equals", boolean.class, Object.class);
            } else {
              invokeVirtual(type, "equals", boolean.class, Object.class);
            }
            if (operation == BooleanOperator.NE) {
              singleCondition.toggleNegation();
            }
          } else {
            if (type.isInterface()) {
              invokeInterface(
                  type, "compareTo", int.class, type == Comparable.class ? Object.class : type);
            } else {
              invokeVirtual(type, "compareTo", int.class, type);
            }
            mv.visitInsn(ICONST_0);
            jitPrimitiveOperation(operation, int.class);
          }
      }

      mv.visitLabel(shortcutEvaluation);
    }