LCOV - code coverage report
Current view: top level - src/compiler - operation-typer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 554 575 96.3 %
Date: 2019-04-17 Functions: 90 95 94.7 %

          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     1393161 : OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
      20     1393161 :     : zone_(zone), cache_(TypeCache::Get()) {
      21             :   Factory* factory = broker->isolate()->factory();
      22     1393162 :   infinity_ = Type::NewConstant(V8_INFINITY, zone);
      23     1393161 :   minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
      24     1393162 :   Type truncating_to_zero = Type::MinusZeroOrNaN();
      25             :   DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
      26             : 
      27             :   singleton_empty_string_ =
      28     1393162 :       Type::HeapConstant(broker, factory->empty_string(), zone);
      29             :   singleton_NaN_string_ =
      30     1393162 :       Type::HeapConstant(broker, factory->NaN_string(), zone);
      31             :   singleton_zero_string_ =
      32     1393163 :       Type::HeapConstant(broker, factory->zero_string(), zone);
      33     1393165 :   singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
      34     1393165 :   singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
      35             :   singleton_the_hole_ =
      36     1393165 :       Type::HeapConstant(broker, factory->the_hole_value(), zone);
      37     1393163 :   signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
      38     1393162 :   unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
      39             : 
      40             :   falsish_ = Type::Union(
      41             :       Type::Undetectable(),
      42     1393162 :       Type::Union(Type::Union(singleton_false_, cache_->kZeroish, zone),
      43             :                   Type::Union(singleton_empty_string_, Type::Hole(), zone),
      44             :                   zone),
      45     2786327 :       zone);
      46             :   truish_ = Type::Union(
      47             :       singleton_true_,
      48     1393166 :       Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
      49     1393165 : }
      50             : 
      51     1202102 : Type OperationTyper::Merge(Type left, Type right) {
      52     1202102 :   return Type::Union(left, right, zone());
      53             : }
      54             : 
      55      447884 : 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      447884 :   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      447883 :   if (current_min != previous_range.Min()) {
     105             :     new_min = -V8_INFINITY;
     106      328270 :     for (double const min : kWeakenMinLimits) {
     107      167807 :       if (min <= current_min) {
     108             :         new_min = min;
     109             :         break;
     110             :       }
     111             :     }
     112             :   }
     113             : 
     114      447883 :   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      447884 :   if (current_max != previous_range.Max()) {
     119             :     new_max = V8_INFINITY;
     120     7106442 :     for (double const max : kWeakenMaxLimits) {
     121     3700467 :       if (max >= current_max) {
     122             :         new_max = max;
     123             :         break;
     124             :       }
     125             :     }
     126             :   }
     127             : 
     128      447885 :   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             : double array_min(double a[], size_t n) {
     145             :   DCHECK_NE(0, n);
     146     1355269 :   double x = +V8_INFINITY;
     147    12197165 :   for (size_t i = 0; i < n; ++i) {
     148     5420948 :     if (!std::isnan(a[i])) {
     149     5420847 :       x = std::min(a[i], x);
     150             :     }
     151             :   }
     152             :   DCHECK(!std::isnan(x));
     153     1355269 :   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             : double array_max(double a[], size_t n) {
     160             :   DCHECK_NE(0, n);
     161     1355269 :   double x = -V8_INFINITY;
     162    12197085 :   for (size_t i = 0; i < n; ++i) {
     163     5420908 :     if (!std::isnan(a[i])) {
     164     5420815 :       x = std::max(a[i], x);
     165             :     }
     166             :   }
     167             :   DCHECK(!std::isnan(x));
     168     1355269 :   return x == 0 ? 0 : x;  // -0 -> 0
     169             : }
     170             : 
     171             : }  // namespace
     172             : 
     173     1245023 : Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
     174             :                                double rhs_max) {
     175             :   double results[4];
     176     1245023 :   results[0] = lhs_min + rhs_min;
     177     1245023 :   results[1] = lhs_min + rhs_max;
     178     1245023 :   results[2] = lhs_max + rhs_min;
     179     1245023 :   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    11204479 :   for (int i = 0; i < 4; ++i) {
     186     4979728 :     if (std::isnan(results[i])) ++nans;
     187             :   }
     188     1245023 :   if (nans == 4) return Type::NaN();
     189     1245017 :   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
     190     1245049 :   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     1245051 :   return type;
     197             : }
     198             : 
     199       54449 : Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
     200             :                                     double rhs_min, double rhs_max) {
     201             :   double results[4];
     202       54449 :   results[0] = lhs_min - rhs_min;
     203       54449 :   results[1] = lhs_min - rhs_max;
     204       54449 :   results[2] = lhs_max - rhs_min;
     205       54449 :   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      490041 :   for (int i = 0; i < 4; ++i) {
     212      217796 :     if (std::isnan(results[i])) ++nans;
     213             :   }
     214       54449 :   if (nans == 4) return Type::NaN();  // [inf..inf] - [inf..inf] (all same sign)
     215       54443 :   Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
     216       54443 :   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       55881 : Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
     225             :                                     double rhs_min, double rhs_max) {
     226             :   double results[4];
     227       55881 :   results[0] = lhs_min * rhs_min;
     228       55881 :   results[1] = lhs_min * rhs_max;
     229       55881 :   results[2] = lhs_max * rhs_min;
     230       55881 :   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      502453 :   for (int i = 0; i < 4; ++i) {
     236      223358 :     if (std::isnan(results[i])) {
     237          72 :       return cache_->kIntegerOrMinusZeroOrNaN;
     238             :     }
     239             :   }
     240             :   double min = array_min(results, 4);
     241             :   double max = array_max(results, 4);
     242       55809 :   Type type = Type::Range(min, max, zone());
     243       55809 :   if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
     244       42766 :     type = Type::Union(type, Type::MinusZero(), zone());
     245             :   }
     246             :   // 0 * V8_INFINITY is NaN, regardless of sign
     247       95197 :   if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
     248       75509 :        (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
     249       55718 :       ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
     250         118 :        (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
     251         182 :     type = Type::Union(type, Type::NaN(), zone());
     252             :   }
     253       55809 :   return type;
     254             : }
     255             : 
     256       80785 : Type OperationTyper::ConvertReceiver(Type type) {
     257       80785 :   if (type.Is(Type::Receiver())) return type;
     258       80776 :   bool const maybe_primitive = type.Maybe(Type::Primitive());
     259       80776 :   type = Type::Intersect(type, Type::Receiver(), zone());
     260       80776 :   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       80776 :     type = Type::Union(type, Type::OtherObject(), zone());
     264             :   }
     265       80776 :   return type;
     266             : }
     267             : 
     268     3296772 : Type OperationTyper::ToNumber(Type type) {
     269     3296729 :   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      714012 :   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      436060 :   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      436071 :   if (type.Maybe(Type::Null())) {
     286             :     // ToNumber(null) => +0
     287      423301 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     288             :   }
     289      436115 :   if (type.Maybe(Type::Undefined())) {
     290             :     // ToNumber(undefined) => NaN
     291      430000 :     type = Type::Union(type, Type::NaN(), zone());
     292             :   }
     293      436090 :   if (type.Maybe(singleton_false_)) {
     294             :     // ToNumber(false) => +0
     295      425326 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     296             :   }
     297      436175 :   if (type.Maybe(singleton_true_)) {
     298             :     // ToNumber(true) => +1
     299      425907 :     type = Type::Union(type, cache_->kSingletonOne, zone());
     300             :   }
     301      436194 :   return Type::Intersect(type, Type::Number(), zone());
     302             : }
     303             : 
     304         360 : 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         360 :       type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
     309         360 :   type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
     310             : 
     311             :   // Any BigInt is rounded to an integer Number in the range [-inf, inf].
     312         360 :   return maybe_bigint ? Type::Union(type, cache_->kInteger, zone()) : type;
     313             : }
     314             : 
     315     1169893 : Type OperationTyper::ToNumeric(Type type) {
     316             :   // If the {type} includes any receivers, then the callbacks
     317             :   // might actually produce BigInt primitive values here.
     318     1169893 :   if (type.Maybe(Type::Receiver())) {
     319       59725 :     type = Type::Union(type, Type::BigInt(), zone());
     320             :   }
     321             :   return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
     322     1169893 :                      Type::Intersect(type, Type::BigInt(), zone()), zone());
     323             : }
     324             : 
     325        1281 : Type OperationTyper::NumberAbs(Type type) {
     326             :   DCHECK(type.Is(Type::Number()));
     327        1281 :   if (type.IsNone()) return type;
     328             : 
     329        1238 :   bool const maybe_nan = type.Maybe(Type::NaN());
     330        1238 :   bool const maybe_minuszero = type.Maybe(Type::MinusZero());
     331             : 
     332        1238 :   type = Type::Intersect(type, Type::PlainNumber(), zone());
     333        1238 :   if (!type.IsNone()) {
     334        1186 :     double const max = type.Max();
     335        1186 :     double const min = type.Min();
     336        1186 :     if (min < 0) {
     337        2016 :       if (type.Is(cache_->kInteger)) {
     338             :         type =
     339         662 :             Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
     340             :       } else {
     341         677 :         type = Type::PlainNumber();
     342             :       }
     343             :     }
     344             :   }
     345             : 
     346        1238 :   if (maybe_minuszero) {
     347         667 :     type = Type::Union(type, cache_->kSingletonZero, zone());
     348             :   }
     349        1238 :   if (maybe_nan) {
     350         757 :     type = Type::Union(type, Type::NaN(), zone());
     351             :   }
     352        1238 :   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         129 : Type OperationTyper::NumberAsin(Type type) {
     366             :   DCHECK(type.Is(Type::Number()));
     367         129 :   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       21858 : Type OperationTyper::NumberCeil(Type type) {
     391             :   DCHECK(type.Is(Type::Number()));
     392       43716 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     393       21213 :   type = Type::Intersect(type, Type::NaN(), zone());
     394       21213 :   type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
     395       21213 :   return type;
     396             : }
     397             : 
     398         201 : Type OperationTyper::NumberClz32(Type type) {
     399             :   DCHECK(type.Is(Type::Number()));
     400         201 :   return cache_->kZeroToThirtyTwo;
     401             : }
     402             : 
     403         157 : Type OperationTyper::NumberCos(Type type) {
     404             :   DCHECK(type.Is(Type::Number()));
     405         157 :   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         210 : Type OperationTyper::NumberExp(Type type) {
     414             :   DCHECK(type.Is(Type::Number()));
     415         210 :   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       86982 : Type OperationTyper::NumberFloor(Type type) {
     424             :   DCHECK(type.Is(Type::Number()));
     425      173964 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     426       86354 :   type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
     427       86354 :   type = Type::Union(type, cache_->kInteger, zone());
     428       86354 :   return type;
     429             : }
     430             : 
     431        4221 : Type OperationTyper::NumberFround(Type type) {
     432             :   DCHECK(type.Is(Type::Number()));
     433        4221 :   return Type::Number();
     434             : }
     435             : 
     436         507 : Type OperationTyper::NumberLog(Type type) {
     437             :   DCHECK(type.Is(Type::Number()));
     438         507 :   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        4846 : Type OperationTyper::NumberRound(Type type) {
     457             :   DCHECK(type.Is(Type::Number()));
     458        9692 :   if (type.Is(cache_->kIntegerOrMinusZeroOrNaN)) return type;
     459        4753 :   type = Type::Intersect(type, Type::NaN(), zone());
     460        4753 :   type = Type::Union(type, cache_->kIntegerOrMinusZero, zone());
     461        4753 :   return type;
     462             : }
     463             : 
     464         212 : Type OperationTyper::NumberSign(Type type) {
     465             :   DCHECK(type.Is(Type::Number()));
     466         424 :   if (type.Is(cache_->kZeroish)) return type;
     467         169 :   bool maybe_minuszero = type.Maybe(Type::MinusZero());
     468         169 :   bool maybe_nan = type.Maybe(Type::NaN());
     469         169 :   type = Type::Intersect(type, Type::PlainNumber(), zone());
     470         169 :   if (type.IsNone()) {
     471             :     // Do nothing.
     472         169 :   } else if (type.Max() < 0.0) {
     473           3 :     type = cache_->kSingletonMinusOne;
     474         166 :   } else if (type.Max() <= 0.0) {
     475           0 :     type = cache_->kMinusOneOrZero;
     476         166 :   } else if (type.Min() > 0.0) {
     477          11 :     type = cache_->kSingletonOne;
     478         155 :   } else if (type.Min() >= 0.0) {
     479           1 :     type = cache_->kZeroOrOne;
     480             :   } else {
     481         154 :     type = Type::Range(-1.0, 1.0, zone());
     482             :   }
     483         169 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     484         169 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     485             :   DCHECK(!type.IsNone());
     486         169 :   return type;
     487             : }
     488             : 
     489         194 : Type OperationTyper::NumberSin(Type type) {
     490             :   DCHECK(type.Is(Type::Number()));
     491         194 :   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         260 : Type OperationTyper::NumberSqrt(Type type) {
     500             :   DCHECK(type.Is(Type::Number()));
     501         260 :   return Type::Number();
     502             : }
     503             : 
     504         185 : Type OperationTyper::NumberTan(Type type) {
     505             :   DCHECK(type.Is(Type::Number()));
     506         185 :   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       21298 : Type OperationTyper::NumberTrunc(Type type) {
     515             :   DCHECK(type.Is(Type::Number()));
     516       42596 :   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       46126 : Type OperationTyper::NumberToBoolean(Type type) {
     523             :   DCHECK(type.Is(Type::Number()));
     524       46126 :   if (type.IsNone()) return type;
     525       92166 :   if (type.Is(cache_->kZeroish)) return singleton_false_;
     526       46082 :   if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
     527        2137 :     return singleton_true_;  // Ruled out nan, -0 and +0.
     528             :   }
     529             :   return Type::Boolean();
     530             : }
     531             : 
     532      191018 : Type OperationTyper::NumberToInt32(Type type) {
     533             :   DCHECK(type.Is(Type::Number()));
     534             : 
     535      191018 :   if (type.Is(Type::Signed32())) return type;
     536      104676 :   if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
     537       48971 :   if (type.Is(signed32ish_)) {
     538        6283 :     return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
     539        6283 :                            Type::Signed32(), zone());
     540             :   }
     541             :   return Type::Signed32();
     542             : }
     543             : 
     544       12502 : Type OperationTyper::NumberToString(Type type) {
     545             :   DCHECK(type.Is(Type::Number()));
     546       12502 :   if (type.IsNone()) return type;
     547       12455 :   if (type.Is(Type::NaN())) return singleton_NaN_string_;
     548       24908 :   if (type.Is(cache_->kZeroOrMinusZero)) return singleton_zero_string_;
     549             :   return Type::String();
     550             : }
     551             : 
     552       54415 : Type OperationTyper::NumberToUint32(Type type) {
     553             :   DCHECK(type.Is(Type::Number()));
     554             : 
     555       54415 :   if (type.Is(Type::Unsigned32())) return type;
     556       47368 :   if (type.Is(cache_->kZeroish)) return cache_->kSingletonZero;
     557       21976 :   if (type.Is(unsigned32ish_)) {
     558          46 :     return Type::Intersect(Type::Union(type, cache_->kSingletonZero, zone()),
     559          46 :                            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        1518 :   return cache_->kUint8;
     569             : }
     570             : 
     571        3569 : 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        3569 :   if (type.Maybe(Type::NaN())) return Type::Number();
     577         995 :   return type;
     578             : }
     579             : 
     580     1747548 : Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
     581             :   DCHECK(lhs.Is(Type::Number()));
     582             :   DCHECK(rhs.Is(Type::Number()));
     583             : 
     584     3493911 :   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     1746243 :   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     1746000 :   if (lhs.Maybe(Type::MinusZero())) {
     593      250662 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     594             :   } else {
     595             :     maybe_minuszero = false;
     596             :   }
     597     1746085 :   if (rhs.Maybe(Type::MinusZero())) {
     598      187649 :     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     1746265 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     606     1746256 :   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     607     3492431 :   if (!lhs.IsNone() && !rhs.IsNone()) {
     608     4853700 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     609     1245004 :       type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
     610             :     } else {
     611     1305459 :       if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
     612      319151 :           (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     1746264 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     621     1746257 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     622     1746270 :   return type;
     623             : }
     624             : 
     625       63522 : Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
     626             :   DCHECK(lhs.Is(Type::Number()));
     627             :   DCHECK(rhs.Is(Type::Number()));
     628             : 
     629      126580 :   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       62962 :   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       62962 :   if (lhs.Maybe(Type::MinusZero())) {
     639        5854 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     640        5854 :     maybe_minuszero = rhs.Maybe(cache_->kSingletonZero);
     641             :   }
     642       62962 :   if (rhs.Maybe(Type::MinusZero())) {
     643        2299 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     644             :   }
     645             : 
     646             :   // We can give more precise types for integers.
     647             :   Type type = Type::None();
     648       62962 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     649       62962 :   rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     650      125799 :   if (!lhs.IsNone() && !rhs.IsNone()) {
     651      181220 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     652       54449 :       type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
     653             :     } else {
     654       22690 :       if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
     655        6926 :           (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       62962 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     664       62962 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     665       62962 :   return type;
     666             : }
     667             : 
     668      506172 : Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
     669      506172 :   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      506265 :   return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
     676             : }
     677             : 
     678       39847 : Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
     679       39847 :   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       39847 :   return Type::Intersect(result, cache_->kSafeIntegerOrMinusZero, zone());
     686             : }
     687             : 
     688       81100 : Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
     689             :   DCHECK(lhs.Is(Type::Number()));
     690             :   DCHECK(rhs.Is(Type::Number()));
     691             : 
     692      161964 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     693      161518 :   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      172410 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
     699       83193 :                    (lhs.Maybe(cache_->kZeroish) &&
     700      200927 :                     (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
     701       47949 :                    (rhs.Maybe(cache_->kZeroish) &&
     702        6278 :                     (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
     703       80634 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
     704             :   DCHECK(!lhs.IsNone());
     705       80634 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
     706             :   DCHECK(!rhs.IsNone());
     707             : 
     708             :   // Try to rule out -0.
     709      124510 :   bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
     710       85969 :                          rhs.Maybe(Type::MinusZero()) ||
     711      184269 :                          (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
     712       27666 :                          (rhs.Maybe(cache_->kZeroish) && lhs.Min() < 0.0);
     713       80634 :   if (lhs.Maybe(Type::MinusZero())) {
     714       36758 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     715       36758 :     lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     716             :   }
     717       80634 :   if (rhs.Maybe(Type::MinusZero())) {
     718        4970 :     rhs = Type::Union(rhs, cache_->kSingletonZero, zone());
     719        4970 :     rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
     720             :   }
     721             : 
     722             :   // Compute the effective type, utilizing range information if possible.
     723      198658 :   Type type = (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger))
     724       55881 :                   ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
     725      136515 :                   : Type::OrderedNumber();
     726             : 
     727             :   // Take into account the -0 and NaN information computed earlier.
     728       80634 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     729       80634 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     730       80634 :   return type;
     731             : }
     732             : 
     733       65461 : Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
     734             :   DCHECK(lhs.Is(Type::Number()));
     735             :   DCHECK(rhs.Is(Type::Number()));
     736             : 
     737      130841 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     738      128373 :   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       93131 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
     742       60163 :                    ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
     743        4223 :                     (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
     744       63490 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
     745             :   DCHECK(!lhs.IsNone());
     746       63490 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
     747             :   DCHECK(!rhs.IsNone());
     748             : 
     749             :   // Try to rule out -0.
     750             :   bool maybe_minuszero =
     751      110021 :       !lhs.Is(cache_->kInteger) ||
     752      117697 :       (lhs.Maybe(cache_->kZeroish) && rhs.Min() < 0.0) ||
     753       62535 :       (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       63490 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     758       63490 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     759       63490 :   return type;
     760             : }
     761             : 
     762       14618 : Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
     763             :   DCHECK(lhs.Is(Type::Number()));
     764             :   DCHECK(rhs.Is(Type::Number()));
     765             : 
     766       29155 :   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       36552 :   bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_->kZeroish) ||
     771       34751 :                    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       14487 :   if (lhs.Maybe(Type::MinusZero())) {
     776             :     maybe_minuszero = true;
     777        3759 :     lhs = Type::Union(lhs, cache_->kSingletonZero, zone());
     778             :   }
     779       14487 :   if (rhs.Maybe(Type::MinusZero())) {
     780         898 :     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       14487 :   lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
     786       14487 :   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       28856 :   if (!lhs.IsNone() && !rhs.Is(cache_->kSingletonZero)) {
     791             :     // Determine the bounds of {lhs} and {rhs}.
     792       14228 :     double const lmin = lhs.Min();
     793       14228 :     double const lmax = lhs.Max();
     794       14228 :     double const rmin = rhs.Min();
     795       14228 :     double const rmax = rhs.Max();
     796             : 
     797             :     // The sign of the result is the sign of the {lhs}.
     798       14228 :     if (lmin < 0.0) maybe_minuszero = true;
     799             : 
     800             :     // For integer inputs {lhs} and {rhs} we can infer a precise type.
     801       40134 :     if (lhs.Is(cache_->kInteger) && rhs.Is(cache_->kInteger)) {
     802       33669 :       double labs = std::max(std::abs(lmin), std::abs(lmax));
     803       33669 :       double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
     804       11223 :       double abs = std::min(labs, rabs);
     805             :       double min = 0.0, max = 0.0;
     806       11223 :       if (lmin >= 0.0) {
     807             :         // {lhs} positive.
     808             :         min = 0.0;
     809             :         max = abs;
     810        8222 :       } else if (lmax <= 0.0) {
     811             :         // {lhs} negative.
     812         725 :         min = 0.0 - abs;
     813             :         max = 0.0;
     814             :       } else {
     815             :         // {lhs} positive or negative.
     816        7497 :         min = 0.0 - abs;
     817             :         max = abs;
     818             :       }
     819       11223 :       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       14487 :   if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
     827       14487 :   if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
     828       14487 :   return type;
     829             : }
     830             : 
     831       45066 : Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
     832             :   DCHECK(lhs.Is(Type::Number()));
     833             :   DCHECK(rhs.Is(Type::Number()));
     834             : 
     835       45066 :   lhs = NumberToInt32(lhs);
     836       45066 :   rhs = NumberToInt32(rhs);
     837             : 
     838       89965 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     839             : 
     840       44849 :   double lmin = lhs.Min();
     841       44849 :   double rmin = rhs.Min();
     842       44849 :   double lmax = lhs.Max();
     843       44849 :   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       89698 :       lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
     848       44849 :   double max = kMaxInt;
     849             : 
     850             :   // Or-ing with 0 is essentially a conversion to int32.
     851       44849 :   if (rmin == 0 && rmax == 0) {
     852             :     min = lmin;
     853       31891 :     max = lmax;
     854             :   }
     855       44849 :   if (lmin == 0 && lmax == 0) {
     856             :     min = rmin;
     857         591 :     max = rmax;
     858             :   }
     859             : 
     860       44849 :   if (lmax < 0 || rmax < 0) {
     861             :     // Or-ing two values of which at least one is negative results in a negative
     862             :     // value.
     863         458 :     max = std::min(max, -1.0);
     864             :   }
     865       44849 :   return Type::Range(min, max, zone());
     866             : }
     867             : 
     868       28173 : Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
     869             :   DCHECK(lhs.Is(Type::Number()));
     870             :   DCHECK(rhs.Is(Type::Number()));
     871             : 
     872       28173 :   lhs = NumberToInt32(lhs);
     873       28173 :   rhs = NumberToInt32(rhs);
     874             : 
     875       56206 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     876             : 
     877       27983 :   double lmin = lhs.Min();
     878       27983 :   double rmin = rhs.Min();
     879       27983 :   double lmax = lhs.Max();
     880       27983 :   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       55966 :       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       27983 :   if (lmin >= 0) {
     889             :     min = 0;
     890        7593 :     max = std::min(max, lmax);
     891             :   }
     892       27983 :   if (rmin >= 0) {
     893             :     min = 0;
     894       25700 :     max = std::min(max, rmax);
     895             :   }
     896       27983 :   return Type::Range(min, max, zone());
     897             : }
     898             : 
     899        4317 : Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
     900             :   DCHECK(lhs.Is(Type::Number()));
     901             :   DCHECK(rhs.Is(Type::Number()));
     902             : 
     903        4317 :   lhs = NumberToInt32(lhs);
     904        4317 :   rhs = NumberToInt32(rhs);
     905             : 
     906        8545 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     907             : 
     908        4178 :   double lmin = lhs.Min();
     909        4178 :   double rmin = rhs.Min();
     910        4178 :   double lmax = lhs.Max();
     911        4178 :   double rmax = rhs.Max();
     912        4178 :   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        3930 :   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        9295 : Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
     925             :   DCHECK(lhs.Is(Type::Number()));
     926             :   DCHECK(rhs.Is(Type::Number()));
     927             : 
     928        9295 :   lhs = NumberToInt32(lhs);
     929        9295 :   rhs = NumberToUint32(rhs);
     930             : 
     931       18502 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     932             : 
     933        9157 :   int32_t min_lhs = lhs.Min();
     934        9157 :   int32_t max_lhs = lhs.Max();
     935        9157 :   uint32_t min_rhs = rhs.Min();
     936        9157 :   uint32_t max_rhs = rhs.Max();
     937        9157 :   if (max_rhs > 31) {
     938             :     // rhs can be larger than the bitmask
     939             :     max_rhs = 31;
     940             :     min_rhs = 0;
     941             :   }
     942             : 
     943        9157 :   if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
     944             :     // overflow possible
     945             :     return Type::Signed32();
     946             :   }
     947             : 
     948             :   double min =
     949        2380 :       std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
     950        3570 :                static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
     951             :   double max =
     952        2380 :       std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
     953        3570 :                static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
     954             : 
     955        1190 :   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
     956         941 :   return Type::Range(min, max, zone());
     957             : }
     958             : 
     959       18222 : Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
     960             :   DCHECK(lhs.Is(Type::Number()));
     961             :   DCHECK(rhs.Is(Type::Number()));
     962             : 
     963       18222 :   lhs = NumberToInt32(lhs);
     964       18222 :   rhs = NumberToUint32(rhs);
     965             : 
     966       36334 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     967             : 
     968       18048 :   int32_t min_lhs = lhs.Min();
     969       18048 :   int32_t max_lhs = lhs.Max();
     970       18048 :   uint32_t min_rhs = rhs.Min();
     971       18048 :   uint32_t max_rhs = rhs.Max();
     972       18048 :   if (max_rhs > 31) {
     973             :     // rhs can be larger than the bitmask
     974             :     max_rhs = 31;
     975             :     min_rhs = 0;
     976             :   }
     977       36096 :   double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
     978       36096 :   double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
     979             : 
     980       18048 :   if (max == kMaxInt && min == kMinInt) return Type::Signed32();
     981       16624 :   return Type::Range(min, max, zone());
     982             : }
     983             : 
     984        7924 : Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
     985             :   DCHECK(lhs.Is(Type::Number()));
     986             :   DCHECK(rhs.Is(Type::Number()));
     987             : 
     988        7924 :   lhs = NumberToUint32(lhs);
     989        7924 :   rhs = NumberToUint32(rhs);
     990             : 
     991       15742 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
     992             : 
     993        7761 :   uint32_t min_lhs = lhs.Min();
     994        7761 :   uint32_t max_lhs = lhs.Max();
     995        7761 :   uint32_t min_rhs = rhs.Min();
     996        7761 :   uint32_t max_rhs = rhs.Max();
     997        7761 :   if (max_rhs > 31) {
     998             :     // rhs can be larger than the bitmask
     999             :     max_rhs = 31;
    1000             :     min_rhs = 0;
    1001             :   }
    1002             : 
    1003        7761 :   double min = min_lhs >> max_rhs;
    1004        7761 :   double max = max_lhs >> min_rhs;
    1005             :   DCHECK_LE(0, min);
    1006             :   DCHECK_LE(max, kMaxUInt32);
    1007             : 
    1008        7761 :   if (min == 0 && max == kMaxInt) return Type::Unsigned31();
    1009        7130 :   if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
    1010        2936 :   return Type::Range(min, max, zone());
    1011             : }
    1012             : 
    1013         138 : Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
    1014             :   DCHECK(lhs.Is(Type::Number()));
    1015             :   DCHECK(rhs.Is(Type::Number()));
    1016         138 :   return Type::Number();
    1017             : }
    1018             : 
    1019        2754 : 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        2754 :   return Type::Signed32();
    1024             : }
    1025             : 
    1026       10319 : Type OperationTyper::NumberMax(Type lhs, Type rhs) {
    1027             :   DCHECK(lhs.Is(Type::Number()));
    1028             :   DCHECK(rhs.Is(Type::Number()));
    1029             : 
    1030       20600 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    1031       20502 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    1032             : 
    1033             :   Type type = Type::None();
    1034       10239 :   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
    1035         250 :     type = Type::Union(type, Type::NaN(), zone());
    1036             :   }
    1037       10239 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
    1038             :   DCHECK(!lhs.IsNone());
    1039       10239 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
    1040             :   DCHECK(!rhs.IsNone());
    1041       30487 :   if (lhs.Is(cache_->kIntegerOrMinusZero) &&
    1042       10009 :       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       19858 :     double max = std::max(lhs.Max(), rhs.Max());
    1046       19858 :     double min = std::max(lhs.Min(), rhs.Min());
    1047        9929 :     type = Type::Union(type, Type::Range(min, max, zone()), zone());
    1048       28246 :     if (min <= 0.0 && 0.0 <= max &&
    1049       16669 :         (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
    1050         182 :       type = Type::Union(type, Type::MinusZero(), zone());
    1051             :     }
    1052             :   } else {
    1053         310 :     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
    1054             :   }
    1055       10239 :   return type;
    1056             : }
    1057             : 
    1058       11854 : Type OperationTyper::NumberMin(Type lhs, Type rhs) {
    1059             :   DCHECK(lhs.Is(Type::Number()));
    1060             :   DCHECK(rhs.Is(Type::Number()));
    1061             : 
    1062       23670 :   if (lhs.IsNone() || rhs.IsNone()) return Type::None();
    1063       23572 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
    1064             : 
    1065             :   Type type = Type::None();
    1066       11774 :   if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
    1067         511 :     type = Type::Union(type, Type::NaN(), zone());
    1068             :   }
    1069       11774 :   lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
    1070             :   DCHECK(!lhs.IsNone());
    1071       11774 :   rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
    1072             :   DCHECK(!rhs.IsNone());
    1073       34876 :   if (lhs.Is(cache_->kIntegerOrMinusZero) &&
    1074       11328 :       rhs.Is(cache_->kIntegerOrMinusZero)) {
    1075       22448 :     double max = std::min(lhs.Max(), rhs.Max());
    1076       22448 :     double min = std::min(lhs.Min(), rhs.Min());
    1077       11224 :     type = Type::Union(type, Type::Range(min, max, zone()), zone());
    1078       33493 :     if (min <= 0.0 && 0.0 <= max &&
    1079       21996 :         (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
    1080         147 :       type = Type::Union(type, Type::MinusZero(), zone());
    1081             :     }
    1082             :   } else {
    1083         550 :     type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
    1084             :   }
    1085       11774 :   return type;
    1086             : }
    1087             : 
    1088        3098 : 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        3098 :   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      602654 : SPECULATIVE_NUMBER_BINOP(NumberAdd)
    1102       40913 : SPECULATIVE_NUMBER_BINOP(NumberSubtract)
    1103       48854 : SPECULATIVE_NUMBER_BINOP(NumberMultiply)
    1104       49788 : SPECULATIVE_NUMBER_BINOP(NumberDivide)
    1105        9304 : SPECULATIVE_NUMBER_BINOP(NumberModulus)
    1106       35313 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
    1107       14024 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
    1108        2503 : SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
    1109        4727 : SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
    1110       14884 : SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
    1111        3680 : SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
    1112             : #undef SPECULATIVE_NUMBER_BINOP
    1113             : 
    1114     1787527 : Type OperationTyper::SpeculativeToNumber(Type type) {
    1115     1787527 :   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      369612 : Type JSType(Type type) {
    1156      369612 :   if (type.Is(Type::Boolean())) return Type::Boolean();
    1157      362159 :   if (type.Is(Type::String())) return Type::String();
    1158      281152 :   if (type.Is(Type::Number())) return Type::Number();
    1159      148203 :   if (type.Is(Type::BigInt())) return Type::BigInt();
    1160      148101 :   if (type.Is(Type::Undefined())) return Type::Undefined();
    1161      145658 :   if (type.Is(Type::Null())) return Type::Null();
    1162      145435 :   if (type.Is(Type::Symbol())) return Type::Symbol();
    1163      145394 :   if (type.Is(Type::Receiver())) return Type::Receiver();  // JS "Object"
    1164             :   return Type::Any();
    1165             : }
    1166             : 
    1167             : }  // namespace
    1168             : 
    1169         467 : Type OperationTyper::SameValue(Type lhs, Type rhs) {
    1170         467 :   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
    1171         467 :   if (lhs.Is(Type::NaN())) {
    1172          40 :     if (rhs.Is(Type::NaN())) return singleton_true();
    1173          40 :     if (!rhs.Maybe(Type::NaN())) return singleton_false();
    1174         427 :   } else if (rhs.Is(Type::NaN())) {
    1175          16 :     if (!lhs.Maybe(Type::NaN())) return singleton_false();
    1176             :   }
    1177         467 :   if (lhs.Is(Type::MinusZero())) {
    1178          93 :     if (rhs.Is(Type::MinusZero())) return singleton_true();
    1179          93 :     if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
    1180         374 :   } else if (rhs.Is(Type::MinusZero())) {
    1181          44 :     if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
    1182             :   }
    1183        1048 :   if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
    1184          60 :       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
    1185             :     return singleton_false();
    1186             :   }
    1187             :   return Type::Boolean();
    1188             : }
    1189             : 
    1190      184339 : Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
    1191      184339 :   if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
    1192      357814 :   if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
    1193      447340 :   if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
    1194       89809 :       (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
    1195             :     return singleton_false();
    1196             :   }
    1197      349322 :   if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
    1198             :     return singleton_false();
    1199             :   }
    1200      176290 :   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       53008 : Type OperationTyper::StringConcat(Type length, Type first, Type second) {
    1209      159020 :   if (length.IsNone() || first.IsNone() || second.IsNone()) return Type::None();
    1210       52987 :   if (first.Is(Type::EmptyString())) return second;
    1211       52743 :   if (second.Is(Type::EmptyString())) return first;
    1212             : 
    1213       52708 :   first = Type::Intersect(first, Type::NonEmptyString(), zone());
    1214       52708 :   second = Type::Intersect(second, Type::NonEmptyString(), zone());
    1215             : 
    1216             :   Type type = Type::NonEmptyString();
    1217       66829 :   if (first.Is(Type::NonEmptyOneByteString()) &&
    1218             :       second.Is(Type::NonEmptyOneByteString())) {
    1219             :     type = Type::NonEmptyOneByteString();
    1220       85624 :   } else if (first.Is(Type::NonEmptyTwoByteString()) ||
    1221             :              second.Is(Type::NonEmptyTwoByteString())) {
    1222             :     type = Type::NonEmptyTwoByteString();
    1223             :   }
    1224             : 
    1225       52708 :   if (length.Min() == 0) {
    1226       26285 :     type = Type::Union(type, Type::EmptyString(), zone());
    1227             :   }
    1228       52708 :   return type;
    1229             : }
    1230             : 
    1231      135673 : Type OperationTyper::CheckBounds(Type index, Type length) {
    1232             :   DCHECK(length.Is(cache_->kPositiveSafeInteger));
    1233      271346 :   if (length.Is(cache_->kSingletonZero)) return Type::None();
    1234      135608 :   Type mask = Type::Range(0.0, length.Max() - 1, zone());
    1235      135608 :   if (index.Maybe(Type::MinusZero())) {
    1236        6236 :     index = Type::Union(index, cache_->kSingletonZero, zone());
    1237             :   }
    1238      135608 :   return Type::Intersect(index, mask, zone());
    1239             : }
    1240             : 
    1241        1249 : Type OperationTyper::CheckFloat64Hole(Type type) {
    1242        1249 :   if (type.Maybe(Type::Hole())) {
    1243             :     // Turn "the hole" into undefined.
    1244        1185 :     type = Type::Intersect(type, Type::Number(), zone());
    1245        1185 :     type = Type::Union(type, Type::Undefined(), zone());
    1246             :   }
    1247        1249 :   return type;
    1248             : }
    1249             : 
    1250        3741 : Type OperationTyper::CheckNumber(Type type) {
    1251        3741 :   return Type::Intersect(type, Type::Number(), zone());
    1252             : }
    1253             : 
    1254        5075 : Type OperationTyper::CheckInternalizedString(Type type) {
    1255        5075 :   return Type::Intersect(type, Type::InternalizedString(), zone());
    1256             : }
    1257             : 
    1258          36 : Type OperationTyper::CheckNonEmptyString(Type type) {
    1259          36 :   return Type::Intersect(type, Type::NonEmptyString(), zone());
    1260             : }
    1261             : 
    1262        3645 : Type OperationTyper::CheckNonEmptyOneByteString(Type type) {
    1263        3645 :   return Type::Intersect(type, Type::NonEmptyOneByteString(), zone());
    1264             : }
    1265             : 
    1266         474 : Type OperationTyper::CheckNonEmptyTwoByteString(Type type) {
    1267         474 :   return Type::Intersect(type, Type::NonEmptyTwoByteString(), zone());
    1268             : }
    1269             : 
    1270       29215 : Type OperationTyper::CheckString(Type type) {
    1271       29215 :   return Type::Intersect(type, Type::String(), zone());
    1272             : }
    1273             : 
    1274      100081 : Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
    1275      100081 :   return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
    1276             : }
    1277             : 
    1278        4673 : Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
    1279        4673 :   if (input.Maybe(Type::Hole())) {
    1280             :     // Turn "the hole" into undefined.
    1281        4623 :     Type type = Type::Intersect(input, Type::NonInternal(), zone());
    1282        4623 :     return Type::Union(type, Type::Undefined(), zone());
    1283             :   }
    1284          50 :   return input;
    1285             : }
    1286             : 
    1287      210594 : Type OperationTyper::ToBoolean(Type type) {
    1288      210594 :   if (type.Is(Type::Boolean())) return type;
    1289      175773 :   if (type.Is(falsish_)) return singleton_false_;
    1290      173270 :   if (type.Is(truish_)) return singleton_true_;
    1291      173147 :   if (type.Is(Type::Number())) {
    1292       45578 :     return NumberToBoolean(type);
    1293             :   }
    1294             :   return Type::Boolean();
    1295             : }
    1296             : 
    1297             : }  // namespace compiler
    1298             : }  // namespace internal
    1299      122004 : }  // namespace v8

Generated by: LCOV version 1.10