5 #include "src/compiler/operation-typer.h" 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" 13 #include "src/objects-inl.h" 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()));
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);
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);
40 falsish_ = Type::Union(
42 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone),
43 Type::Union(singleton_empty_string_, Type::Hole(), zone),
46 truish_ = Type::Union(
48 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone);
52 return Type::Union(left, right, zone());
55 Type OperationTyper::WeakenRange(
Type previous_range,
Type current_range) {
56 static const double kWeakenMinLimits[] = {0.0,
77 static const double kWeakenMaxLimits[] = {0.0,
98 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits));
100 double current_min = current_range.Min();
101 double new_min = current_min;
104 if (current_min != previous_range.Min()) {
105 new_min = -V8_INFINITY;
106 for (
double const min : kWeakenMinLimits) {
107 if (min <= current_min) {
114 double current_max = current_range.Max();
115 double new_max = current_max;
118 if (current_max != previous_range.Max()) {
119 new_max = V8_INFINITY;
120 for (
double const max : kWeakenMaxLimits) {
121 if (max >= current_max) {
128 return Type::Range(new_min, new_max, zone());
131 Type OperationTyper::Rangify(
Type type) {
132 if (type.IsRange())
return type;
133 if (!type.Is(cache_.kInteger)) {
136 return Type::Range(type.Min(), type.Max(), zone());
144 double array_min(
double a[],
size_t 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);
152 DCHECK(!std::isnan(x));
153 return x == 0 ? 0 : x;
159 double array_max(
double a[],
size_t 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);
167 DCHECK(!std::isnan(x));
168 return x == 0 ? 0 : x;
173 Type OperationTyper::AddRanger(
double lhs_min,
double lhs_max,
double rhs_min,
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;
185 for (
int i = 0;
i < 4; ++
i) {
186 if (std::isnan(results[
i])) ++nans;
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());
199 Type OperationTyper::SubtractRanger(
double lhs_min,
double lhs_max,
200 double rhs_min,
double rhs_max) {
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;
211 for (
int i = 0;
i < 4; ++
i) {
212 if (std::isnan(results[
i])) ++nans;
214 if (nans == 4)
return Type::NaN();
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());
224 Type OperationTyper::MultiplyRanger(
double lhs_min,
double lhs_max,
225 double rhs_min,
double rhs_max) {
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;
235 for (
int i = 0;
i < 4; ++
i) {
236 if (std::isnan(results[
i])) {
237 return cache_.kIntegerOrMinusZeroOrNaN;
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());
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());
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) {
263 type = Type::Union(type, Type::OtherObject(), zone());
268 Type OperationTyper::ToNumber(
Type type) {
269 if (type.Is(Type::Number()))
return type;
275 if (type.Maybe(Type::StringOrReceiver()))
return Type::Number();
280 type = Type::Intersect(type, Type::PlainPrimitive(), zone());
284 DCHECK(type.Is(Type::NumberOrOddball()));
285 if (type.Maybe(Type::Null())) {
287 type = Type::Union(type, cache_.kSingletonZero, zone());
289 if (type.Maybe(Type::Undefined())) {
291 type = Type::Union(type, Type::NaN(), zone());
293 if (type.Maybe(singleton_false_)) {
295 type = Type::Union(type, cache_.kSingletonZero, zone());
297 if (type.Maybe(singleton_true_)) {
299 type = Type::Union(type, cache_.kSingletonOne, zone());
301 return Type::Intersect(type, Type::Number(), zone());
304 Type OperationTyper::ToNumberConvertBigInt(
Type type) {
308 type.Maybe(Type::BigInt()) || type.Maybe(Type::Receiver());
309 type = ToNumber(Type::Intersect(type, Type::NonBigInt(), zone()));
312 return maybe_bigint ? Type::Union(type, cache_.kInteger, zone()) : type;
315 Type OperationTyper::ToNumeric(
Type type) {
318 if (type.Maybe(Type::Receiver())) {
319 type = Type::Union(type, Type::BigInt(), zone());
321 return Type::Union(ToNumber(Type::Intersect(type, Type::NonBigInt(), zone())),
322 Type::Intersect(type, Type::BigInt(), zone()), zone());
325 Type OperationTyper::NumberAbs(
Type type) {
326 DCHECK(type.Is(Type::Number()));
327 if (type.IsNone())
return type;
329 bool const maybe_nan = type.Maybe(Type::NaN());
330 bool const maybe_minuszero = type.Maybe(Type::MinusZero());
332 type = Type::Intersect(type, Type::PlainNumber(), zone());
333 if (!type.IsNone()) {
334 double const max = type.Max();
335 double const min = type.Min();
337 if (type.Is(cache_.kInteger)) {
339 Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
341 type = Type::PlainNumber();
346 if (maybe_minuszero) {
347 type = Type::Union(type, cache_.kSingletonZero, zone());
350 type = Type::Union(type, Type::NaN(), zone());
355 Type OperationTyper::NumberAcos(
Type type) {
356 DCHECK(type.Is(Type::Number()));
357 return Type::Number();
360 Type OperationTyper::NumberAcosh(
Type type) {
361 DCHECK(type.Is(Type::Number()));
362 return Type::Number();
365 Type OperationTyper::NumberAsin(
Type type) {
366 DCHECK(type.Is(Type::Number()));
367 return Type::Number();
370 Type OperationTyper::NumberAsinh(
Type type) {
371 DCHECK(type.Is(Type::Number()));
372 return Type::Number();
375 Type OperationTyper::NumberAtan(
Type type) {
376 DCHECK(type.Is(Type::Number()));
377 return Type::Number();
380 Type OperationTyper::NumberAtanh(
Type type) {
381 DCHECK(type.Is(Type::Number()));
382 return Type::Number();
385 Type OperationTyper::NumberCbrt(
Type type) {
386 DCHECK(type.Is(Type::Number()));
387 return Type::Number();
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());
398 Type OperationTyper::NumberClz32(
Type type) {
399 DCHECK(type.Is(Type::Number()));
400 return cache_.kZeroToThirtyTwo;
403 Type OperationTyper::NumberCos(
Type type) {
404 DCHECK(type.Is(Type::Number()));
405 return Type::Number();
408 Type OperationTyper::NumberCosh(
Type type) {
409 DCHECK(type.Is(Type::Number()));
410 return Type::Number();
413 Type OperationTyper::NumberExp(
Type type) {
414 DCHECK(type.Is(Type::Number()));
415 return Type::Union(Type::PlainNumber(), Type::NaN(), zone());
418 Type OperationTyper::NumberExpm1(
Type type) {
419 DCHECK(type.Is(Type::Number()));
420 return Type::Number();
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());
431 Type OperationTyper::NumberFround(
Type type) {
432 DCHECK(type.Is(Type::Number()));
433 return Type::Number();
436 Type OperationTyper::NumberLog(
Type type) {
437 DCHECK(type.Is(Type::Number()));
438 return Type::Number();
441 Type OperationTyper::NumberLog1p(
Type type) {
442 DCHECK(type.Is(Type::Number()));
443 return Type::Number();
446 Type OperationTyper::NumberLog2(
Type type) {
447 DCHECK(type.Is(Type::Number()));
448 return Type::Number();
451 Type OperationTyper::NumberLog10(
Type type) {
452 DCHECK(type.Is(Type::Number()));
453 return Type::Number();
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());
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());
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;
481 type = Type::Range(-1.0, 1.0, zone());
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());
489 Type OperationTyper::NumberSin(
Type type) {
490 DCHECK(type.Is(Type::Number()));
491 return Type::Number();
494 Type OperationTyper::NumberSinh(
Type type) {
495 DCHECK(type.Is(Type::Number()));
496 return Type::Number();
499 Type OperationTyper::NumberSqrt(
Type type) {
500 DCHECK(type.Is(Type::Number()));
501 return Type::Number();
504 Type OperationTyper::NumberTan(
Type type) {
505 DCHECK(type.Is(Type::Number()));
506 return Type::Number();
509 Type OperationTyper::NumberTanh(
Type type) {
510 DCHECK(type.Is(Type::Number()));
511 return Type::Number();
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());
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_;
529 return Type::Boolean();
532 Type OperationTyper::NumberToInt32(
Type type) {
533 DCHECK(type.Is(Type::Number()));
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());
541 return Type::Signed32();
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();
552 Type OperationTyper::NumberToUint32(
Type type) {
553 DCHECK(type.Is(Type::Number()));
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());
561 return Type::Unsigned32();
564 Type OperationTyper::NumberToUint8Clamped(
Type type) {
565 DCHECK(type.Is(Type::Number()));
567 if (type.Is(cache_.kUint8))
return type;
568 return cache_.kUint8;
571 Type OperationTyper::NumberSilenceNaN(
Type type) {
572 DCHECK(type.Is(Type::Number()));
576 if (type.Maybe(Type::NaN()))
return Type::Number();
581 DCHECK(lhs.Is(Type::Number()));
582 DCHECK(rhs.Is(Type::Number()));
584 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
588 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
591 bool maybe_minuszero =
true;
592 if (lhs.Maybe(Type::MinusZero())) {
593 lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
595 maybe_minuszero =
false;
597 if (rhs.Maybe(Type::MinusZero())) {
598 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
600 maybe_minuszero =
false;
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());
611 if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) ||
612 (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) {
615 type = Type::PlainNumber();
620 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
621 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
625 Type OperationTyper::NumberSubtract(
Type lhs,
Type rhs) {
626 DCHECK(lhs.Is(Type::Number()));
627 DCHECK(rhs.Is(Type::Number()));
629 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
633 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN());
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);
642 if (rhs.Maybe(Type::MinusZero())) {
643 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
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());
654 if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) ||
655 (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) {
658 type = Type::PlainNumber();
663 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
664 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
668 Type OperationTyper::SpeculativeSafeIntegerAdd(
Type lhs,
Type rhs) {
669 Type result = SpeculativeNumberAdd(lhs, rhs);
675 return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
678 Type OperationTyper::SpeculativeSafeIntegerSubtract(
Type lhs,
Type rhs) {
679 Type result = SpeculativeNumberSubtract(lhs, rhs);
685 return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone());
688 Type OperationTyper::NumberMultiply(
Type lhs,
Type rhs) {
689 DCHECK(lhs.Is(Type::Number()));
690 DCHECK(rhs.Is(Type::Number()));
692 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
693 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN()))
return Type::NaN();
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());
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());
717 if (rhs.Maybe(Type::MinusZero())) {
718 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
719 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
723 Type type = (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger))
724 ? MultiplyRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max())
725 : Type::OrderedNumber();
728 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
729 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
734 DCHECK(lhs.Is(Type::Number()));
735 DCHECK(rhs.Is(Type::Number()));
737 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
738 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN()))
return Type::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());
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);
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());
762 Type OperationTyper::NumberModulus(
Type lhs,
Type rhs) {
763 DCHECK(lhs.Is(Type::Number()));
764 DCHECK(rhs.Is(Type::Number()));
766 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
770 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) ||
771 lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY;
774 bool maybe_minuszero =
false;
775 if (lhs.Maybe(Type::MinusZero())) {
776 maybe_minuszero =
true;
777 lhs = Type::Union(lhs, cache_.kSingletonZero, zone());
779 if (rhs.Maybe(Type::MinusZero())) {
780 rhs = Type::Union(rhs, cache_.kSingletonZero, zone());
784 Type type = Type::None();
785 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone());
786 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone());
790 if (!lhs.IsNone() && !rhs.Is(cache_.kSingletonZero)) {
792 double const lmin = lhs.Min();
793 double const lmax = lhs.Max();
794 double const rmin = rhs.Min();
795 double const rmax = rhs.Max();
798 if (lmin < 0.0) maybe_minuszero =
true;
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;
810 }
else if (lmax <= 0.0) {
819 type = Type::Range(min, max, zone());
821 type = Type::PlainNumber();
826 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
827 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
831 Type OperationTyper::NumberBitwiseOr(
Type lhs,
Type rhs) {
832 DCHECK(lhs.Is(Type::Number()));
833 DCHECK(rhs.Is(Type::Number()));
835 lhs = NumberToInt32(lhs);
836 rhs = NumberToInt32(rhs);
838 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
840 double lmin = lhs.Min();
841 double rmin = rhs.Min();
842 double lmax = lhs.Max();
843 double rmax = rhs.Max();
847 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) :
std::min(lmin, rmin);
848 double max = kMaxInt;
851 if (rmin == 0 && rmax == 0) {
855 if (lmin == 0 && lmax == 0) {
860 if (lmax < 0 || rmax < 0) {
863 max = std::min(max, -1.0);
865 return Type::Range(min, max, zone());
868 Type OperationTyper::NumberBitwiseAnd(
Type lhs,
Type rhs) {
869 DCHECK(lhs.Is(Type::Number()));
870 DCHECK(rhs.Is(Type::Number()));
872 lhs = NumberToInt32(lhs);
873 rhs = NumberToInt32(rhs);
875 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
877 double lmin = lhs.Min();
878 double rmin = rhs.Min();
879 double lmax = lhs.Max();
880 double rmax = rhs.Max();
881 double min = kMinInt;
885 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) :
std::max(lmax, rmax);
890 max = std::min(max, lmax);
894 max = std::min(max, rmax);
896 return Type::Range(min, max, zone());
899 Type OperationTyper::NumberBitwiseXor(
Type lhs,
Type rhs) {
900 DCHECK(lhs.Is(Type::Number()));
901 DCHECK(rhs.Is(Type::Number()));
903 lhs = NumberToInt32(lhs);
904 rhs = NumberToInt32(rhs);
906 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
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)) {
914 return Type::Unsigned31();
916 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
919 return Type::Negative32();
921 return Type::Signed32();
924 Type OperationTyper::NumberShiftLeft(
Type lhs,
Type rhs) {
925 DCHECK(lhs.Is(Type::Number()));
926 DCHECK(rhs.Is(Type::Number()));
928 lhs = NumberToInt32(lhs);
929 rhs = NumberToUint32(rhs);
931 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
933 int32_t min_lhs = lhs.Min();
934 int32_t max_lhs = lhs.Max();
943 if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
945 return Type::Signed32();
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));
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));
955 if (max == kMaxInt && min == kMinInt)
return Type::Signed32();
956 return Type::Range(min, max, zone());
959 Type OperationTyper::NumberShiftRight(
Type lhs,
Type rhs) {
960 DCHECK(lhs.Is(Type::Number()));
961 DCHECK(rhs.Is(Type::Number()));
963 lhs = NumberToInt32(lhs);
964 rhs = NumberToUint32(rhs);
966 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
968 int32_t min_lhs = lhs.Min();
969 int32_t max_lhs = lhs.Max();
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);
980 if (max == kMaxInt && min == kMinInt)
return Type::Signed32();
981 return Type::Range(min, max, zone());
984 Type OperationTyper::NumberShiftRightLogical(
Type lhs,
Type rhs) {
985 DCHECK(lhs.Is(Type::Number()));
986 DCHECK(rhs.Is(Type::Number()));
988 lhs = NumberToUint32(lhs);
989 rhs = NumberToUint32(rhs);
991 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
1003 double min = min_lhs >> max_rhs;
1004 double max = max_lhs >> min_rhs;
1006 DCHECK_LE(max, kMaxUInt32);
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());
1014 DCHECK(lhs.Is(Type::Number()));
1015 DCHECK(rhs.Is(Type::Number()));
1016 return Type::Number();
1020 DCHECK(lhs.Is(Type::Number()));
1021 DCHECK(rhs.Is(Type::Number()));
1023 return Type::Signed32();
1027 DCHECK(lhs.Is(Type::Number()));
1028 DCHECK(rhs.Is(Type::Number()));
1030 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
1031 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN()))
return Type::NaN();
1033 Type type = Type::None();
1034 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1035 type = Type::Union(type, Type::NaN(), zone());
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)) {
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());
1053 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1059 DCHECK(lhs.Is(Type::Number()));
1060 DCHECK(rhs.Is(Type::Number()));
1062 if (lhs.IsNone() || rhs.IsNone())
return Type::None();
1063 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN()))
return Type::NaN();
1065 Type type = Type::None();
1066 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) {
1067 type = Type::Union(type, Type::NaN(), zone());
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());
1083 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone());
1089 DCHECK(lhs.Is(Type::Number()));
1090 DCHECK(rhs.Is(Type::Number()));
1092 return Type::Number();
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); \ 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 1114 Type OperationTyper::SpeculativeToNumber(
Type type) {
1115 return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
1118 Type OperationTyper::ToPrimitive(
Type type) {
1119 if (type.Is(Type::Primitive())) {
1122 return Type::Primitive();
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();
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;
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();
1149 DCHECK_NE(0, outcome & kComparisonTrue);
1150 return singleton_true();
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();
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();
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();
1183 if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) &&
1184 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) {
1185 return singleton_false();
1187 return Type::Boolean();
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();
1197 if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) {
1198 return singleton_false();
1200 if (lhs.IsHeapConstant() && rhs.Is(lhs)) {
1203 return singleton_true();
1205 return Type::Boolean();
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());
1215 return Type::Intersect(index, mask, zone());
1218 Type OperationTyper::CheckFloat64Hole(
Type type) {
1219 if (type.Maybe(Type::Hole())) {
1221 type = Type::Intersect(type, Type::Number(), zone());
1222 type = Type::Union(type, Type::Undefined(), zone());
1227 Type OperationTyper::CheckNumber(
Type type) {
1228 return Type::Intersect(type, Type::Number(), zone());
1231 Type OperationTyper::TypeTypeGuard(
const Operator* sigma_op,
Type input) {
1232 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone());
1235 Type OperationTyper::ConvertTaggedHoleToUndefined(
Type input) {
1236 if (input.Maybe(Type::Hole())) {
1238 Type type = Type::Intersect(input, Type::NonInternal(), zone());
1239 return Type::Union(type, Type::Undefined(), zone());
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);
1251 return Type::Boolean();