Home | History | Annotate | Download | only in compiler
      1 // Copyright 2016 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compiler/operation-typer.h"
      6 
      7 #include "src/compiler/common-operator.h"
      8 #include "src/compiler/type-cache.h"
      9 #include "src/compiler/types.h"
     10 #include "src/heap/factory.h"
     11 #include "src/isolate.h"
     12 
     13 #include "src/objects-inl.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 OperationTyper::OperationTyper(Isolate* isolate, JSHeapBroker* js_heap_broker,
     20                                Zone* zone)
     21     : zone_(zone), cache_(TypeCache::Get()) {
     22   Factory* factory = isolate->factory();
     23   infinity_ =
     24       Type::NewConstant(js_heap_broker, factory->infinity_value(), zone);
     25   minus_infinity_ =
     26       Type::NewConstant(js_heap_broker, factory->minus_infinity_value(), zone);
     27   Type truncating_to_zero = Type::MinusZeroOrNaN();
     28   DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
     29 
     30   singleton_empty_string_ =
     31       Type::HeapConstant(js_heap_broker, factory->empty_string(), zone);
     32   singleton_NaN_string_ =
     33       Type::HeapConstant(js_heap_broker, factory->NaN_string(), zone);
     34   singleton_zero_string_ =
     35       Type::HeapConstant(js_heap_broker, factory->zero_string(), zone);
     36   singleton_false_ =
     37       Type::HeapConstant(js_heap_broker, factory->false_value(), zone);
     38   singleton_true_ =
     39       Type::HeapConstant(js_heap_broker, factory->true_value(), zone);
     40   singleton_the_hole_ =
     41       Type::HeapConstant(js_heap_broker, factory->the_hole_value(), zone);
     42   signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
     43   unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
     44 
     45   falsish_ = Type::Union(
     46       Type::Undetectable(),
     47       Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
     48                   Type::Union(singleton_empty_string_, Type::Hole(), zone),
     49                   zone),
     50       zone);
     51   truish_ = Type::Union(
     52       singleton_true_,
     53       Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
     54 }
     55 
     56 Type OperationTyper::Merge(Type left, Type right) {
     57   return Type::Union(left, right, zone());
     58 }
     59 
     60 Type OperationTyper::WeakenRange(Type previous_range, Type current_range) {
     61   static const double kWeakenMinLimits[] = {0.0,
     62                                             -1073741824.0,
     63                                             -2147483648.0,
     64                                             -4294967296.0,
     65                                             -8589934592.0,
     66                                             -17179869184.0,
     67                                             -34359738368.0,
     68                                             -68719476736.0,
     69                                             -137438953472.0,
     70                                             -274877906944.0,
     71                                             -549755813888.0,
     72                                             -1099511627776.0,
     73                                             -2199023255552.0,
     74                                             -4398046511104.0,
     75                                             -8796093022208.0,
     76                                             -17592186044416.0,
     77                                             -35184372088832.0,
     78                                             -70368744177664.0,
     79                                             -140737488355328.0,
     80                                             -281474976710656.0,
     81                                             -562949953421312.0};
     82   static const double kWeakenMaxLimits[] = {0.0,
     83                                             1073741823.0,
     84                                             2147483647.0,
     85                                             4294967295.0,
     86                                             8589934591.0,
     87                                             17179869183.0,
     88                                             34359738367.0,
     89                                             68719476735.0,
     90                                             137438953471.0,
     91                                             274877906943.0,
     92                                             549755813887.0,
     93                                             1099511627775.0,
     94                                             2199023255551.0,
     95                                             4398046511103.0,
     96                                             8796093022207.0,
     97                                             17592186044415.0,
     98                                             35184372088831.0,
     99                                             70368744177663.0,
    100                                             140737488355327.0,
    101                                             281474976710655.0,
    102                                             562949953421311.0};
    103   STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
    104 
    105   double current_min = current_range.Min();
    106   double new_min = current_min;
    107   // Find the closest lower entry in the list of allowed
    108   // minima (or negative infinity if there is no such entry).
    109   if (current_min != previous_range.Min()) {
    110     new_min = -V8_INFINITY;
    111     for (double const min : kWeakenMinLimits) {
    112       if (min <= current_min) {
    113         new_min = min;
    114         break;
    115       }
    116     }
    117   }
    118 
    119   double current_max = current_range.Max();
    120   double new_max = current_max;
    121   // Find the closest greater entry in the list of allowed
    122   // maxima (or infinity if there is no such entry).
    123   if (current_max != previous_range.Max()) {
    124     new_max = V8_INFINITY;
    125     for (double const max : kWeakenMaxLimits) {
    126       if (max >= current_max) {
    127         new_max = max;
    128         break;
    129       }
    130     }
    131   }
    132 
    133   return Type::Range(new_min, new_max, zone());
    134 }
    135 
    136 Type OperationTyper::Rangify(Type type) {
    137   if (type.IsRange()) return type;  // Shortcut.
    138   if (!type.Is(cache_.kInteger)) {
    139     return type;  // Give up on non-integer types.
    140   }
    141   return Type::Range(type.Min(), type.Max(), zone());
    142 }
    143 
    144 namespace {
    145 
    146 // Returns the array's least element, ignoring NaN.
    147 // There must be at least one non-NaN element.
    148 // Any -0 is converted to 0.
    149 double array_min(double a[], size_t n) {
    150   DCHECK_NE(0, n);
    151   double x = +V8_INFINITY;
    152   for (size_t i = 0; i < n; ++i) {
    153     if (!std::isnan(a[i])) {
    154       x = std::min(a[i], x);
    155     }
    156   }
    157   DCHECK(!std::isnan(x));
    158   return x == 0 ? 0 : x;  // -0 -> 0
    159 }
    160 
    161 // Returns the array's greatest element, ignoring NaN.
    162 // There must be at least one non-NaN element.
    163 // Any -0 is converted to 0.
    164 double array_max(double a[], size_t n) {
    165   DCHECK_NE(0, n);
    166   double x = -V8_INFINITY;
    167   for (size_t i = 0; i < n; ++i) {
    168     if (!std::isnan(a[i])) {
    169       x = std::max(a[i], x);
    170     }
    171   }
    172   DCHECK(!std::isnan(x));
    173   return x == 0 ? 0 : x;  // -0 -> 0
    174 }
    175 
    176 }  // namespace
    177 
    178 Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
    179                                double rhs_max) {
    180   double results[4];
    181   results[0] = lhs_min + rhs_min;
    182   results[1] = lhs_min + rhs_max;
    183   results[2] = lhs_max + rhs_min;
    184   results[3] = lhs_max + rhs_max;
    185   // Since none of the inputs can be -0, the result cannot be -0 either.
    186   // However, it can be nan (the sum of two infinities of opposite sign).
    187   // On the other hand, if none of the "results" above is nan, then the
    188   // actual result cannot be nan either.
    189   int nans = 0;
    190   for (int i = 0; i < 4; ++i) {
    191     if (std::isnan(results[i])) ++nans;
    192   }
    193   if (nans == 4) return Type::NaN();
    194   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
    195   if (nans > 0) type = Type::Union(type, Type::NaN(), zone());
    196   // Examples:
    197   //   [-inf, -inf] + [+inf, +inf] = NaN
    198   //   [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
    199   //   [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
    200   //   [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
    201   return type;
    202 }
    203 
    204 Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
    205                                     double rhs_min, double rhs_max) {
    206   double results[4];
    207   results[0] = lhs_min - rhs_min;
    208   results[1] = lhs_min - rhs_max;
    209   results[2] = lhs_max - rhs_min;
    210   results[3] = lhs_max - rhs_max;
    211   // Since none of the inputs can be -0, the result cannot be -0.
    212   // However, it can be nan (the subtraction of two infinities of same sign).
    213   // On the other hand, if none of the "results" above is nan, then the actual
    214   // result cannot be nan either.
    215   int nans = 0;
    216   for (int i = 0; i < 4; ++i) {
    217     if (std::isnan(results[i])) ++nans;
    218   }
    219   if (nans == 4) return Type::NaN();  // [inf..inf] - [inf..inf] (all same sign)
    220   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
    221   return nans == 0 ? type : Type::Union(type, Type::NaN(), zone());
    222   // Examples:
    223   //   [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
    224   //   [-inf, -inf] - [-inf, -inf] = NaN
    225   //   [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
    226   //   [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
    227 }
    228 
    229 Type OperationTyper::MultiplyRanger(Type lhs, Type rhs) {
    230   double results[4];
    231   double lmin = lhs.AsRange()->Min();
    232   double lmax = lhs.AsRange()->Max();
    233   double rmin = rhs.AsRange()->Min();
    234   double rmax = rhs.AsRange()->Max();
    235   results[0] = lmin * rmin;
    236   results[1] = lmin * rmax;
    237   results[2] = lmax * rmin;
    238   results[3] = lmax * rmax;
    239   // If the result may be nan, we give up on calculating a precise type, because
    240   // the discontinuity makes it too complicated.  Note that even if none of the
    241   // "results" above is nan, the actual result may still be, so we have to do a
    242   // different check:
    243   bool maybe_nan = (lhs.Maybe(cache_.kSingletonZero) &&
    244                     (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) ||
    245                    (rhs.Maybe(cache_.kSingletonZero) &&
    246                     (lmin == -V8_INFINITY || lmax == +V8_INFINITY));
    247   if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN;  // Giving up.
    248   bool maybe_minuszero = (lhs.Maybe(cache_.kSingletonZero) && rmin < 0) ||
    249                          (rhs.Maybe(cache_.kSingletonZero) && lmin < 0);
    250   Type range =
    251       Type::Range(array_min(results, 4), array_max(results, 4), zone());
    252   return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone())
    253                          : range;
    254 }
    255 
    256 Type OperationTyper::ConvertReceiver(Type type) {
    257   if (type.Is(Type::Receiver())) return type;
    258   bool const maybe_primitive = type.Maybe(Type::Primitive());
    259   type = Type::Intersect(type, Type::Receiver(), zone());
    260   if (maybe_primitive) {
    261     // ConvertReceiver maps null and undefined to the JSGlobalProxy of the
    262     // target function, and all other primitives are wrapped into a JSValue.
    263     type = Type::Union(type, Type::OtherObject(), zone());
    264   }
    265   return type;
    266 }
    267 
    268 // Returns the result type of converting {type} to number, if the
    269 // result does not depend on conversion options.
    270 base::Optional<Type> OperationTyper::ToNumberCommon(Type type) {
    271   if (type.Is(Type::Number())) return type;
    272   if (type.Is(Type::NullOrUndefined())) {
    273     if (type.Is(Type::Null())) return cache_.kSingletonZero;
    274     if (type.Is(Type::Undefined())) return Type::NaN();
    275     return Type::Union(Type::NaN(), cache_.kSingletonZero, zone());
    276   }
    277   if (type.Is(Type::Boolean())) {
    278     if (type.Is(singleton_false_)) return cache_.kSingletonZero;
    279     if (type.Is(singleton_true_)) return cache_.kSingletonOne;
    280     return cache_.kZeroOrOne;
    281   }
    282   if (type.Is(Type::NumberOrOddball())) {
    283     if (type.Is(Type::NumberOrUndefined())) {
    284       type = Type::Union(type, Type::NaN(), zone());
    285     } else if (type.Is(Type::NullOrNumber())) {
    286       type = Type::Union(type, cache_.kSingletonZero, zone());
    287     } else if (type.Is(Type::BooleanOrNullOrNumber())) {
    288       type = Type::Union(type, cache_.kZeroOrOne, zone());
    289     } else {
    290       type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone());
    291     }
    292     return Type::Intersect(type, Type::Number(), zone());
    293   }
    294   return base::Optional<Type>();
    295 }
    296 
    297 Type OperationTyper::ToNumberOrNumeric(Object::Conversion mode, Type type) {
    298   if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) {
    299     return *maybe_result_type;
    300   }
    301   if (type.Is(Type::BigInt())) {
    302     return mode == Object::Conversion::kToNumber ? Type::None() : type;
    303   }
    304   return mode == Object::Conversion::kToNumber ? Type::Number()
    305                                                : Type::Numeric();
    306 }
    307 
    308 Type OperationTyper::ToNumber(Type type) {
    309   return ToNumberOrNumeric(Object::Conversion::kToNumber, type);
    310 }
    311 
    312 Type OperationTyper::ToNumberConvertBigInt(Type type) {
    313   if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) {
    314     return *maybe_result_type;
    315   }
    316   return Type::Number();
    317 }
    318 
    319 Type OperationTyper::ToNumeric(Type type) {
    320   return ToNumberOrNumeric(Object::Conversion::kToNumeric, type);
    321 }
    322 
    323 Type OperationTyper::NumberAbs(Type type) {
    324   DCHECK(type.Is(Type::Number()));
    325   if (type.IsNone()) return type;
    326 
    327   bool const maybe_nan = type.Maybe(Type::NaN());
    328   bool const maybe_minuszero = type.Maybe(Type::MinusZero());
    329 
    330   type = Type::Intersect(type, Type::PlainNumber(), zone());
    331   if (!type.IsNone()) {
    332     double const max = type.Max();
    333     double const min = type.Min();
    334     if (min < 0) {
    335       if (type.Is(cache_.kInteger)) {
    336         type =
    337             Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
    338       } else {
    339         type = Type::PlainNumber();
    340       }
    341     }
    342   }
    343 
    344   if (maybe_minuszero) {
    345     type = Type::Union(type, cache_.kSingletonZero, zone());
    346   }
    347   if (maybe_nan) {
    348     type = Type::Union(type, Type::NaN(), zone());
    349   }
    350   return type;
    351 }
    352 
    353 Type OperationTyper::NumberAcos(Type type) {
    354   DCHECK(type.Is(Type::Number()));
    355   return Type::Number();
    356 }
    357 
    358 Type OperationTyper::NumberAcosh(Type type) {
    359   DCHECK(type.Is(Type::Number()));
    360   return Type::Number();
    361 }
    362 
    363 Type OperationTyper::NumberAsin(Type type) {
    364   DCHECK(type.Is(Type::Number()));
    365   return Type::Number();
    366 }
    367 
    368 Type OperationTyper::NumberAsinh(Type type) {
    369   DCHECK(type.Is(Type::Number()));
    370   return Type::Number();
    371 }
    372 
    373 Type OperationTyper::NumberAtan(Type type) {
    374   DCHECK(type.Is(Type::Number()));
    375   return Type::Number();
    376 }
    377 
    378 Type OperationTyper::NumberAtanh(Type type) {
    379   DCHECK(type.Is(Type::Number()));
    380   return Type::Number();
    381 }
    382 
    383 Type OperationTyper::NumberCbrt(Type type) {
    384   DCHECK(type.Is(Type::Number()));
    385   return Type::Number();
    386 }
    387 
    388 Type OperationTyper::NumberCeil(Type type) {
    389   DCHECK(type.Is(Type::Number()));
    390   if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
    391   type = Type::Intersect(type, Type::NaN(), zone());
    392   type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
    393   return type;
    394 }
    395 
    396 Type OperationTyper::NumberClz32(Type type) {
    397   DCHECK(type.Is(Type::Number()));
    398   return cache_.kZeroToThirtyTwo;
    399 }
    400 
    401 Type OperationTyper::NumberCos(Type type) {
    402   DCHECK(type.Is(Type::Number()));
    403   return Type::Number();
    404 }
    405 
    406 Type OperationTyper::NumberCosh(Type type) {
    407   DCHECK(type.Is(Type::Number()));
    408   return Type::Number();
    409 }
    410 
    411 Type OperationTyper::NumberExp(Type type) {
    412   DCHECK(type.Is(Type::Number()));
    413   return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
    414 }
    415 
    416 Type OperationTyper::NumberExpm1(Type type) {
    417   DCHECK(type.Is(Type::Number()));
    418   return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
    419 }
    420 
    421 Type OperationTyper::NumberFloor(Type type) {
    422   DCHECK(type.Is(Type::Number()));
    423   if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
    424   type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
    425   type = Type::Union(type, cache_.kInteger, zone());
    426   return type;
    427 }
    428 
    429 Type OperationTyper::NumberFround(Type type) {
    430   DCHECK(type.Is(Type::Number()));
    431   return Type::Number();
    432 }
    433 
    434 Type OperationTyper::NumberLog(Type type) {
    435   DCHECK(type.Is(Type::Number()));
    436   return Type::Number();
    437 }
    438 
    439 Type OperationTyper::NumberLog1p(Type type) {
    440   DCHECK(type.Is(Type::Number()));
    441   return Type::Number();
    442 }
    443 
    444 Type OperationTyper::NumberLog2(Type type) {
    445   DCHECK(type.Is(Type::Number()));
    446   return Type::Number();
    447 }
    448 
    449 Type OperationTyper::NumberLog10(Type type) {
    450   DCHECK(type.Is(Type::Number()));
    451   return Type::Number();
    452 }
    453 
    454 Type OperationTyper::NumberRound(Type type) {
    455   DCHECK(type.Is(Type::Number()));
    456   if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
    457   type = Type::Intersect(type, Type::NaN(), zone());
    458   type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
    459   return type;
    460 }
    461 
    462 Type OperationTyper::NumberSign(Type type) {
    463   DCHECK(type.Is(Type::Number()));
    464   if (type.Is(cache_.kZeroish)) return type;
    465   bool maybe_minuszero = type.Maybe(Type::MinusZero());
    466   bool maybe_nan = type.Maybe(Type::NaN());
    467   type = Type::Intersect(type, Type::PlainNumber(), zone());
    468   if (type.IsNone()) {
    469     // Do nothing.
    470   } else if (type.Max() < 0.0) {
    471     type = cache_.kSingletonMinusOne;
    472   } else if (type.Max() <= 0.0) {
    473     type = cache_.kMinusOneOrZero;
    474   } else if (type.Min() > 0.0) {
    475     type = cache_.kSingletonOne;
    476   } else if (type.Min() >= 0.0) {
    477     type = cache_.kZeroOrOne;
    478   } else {
    479     type = Type::Range(-1.0, 1.0, zone());
    480   }
    481   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
    482   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
    483   DCHECK(!type.IsNone());
    484   return type;
    485 }
    486 
    487 Type OperationTyper::NumberSin(Type type) {
    488   DCHECK(type.Is(Type::Number()));
    489   return Type::Number();
    490 }
    491 
    492 Type OperationTyper::NumberSinh(Type type) {
    493   DCHECK(type.Is(Type::Number()));
    494   return Type::Number();
    495 }
    496 
    497 Type OperationTyper::NumberSqrt(Type type) {
    498   DCHECK(type.Is(Type::Number()));
    499   return Type::Number();
    500 }
    501 
    502 Type OperationTyper::NumberTan(Type type) {
    503   DCHECK(type.Is(Type::Number()));
    504   return Type::Number();
    505 }
    506 
    507 Type OperationTyper::NumberTanh(Type type) {
    508   DCHECK(type.Is(Type::Number()));
    509   return Type::Number();
    510 }
    511 
    512 Type OperationTyper::NumberTrunc(Type type) {
    513   DCHECK(type.Is(Type::Number()));
    514   if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
    515   type = Type::Intersect(type, Type::NaN(), zone());
    516   type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
    517   return type;
    518 }
    519 
    520 Type OperationTyper::NumberToBoolean(Type type) {
    521   DCHECK(type.Is(Type::Number()));
    522   if (type.IsNone()) return type;
    523   if (type.Is(cache_.kZeroish)) return singleton_false_;
    524   if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
    525     return singleton_true_;  // Ruled out nan, -0 and +0.
    526   }
    527   return Type::Boolean();
    528 }
    529 
    530 Type OperationTyper::NumberToInt32(Type type) {
    531   DCHECK(type.Is(Type::Number()));
    532 
    533   if (type.Is(Type::Signed32())) return type;
    534   if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
    535   if (type.Is(signed32ish_)) {
    536     return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
    537                            Type::Signed32(), zone());
    538   }
    539   return Type::Signed32();
    540 }
    541 
    542 Type OperationTyper::NumberToString(Type type) {
    543   DCHECK(type.Is(Type::Number()));
    544   if (type.IsNone()) return type;
    545   if (type.Is(Type::NaN())) return singleton_NaN_string_;
    546   if (type.Is(cache_.kZeroOrMinusZero)) return singleton_zero_string_;
    547   return Type::String();
    548 }
    549 
    550 Type OperationTyper::NumberToUint32(Type type) {
    551   DCHECK(type.Is(Type::Number()));
    552 
    553   if (type.Is(Type::Unsigned32())) return type;
    554   if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
    555   if (type.Is(unsigned32ish_)) {
    556     return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
    557                            Type::Unsigned32(), zone());
    558   }
    559   return Type::Unsigned32();
    560 }
    561 
    562 Type OperationTyper::NumberToUint8Clamped(Type type) {
    563   DCHECK(type.Is(Type::Number()));
    564 
    565   if (type.Is(cache_.kUint8)) return type;
    566   return cache_.kUint8;
    567 }
    568 
    569 Type OperationTyper::NumberSilenceNaN(Type type) {
    570   DCHECK(type.Is(Type::Number()));
    571   // TODO(jarin): This is a terrible hack; we definitely need a dedicated type
    572   // for the hole (tagged and/or double). Otherwise if the input is the hole
    573   // NaN constant, we'd just eliminate this node in JSTypedLowering.
    574   if (type.Maybe(Type::NaN())) return Type::Number();
    575   return type;
    576 }
    577 
    578 Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
    579   DCHECK(lhs.Is(Type::Number()));
    580   DCHECK(rhs.Is(Type::Number()));
    581 
    582   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    583 
    584   // Addition can return NaN if either input can be NaN or we try to compute
    585   // the sum of two infinities of opposite sign.
    586   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
    587 
    588   // Addition can yield minus zero only if both inputs can be minus zero.
    589   bool maybe_minuszero = true;
    590   if (lhs.Maybe(Type::MinusZero())) {
    591     lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
    592   } else {
    593     maybe_minuszero = false;
    594   }
    595   if (rhs.Maybe(Type::MinusZero())) {
    596     rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
    597   } else {
    598     maybe_minuszero = false;
    599   }
    600 
    601   // We can give more precise types for integers.
    602   Type type = Type::None();
    603   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
    604   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
    605   if (!lhs.IsNone() && !rhs.IsNone()) {
    606     if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
    607       type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
    608     } else {
    609       if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
    610           (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) {
    611         maybe_nan = true;
    612       }
    613       type = Type::PlainNumber();
    614     }
    615   }
    616 
    617   // Take into account the -0 and NaN information computed earlier.
    618   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
    619   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
    620   return type;
    621 }
    622 
    623 Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
    624   DCHECK(lhs.Is(Type::Number()));
    625   DCHECK(rhs.Is(Type::Number()));
    626 
    627   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    628 
    629   // Subtraction can return NaN if either input can be NaN or we try to
    630   // compute the sum of two infinities of opposite sign.
    631   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
    632 
    633   // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs}
    634   // can be zero.
    635   bool maybe_minuszero = false;
    636   if (lhs.Maybe(Type::MinusZero())) {
    637     lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
    638     maybe_minuszero = rhs.Maybe(cache_.kSingletonZero);
    639   }
    640   if (rhs.Maybe(Type::MinusZero())) {
    641     rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
    642   }
    643 
    644   // We can give more precise types for integers.
    645   Type type = Type::None();
    646   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
    647   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
    648   if (!lhs.IsNone() && !rhs.IsNone()) {
    649     if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
    650       type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
    651     } else {
    652       if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
    653           (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) {
    654         maybe_nan = true;
    655       }
    656       type = Type::PlainNumber();
    657     }
    658   }
    659 
    660   // Take into account the -0 and NaN information computed earlier.
    661   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
    662   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
    663   return type;
    664 }
    665 
    666 Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
    667   Type result = SpeculativeNumberAdd(lhs, rhs);
    668   // If we have a Smi or Int32 feedback, the representation selection will
    669   // either truncate or it will check the inputs (i.e., deopt if not int32).
    670   // In either case the result will be in the safe integer range, so we
    671   // can bake in the type here. This needs to be in sync with
    672   // SimplifiedLowering::VisitSpeculativeAdditiveOp.
    673   return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
    674 }
    675 
    676 Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
    677   Type result = SpeculativeNumberSubtract(lhs, rhs);
    678   // If we have a Smi or Int32 feedback, the representation selection will
    679   // either truncate or it will check the inputs (i.e., deopt if not int32).
    680   // In either case the result will be in the safe integer range, so we
    681   // can bake in the type here. This needs to be in sync with
    682   // SimplifiedLowering::VisitSpeculativeAdditiveOp.
    683   return result = Type::Intersect(result, cache_.kSafeInteger, zone());
    684 }
    685 
    686 Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
    687   DCHECK(lhs.Is(Type::Number()));
    688   DCHECK(rhs.Is(Type::Number()));
    689 
    690   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    691 
    692   lhs = Rangify(lhs);
    693   rhs = Rangify(rhs);
    694   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    695   if (lhs.IsRange() && rhs.IsRange()) {
    696     return MultiplyRanger(lhs, rhs);
    697   }
    698   return Type::Number();
    699 }
    700 
    701 Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
    702   DCHECK(lhs.Is(Type::Number()));
    703   DCHECK(rhs.Is(Type::Number()));
    704 
    705   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    706   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    707 
    708   // Division is tricky, so all we do is try ruling out -0 and NaN.
    709   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
    710                    ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
    711                     (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
    712   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
    713   DCHECK(!lhs.IsNone());
    714   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
    715   DCHECK(!rhs.IsNone());
    716 
    717   // Try to rule out -0.
    718   bool maybe_minuszero =
    719       !lhs.Is(cache_.kInteger) ||
    720       (lhs.Maybe(cache_.kZeroish) && rhs.Min() < 0.0) ||
    721       (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY);
    722 
    723   // Take into account the -0 and NaN information computed earlier.
    724   Type type = Type::PlainNumber();
    725   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
    726   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
    727   return type;
    728 }
    729 
    730 Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
    731   DCHECK(lhs.Is(Type::Number()));
    732   DCHECK(rhs.Is(Type::Number()));
    733 
    734   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    735 
    736   // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or
    737   // {lhs} is not finite, or the {rhs} is a zero value.
    738   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
    739                    lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY;
    740 
    741   // Deal with -0 inputs, only the signbit of {lhs} matters for the result.
    742   bool maybe_minuszero = false;
    743   if (lhs.Maybe(Type::MinusZero())) {
    744     maybe_minuszero = true;
    745     lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
    746   }
    747   if (rhs.Maybe(Type::MinusZero())) {
    748     rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
    749   }
    750 
    751   // Rule out NaN and -0, and check what we can do with the remaining type info.
    752   Type type = Type::None();
    753   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
    754   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
    755 
    756   // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited,
    757   // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}.
    758   if (!lhs.IsNone() && !rhs.Is(cache_.kSingletonZero)) {
    759     // Determine the bounds of {lhs} and {rhs}.
    760     double const lmin = lhs.Min();
    761     double const lmax = lhs.Max();
    762     double const rmin = rhs.Min();
    763     double const rmax = rhs.Max();
    764 
    765     // The sign of the result is the sign of the {lhs}.
    766     if (lmin < 0.0) maybe_minuszero = true;
    767 
    768     // For integer inputs {lhs} and {rhs} we can infer a precise type.
    769     if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
    770       double labs = std::max(std::abs(lmin), std::abs(lmax));
    771       double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
    772       double abs = std::min(labs, rabs);
    773       double min = 0.0, max = 0.0;
    774       if (lmin >= 0.0) {
    775         // {lhs} positive.
    776         min = 0.0;
    777         max = abs;
    778       } else if (lmax <= 0.0) {
    779         // {lhs} negative.
    780         min = 0.0 - abs;
    781         max = 0.0;
    782       } else {
    783         // {lhs} positive or negative.
    784         min = 0.0 - abs;
    785         max = abs;
    786       }
    787       type = Type::Range(min, max, zone());
    788     } else {
    789       type = Type::PlainNumber();
    790     }
    791   }
    792 
    793   // Take into account the -0 and NaN information computed earlier.
    794   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
    795   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
    796   return type;
    797 }
    798 
    799 Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
    800   DCHECK(lhs.Is(Type::Number()));
    801   DCHECK(rhs.Is(Type::Number()));
    802 
    803   lhs = NumberToInt32(lhs);
    804   rhs = NumberToInt32(rhs);
    805 
    806   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    807 
    808   double lmin = lhs.Min();
    809   double rmin = rhs.Min();
    810   double lmax = lhs.Max();
    811   double rmax = rhs.Max();
    812   // Or-ing any two values results in a value no smaller than their minimum.
    813   // Even no smaller than their maximum if both values are non-negative.
    814   double min =
    815       lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
    816   double max = kMaxInt;
    817 
    818   // Or-ing with 0 is essentially a conversion to int32.
    819   if (rmin == 0 && rmax == 0) {
    820     min = lmin;
    821     max = lmax;
    822   }
    823   if (lmin == 0 && lmax == 0) {
    824     min = rmin;
    825     max = rmax;
    826   }
    827 
    828   if (lmax < 0 || rmax < 0) {
    829     // Or-ing two values of which at least one is negative results in a negative
    830     // value.
    831     max = std::min(max, -1.0);
    832   }
    833   return Type::Range(min, max, zone());
    834 }
    835 
    836 Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
    837   DCHECK(lhs.Is(Type::Number()));
    838   DCHECK(rhs.Is(Type::Number()));
    839 
    840   lhs = NumberToInt32(lhs);
    841   rhs = NumberToInt32(rhs);
    842 
    843   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    844 
    845   double lmin = lhs.Min();
    846   double rmin = rhs.Min();
    847   double lmax = lhs.Max();
    848   double rmax = rhs.Max();
    849   double min = kMinInt;
    850   // And-ing any two values results in a value no larger than their maximum.
    851   // Even no larger than their minimum if both values are non-negative.
    852   double max =
    853       lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
    854   // And-ing with a non-negative value x causes the result to be between
    855   // zero and x.
    856   if (lmin >= 0) {
    857     min = 0;
    858     max = std::min(max, lmax);
    859   }
    860   if (rmin >= 0) {
    861     min = 0;
    862     max = std::min(max, rmax);
    863   }
    864   return Type::Range(min, max, zone());
    865 }
    866 
    867 Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
    868   DCHECK(lhs.Is(Type::Number()));
    869   DCHECK(rhs.Is(Type::Number()));
    870 
    871   lhs = NumberToInt32(lhs);
    872   rhs = NumberToInt32(rhs);
    873 
    874   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    875 
    876   double lmin = lhs.Min();
    877   double rmin = rhs.Min();
    878   double lmax = lhs.Max();
    879   double rmax = rhs.Max();
    880   if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
    881     // Xor-ing negative or non-negative values results in a non-negative value.
    882     return Type::Unsigned31();
    883   }
    884   if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
    885     // Xor-ing a negative and a non-negative value results in a negative value.
    886     // TODO(jarin) Use a range here.
    887     return Type::Negative32();
    888   }
    889   return Type::Signed32();
    890 }
    891 
    892 Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
    893   DCHECK(lhs.Is(Type::Number()));
    894   DCHECK(rhs.Is(Type::Number()));
    895 
    896   lhs = NumberToInt32(lhs);
    897   rhs = NumberToUint32(rhs);
    898 
    899   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    900 
    901   int32_t min_lhs = lhs.Min();
    902   int32_t max_lhs = lhs.Max();
    903   uint32_t min_rhs = rhs.Min();
    904   uint32_t max_rhs = rhs.Max();
    905   if (max_rhs > 31) {
    906     // rhs can be larger than the bitmask
    907     max_rhs = 31;
    908     min_rhs = 0;
    909   }
    910 
    911   if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
    912     // overflow possible
    913     return Type::Signed32();
    914   }
    915 
    916   double min =
    917       std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
    918                static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
    919   double max =
    920       std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
    921                static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
    922 
    923   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
    924   return Type::Range(min, max, zone());
    925 }
    926 
    927 Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
    928   DCHECK(lhs.Is(Type::Number()));
    929   DCHECK(rhs.Is(Type::Number()));
    930 
    931   lhs = NumberToInt32(lhs);
    932   rhs = NumberToUint32(rhs);
    933 
    934   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    935 
    936   int32_t min_lhs = lhs.Min();
    937   int32_t max_lhs = lhs.Max();
    938   uint32_t min_rhs = rhs.Min();
    939   uint32_t max_rhs = rhs.Max();
    940   if (max_rhs > 31) {
    941     // rhs can be larger than the bitmask
    942     max_rhs = 31;
    943     min_rhs = 0;
    944   }
    945   double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
    946   double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
    947 
    948   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
    949   return Type::Range(min, max, zone());
    950 }
    951 
    952 Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
    953   DCHECK(lhs.Is(Type::Number()));
    954   DCHECK(rhs.Is(Type::Number()));
    955 
    956   lhs = NumberToUint32(lhs);
    957   rhs = NumberToUint32(rhs);
    958 
    959   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    960 
    961   uint32_t min_lhs = lhs.Min();
    962   uint32_t max_lhs = lhs.Max();
    963   uint32_t min_rhs = rhs.Min();
    964   uint32_t max_rhs = rhs.Max();
    965   if (max_rhs > 31) {
    966     // rhs can be larger than the bitmask
    967     max_rhs = 31;
    968     min_rhs = 0;
    969   }
    970 
    971   double min = min_lhs >> max_rhs;
    972   double max = max_lhs >> min_rhs;
    973   DCHECK_LE(0, min);
    974   DCHECK_LE(max, kMaxUInt32);
    975 
    976   if (min == 0 && max == kMaxInt) return Type::Unsigned31();
    977   if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
    978   return Type::Range(min, max, zone());
    979 }
    980 
    981 Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
    982   DCHECK(lhs.Is(Type::Number()));
    983   DCHECK(rhs.Is(Type::Number()));
    984   return Type::Number();
    985 }
    986 
    987 Type OperationTyper::NumberImul(Type lhs, Type rhs) {
    988   DCHECK(lhs.Is(Type::Number()));
    989   DCHECK(rhs.Is(Type::Number()));
    990   // TODO(turbofan): We should be able to do better here.
    991   return Type::Signed32();
    992 }
    993 
    994 Type OperationTyper::NumberMax(Type lhs, Type rhs) {
    995   DCHECK(lhs.Is(Type::Number()));
    996   DCHECK(rhs.Is(Type::Number()));
    997 
    998   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    999   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
   1000 
   1001   Type type = Type::None();
   1002   // TODO(turbofan): Improve minus zero handling here.
   1003   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
   1004     type = Type::Union(type, Type::NaN(), zone());
   1005   }
   1006   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
   1007   DCHECK(!lhs.IsNone());
   1008   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
   1009   DCHECK(!rhs.IsNone());
   1010   if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
   1011     double max = std::max(lhs.Max(), rhs.Max());
   1012     double min = std::max(lhs.Min(), rhs.Min());
   1013     type = Type::Union(type, Type::Range(min, max, zone()), zone());
   1014   } else {
   1015     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
   1016   }
   1017   return type;
   1018 }
   1019 
   1020 Type OperationTyper::NumberMin(Type lhs, Type rhs) {
   1021   DCHECK(lhs.Is(Type::Number()));
   1022   DCHECK(rhs.Is(Type::Number()));
   1023 
   1024   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
   1025   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
   1026 
   1027   Type type = Type::None();
   1028   // TODO(turbofan): Improve minus zero handling here.
   1029   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
   1030     type = Type::Union(type, Type::NaN(), zone());
   1031   }
   1032   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
   1033   DCHECK(!lhs.IsNone());
   1034   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
   1035   DCHECK(!rhs.IsNone());
   1036   if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
   1037     double max = std::min(lhs.Max(), rhs.Max());
   1038     double min = std::min(lhs.Min(), rhs.Min());
   1039     type = Type::Union(type, Type::Range(min, max, zone()), zone());
   1040   } else {
   1041     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
   1042   }
   1043   return type;
   1044 }
   1045 
   1046 Type OperationTyper::NumberPow(Type lhs, Type rhs) {
   1047   DCHECK(lhs.Is(Type::Number()));
   1048   DCHECK(rhs.Is(Type::Number()));
   1049   // TODO(turbofan): We should be able to do better here.
   1050   return Type::Number();
   1051 }
   1052 
   1053 #define SPECULATIVE_NUMBER_BINOP(Name)                         \
   1054   Type OperationTyper::Speculative##Name(Type lhs, Type rhs) { \
   1055     lhs = SpeculativeToNumber(lhs);                            \
   1056     rhs = SpeculativeToNumber(rhs);                            \
   1057     return Name(lhs, rhs);                                     \
   1058   }
   1059 SPECULATIVE_NUMBER_BINOP(NumberAdd)
   1060 SPECULATIVE_NUMBER_BINOP(NumberSubtract)
   1061 SPECULATIVE_NUMBER_BINOP(NumberMultiply)
   1062 SPECULATIVE_NUMBER_BINOP(NumberDivide)
   1063 SPECULATIVE_NUMBER_BINOP(NumberModulus)
   1064 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
   1065 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
   1066 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
   1067 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
   1068 SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
   1069 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
   1070 #undef SPECULATIVE_NUMBER_BINOP
   1071 
   1072 Type OperationTyper::SpeculativeToNumber(Type type) {
   1073   return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
   1074 }
   1075 
   1076 Type OperationTyper::ToPrimitive(Type type) {
   1077   if (type.Is(Type::Primitive())) {
   1078     return type;
   1079   }
   1080   return Type::Primitive();
   1081 }
   1082 
   1083 Type OperationTyper::Invert(Type type) {
   1084   DCHECK(type.Is(Type::Boolean()));
   1085   DCHECK(!type.IsNone());
   1086   if (type.Is(singleton_false())) return singleton_true();
   1087   if (type.Is(singleton_true())) return singleton_false();
   1088   return type;
   1089 }
   1090 
   1091 OperationTyper::ComparisonOutcome OperationTyper::Invert(
   1092     ComparisonOutcome outcome) {
   1093   ComparisonOutcome result(0);
   1094   if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
   1095   if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
   1096   if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
   1097   return result;
   1098 }
   1099 
   1100 Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
   1101   if ((outcome & kComparisonFalse) != 0 ||
   1102       (outcome & kComparisonUndefined) != 0) {
   1103     return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
   1104                                             : singleton_false();
   1105   }
   1106   // Type should be non empty, so we know it should be true.
   1107   DCHECK_NE(0, outcome & kComparisonTrue);
   1108   return singleton_true();
   1109 }
   1110 
   1111 namespace {
   1112 
   1113 Type JSType(Type type) {
   1114   if (type.Is(Type::Boolean())) return Type::Boolean();
   1115   if (type.Is(Type::String())) return Type::String();
   1116   if (type.Is(Type::Number())) return Type::Number();
   1117   if (type.Is(Type::BigInt())) return Type::BigInt();
   1118   if (type.Is(Type::Undefined())) return Type::Undefined();
   1119   if (type.Is(Type::Null())) return Type::Null();
   1120   if (type.Is(Type::Symbol())) return Type::Symbol();
   1121   if (type.Is(Type::Receiver())) return Type::Receiver();  // JS "Object"
   1122   return Type::Any();
   1123 }
   1124 
   1125 }  // namespace
   1126 
   1127 Type OperationTyper::SameValue(Type lhs, Type rhs) {
   1128   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
   1129   if (lhs.Is(Type::NaN())) {
   1130     if (rhs.Is(Type::NaN())) return singleton_true();
   1131     if (!rhs.Maybe(Type::NaN())) return singleton_false();
   1132   } else if (rhs.Is(Type::NaN())) {
   1133     if (!lhs.Maybe(Type::NaN())) return singleton_false();
   1134   }
   1135   if (lhs.Is(Type::MinusZero())) {
   1136     if (rhs.Is(Type::MinusZero())) return singleton_true();
   1137     if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
   1138   } else if (rhs.Is(Type::MinusZero())) {
   1139     if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
   1140   }
   1141   if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
   1142       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
   1143     return singleton_false();
   1144   }
   1145   return Type::Boolean();
   1146 }
   1147 
   1148 Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
   1149   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
   1150   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
   1151   if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
   1152       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
   1153     return singleton_false();
   1154   }
   1155   if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
   1156     return singleton_false();
   1157   }
   1158   if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
   1159     // Types are equal and are inhabited only by a single semantic value,
   1160     // which is not nan due to the earlier check.
   1161     return singleton_true();
   1162   }
   1163   return Type::Boolean();
   1164 }
   1165 
   1166 Type OperationTyper::CheckFloat64Hole(Type type) {
   1167   if (type.Maybe(Type::Hole())) {
   1168     // Turn "the hole" into undefined.
   1169     type = Type::Intersect(type, Type::Number(), zone());
   1170     type = Type::Union(type, Type::Undefined(), zone());
   1171   }
   1172   return type;
   1173 }
   1174 
   1175 Type OperationTyper::CheckNumber(Type type) {
   1176   return Type::Intersect(type, Type::Number(), zone());
   1177 }
   1178 
   1179 Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
   1180   return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
   1181 }
   1182 
   1183 Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
   1184   if (input.Maybe(Type::Hole())) {
   1185     // Turn "the hole" into undefined.
   1186     Type type = Type::Intersect(input, Type::NonInternal(), zone());
   1187     return Type::Union(type, Type::Undefined(), zone());
   1188   }
   1189   return input;
   1190 }
   1191 
   1192 Type OperationTyper::ToBoolean(Type type) {
   1193   if (type.Is(Type::Boolean())) return type;
   1194   if (type.Is(falsish_)) return singleton_false_;
   1195   if (type.Is(truish_)) return singleton_true_;
   1196   if (type.Is(Type::Number())) {
   1197     return NumberToBoolean(type);
   1198   }
   1199   return Type::Boolean();
   1200 }
   1201 
   1202 }  // namespace compiler
   1203 }  // namespace internal
   1204 }  // namespace v8
   1205