V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
operation-typer.cc
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/operation-typer.h"
6 
7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/type-cache.h"
9 #include "src/compiler/types.h"
10 #include "src/heap/factory.h"
11 #include "src/isolate.h"
12 
13 #include "src/objects-inl.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
19 OperationTyper::OperationTyper(JSHeapBroker* broker, Zone* zone)
20  : zone_(zone), cache_(TypeCache::Get()) {
21  Factory* factory = broker->isolate()->factory();
22  infinity_ = Type::NewConstant(V8_INFINITY, zone);
23  minus_infinity_ = Type::NewConstant(-V8_INFINITY, zone);
24  Type truncating_to_zero = Type::MinusZeroOrNaN();
25  DCHECK(!truncating_to_zero.Maybe(Type::Integral32()));
26 
27  singleton_empty_string_ =
28  Type::HeapConstant(broker, factory->empty_string(), zone);
29  singleton_NaN_string_ =
30  Type::HeapConstant(broker, factory->NaN_string(), zone);
31  singleton_zero_string_ =
32  Type::HeapConstant(broker, factory->zero_string(), zone);
33  singleton_false_ = Type::HeapConstant(broker, factory->false_value(), zone);
34  singleton_true_ = Type::HeapConstant(broker, factory->true_value(), zone);
35  singleton_the_hole_ =
36  Type::HeapConstant(broker, factory->the_hole_value(), zone);
37  signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone);
38  unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone);
39 
40  falsish_ = Type::Union(
41  Type::Undetectable(),
42  Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
43  Type::Union(singleton_empty_string_, Type::Hole(), zone),
44  zone),
45  zone);
46  truish_ = Type::Union(
47  singleton_true_,
48  Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
49 }
50 
51 Type OperationTyper::Merge(Type left, Type right) {
52  return Type::Union(left, right, zone());
53 }
54 
55 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  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  if (current_min != previous_range.Min()) {
105  new_min = -V8_INFINITY;
106  for (double const min : kWeakenMinLimits) {
107  if (min <= current_min) {
108  new_min = min;
109  break;
110  }
111  }
112  }
113 
114  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  if (current_max != previous_range.Max()) {
119  new_max = V8_INFINITY;
120  for (double const max : kWeakenMaxLimits) {
121  if (max >= current_max) {
122  new_max = max;
123  break;
124  }
125  }
126  }
127 
128  return Type::Range(new_min, new_max, zone());
129 }
130 
131 Type OperationTyper::Rangify(Type type) {
132  if (type.IsRange()) return type; // Shortcut.
133  if (!type.Is(cache_.kInteger)) {
134  return type; // Give up on non-integer types.
135  }
136  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  double x = +V8_INFINITY;
147  for (size_t i = 0; i < n; ++i) {
148  if (!std::isnan(a[i])) {
149  x = std::min(a[i], x);
150  }
151  }
152  DCHECK(!std::isnan(x));
153  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  double x = -V8_INFINITY;
162  for (size_t i = 0; i < n; ++i) {
163  if (!std::isnan(a[i])) {
164  x = std::max(a[i], x);
165  }
166  }
167  DCHECK(!std::isnan(x));
168  return x == 0 ? 0 : x; // -0 -> 0
169 }
170 
171 } // namespace
172 
173 Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min,
174  double rhs_max) {
175  double results[4];
176  results[0] = lhs_min + rhs_min;
177  results[1] = lhs_min + rhs_max;
178  results[2] = lhs_max + rhs_min;
179  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  for (int i = 0; i < 4; ++i) {
186  if (std::isnan(results[i])) ++nans;
187  }
188  if (nans == 4) return Type::NaN();
189  Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
190  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  return type;
197 }
198 
199 Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max,
200  double rhs_min, double rhs_max) {
201  double results[4];
202  results[0] = lhs_min - rhs_min;
203  results[1] = lhs_min - rhs_max;
204  results[2] = lhs_max - rhs_min;
205  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  for (int i = 0; i < 4; ++i) {
212  if (std::isnan(results[i])) ++nans;
213  }
214  if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign)
215  Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone());
216  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 Type OperationTyper::MultiplyRanger(double lhs_min, double lhs_max,
225  double rhs_min, double rhs_max) {
226  double results[4];
227  results[0] = lhs_min * rhs_min;
228  results[1] = lhs_min * rhs_max;
229  results[2] = lhs_max * rhs_min;
230  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  for (int i = 0; i < 4; ++i) {
236  if (std::isnan(results[i])) {
237  return cache_.kIntegerOrMinusZeroOrNaN;
238  }
239  }
240  double min = array_min(results, 4);
241  double max = array_max(results, 4);
242  Type type = Type::Range(min, max, zone());
243  if (min <= 0.0 && 0.0 <= max && (lhs_min < 0.0 || rhs_min < 0.0)) {
244  type = Type::Union(type, Type::MinusZero(), zone());
245  }
246  // 0 * V8_INFINITY is NaN, regardless of sign
247  if (((lhs_min == -V8_INFINITY || lhs_max == V8_INFINITY) &&
248  (rhs_min <= 0.0 && 0.0 <= rhs_max)) ||
249  ((rhs_min == -V8_INFINITY || rhs_max == V8_INFINITY) &&
250  (lhs_min <= 0.0 && 0.0 <= lhs_max))) {
251  type = Type::Union(type, Type::NaN(), zone());
252  }
253  return type;
254 }
255 
256 Type OperationTyper::ConvertReceiver(Type type) {
257  if (type.Is(Type::Receiver())) return type;
258  bool const maybe_primitive = type.Maybe(Type::Primitive());
259  type = Type::Intersect(type, Type::Receiver(), zone());
260  if (maybe_primitive) {
261  // ConvertReceiver maps null and undefined to the JSGlobalProxy of the
262  // target function, and all other primitives are wrapped into a JSValue.
263  type = Type::Union(type, Type::OtherObject(), zone());
264  }
265  return type;
266 }
267 
268 Type OperationTyper::ToNumber(Type type) {
269  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  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  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  if (type.Maybe(Type::Null())) {
286  // ToNumber(null) => +0
287  type = Type::Union(type, cache_.kSingletonZero, zone());
288  }
289  if (type.Maybe(Type::Undefined())) {
290  // ToNumber(undefined) => NaN
291  type = Type::Union(type, Type::NaN(), zone());
292  }
293  if (type.Maybe(singleton_false_)) {
294  // ToNumber(false) => +0
295  type = Type::Union(type, cache_.kSingletonZero, zone());
296  }
297  if (type.Maybe(singleton_true_)) {
298  // ToNumber(true) => +1
299  type = Type::Union(type, cache_.kSingletonOne, zone());
300  }
301  return Type::Intersect(type, Type::Number(), zone());
302 }
303 
304 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  type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
309  type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
310 
311  // Any BigInt is rounded to an integer Number in the range [-inf, inf].
312  return maybe_bigint ? Type::Union(type, cache_.kInteger, zone()) : type;
313 }
314 
315 Type OperationTyper::ToNumeric(Type type) {
316  // If the {type} includes any receivers, then the callbacks
317  // might actually produce BigInt primitive values here.
318  if (type.Maybe(Type::Receiver())) {
319  type = Type::Union(type, Type::BigInt(), zone());
320  }
321  return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322  Type::Intersect(type, Type::BigInt(), zone()), zone());
323 }
324 
325 Type OperationTyper::NumberAbs(Type type) {
326  DCHECK(type.Is(Type::Number()));
327  if (type.IsNone()) return type;
328 
329  bool const maybe_nan = type.Maybe(Type::NaN());
330  bool const maybe_minuszero = type.Maybe(Type::MinusZero());
331 
332  type = Type::Intersect(type, Type::PlainNumber(), zone());
333  if (!type.IsNone()) {
334  double const max = type.Max();
335  double const min = type.Min();
336  if (min < 0) {
337  if (type.Is(cache_.kInteger)) {
338  type =
339  Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
340  } else {
341  type = Type::PlainNumber();
342  }
343  }
344  }
345 
346  if (maybe_minuszero) {
347  type = Type::Union(type, cache_.kSingletonZero, zone());
348  }
349  if (maybe_nan) {
350  type = Type::Union(type, Type::NaN(), zone());
351  }
352  return type;
353 }
354 
355 Type OperationTyper::NumberAcos(Type type) {
356  DCHECK(type.Is(Type::Number()));
357  return Type::Number();
358 }
359 
360 Type OperationTyper::NumberAcosh(Type type) {
361  DCHECK(type.Is(Type::Number()));
362  return Type::Number();
363 }
364 
365 Type OperationTyper::NumberAsin(Type type) {
366  DCHECK(type.Is(Type::Number()));
367  return Type::Number();
368 }
369 
370 Type OperationTyper::NumberAsinh(Type type) {
371  DCHECK(type.Is(Type::Number()));
372  return Type::Number();
373 }
374 
375 Type OperationTyper::NumberAtan(Type type) {
376  DCHECK(type.Is(Type::Number()));
377  return Type::Number();
378 }
379 
380 Type OperationTyper::NumberAtanh(Type type) {
381  DCHECK(type.Is(Type::Number()));
382  return Type::Number();
383 }
384 
385 Type OperationTyper::NumberCbrt(Type type) {
386  DCHECK(type.Is(Type::Number()));
387  return Type::Number();
388 }
389 
390 Type OperationTyper::NumberCeil(Type type) {
391  DCHECK(type.Is(Type::Number()));
392  if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
393  type = Type::Intersect(type, Type::NaN(), zone());
394  type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
395  return type;
396 }
397 
398 Type OperationTyper::NumberClz32(Type type) {
399  DCHECK(type.Is(Type::Number()));
400  return cache_.kZeroToThirtyTwo;
401 }
402 
403 Type OperationTyper::NumberCos(Type type) {
404  DCHECK(type.Is(Type::Number()));
405  return Type::Number();
406 }
407 
408 Type OperationTyper::NumberCosh(Type type) {
409  DCHECK(type.Is(Type::Number()));
410  return Type::Number();
411 }
412 
413 Type OperationTyper::NumberExp(Type type) {
414  DCHECK(type.Is(Type::Number()));
415  return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
416 }
417 
418 Type OperationTyper::NumberExpm1(Type type) {
419  DCHECK(type.Is(Type::Number()));
420  return Type::Number();
421 }
422 
423 Type OperationTyper::NumberFloor(Type type) {
424  DCHECK(type.Is(Type::Number()));
425  if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
426  type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
427  type = Type::Union(type, cache_.kInteger, zone());
428  return type;
429 }
430 
431 Type OperationTyper::NumberFround(Type type) {
432  DCHECK(type.Is(Type::Number()));
433  return Type::Number();
434 }
435 
436 Type OperationTyper::NumberLog(Type type) {
437  DCHECK(type.Is(Type::Number()));
438  return Type::Number();
439 }
440 
441 Type OperationTyper::NumberLog1p(Type type) {
442  DCHECK(type.Is(Type::Number()));
443  return Type::Number();
444 }
445 
446 Type OperationTyper::NumberLog2(Type type) {
447  DCHECK(type.Is(Type::Number()));
448  return Type::Number();
449 }
450 
451 Type OperationTyper::NumberLog10(Type type) {
452  DCHECK(type.Is(Type::Number()));
453  return Type::Number();
454 }
455 
456 Type OperationTyper::NumberRound(Type type) {
457  DCHECK(type.Is(Type::Number()));
458  if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
459  type = Type::Intersect(type, Type::NaN(), zone());
460  type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
461  return type;
462 }
463 
464 Type OperationTyper::NumberSign(Type type) {
465  DCHECK(type.Is(Type::Number()));
466  if (type.Is(cache_.kZeroish)) return type;
467  bool maybe_minuszero = type.Maybe(Type::MinusZero());
468  bool maybe_nan = type.Maybe(Type::NaN());
469  type = Type::Intersect(type, Type::PlainNumber(), zone());
470  if (type.IsNone()) {
471  // Do nothing.
472  } else if (type.Max() < 0.0) {
473  type = cache_.kSingletonMinusOne;
474  } else if (type.Max() <= 0.0) {
475  type = cache_.kMinusOneOrZero;
476  } else if (type.Min() > 0.0) {
477  type = cache_.kSingletonOne;
478  } else if (type.Min() >= 0.0) {
479  type = cache_.kZeroOrOne;
480  } else {
481  type = Type::Range(-1.0, 1.0, zone());
482  }
483  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
484  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
485  DCHECK(!type.IsNone());
486  return type;
487 }
488 
489 Type OperationTyper::NumberSin(Type type) {
490  DCHECK(type.Is(Type::Number()));
491  return Type::Number();
492 }
493 
494 Type OperationTyper::NumberSinh(Type type) {
495  DCHECK(type.Is(Type::Number()));
496  return Type::Number();
497 }
498 
499 Type OperationTyper::NumberSqrt(Type type) {
500  DCHECK(type.Is(Type::Number()));
501  return Type::Number();
502 }
503 
504 Type OperationTyper::NumberTan(Type type) {
505  DCHECK(type.Is(Type::Number()));
506  return Type::Number();
507 }
508 
509 Type OperationTyper::NumberTanh(Type type) {
510  DCHECK(type.Is(Type::Number()));
511  return Type::Number();
512 }
513 
514 Type OperationTyper::NumberTrunc(Type type) {
515  DCHECK(type.Is(Type::Number()));
516  if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
517  type = Type::Intersect(type, Type::NaN(), zone());
518  type = Type::Union(type, cache_.kIntegerOrMinusZero, zone());
519  return type;
520 }
521 
522 Type OperationTyper::NumberToBoolean(Type type) {
523  DCHECK(type.Is(Type::Number()));
524  if (type.IsNone()) return type;
525  if (type.Is(cache_.kZeroish)) return singleton_false_;
526  if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) {
527  return singleton_true_; // Ruled out nan, -0 and +0.
528  }
529  return Type::Boolean();
530 }
531 
532 Type OperationTyper::NumberToInt32(Type type) {
533  DCHECK(type.Is(Type::Number()));
534 
535  if (type.Is(Type::Signed32())) return type;
536  if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
537  if (type.Is(signed32ish_)) {
538  return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
539  Type::Signed32(), zone());
540  }
541  return Type::Signed32();
542 }
543 
544 Type OperationTyper::NumberToString(Type type) {
545  DCHECK(type.Is(Type::Number()));
546  if (type.IsNone()) return type;
547  if (type.Is(Type::NaN())) return singleton_NaN_string_;
548  if (type.Is(cache_.kZeroOrMinusZero)) return singleton_zero_string_;
549  return Type::String();
550 }
551 
552 Type OperationTyper::NumberToUint32(Type type) {
553  DCHECK(type.Is(Type::Number()));
554 
555  if (type.Is(Type::Unsigned32())) return type;
556  if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero;
557  if (type.Is(unsigned32ish_)) {
558  return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()),
559  Type::Unsigned32(), zone());
560  }
561  return Type::Unsigned32();
562 }
563 
564 Type OperationTyper::NumberToUint8Clamped(Type type) {
565  DCHECK(type.Is(Type::Number()));
566 
567  if (type.Is(cache_.kUint8)) return type;
568  return cache_.kUint8;
569 }
570 
571 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  if (type.Maybe(Type::NaN())) return Type::Number();
577  return type;
578 }
579 
580 Type OperationTyper::NumberAdd(Type lhs, Type rhs) {
581  DCHECK(lhs.Is(Type::Number()));
582  DCHECK(rhs.Is(Type::Number()));
583 
584  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  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  if (lhs.Maybe(Type::MinusZero())) {
593  lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
594  } else {
595  maybe_minuszero = false;
596  }
597  if (rhs.Maybe(Type::MinusZero())) {
598  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  lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
606  rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
607  if (!lhs.IsNone() && !rhs.IsNone()) {
608  if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
609  type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
610  } else {
611  if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612  (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  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
622  return type;
623 }
624 
625 Type OperationTyper::NumberSubtract(Type lhs, Type rhs) {
626  DCHECK(lhs.Is(Type::Number()));
627  DCHECK(rhs.Is(Type::Number()));
628 
629  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  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  if (lhs.Maybe(Type::MinusZero())) {
639  lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
640  maybe_minuszero = rhs.Maybe(cache_.kSingletonZero);
641  }
642  if (rhs.Maybe(Type::MinusZero())) {
643  rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
644  }
645 
646  // We can give more precise types for integers.
647  Type type = Type::None();
648  lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
649  rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
650  if (!lhs.IsNone() && !rhs.IsNone()) {
651  if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
652  type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max());
653  } else {
654  if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655  (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  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
665  return type;
666 }
667 
668 Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) {
669  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  return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
676 }
677 
678 Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) {
679  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  return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
686 }
687 
688 Type OperationTyper::NumberMultiply(Type lhs, Type rhs) {
689  DCHECK(lhs.Is(Type::Number()));
690  DCHECK(rhs.Is(Type::Number()));
691 
692  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
693  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  bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()) ||
699  (lhs.Maybe(cache_.kZeroish) &&
700  (rhs.Min() == -V8_INFINITY || rhs.Max() == V8_INFINITY)) ||
701  (rhs.Maybe(cache_.kZeroish) &&
702  (lhs.Min() == -V8_INFINITY || lhs.Max() == V8_INFINITY));
703  lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
704  DCHECK(!lhs.IsNone());
705  rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
706  DCHECK(!rhs.IsNone());
707 
708  // Try to rule out -0.
709  bool maybe_minuszero = lhs.Maybe(Type::MinusZero()) ||
710  rhs.Maybe(Type::MinusZero()) ||
711  (lhs.Maybe(cache_.kZeroish) && rhs.Min() < 0.0) ||
712  (rhs.Maybe(cache_.kZeroish) && lhs.Min() < 0.0);
713  if (lhs.Maybe(Type::MinusZero())) {
714  lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
715  lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
716  }
717  if (rhs.Maybe(Type::MinusZero())) {
718  rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
719  rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
720  }
721 
722  // Compute the effective type, utilizing range information if possible.
723  Type type = (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger))
724  ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725  : Type::OrderedNumber();
726 
727  // Take into account the -0 and NaN information computed earlier.
728  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
730  return type;
731 }
732 
733 Type OperationTyper::NumberDivide(Type lhs, Type rhs) {
734  DCHECK(lhs.Is(Type::Number()));
735  DCHECK(rhs.Is(Type::Number()));
736 
737  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
738  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  bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
742  ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) &&
743  (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY));
744  lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
745  DCHECK(!lhs.IsNone());
746  rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
747  DCHECK(!rhs.IsNone());
748 
749  // Try to rule out -0.
750  bool maybe_minuszero =
751  !lhs.Is(cache_.kInteger) ||
752  (lhs.Maybe(cache_.kZeroish) && rhs.Min() < 0.0) ||
753  (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  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
758  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
759  return type;
760 }
761 
762 Type OperationTyper::NumberModulus(Type lhs, Type rhs) {
763  DCHECK(lhs.Is(Type::Number()));
764  DCHECK(rhs.Is(Type::Number()));
765 
766  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  bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
771  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  if (lhs.Maybe(Type::MinusZero())) {
776  maybe_minuszero = true;
777  lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
778  }
779  if (rhs.Maybe(Type::MinusZero())) {
780  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  lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786  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  if (!lhs.IsNone() && !rhs.Is(cache_.kSingletonZero)) {
791  // Determine the bounds of {lhs} and {rhs}.
792  double const lmin = lhs.Min();
793  double const lmax = lhs.Max();
794  double const rmin = rhs.Min();
795  double const rmax = rhs.Max();
796 
797  // The sign of the result is the sign of the {lhs}.
798  if (lmin < 0.0) maybe_minuszero = true;
799 
800  // For integer inputs {lhs} and {rhs} we can infer a precise type.
801  if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) {
802  double labs = std::max(std::abs(lmin), std::abs(lmax));
803  double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1;
804  double abs = std::min(labs, rabs);
805  double min = 0.0, max = 0.0;
806  if (lmin >= 0.0) {
807  // {lhs} positive.
808  min = 0.0;
809  max = abs;
810  } else if (lmax <= 0.0) {
811  // {lhs} negative.
812  min = 0.0 - abs;
813  max = 0.0;
814  } else {
815  // {lhs} positive or negative.
816  min = 0.0 - abs;
817  max = abs;
818  }
819  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  if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827  if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
828  return type;
829 }
830 
831 Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) {
832  DCHECK(lhs.Is(Type::Number()));
833  DCHECK(rhs.Is(Type::Number()));
834 
835  lhs = NumberToInt32(lhs);
836  rhs = NumberToInt32(rhs);
837 
838  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
839 
840  double lmin = lhs.Min();
841  double rmin = rhs.Min();
842  double lmax = lhs.Max();
843  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  lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
848  double max = kMaxInt;
849 
850  // Or-ing with 0 is essentially a conversion to int32.
851  if (rmin == 0 && rmax == 0) {
852  min = lmin;
853  max = lmax;
854  }
855  if (lmin == 0 && lmax == 0) {
856  min = rmin;
857  max = rmax;
858  }
859 
860  if (lmax < 0 || rmax < 0) {
861  // Or-ing two values of which at least one is negative results in a negative
862  // value.
863  max = std::min(max, -1.0);
864  }
865  return Type::Range(min, max, zone());
866 }
867 
868 Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) {
869  DCHECK(lhs.Is(Type::Number()));
870  DCHECK(rhs.Is(Type::Number()));
871 
872  lhs = NumberToInt32(lhs);
873  rhs = NumberToInt32(rhs);
874 
875  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
876 
877  double lmin = lhs.Min();
878  double rmin = rhs.Min();
879  double lmax = lhs.Max();
880  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  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  if (lmin >= 0) {
889  min = 0;
890  max = std::min(max, lmax);
891  }
892  if (rmin >= 0) {
893  min = 0;
894  max = std::min(max, rmax);
895  }
896  return Type::Range(min, max, zone());
897 }
898 
899 Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) {
900  DCHECK(lhs.Is(Type::Number()));
901  DCHECK(rhs.Is(Type::Number()));
902 
903  lhs = NumberToInt32(lhs);
904  rhs = NumberToInt32(rhs);
905 
906  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
907 
908  double lmin = lhs.Min();
909  double rmin = rhs.Min();
910  double lmax = lhs.Max();
911  double rmax = rhs.Max();
912  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  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 Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) {
925  DCHECK(lhs.Is(Type::Number()));
926  DCHECK(rhs.Is(Type::Number()));
927 
928  lhs = NumberToInt32(lhs);
929  rhs = NumberToUint32(rhs);
930 
931  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
932 
933  int32_t min_lhs = lhs.Min();
934  int32_t max_lhs = lhs.Max();
935  uint32_t min_rhs = rhs.Min();
936  uint32_t max_rhs = rhs.Max();
937  if (max_rhs > 31) {
938  // rhs can be larger than the bitmask
939  max_rhs = 31;
940  min_rhs = 0;
941  }
942 
943  if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
944  // overflow possible
945  return Type::Signed32();
946  }
947 
948  double min =
949  std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
950  static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
951  double max =
952  std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
953  static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
954 
955  if (max == kMaxInt && min == kMinInt) return Type::Signed32();
956  return Type::Range(min, max, zone());
957 }
958 
959 Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) {
960  DCHECK(lhs.Is(Type::Number()));
961  DCHECK(rhs.Is(Type::Number()));
962 
963  lhs = NumberToInt32(lhs);
964  rhs = NumberToUint32(rhs);
965 
966  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
967 
968  int32_t min_lhs = lhs.Min();
969  int32_t max_lhs = lhs.Max();
970  uint32_t min_rhs = rhs.Min();
971  uint32_t max_rhs = rhs.Max();
972  if (max_rhs > 31) {
973  // rhs can be larger than the bitmask
974  max_rhs = 31;
975  min_rhs = 0;
976  }
977  double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
978  double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
979 
980  if (max == kMaxInt && min == kMinInt) return Type::Signed32();
981  return Type::Range(min, max, zone());
982 }
983 
984 Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) {
985  DCHECK(lhs.Is(Type::Number()));
986  DCHECK(rhs.Is(Type::Number()));
987 
988  lhs = NumberToUint32(lhs);
989  rhs = NumberToUint32(rhs);
990 
991  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
992 
993  uint32_t min_lhs = lhs.Min();
994  uint32_t max_lhs = lhs.Max();
995  uint32_t min_rhs = rhs.Min();
996  uint32_t max_rhs = rhs.Max();
997  if (max_rhs > 31) {
998  // rhs can be larger than the bitmask
999  max_rhs = 31;
1000  min_rhs = 0;
1001  }
1002 
1003  double min = min_lhs >> max_rhs;
1004  double max = max_lhs >> min_rhs;
1005  DCHECK_LE(0, min);
1006  DCHECK_LE(max, kMaxUInt32);
1007 
1008  if (min == 0 && max == kMaxInt) return Type::Unsigned31();
1009  if (min == 0 && max == kMaxUInt32) return Type::Unsigned32();
1010  return Type::Range(min, max, zone());
1011 }
1012 
1013 Type OperationTyper::NumberAtan2(Type lhs, Type rhs) {
1014  DCHECK(lhs.Is(Type::Number()));
1015  DCHECK(rhs.Is(Type::Number()));
1016  return Type::Number();
1017 }
1018 
1019 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  return Type::Signed32();
1024 }
1025 
1026 Type OperationTyper::NumberMax(Type lhs, Type rhs) {
1027  DCHECK(lhs.Is(Type::Number()));
1028  DCHECK(rhs.Is(Type::Number()));
1029 
1030  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1031  if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1032 
1033  Type type = Type::None();
1034  if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035  type = Type::Union(type, Type::NaN(), zone());
1036  }
1037  lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1038  DCHECK(!lhs.IsNone());
1039  rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1040  DCHECK(!rhs.IsNone());
1041  if (lhs.Is(cache_.kIntegerOrMinusZero) &&
1042  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  double max = std::max(lhs.Max(), rhs.Max());
1046  double min = std::max(lhs.Min(), rhs.Min());
1047  type = Type::Union(type, Type::Range(min, max, zone()), zone());
1048  if (min <= 0.0 && 0.0 <= max &&
1049  (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1050  type = Type::Union(type, Type::MinusZero(), zone());
1051  }
1052  } else {
1053  type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1054  }
1055  return type;
1056 }
1057 
1058 Type OperationTyper::NumberMin(Type lhs, Type rhs) {
1059  DCHECK(lhs.Is(Type::Number()));
1060  DCHECK(rhs.Is(Type::Number()));
1061 
1062  if (lhs.IsNone() || rhs.IsNone()) return Type::None();
1063  if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN();
1064 
1065  Type type = Type::None();
1066  if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067  type = Type::Union(type, Type::NaN(), zone());
1068  }
1069  lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone());
1070  DCHECK(!lhs.IsNone());
1071  rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone());
1072  DCHECK(!rhs.IsNone());
1073  if (lhs.Is(cache_.kIntegerOrMinusZero) &&
1074  rhs.Is(cache_.kIntegerOrMinusZero)) {
1075  double max = std::min(lhs.Max(), rhs.Max());
1076  double min = std::min(lhs.Min(), rhs.Min());
1077  type = Type::Union(type, Type::Range(min, max, zone()), zone());
1078  if (min <= 0.0 && 0.0 <= max &&
1079  (lhs.Maybe(Type::MinusZero()) || rhs.Maybe(Type::MinusZero()))) {
1080  type = Type::Union(type, Type::MinusZero(), zone());
1081  }
1082  } else {
1083  type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1084  }
1085  return type;
1086 }
1087 
1088 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  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 SPECULATIVE_NUMBER_BINOP(NumberAdd)
1102 SPECULATIVE_NUMBER_BINOP(NumberSubtract)
1103 SPECULATIVE_NUMBER_BINOP(NumberMultiply)
1104 SPECULATIVE_NUMBER_BINOP(NumberDivide)
1105 SPECULATIVE_NUMBER_BINOP(NumberModulus)
1106 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr)
1107 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd)
1108 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor)
1109 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft)
1110 SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
1111 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
1112 #undef SPECULATIVE_NUMBER_BINOP
1113 
1114 Type OperationTyper::SpeculativeToNumber(Type type) {
1115  return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
1116 }
1117 
1118 Type OperationTyper::ToPrimitive(Type type) {
1119  if (type.Is(Type::Primitive())) {
1120  return type;
1121  }
1122  return Type::Primitive();
1123 }
1124 
1125 Type OperationTyper::Invert(Type type) {
1126  DCHECK(type.Is(Type::Boolean()));
1127  DCHECK(!type.IsNone());
1128  if (type.Is(singleton_false())) return singleton_true();
1129  if (type.Is(singleton_true())) return singleton_false();
1130  return type;
1131 }
1132 
1133 OperationTyper::ComparisonOutcome OperationTyper::Invert(
1134  ComparisonOutcome outcome) {
1135  ComparisonOutcome result(0);
1136  if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined;
1137  if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse;
1138  if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue;
1139  return result;
1140 }
1141 
1142 Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) {
1143  if ((outcome & kComparisonFalse) != 0 ||
1144  (outcome & kComparisonUndefined) != 0) {
1145  return (outcome & kComparisonTrue) != 0 ? Type::Boolean()
1146  : 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 Type JSType(Type type) {
1156  if (type.Is(Type::Boolean())) return Type::Boolean();
1157  if (type.Is(Type::String())) return Type::String();
1158  if (type.Is(Type::Number())) return Type::Number();
1159  if (type.Is(Type::BigInt())) return Type::BigInt();
1160  if (type.Is(Type::Undefined())) return Type::Undefined();
1161  if (type.Is(Type::Null())) return Type::Null();
1162  if (type.Is(Type::Symbol())) return Type::Symbol();
1163  if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object"
1164  return Type::Any();
1165 }
1166 
1167 } // namespace
1168 
1169 Type OperationTyper::SameValue(Type lhs, Type rhs) {
1170  if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1171  if (lhs.Is(Type::NaN())) {
1172  if (rhs.Is(Type::NaN())) return singleton_true();
1173  if (!rhs.Maybe(Type::NaN())) return singleton_false();
1174  } else if (rhs.Is(Type::NaN())) {
1175  if (!lhs.Maybe(Type::NaN())) return singleton_false();
1176  }
1177  if (lhs.Is(Type::MinusZero())) {
1178  if (rhs.Is(Type::MinusZero())) return singleton_true();
1179  if (!rhs.Maybe(Type::MinusZero())) return singleton_false();
1180  } else if (rhs.Is(Type::MinusZero())) {
1181  if (!lhs.Maybe(Type::MinusZero())) return singleton_false();
1182  }
1183  if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1184  (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1185  return singleton_false();
1186  }
1187  return Type::Boolean();
1188 }
1189 
1190 Type OperationTyper::StrictEqual(Type lhs, Type rhs) {
1191  if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false();
1192  if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false();
1193  if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) &&
1194  (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1195  return singleton_false();
1196  }
1197  if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1198  return singleton_false();
1199  }
1200  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 Type OperationTyper::CheckBounds(Type index, Type length) {
1209  DCHECK(length.Is(cache_.kPositiveSafeInteger));
1210  if (length.Is(cache_.kSingletonZero)) return Type::None();
1211  Type mask = Type::Range(0.0, length.Max() - 1, zone());
1212  if (index.Maybe(Type::MinusZero())) {
1213  index = Type::Union(index, cache_.kSingletonZero, zone());
1214  }
1215  return Type::Intersect(index, mask, zone());
1216 }
1217 
1218 Type OperationTyper::CheckFloat64Hole(Type type) {
1219  if (type.Maybe(Type::Hole())) {
1220  // Turn "the hole" into undefined.
1221  type = Type::Intersect(type, Type::Number(), zone());
1222  type = Type::Union(type, Type::Undefined(), zone());
1223  }
1224  return type;
1225 }
1226 
1227 Type OperationTyper::CheckNumber(Type type) {
1228  return Type::Intersect(type, Type::Number(), zone());
1229 }
1230 
1231 Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) {
1232  return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1233 }
1234 
1235 Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) {
1236  if (input.Maybe(Type::Hole())) {
1237  // Turn "the hole" into undefined.
1238  Type type = Type::Intersect(input, Type::NonInternal(), zone());
1239  return Type::Union(type, Type::Undefined(), zone());
1240  }
1241  return input;
1242 }
1243 
1244 Type OperationTyper::ToBoolean(Type type) {
1245  if (type.Is(Type::Boolean())) return type;
1246  if (type.Is(falsish_)) return singleton_false_;
1247  if (type.Is(truish_)) return singleton_true_;
1248  if (type.Is(Type::Number())) {
1249  return NumberToBoolean(type);
1250  }
1251  return Type::Boolean();
1252 }
1253 
1254 } // namespace compiler
1255 } // namespace internal
1256 } // namespace v8
STL namespace.
Definition: libplatform.h:13