Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 9af65597bf5527e9d60ca3c67b38300726cfe1bb..288fedce8ec09cd47a8fa7c12783a3ad2557cced 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -350,6 +350,7 @@ class Typer::Visitor : public Reducer { |
static Type* JSMultiplyRanger(Type::RangeType*, Type::RangeType*, Typer*); |
static Type* JSDivideRanger(Type::RangeType*, Type::RangeType*, Typer*); |
static Type* JSModulusRanger(Type::RangeType*, Type::RangeType*, Typer*); |
+ static Type* JSExponentiateRanger(Type::RangeType*, Type::RangeType*, Typer*); |
static ComparisonOutcome JSCompareTyper(Type*, Type*, Typer*); |
@@ -1223,6 +1224,54 @@ Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) { |
} |
+Type* Typer::Visitor::JSExponentiateRanger(Type::RangeType* lhs, |
+ Type::RangeType* rhs, Typer* t) { |
+ double lmin = lhs->Min(); |
+ double lmax = lhs->Max(); |
+ double rmin = rhs->Min(); |
+ double rmax = rhs->Max(); |
+ |
+ if (lmin > 0.0) { |
+ // +x ** -y : epsilon...1 |
+ if (rmax < 0.0) return Type::Range(0.0, 1.0, t->zone()); |
+ |
+ // +x ** +y : epsilon...infinity |
+ if (rmin > 0.0) return Type::Range(0.0, +V8_INFINITY, t->zone()); |
+ } else if (lmax < 0.0) { |
+ // -x ** -y : -1.0...1.0 |
+ if (rmax < 0.0) return Type::Range(-1.0, 1.0, t->zone()); |
+ } |
+ |
+ // pow(lmin, rmax) does not limit range by much. |
+ return Type::Number(); |
+} |
+ |
+ |
+Type* Typer::Visitor::JSExponentiateTyper(Type* lhs, Type* rhs, Typer* t) { |
+ lhs = ToNumber(lhs, t); |
+ rhs = ToNumber(rhs, t); |
+ |
+ // x ** NaN|undefined : NaN |
+ if (rhs->Is(Type::NaN())) return Type::NaN(); |
+ |
+ // x ** 0|false|null : 1 |
+ if (rhs->Is(t->singleton_zero)) return t->singleton_one; |
+ |
+ // NaN ** x [~0] : NaN |
+ if (lhs->Is(Type::NaN())) return Type::NaN(); |
+ |
+ // 0|false|null ** x [~0] : 0 |
+ if (lhs->Is(t->singleton_zero)) return t->singleton_zero; |
+ |
+ lhs = Rangify(lhs, t); |
+ rhs = Rangify(rhs, t); |
+ if (lhs->IsRange() && rhs->IsRange()) { |
+ return JSExponentiateRanger(lhs->AsRange(), rhs->AsRange(), t); |
+ } |
+ return Type::Number(); |
+} |
+ |
+ |
// JS unary operators. |