LCOV - code coverage report
Current view: top level - src/compiler - operation-typer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 536 558 96.1 %
Date: 2019-01-20 Functions: 87 92 94.6 %

          Line data    Source code
       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     2737996 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
      20     1368995 :     : zone_(zone), cache_(TypeCache::Get()) {
      21             :   Factory* factory = broker->isolate()->factory();
      22     1369001 :   infinity_ = Type::NewConstant(V8_INFINITY, zone);
      23     1368995 :   minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
      24     1368995 :   Type truncating_to_zero = Type::MinusZeroOrNaN();
      25             :   DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
      26             : 
      27             :   singleton_empty_string_ =
      28     1368995 :       Type::HeapConstant(broker, factory->empty_string(), zone);
      29             :   singleton_NaN_string_ =
      30     1369001 :       Type::HeapConstant(broker, factory->NaN_string(), zone);
      31             :   singleton_zero_string_ =
      32     1369009 :       Type::HeapConstant(broker, factory->zero_string(), zone);
      33     1369006 :   singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
      34     1369009 :   singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
      35             :   singleton_the_hole_ =
      36     1369006 :       Type::HeapConstant(broker, factory->the_hole_value(), zone);
      37     1369011 :   signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
      38     1369009 :   unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
      39             : 
      40             :   falsish_ = Type::Union(
      41             :       Type::Undetectable(),
      42             :       Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
      43             :                   Type::Union(singleton_empty_string_, Type::Hole(), zone),
      44             :                   zone),
      45     1369008 :       zone);
      46             :   truish_ = Type::Union(
      47             :       singleton_true_,
      48     1369012 :       Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
      49     1369014 : }
      50             : 
      51     1140711 : Type OperationTyper::Merge(Type left, Type right) {
      52     1140711 :   return Type::Union(left, right, zone());
      53             : }
      54             : 
      55      867994 : Type OperationTyper::WeakenRange(Type previous_range, Type current_range) {
      56             :   static const double kWeakenMinLimits[] = {0.0,
      57             :                                             -1073741824.0,
      58             :                                             -2147483648.0,
      59             :                                             -4294967296.0,
      60             :                                             -8589934592.0,
      61             :                                             -17179869184.0,
      62             :                                             -34359738368.0,
      63             :                                             -68719476736.0,
      64             :                                             -137438953472.0,
      65             :                                             -274877906944.0,
      66             :                                             -549755813888.0,
      67             :                                             -1099511627776.0,
      68             :                                             -2199023255552.0,
      69             :                                             -4398046511104.0,
      70             :                                             -8796093022208.0,
      71             :                                             -17592186044416.0,
      72             :                                             -35184372088832.0,
      73             :                                             -70368744177664.0,
      74             :                                             -140737488355328.0,
      75             :                                             -281474976710656.0,
      76             :                                             -562949953421312.0};
      77             :   static const double kWeakenMaxLimits[] = {0.0,
      78             :                                             1073741823.0,
      79             :                                             2147483647.0,
      80             :                                             4294967295.0,
      81             :                                             8589934591.0,
      82             :                                             17179869183.0,
      83             :                                             34359738367.0,
      84             :                                             68719476735.0,
      85             :                                             137438953471.0,
      86             :                                             274877906943.0,
      87             :                                             549755813887.0,
      88             :                                             1099511627775.0,
      89             :                                             2199023255551.0,
      90             :                                             4398046511103.0,
      91             :                                             8796093022207.0,
      92             :                                             17592186044415.0,
      93             :                                             35184372088831.0,
      94             :                                             70368744177663.0,
      95             :                                             140737488355327.0,
      96             :                                             281474976710655.0,
      97             :                                             562949953421311.0};
      98             :   STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
      99             : 
     100      433996 :   double current_min = current_range.Min();
     101             :   double new_min = current_min;
     102             :   // Find the closest lower entry in the list of allowed
     103             :   // minima (or negative infinity if there is no such entry).
     104      433996 :   if (current_min != previous_range.Min()) {
     105             :     new_min = -V8_INFINITY;
     106      323339 :     for (double const min : kWeakenMinLimits) {
     107      167596 :       if (min <= current_min) {
     108             :         new_min = min;
     109             :         break;
     110             :       }
     111             :     }
     112             :   }
     113             : 
     114      433998 :   double current_max = current_range.Max();
     115             :   double new_max = current_max;
     116             :   // Find the closest greater entry in the list of allowed
     117             :   // maxima (or infinity if there is no such entry).
     118      433997 :   if (current_max != previous_range.Max()) {
     119             :     new_max = V8_INFINITY;
     120     6714287 :     for (double const max : kWeakenMaxLimits) {
     121     3506063 :       if (max >= current_max) {
     122             :         new_max = max;
     123             :         break;
     124             :       }
     125             :     }
     126             :   }
     127             : 
     128      433998 :   return Type::Range(new_min, new_max, zone());
     129             : }
     130             : 
     131           0 : Type OperationTyper::Rangify(Type type) {
     132           0 :   if (type.IsRange()) return type;  // Shortcut.
     133           0 :   if (!type.Is(cache_->kInteger)) {
     134           0 :     return type;  // Give up on non-integer types.
     135             :   }
     136           0 :   return Type::Range(type.Min(), type.Max(), zone());
     137             : }
     138             : 
     139             : namespace {
     140             : 
     141             : // Returns the array's least element, ignoring NaN.
     142             : // There must be at least one non-NaN element.
     143             : // Any -0 is converted to 0.
     144     1335398 : double array_min(double a[], size_t n) {
     145             :   DCHECK_NE(0, n);
     146     1335398 :   double x = +V8_INFINITY;
     147     6676966 :   for (size_t i = 0; i < n; ++i) {
     148     5341568 :     if (!std::isnan(a[i])) {
     149     5341427 :       x = std::min(a[i], x);
     150             :     }
     151             :   }
     152             :   DCHECK(!std::isnan(x));
     153     1335398 :   return x == 0 ? 0 : x;  // -0 -> 0
     154             : }
     155             : 
     156             : // Returns the array's greatest element, ignoring NaN.
     157             : // There must be at least one non-NaN element.
     158             : // Any -0 is converted to 0.
     159     1335396 : double array_max(double a[], size_t n) {
     160             :   DCHECK_NE(0, n);
     161     1335396 :   double x = -V8_INFINITY;
     162     6675892 :   for (size_t i = 0; i < n; ++i) {
     163     5340496 :     if (!std::isnan(a[i])) {
     164     5340359 :       x = std::max(a[i], x);
     165             :     }
     166             :   }
     167             :   DCHECK(!std::isnan(x));
     168     1335396 :   return x == 0 ? 0 : x;  // -0 -> 0
     169             : }
     170             : 
     171             : }  // namespace
     172             : 
     173     1221076 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
     174     1221125 :                                double rhs_max) {
     175             :   double results[4];
     176     1221076 :   results[0] = lhs_min + rhs_min;
     177     1221076 :   results[1] = lhs_min + rhs_max;
     178     1221076 :   results[2] = lhs_max + rhs_min;
     179     1221076 :   results[3] = lhs_max + rhs_max;
     180             :   // Since none of the inputs can be -0, the result cannot be -0 either.
     181             :   // However, it can be nan (the sum of two infinities of opposite sign).
     182             :   // On the other hand, if none of the "results" above is nan, then the
     183             :   // actual result cannot be nan either.
     184             :   int nans = 0;
     185     6105356 :   for (int i = 0; i < 4; ++i) {
     186     4884280 :     if (std::isnan(results[i])) ++nans;
     187             :   }
     188     1221076 :   if (nans == 4) return Type::NaN();
     189     1221067 :   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
     190     1221111 :   if (nans > 0) type = Type::Union(type, Type::NaN(), zone());
     191             :   // Examples:
     192             :   //   [-inf, -inf] + [+inf, +inf] = NaN
     193             :   //   [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN
     194             :   //   [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN
     195             :   //   [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN
     196     1221051 :   return type;
     197             : }
     198             : 
     199       55806 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
     200       55845 :                                     double rhs_min, double rhs_max) {
     201             :   double results[4];
     202       55806 :   results[0] = lhs_min - rhs_min;
     203       55806 :   results[1] = lhs_min - rhs_max;
     204       55806 :   results[2] = lhs_max - rhs_min;
     205       55806 :   results[3] = lhs_max - rhs_max;
     206             :   // Since none of the inputs can be -0, the result cannot be -0.
     207             :   // However, it can be nan (the subtraction of two infinities of same sign).
     208             :   // On the other hand, if none of the "results" above is nan, then the actual
     209             :   // result cannot be nan either.
     210             :   int nans = 0;
     211      279030 :   for (int i = 0; i < 4; ++i) {
     212      223224 :     if (std::isnan(results[i])) ++nans;
     213             :   }
     214       55806 :   if (nans == 4) return Type::NaN();  // [inf..inf] - [inf..inf] (all same sign)
     215       55797 :   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
     216       55845 :   return nans == 0 ? type : Type::Union(type, Type::NaN(), zone());
     217             :   // Examples:
     218             :   //   [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN
     219             :   //   [-inf, -inf] - [-inf, -inf] = NaN
     220             :   //   [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN
     221             :   //   [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN
     222             : }
     223             : 
     224       58608 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
     225      105432 :                                     double rhs_min, double rhs_max) {
     226             :   double results[4];
     227       58608 :   results[0] = lhs_min * rhs_min;
     228       58608 :   results[1] = lhs_min * rhs_max;
     229       58608 :   results[2] = lhs_max * rhs_min;
     230       58608 :   results[3] = lhs_max * rhs_max;
     231             :   // If the result may be nan, we give up on calculating a precise type,
     232             :   // because the discontinuity makes it too complicated.  Note that even if
     233             :   // none of the "results" above is nan, the actual result may still be, so we
     234             :   // have to do a different check:
     235      292785 :   for (int i = 0; i < 4; ++i) {
     236      234254 :     if (std::isnan(results[i])) {
     237          77 :       return cache_->kIntegerOrMinusZeroOrNaN;
     238             :     }
     239             :   }
     240       58531 :   double min = array_min(results, 4);
     241       58531 :   double max = array_max(results, 4);
     242       58531 :   Type type = Type::Range(min, max, zone());
     243       58531 :   if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
     244       46704 :     type = Type::Union(type, Type::MinusZero(), zone());
     245             :   }
     246             :   // 0 * V8_INFINITY is NaN, regardless of sign
     247      100636 :   if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
     248       79478 :        (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
     249       58426 :       ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
     250         125 :        (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
     251         197 :     type = Type::Union(type, Type::NaN(), zone());
     252             :   }
     253       58531 :   return type;
     254             : }
     255             : 
     256      527223 : Type OperationTyper::ConvertReceiver(Type type) {
     257      175751 :   if (type.Is(Type::Receiver())) return type;
     258      175736 :   bool const maybe_primitive = type.Maybe(Type::Primitive());
     259      175736 :   type = Type::Intersect(type, Type::Receiver(), zone());
     260      175736 :   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      175736 :     type = Type::Union(type, Type::OtherObject(), zone());
     264             :   }
     265      175736 :   return type;
     266             : }
     267             : 
     268     6020015 : Type OperationTyper::ToNumber(Type type) {
     269     3328314 :   if (type.Is(Type::Number())) return type;
     270             : 
     271             :   // If {type} includes any receivers, we cannot tell what kind of
     272             :   // Number their callbacks might produce. Similarly in the case
     273             :   // where {type} includes String, it's not possible at this point
     274             :   // to tell which exact numbers are going to be produced.
     275      712887 :   if (type.Maybe(Type::StringOrReceiver())) return Type::Number();
     276             : 
     277             :   // Both Symbol and BigInt primitives will cause exceptions
     278             :   // to be thrown from ToNumber conversions, so they don't
     279             :   // contribute to the resulting type anyways.
     280      454914 :   type = Type::Intersect(type, Type::PlainPrimitive(), zone());
     281             : 
     282             :   // This leaves us with Number\/Oddball, so deal with the individual
     283             :   // Oddball primitives below.
     284             :   DCHECK(type.Is(Type::NumberOrOddball()));
     285      454927 :   if (type.Maybe(Type::Null())) {
     286             :     // ToNumber(null) => +0
     287      442789 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     288             :   }
     289      454941 :   if (type.Maybe(Type::Undefined())) {
     290             :     // ToNumber(undefined) => NaN
     291      448802 :     type = Type::Union(type, Type::NaN(), zone());
     292             :   }
     293      454917 :   if (type.Maybe(singleton_false_)) {
     294             :     // ToNumber(false) => +0
     295      444820 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     296             :   }
     297      454978 :   if (type.Maybe(singleton_true_)) {
     298             :     // ToNumber(true) => +1
     299      445390 :     type = Type::Union(type, cache_->kSingletonOne, zone());
     300             :   }
     301      454965 :   return Type::Intersect(type, Type::Number(), zone());
     302             : }
     303             : 
     304        1185 : Type OperationTyper::ToNumberConvertBigInt(Type type) {
     305             :   // If the {type} includes any receivers, then the callbacks
     306             :   // might actually produce BigInt primitive values here.
     307             :   bool maybe_bigint =
     308         506 :       type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
     309         506 :   type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
     310             : 
     311             :   // Any BigInt is rounded to an integer Number in the range [-inf, inf].
     312         679 :   return maybe_bigint ? Type::Union(type, cache_->kInteger, zone()) : type;
     313             : }
     314             : 
     315     3534609 : Type OperationTyper::ToNumeric(Type type) {
     316             :   // If the {type} includes any receivers, then the callbacks
     317             :   // might actually produce BigInt primitive values here.
     318     1160903 :   if (type.Maybe(Type::Receiver())) {
     319       51898 :     type = Type::Union(type, Type::BigInt(), zone());
     320             :   }
     321             :   return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
     322     2321808 :                      Type::Intersect(type, Type::BigInt(), zone()), zone());
     323             : }
     324             : 
     325        4322 : Type OperationTyper::NumberAbs(Type type) {
     326             :   DCHECK(type.Is(Type::Number()));
     327        1292 :   if (type.IsNone()) return type;
     328             : 
     329        1255 :   bool const maybe_nan = type.Maybe(Type::NaN());
     330        1255 :   bool const maybe_minuszero = type.Maybe(Type::MinusZero());
     331             : 
     332        1255 :   type = Type::Intersect(type, Type::PlainNumber(), zone());
     333        1255 :   if (!type.IsNone()) {
     334        1191 :     double const max = type.Max();
     335        1191 :     double const min = type.Min();
     336        1191 :     if (min < 0) {
     337        2018 :       if (type.Is(cache_->kInteger)) {
     338             :         type =
     339         654 :             Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
     340             :       } else {
     341         682 :         type = Type::PlainNumber();
     342             :       }
     343             :     }
     344             :   }
     345             : 
     346        1255 :   if (maybe_minuszero) {
     347         675 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     348             :   }
     349        1255 :   if (maybe_nan) {
     350         773 :     type = Type::Union(type, Type::NaN(), zone());
     351             :   }
     352        1255 :   return type;
     353             : }
     354             : 
     355         101 : Type OperationTyper::NumberAcos(Type type) {
     356             :   DCHECK(type.Is(Type::Number()));
     357         101 :   return Type::Number();
     358             : }
     359             : 
     360         101 : Type OperationTyper::NumberAcosh(Type type) {
     361             :   DCHECK(type.Is(Type::Number()));
     362         101 :   return Type::Number();
     363             : }
     364             : 
     365         101 : Type OperationTyper::NumberAsin(Type type) {
     366             :   DCHECK(type.Is(Type::Number()));
     367         101 :   return Type::Number();
     368             : }
     369             : 
     370         101 : Type OperationTyper::NumberAsinh(Type type) {
     371             :   DCHECK(type.Is(Type::Number()));
     372         101 :   return Type::Number();
     373             : }
     374             : 
     375         101 : Type OperationTyper::NumberAtan(Type type) {
     376             :   DCHECK(type.Is(Type::Number()));
     377         101 :   return Type::Number();
     378             : }
     379             : 
     380         100 : Type OperationTyper::NumberAtanh(Type type) {
     381             :   DCHECK(type.Is(Type::Number()));
     382         100 :   return Type::Number();
     383             : }
     384             : 
     385         101 : Type OperationTyper::NumberCbrt(Type type) {
     386             :   DCHECK(type.Is(Type::Number()));
     387         101 :   return Type::Number();
     388             : }
     389             : 
     390       64296 : Type OperationTyper::NumberCeil(Type type) {
     391             :   DCHECK(type.Is(Type::Number()));
     392       43728 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     393       21216 :   type = Type::Intersect(type, Type::NaN(), zone());
     394       21216 :   type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
     395       21216 :   return type;
     396             : }
     397             : 
     398         216 : Type OperationTyper::NumberClz32(Type type) {
     399             :   DCHECK(type.Is(Type::Number()));
     400         216 :   return cache_->kZeroToThirtyTwo;
     401             : }
     402             : 
     403         144 : Type OperationTyper::NumberCos(Type type) {
     404             :   DCHECK(type.Is(Type::Number()));
     405         144 :   return Type::Number();
     406             : }
     407             : 
     408         122 : Type OperationTyper::NumberCosh(Type type) {
     409             :   DCHECK(type.Is(Type::Number()));
     410         122 :   return Type::Number();
     411             : }
     412             : 
     413         233 : Type OperationTyper::NumberExp(Type type) {
     414             :   DCHECK(type.Is(Type::Number()));
     415         233 :   return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
     416             : }
     417             : 
     418         143 : Type OperationTyper::NumberExpm1(Type type) {
     419             :   DCHECK(type.Is(Type::Number()));
     420         143 :   return Type::Number();
     421             : }
     422             : 
     423      251768 : Type OperationTyper::NumberFloor(Type type) {
     424             :   DCHECK(type.Is(Type::Number()));
     425      168692 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     426       83711 :   type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
     427       83711 :   type = Type::Union(type, cache_->kInteger, zone());
     428       83711 :   return type;
     429             : }
     430             : 
     431        4399 : Type OperationTyper::NumberFround(Type type) {
     432             :   DCHECK(type.Is(Type::Number()));
     433        4399 :   return Type::Number();
     434             : }
     435             : 
     436         617 : Type OperationTyper::NumberLog(Type type) {
     437             :   DCHECK(type.Is(Type::Number()));
     438         617 :   return Type::Number();
     439             : }
     440             : 
     441         101 : Type OperationTyper::NumberLog1p(Type type) {
     442             :   DCHECK(type.Is(Type::Number()));
     443         101 :   return Type::Number();
     444             : }
     445             : 
     446         101 : Type OperationTyper::NumberLog2(Type type) {
     447             :   DCHECK(type.Is(Type::Number()));
     448         101 :   return Type::Number();
     449             : }
     450             : 
     451         101 : Type OperationTyper::NumberLog10(Type type) {
     452             :   DCHECK(type.Is(Type::Number()));
     453         101 :   return Type::Number();
     454             : }
     455             : 
     456       14381 : Type OperationTyper::NumberRound(Type type) {
     457             :   DCHECK(type.Is(Type::Number()));
     458        9710 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     459        4763 :   type = Type::Intersect(type, Type::NaN(), zone());
     460        4763 :   type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
     461        4763 :   return type;
     462             : }
     463             : 
     464         808 : Type OperationTyper::NumberSign(Type type) {
     465             :   DCHECK(type.Is(Type::Number()));
     466         424 :   if (type.Is(cache_->kZeroish)) return type;
     467         173 :   bool maybe_minuszero = type.Maybe(Type::MinusZero());
     468         173 :   bool maybe_nan = type.Maybe(Type::NaN());
     469         173 :   type = Type::Intersect(type, Type::PlainNumber(), zone());
     470         173 :   if (type.IsNone()) {
     471             :     // Do nothing.
     472         173 :   } else if (type.Max() < 0.0) {
     473           1 :     type = cache_->kSingletonMinusOne;
     474         172 :   } else if (type.Max() <= 0.0) {
     475           0 :     type = cache_->kMinusOneOrZero;
     476         172 :   } else if (type.Min() > 0.0) {
     477          14 :     type = cache_->kSingletonOne;
     478         158 :   } else if (type.Min() >= 0.0) {
     479           0 :     type = cache_->kZeroOrOne;
     480             :   } else {
     481         158 :     type = Type::Range(-1.0, 1.0, zone());
     482             :   }
     483         306 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     484         305 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     485             :   DCHECK(!type.IsNone());
     486         173 :   return type;
     487             : }
     488             : 
     489         203 : Type OperationTyper::NumberSin(Type type) {
     490             :   DCHECK(type.Is(Type::Number()));
     491         203 :   return Type::Number();
     492             : }
     493             : 
     494         122 : Type OperationTyper::NumberSinh(Type type) {
     495             :   DCHECK(type.Is(Type::Number()));
     496         122 :   return Type::Number();
     497             : }
     498             : 
     499         295 : Type OperationTyper::NumberSqrt(Type type) {
     500             :   DCHECK(type.Is(Type::Number()));
     501         295 :   return Type::Number();
     502             : }
     503             : 
     504         188 : Type OperationTyper::NumberTan(Type type) {
     505             :   DCHECK(type.Is(Type::Number()));
     506         188 :   return Type::Number();
     507             : }
     508             : 
     509         122 : Type OperationTyper::NumberTanh(Type type) {
     510             :   DCHECK(type.Is(Type::Number()));
     511         122 :   return Type::Number();
     512             : }
     513             : 
     514       63447 : Type OperationTyper::NumberTrunc(Type type) {
     515             :   DCHECK(type.Is(Type::Number()));
     516       42582 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     517       21078 :   type = Type::Intersect(type, Type::NaN(), zone());
     518       21078 :   type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
     519       21078 :   return type;
     520             : }
     521             : 
     522       46171 : Type OperationTyper::NumberToBoolean(Type type) {
     523             :   DCHECK(type.Is(Type::Number()));
     524       46171 :   if (type.IsNone()) return type;
     525       92268 :   if (type.Is(cache_->kZeroish)) return singleton_false_;
     526       46131 :   if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
     527        2149 :     return singleton_true_;  // Ruled out nan, -0 and +0.
     528             :   }
     529             :   return Type::Boolean();
     530             : }
     531             : 
     532      230790 : Type OperationTyper::NumberToInt32(Type type) {
     533             :   DCHECK(type.Is(Type::Number()));
     534             : 
     535      224778 :   if (type.Is(Type::Signed32())) return type;
     536      145654 :   if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
     537       69400 :   if (type.Is(signed32ish_)) {
     538             :     return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
     539        6012 :                            Type::Signed32(), zone());
     540             :   }
     541             :   return Type::Signed32();
     542             : }
     543             : 
     544       12820 : Type OperationTyper::NumberToString(Type type) {
     545             :   DCHECK(type.Is(Type::Number()));
     546       12820 :   if (type.IsNone()) return type;
     547       12783 :   if (type.Is(Type::NaN())) return singleton_NaN_string_;
     548       25564 :   if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
     549             :   return Type::String();
     550             : }
     551             : 
     552       85202 : Type OperationTyper::NumberToUint32(Type type) {
     553             :   DCHECK(type.Is(Type::Number()));
     554             : 
     555       85052 :   if (type.Is(Type::Unsigned32())) return type;
     556       81422 :   if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
     557       38994 :   if (type.Is(unsigned32ish_)) {
     558             :     return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
     559         150 :                            Type::Unsigned32(), zone());
     560             :   }
     561             :   return Type::Unsigned32();
     562             : }
     563             : 
     564        1618 : Type OperationTyper::NumberToUint8Clamped(Type type) {
     565             :   DCHECK(type.Is(Type::Number()));
     566             : 
     567        3236 :   if (type.Is(cache_->kUint8)) return type;
     568        1525 :   return cache_->kUint8;
     569             : }
     570             : 
     571        3573 : Type OperationTyper::NumberSilenceNaN(Type type) {
     572             :   DCHECK(type.Is(Type::Number()));
     573             :   // TODO(jarin): This is a terrible hack; we definitely need a dedicated type
     574             :   // for the hole (tagged and/or double). Otherwise if the input is the hole
     575             :   // NaN constant, we'd just eliminate this node in JSTypedLowering.
     576        3573 :   if (type.Maybe(Type::NaN())) return Type::Number();
     577         892 :   return type;
     578             : }
     579             : 
     580     6153941 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
     581             :   DCHECK(lhs.Is(Type::Number()));
     582             :   DCHECK(rhs.Is(Type::Number()));
     583             : 
     584     3466103 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     585             : 
     586             :   // Addition can return NaN if either input can be NaN or we try to compute
     587             :   // the sum of two infinities of opposite sign.
     588     1732375 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
     589             : 
     590             :   // Addition can yield minus zero only if both inputs can be minus zero.
     591             :   bool maybe_minuszero = true;
     592     1732219 :   if (lhs.Maybe(Type::MinusZero())) {
     593      255459 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     594             :   } else {
     595             :     maybe_minuszero = false;
     596             :   }
     597     1732272 :   if (rhs.Maybe(Type::MinusZero())) {
     598      191578 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     599             :   } else {
     600             :     maybe_minuszero = false;
     601             :   }
     602             : 
     603             :   // We can give more precise types for integers.
     604             :   Type type = Type::None();
     605     1732370 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     606     1732382 :   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     607     3464552 :   if (!lhs.IsNone() && !rhs.IsNone()) {
     608     4804246 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     609     1221073 :       type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
     610             :     } else {
     611     1331262 :       if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
     612      326502 :           (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) {
     613             :         maybe_nan = true;
     614             :       }
     615             :       type = Type::PlainNumber();
     616             :     }
     617             :   }
     618             : 
     619             :   // Take into account the -0 and NaN information computed earlier.
     620     1906115 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     621     2066912 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     622     1732265 :   return type;
     623             : }
     624             : 
     625      225393 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
     626             :   DCHECK(lhs.Is(Type::Number()));
     627             :   DCHECK(rhs.Is(Type::Number()));
     628             : 
     629      135144 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     630             : 
     631             :   // Subtraction can return NaN if either input can be NaN or we try to
     632             :   // compute the sum of two infinities of opposite sign.
     633       67276 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
     634             : 
     635             :   // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs}
     636             :   // can be zero.
     637             :   bool maybe_minuszero = false;
     638       67276 :   if (lhs.Maybe(Type::MinusZero())) {
     639        6990 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     640        6990 :     maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
     641             :   }
     642       67276 :   if (rhs.Maybe(Type::MinusZero())) {
     643        2991 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     644             :   }
     645             : 
     646             :   // We can give more precise types for integers.
     647             :   Type type = Type::None();
     648       67276 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     649       67276 :   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     650      134406 :   if (!lhs.IsNone() && !rhs.IsNone()) {
     651      192118 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     652       55806 :       type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
     653             :     } else {
     654       30996 :       if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
     655        9904 :           (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) {
     656             :         maybe_nan = true;
     657             :       }
     658             :       type = Type::PlainNumber();
     659             :     }
     660             :   }
     661             : 
     662             :   // Take into account the -0 and NaN information computed earlier.
     663       69382 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     664       78249 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     665       67276 :   return type;
     666             : }
     667             : 
     668     1027374 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
     669      513691 :   Type result = SpeculativeNumberAdd(lhs, rhs);
     670             :   // If we have a Smi or Int32 feedback, the representation selection will
     671             :   // either truncate or it will check the inputs (i.e., deopt if not int32).
     672             :   // In either case the result will be in the safe integer range, so we
     673             :   // can bake in the type here. This needs to be in sync with
     674             :   // SimplifiedLowering::VisitSpeculativeAdditiveOp.
     675      513683 :   return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
     676             : }
     677             : 
     678       77454 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
     679       38727 :   Type result = SpeculativeNumberSubtract(lhs, rhs);
     680             :   // If we have a Smi or Int32 feedback, the representation selection will
     681             :   // either truncate or it will check the inputs (i.e., deopt if not int32).
     682             :   // In either case the result will be in the safe integer range, so we
     683             :   // can bake in the type here. This needs to be in sync with
     684             :   // SimplifiedLowering::VisitSpeculativeAdditiveOp.
     685       38727 :   return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
     686             : }
     687             : 
     688      444147 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
     689             :   DCHECK(lhs.Is(Type::Number()));
     690             :   DCHECK(rhs.Is(Type::Number()));
     691             : 
     692      173962 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     693      173538 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
     694             : 
     695             :   // Multiplication propagates NaN:
     696             :   //   NaN * x = NaN         (regardless of sign of x)
     697             :   //   0 * Infinity = NaN    (regardless of signs)
     698      188619 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
     699       90941 :                    (lhs.Maybe(cache_->kZeroish) &&
     700      217056 :                     (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
     701       53968 :                    (rhs.Maybe(cache_->kZeroish) &&
     702        8614 :                     (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
     703       86631 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
     704             :   DCHECK(!lhs.IsNone());
     705       86631 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
     706             :   DCHECK(!rhs.IsNone());
     707             : 
     708             :   // Try to rule out -0.
     709      135480 :   bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
     710       95491 :                          rhs.Maybe(Type::MinusZero()) ||
     711      197949 :                          (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
     712       28961 :                          (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
     713       86631 :   if (lhs.Maybe(Type::MinusZero())) {
     714       37782 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     715       37782 :     lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     716             :   }
     717       86631 :   if (rhs.Maybe(Type::MinusZero())) {
     718        5610 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     719        5610 :     rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     720             :   }
     721             : 
     722             :   // Compute the effective type, utilizing range information if possible.
     723      212903 :   Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
     724       58608 :                   ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
     725      145239 :                   : Type::OrderedNumber();
     726             : 
     727             :   // Take into account the -0 and NaN information computed earlier.
     728      146386 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     729      123893 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     730       86631 :   return type;
     731             : }
     732             : 
     733      293454 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
     734             :   DCHECK(lhs.Is(Type::Number()));
     735             :   DCHECK(rhs.Is(Type::Number()));
     736             : 
     737      143391 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     738      141070 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
     739             : 
     740             :   // Division is tricky, so all we do is try ruling out -0 and NaN.
     741      103003 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
     742       67436 :                    ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
     743        5213 :                     (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
     744       69825 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
     745             :   DCHECK(!lhs.IsNone());
     746       69825 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
     747             :   DCHECK(!rhs.IsNone());
     748             : 
     749             :   // Try to rule out -0.
     750             :   bool maybe_minuszero =
     751      120307 :       !lhs.Is(cache_->kInteger) ||
     752      128824 :       (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
     753       66822 :       (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY);
     754             : 
     755             :   // Take into account the -0 and NaN information computed earlier.
     756             :   Type type = Type::PlainNumber();
     757      115234 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     758      106494 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     759       69825 :   return type;
     760             : }
     761             : 
     762       92594 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
     763             :   DCHECK(lhs.Is(Type::Number()));
     764             :   DCHECK(rhs.Is(Type::Number()));
     765             : 
     766       35789 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     767             : 
     768             :   // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or
     769             :   // {lhs} is not finite, or the {rhs} is a zero value.
     770       43558 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
     771       39569 :                    lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY;
     772             : 
     773             :   // Deal with -0 inputs, only the signbit of {lhs} matters for the result.
     774             :   bool maybe_minuszero = false;
     775       17823 :   if (lhs.Maybe(Type::MinusZero())) {
     776             :     maybe_minuszero = true;
     777        4394 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     778             :   }
     779       17823 :   if (rhs.Maybe(Type::MinusZero())) {
     780        1501 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     781             :   }
     782             : 
     783             :   // Rule out NaN and -0, and check what we can do with the remaining type info.
     784             :   Type type = Type::None();
     785       17823 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     786       17823 :   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     787             : 
     788             :   // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited,
     789             :   // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}.
     790       35526 :   if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
     791             :     // Determine the bounds of {lhs} and {rhs}.
     792       17563 :     double const lmin = lhs.Min();
     793       17563 :     double const lmax = lhs.Max();
     794       17563 :     double const rmin = rhs.Min();
     795       17563 :     double const rmax = rhs.Max();
     796             : 
     797             :     // The sign of the result is the sign of the {lhs}.
     798       17563 :     if (lmin < 0.0) maybe_minuszero = true;
     799             : 
     800             :     // For integer inputs {lhs} and {rhs} we can infer a precise type.
     801       48840 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     802       37077 :       double labs = std::max(std::abs(lmin), std::abs(lmax));
     803       37077 :       double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
     804       12359 :       double abs = std::min(labs, rabs);
     805             :       double min = 0.0, max = 0.0;
     806       12359 :       if (lmin >= 0.0) {
     807             :         // {lhs} positive.
     808             :         min = 0.0;
     809             :         max = abs;
     810        8955 :       } else if (lmax <= 0.0) {
     811             :         // {lhs} negative.
     812         948 :         min = 0.0 - abs;
     813             :         max = 0.0;
     814             :       } else {
     815             :         // {lhs} positive or negative.
     816        8007 :         min = 0.0 - abs;
     817             :         max = abs;
     818             :       }
     819       12359 :       type = Type::Range(min, max, zone());
     820             :     } else {
     821             :       type = Type::PlainNumber();
     822             :     }
     823             :   }
     824             : 
     825             :   // Take into account the -0 and NaN information computed earlier.
     826       31366 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     827       25049 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     828       17823 :   return type;
     829             : }
     830             : 
     831       86454 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
     832             :   DCHECK(lhs.Is(Type::Number()));
     833             :   DCHECK(rhs.Is(Type::Number()));
     834             : 
     835       43345 :   lhs = NumberToInt32(lhs);
     836       43345 :   rhs = NumberToInt32(rhs);
     837             : 
     838       86495 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     839             : 
     840       43109 :   double lmin = lhs.Min();
     841       43109 :   double rmin = rhs.Min();
     842       43109 :   double lmax = lhs.Max();
     843       43109 :   double rmax = rhs.Max();
     844             :   // Or-ing any two values results in a value no smaller than their minimum.
     845             :   // Even no smaller than their maximum if both values are non-negative.
     846             :   double min =
     847       86218 :       lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
     848       43109 :   double max = kMaxInt;
     849             : 
     850             :   // Or-ing with 0 is essentially a conversion to int32.
     851       43109 :   if (rmin == 0 && rmax == 0) {
     852             :     min = lmin;
     853       29299 :     max = lmax;
     854             :   }
     855       43109 :   if (lmin == 0 && lmax == 0) {
     856             :     min = rmin;
     857         620 :     max = rmax;
     858             :   }
     859             : 
     860       43109 :   if (lmax < 0 || rmax < 0) {
     861             :     // Or-ing two values of which at least one is negative results in a negative
     862             :     // value.
     863        1336 :     max = std::min(max, -1.0);
     864             :   }
     865       43109 :   return Type::Range(min, max, zone());
     866             : }
     867             : 
     868       60912 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
     869             :   DCHECK(lhs.Is(Type::Number()));
     870             :   DCHECK(rhs.Is(Type::Number()));
     871             : 
     872       30564 :   lhs = NumberToInt32(lhs);
     873       30564 :   rhs = NumberToInt32(rhs);
     874             : 
     875       60953 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     876             : 
     877       30348 :   double lmin = lhs.Min();
     878       30348 :   double rmin = rhs.Min();
     879       30348 :   double lmax = lhs.Max();
     880       30348 :   double rmax = rhs.Max();
     881             :   double min = kMinInt;
     882             :   // And-ing any two values results in a value no larger than their maximum.
     883             :   // Even no larger than their minimum if both values are non-negative.
     884             :   double max =
     885       60696 :       lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
     886             :   // And-ing with a non-negative value x causes the result to be between
     887             :   // zero and x.
     888       30348 :   if (lmin >= 0) {
     889             :     min = 0;
     890        9831 :     max = std::min(max, lmax);
     891             :   }
     892       30348 :   if (rmin >= 0) {
     893             :     min = 0;
     894       24642 :     max = std::min(max, rmax);
     895             :   }
     896       30348 :   return Type::Range(min, max, zone());
     897             : }
     898             : 
     899        8439 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
     900             :   DCHECK(lhs.Is(Type::Number()));
     901             :   DCHECK(rhs.Is(Type::Number()));
     902             : 
     903        8439 :   lhs = NumberToInt32(lhs);
     904        8439 :   rhs = NumberToInt32(rhs);
     905             : 
     906       16809 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     907             : 
     908        8329 :   double lmin = lhs.Min();
     909        8329 :   double rmin = rhs.Min();
     910        8329 :   double lmax = lhs.Max();
     911        8329 :   double rmax = rhs.Max();
     912        8329 :   if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
     913             :     // Xor-ing negative or non-negative values results in a non-negative value.
     914             :     return Type::Unsigned31();
     915             :   }
     916        7994 :   if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
     917             :     // Xor-ing a negative and a non-negative value results in a negative value.
     918             :     // TODO(jarin) Use a range here.
     919             :     return Type::Negative32();
     920             :   }
     921             :   return Type::Signed32();
     922             : }
     923             : 
     924       13966 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
     925             :   DCHECK(lhs.Is(Type::Number()));
     926             :   DCHECK(rhs.Is(Type::Number()));
     927             : 
     928       13040 :   lhs = NumberToInt32(lhs);
     929       13040 :   rhs = NumberToUint32(rhs);
     930             : 
     931       26010 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     932             : 
     933       12929 :   int32_t min_lhs = lhs.Min();
     934       12929 :   int32_t max_lhs = lhs.Max();
     935       12929 :   uint32_t min_rhs = rhs.Min();
     936       12929 :   uint32_t max_rhs = rhs.Max();
     937       12929 :   if (max_rhs > 31) {
     938             :     // rhs can be larger than the bitmask
     939             :     max_rhs = 31;
     940             :     min_rhs = 0;
     941             :   }
     942             : 
     943       12929 :   if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
     944             :     // overflow possible
     945             :     return Type::Signed32();
     946             :   }
     947             : 
     948             :   double min =
     949        1175 :       std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
     950        3525 :                static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
     951             :   double max =
     952        1175 :       std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
     953        3525 :                static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
     954             : 
     955        1175 :   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
     956         926 :   return Type::Range(min, max, zone());
     957             : }
     958             : 
     959       38997 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
     960             :   DCHECK(lhs.Is(Type::Number()));
     961             :   DCHECK(rhs.Is(Type::Number()));
     962             : 
     963       21984 :   lhs = NumberToInt32(lhs);
     964       21984 :   rhs = NumberToUint32(rhs);
     965             : 
     966       43878 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     967             : 
     968       21839 :   int32_t min_lhs = lhs.Min();
     969       21839 :   int32_t max_lhs = lhs.Max();
     970       21839 :   uint32_t min_rhs = rhs.Min();
     971       21839 :   uint32_t max_rhs = rhs.Max();
     972       21839 :   if (max_rhs > 31) {
     973             :     // rhs can be larger than the bitmask
     974             :     max_rhs = 31;
     975             :     min_rhs = 0;
     976             :   }
     977       43678 :   double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
     978       43678 :   double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
     979             : 
     980       21839 :   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
     981       17013 :   return Type::Range(min, max, zone());
     982             : }
     983             : 
     984       17950 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
     985             :   DCHECK(lhs.Is(Type::Number()));
     986             :   DCHECK(rhs.Is(Type::Number()));
     987             : 
     988       13288 :   lhs = NumberToUint32(lhs);
     989       13288 :   rhs = NumberToUint32(rhs);
     990             : 
     991       26441 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     992             : 
     993       13105 :   uint32_t min_lhs = lhs.Min();
     994       13105 :   uint32_t max_lhs = lhs.Max();
     995       13105 :   uint32_t min_rhs = rhs.Min();
     996       13105 :   uint32_t max_rhs = rhs.Max();
     997       13105 :   if (max_rhs > 31) {
     998             :     // rhs can be larger than the bitmask
     999             :     max_rhs = 31;
    1000             :     min_rhs = 0;
    1001             :   }
    1002             : 
    1003       13105 :   double min = min_lhs >> max_rhs;
    1004       13105 :   double max = max_lhs >> min_rhs;
    1005             :   DCHECK_LE(0, min);
    1006             :   DCHECK_LE(max, kMaxUInt32);
    1007             : 
    1008       13105 :   if (min == 0 && max == kMaxInt) return Type::Unsigned31();
    1009       12443 :   if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
    1010        4662 :   return Type::Range(min, max, zone());
    1011             : }
    1012             : 
    1013         158 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
    1014             :   DCHECK(lhs.Is(Type::Number()));
    1015             :   DCHECK(rhs.Is(Type::Number()));
    1016         158 :   return Type::Number();
    1017             : }
    1018             : 
    1019        2703 : Type OperationTyper::NumberImul(Type lhs, Type rhs) {
    1020             :   DCHECK(lhs.Is(Type::Number()));
    1021             :   DCHECK(rhs.Is(Type::Number()));
    1022             :   // TODO(turbofan): We should be able to do better here.
    1023        2703 :   return Type::Signed32();
    1024             : }
    1025             : 
    1026       40737 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
    1027             :   DCHECK(lhs.Is(Type::Number()));
    1028             :   DCHECK(rhs.Is(Type::Number()));
    1029             : 
    1030       20219 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    1031       20141 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    1032             : 
    1033             :   Type type = Type::None();
    1034       10058 :   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
    1035         270 :     type = Type::Union(type, Type::NaN(), zone());
    1036             :   }
    1037       10058 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
    1038             :   DCHECK(!lhs.IsNone());
    1039       10058 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
    1040             :   DCHECK(!rhs.IsNone());
    1041       29915 :   if (lhs.Is(cache_->kIntegerOrMinusZero) &&
    1042        9799 :       rhs.Is(cache_->kIntegerOrMinusZero)) {
    1043             :     // TODO(turbofan): This could still be improved in ruling out -0 when
    1044             :     // one of the inputs' min is 0.
    1045       19434 :     double max = std::max(lhs.Max(), rhs.Max());
    1046       19434 :     double min = std::max(lhs.Min(), rhs.Min());
    1047        9717 :     type = Type::Union(type, Type::Range(min, max, zone()), zone());
    1048       27723 :     if (min <= 0.0 && 0.0 <= max &&
    1049       16487 :         (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
    1050         166 :       type = Type::Union(type, Type::MinusZero(), zone());
    1051             :     }
    1052             :   } else {
    1053         341 :     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
    1054             :   }
    1055       10058 :   return type;
    1056             : }
    1057             : 
    1058       47297 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
    1059             :   DCHECK(lhs.Is(Type::Number()));
    1060             :   DCHECK(rhs.Is(Type::Number()));
    1061             : 
    1062       23387 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    1063       23300 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    1064             : 
    1065             :   Type type = Type::None();
    1066       11633 :   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
    1067         537 :     type = Type::Union(type, Type::NaN(), zone());
    1068             :   }
    1069       11633 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
    1070             :   DCHECK(!lhs.IsNone());
    1071       11633 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
    1072             :   DCHECK(!rhs.IsNone());
    1073       34424 :   if (lhs.Is(cache_->kIntegerOrMinusZero) &&
    1074       11158 :       rhs.Is(cache_->kIntegerOrMinusZero)) {
    1075       22092 :     double max = std::min(lhs.Max(), rhs.Max());
    1076       22092 :     double min = std::min(lhs.Min(), rhs.Min());
    1077       11046 :     type = Type::Union(type, Type::Range(min, max, zone()), zone());
    1078       33015 :     if (min <= 0.0 && 0.0 <= max &&
    1079       21750 :         (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
    1080         150 :       type = Type::Union(type, Type::MinusZero(), zone());
    1081             :     }
    1082             :   } else {
    1083         587 :     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
    1084             :   }
    1085       11633 :   return type;
    1086             : }
    1087             : 
    1088        3303 : Type OperationTyper::NumberPow(Type lhs, Type rhs) {
    1089             :   DCHECK(lhs.Is(Type::Number()));
    1090             :   DCHECK(rhs.Is(Type::Number()));
    1091             :   // TODO(turbofan): We should be able to do better here.
    1092        3303 :   return Type::Number();
    1093             : }
    1094             : 
    1095             : #define SPECULATIVE_NUMBER_BINOP(Name)                         \
    1096             :   Type OperationTyper::Speculative##Name(Type lhs, Type rhs) { \
    1097             :     lhs = SpeculativeToNumber(lhs);                            \
    1098             :     rhs = SpeculativeToNumber(rhs);                            \
    1099             :     return Name(lhs, rhs);                                     \
    1100             :   }
    1101      611359 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
    1102       39897 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
    1103       46049 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
    1104       48855 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
    1105        8497 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
    1106       33629 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
    1107       15923 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
    1108        2667 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
    1109        4696 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
    1110       14722 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
    1111        5204 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
    1112             : #undef SPECULATIVE_NUMBER_BINOP
    1113             : 
    1114     1811831 : Type OperationTyper::SpeculativeToNumber(Type type) {
    1115     1811831 :   return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
    1116             : }
    1117             : 
    1118           0 : Type OperationTyper::ToPrimitive(Type type) {
    1119           0 :   if (type.Is(Type::Primitive())) {
    1120           0 :     return type;
    1121             :   }
    1122             :   return Type::Primitive();
    1123             : }
    1124             : 
    1125           0 : Type OperationTyper::Invert(Type type) {
    1126             :   DCHECK(type.Is(Type::Boolean()));
    1127             :   DCHECK(!type.IsNone());
    1128           0 :   if (type.Is(singleton_false())) return singleton_true();
    1129           0 :   if (type.Is(singleton_true())) return singleton_false();
    1130           0 :   return type;
    1131             : }
    1132             : 
    1133           0 : OperationTyper::ComparisonOutcome OperationTyper::Invert(
    1134             :     ComparisonOutcome outcome) {
    1135             :   ComparisonOutcome result(0);
    1136           0 :   if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
    1137           0 :   if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
    1138           0 :   if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
    1139           0 :   return result;
    1140             : }
    1141             : 
    1142           0 : Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
    1143           0 :   if ((outcome & kComparisonFalse) != 0 ||
    1144             :       (outcome & kComparisonUndefined) != 0) {
    1145             :     return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
    1146           0 :                                             : singleton_false();
    1147             :   }
    1148             :   // Type should be non empty, so we know it should be true.
    1149             :   DCHECK_NE(0, outcome & kComparisonTrue);
    1150             :   return singleton_true();
    1151             : }
    1152             : 
    1153             : namespace {
    1154             : 
    1155      363568 : Type JSType(Type type) {
    1156      363568 :   if (type.Is(Type::Boolean())) return Type::Boolean();
    1157      355913 :   if (type.Is(Type::String())) return Type::String();
    1158      277888 :   if (type.Is(Type::Number())) return Type::Number();
    1159      143215 :   if (type.Is(Type::BigInt())) return Type::BigInt();
    1160      143107 :   if (type.Is(Type::Undefined())) return Type::Undefined();
    1161      140398 :   if (type.Is(Type::Null())) return Type::Null();
    1162      140173 :   if (type.Is(Type::Symbol())) return Type::Symbol();
    1163      140130 :   if (type.Is(Type::Receiver())) return Type::Receiver();  // JS "Object"
    1164             :   return Type::Any();
    1165             : }
    1166             : 
    1167             : }  // namespace
    1168             : 
    1169         247 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
    1170         247 :   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
    1171         247 :   if (lhs.Is(Type::NaN())) {
    1172          35 :     if (rhs.Is(Type::NaN())) return singleton_true();
    1173          35 :     if (!rhs.Maybe(Type::NaN())) return singleton_false();
    1174         212 :   } else if (rhs.Is(Type::NaN())) {
    1175          14 :     if (!lhs.Maybe(Type::NaN())) return singleton_false();
    1176             :   }
    1177         247 :   if (lhs.Is(Type::MinusZero())) {
    1178          85 :     if (rhs.Is(Type::MinusZero())) return singleton_true();
    1179          85 :     if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
    1180         162 :   } else if (rhs.Is(Type::MinusZero())) {
    1181          42 :     if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
    1182             :   }
    1183         601 :   if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
    1184          58 :       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
    1185             :     return singleton_false();
    1186             :   }
    1187             :   return Type::Boolean();
    1188             : }
    1189             : 
    1190      181537 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
    1191      181537 :   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
    1192      351504 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
    1193      442410 :   if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
    1194       91731 :       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
    1195             :     return singleton_false();
    1196             :   }
    1197      341676 :   if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
    1198             :     return singleton_false();
    1199             :   }
    1200      172635 :   if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
    1201             :     // Types are equal and are inhabited only by a single semantic value,
    1202             :     // which is not nan due to the earlier check.
    1203             :     return singleton_true();
    1204             :   }
    1205             :   return Type::Boolean();
    1206             : }
    1207             : 
    1208      387910 : Type OperationTyper::CheckBounds(Type index, Type length) {
    1209             :   DCHECK(length.Is(cache_->kPositiveSafeInteger));
    1210      254218 :   if (length.Is(cache_->kSingletonZero)) return Type::None();
    1211      127027 :   Type mask = Type::Range(0.0, length.Max() - 1, zone());
    1212      127027 :   if (index.Maybe(Type::MinusZero())) {
    1213        6747 :     index = Type::Union(index, cache_->kSingletonZero, zone());
    1214             :   }
    1215      127027 :   return Type::Intersect(index, mask, zone());
    1216             : }
    1217             : 
    1218        3509 : Type OperationTyper::CheckFloat64Hole(Type type) {
    1219        1213 :   if (type.Maybe(Type::Hole())) {
    1220             :     // Turn "the hole" into undefined.
    1221        1148 :     type = Type::Intersect(type, Type::Number(), zone());
    1222        1148 :     type = Type::Union(type, Type::Undefined(), zone());
    1223             :   }
    1224        1213 :   return type;
    1225             : }
    1226             : 
    1227        4114 : Type OperationTyper::CheckNumber(Type type) {
    1228        4114 :   return Type::Intersect(type, Type::Number(), zone());
    1229             : }
    1230             : 
    1231       95008 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
    1232       95008 :   return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
    1233             : }
    1234             : 
    1235       12238 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
    1236        4110 :   if (input.Maybe(Type::Hole())) {
    1237             :     // Turn "the hole" into undefined.
    1238        4064 :     Type type = Type::Intersect(input, Type::NonInternal(), zone());
    1239        4064 :     return Type::Union(type, Type::Undefined(), zone());
    1240             :   }
    1241          46 :   return input;
    1242             : }
    1243             : 
    1244      203298 : Type OperationTyper::ToBoolean(Type type) {
    1245      203298 :   if (type.Is(Type::Boolean())) return type;
    1246      162026 :   if (type.Is(falsish_)) return singleton_false_;
    1247      159370 :   if (type.Is(truish_)) return singleton_true_;
    1248      159133 :   if (type.Is(Type::Number())) {
    1249       45617 :     return NumberToBoolean(type);
    1250             :   }
    1251             :   return Type::Boolean();
    1252             : }
    1253             : 
    1254             : }  // namespace compiler
    1255             : }  // namespace internal
    1256      183867 : }  // namespace v8

Generated by: LCOV version 1.10