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