Index: src/compiler/operation-typer.cc |
diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc |
index 16004a047a1c4f8bf0fa2b434ede334ac31895a6..0ab24732c75c7d04817893a39edcd32d71785080 100644 |
--- a/src/compiler/operation-typer.cc |
+++ b/src/compiler/operation-typer.cc |
@@ -233,6 +233,36 @@ Type* OperationTyper::ModulusRanger(RangeType* lhs, RangeType* rhs) { |
return result; |
} |
+Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { |
+ double results[4]; |
+ double lmin = lhs->AsRange()->Min(); |
+ double lmax = lhs->AsRange()->Max(); |
+ double rmin = rhs->AsRange()->Min(); |
+ double rmax = rhs->AsRange()->Max(); |
+ results[0] = lmin * rmin; |
+ results[1] = lmin * rmax; |
+ results[2] = lmax * rmin; |
+ results[3] = lmax * rmax; |
+ // If the result may be nan, we give up on calculating a precise type, |
+ // because |
+ // the discontinuity makes it too complicated. Note that even if none of |
+ // the |
+ // "results" above is nan, the actual result may still be, so we have to do |
+ // a |
+ // different check: |
+ bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) && |
+ (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
+ (rhs->Maybe(cache_.kSingletonZero) && |
+ (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
+ if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. |
+ bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) || |
+ (rhs->Maybe(cache_.kSingletonZero) && lmin < 0); |
+ Type* range = |
+ Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
+ return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) |
+ : range; |
+} |
+ |
Type* OperationTyper::ToNumber(Type* type) { |
if (type->Is(Type::Number())) return type; |
if (type->Is(Type::NullOrUndefined())) { |
@@ -282,6 +312,50 @@ Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { |
return Type::Number(); |
} |
+Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) { |
+ DCHECK(lhs->Is(Type::Number())); |
+ DCHECK(rhs->Is(Type::Number())); |
+ lhs = Rangify(lhs); |
+ rhs = Rangify(rhs); |
+ if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
+ if (lhs->IsRange() && rhs->IsRange()) { |
+ return MultiplyRanger(lhs, rhs); |
+ } |
+ return Type::Number(); |
+} |
+ |
+Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) { |
+ DCHECK(lhs->Is(Type::Number())); |
+ DCHECK(rhs->Is(Type::Number())); |
+ |
+ if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
+ // Division is tricky, so all we do is try ruling out nan. |
+ bool maybe_nan = |
+ lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
+ ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
+ (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
+ return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
+} |
+ |
+Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) { |
+ DCHECK(lhs->Is(Type::Number())); |
+ DCHECK(rhs->Is(Type::Number())); |
+ if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
+ |
+ if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
+ lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { |
+ // Result maybe NaN. |
+ return Type::Number(); |
+ } |
+ |
+ lhs = Rangify(lhs); |
+ rhs = Rangify(rhs); |
+ if (lhs->IsRange() && rhs->IsRange()) { |
+ return ModulusRanger(lhs->AsRange(), rhs->AsRange()); |
+ } |
+ return Type::OrderedNumber(); |
+} |
+ |
Type* OperationTyper::ToPrimitive(Type* type) { |
if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
return type; |