Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 1966e950678f1ba02d1322e95778de977267424e..39070a6cb260998e8e93675e51a5c4eb3dee73f7 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -256,7 +256,8 @@ class Typer::Visitor : public Reducer { |
static Type* ObjectIsString(Type*, Typer*); |
static Type* ObjectIsUndetectable(Type*, Typer*); |
- static Type* JSAddRanger(RangeType*, RangeType*, Typer*); |
+ static Type* JSAddRanger(double lhs_min, double lhs_max, double rhs_min, |
+ double rhs_max, Typer* t); |
static Type* JSSubtractRanger(RangeType*, RangeType*, Typer*); |
static Type* JSDivideRanger(RangeType*, RangeType*, Typer*); |
static Type* JSModulusRanger(RangeType*, RangeType*, Typer*); |
@@ -1037,14 +1038,14 @@ static double array_max(double a[], size_t n) { |
return x == 0 ? 0 : x; // -0 -> 0 |
} |
-Type* Typer::Visitor::JSAddRanger(RangeType* lhs, RangeType* rhs, Typer* t) { |
+Type* Typer::Visitor::JSAddRanger(double lhs_min, double lhs_max, |
+ double rhs_min, double rhs_max, Typer* t) { |
double results[4]; |
- results[0] = lhs->Min() + rhs->Min(); |
- results[1] = lhs->Min() + rhs->Max(); |
- results[2] = lhs->Max() + rhs->Min(); |
- results[3] = lhs->Max() + rhs->Max(); |
- // Since none of the inputs can be -0, the result cannot be -0 either. |
- // However, it can be nan (the sum of two infinities of opposite sign). |
+ results[0] = lhs_min + rhs_min; |
+ results[1] = lhs_min + rhs_max; |
+ results[2] = lhs_max + rhs_min; |
+ results[3] = lhs_max + rhs_max; |
+ // The results can be nan (the sum of two infinities of opposite sign). |
// On the other hand, if none of the "results" above is nan, then the actual |
// result cannot be nan either. |
int nans = 0; |
@@ -1073,13 +1074,25 @@ Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) { |
return Type::NumberOrString(); |
} |
} |
- lhs = Rangify(ToNumber(lhs, t), t); |
- rhs = Rangify(ToNumber(rhs, t), t); |
- if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
- if (lhs->IsRange() && rhs->IsRange()) { |
- return JSAddRanger(lhs->AsRange(), rhs->AsRange(), t); |
+ // The addition must be numeric. |
+ lhs = ToNumber(lhs, t); |
+ rhs = ToNumber(rhs, t); |
+ // We can give more precise types for integers. |
+ if (!lhs->Is(t->cache_.kIntegerOrMinusZeroOrNaN) || |
+ !rhs->Is(t->cache_.kIntegerOrMinusZeroOrNaN)) { |
+ return Type::Number(); |
} |
- return Type::Number(); |
+ Type* int_lhs = Type::Intersect(lhs, t->cache_.kInteger, t->zone()); |
+ Type* int_rhs = Type::Intersect(rhs, t->cache_.kInteger, t->zone()); |
+ Type* result = JSAddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), |
+ int_rhs->Max(), t); |
+ if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
+ result = Type::Union(result, Type::NaN(), t->zone()); |
+ } |
+ if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { |
+ result = Type::Union(result, Type::MinusZero(), t->zone()); |
+ } |
+ return result; |
} |
Type* Typer::Visitor::JSSubtractRanger(RangeType* lhs, RangeType* rhs, |