Index: src/compiler/typer.cc |
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc |
index 20a39d94493ff1eed1463e1a142d7cd037c90655..996eecd361caacde8ae062304ac1180d68902e75 100644 |
--- a/src/compiler/typer.cc |
+++ b/src/compiler/typer.cc |
@@ -717,16 +717,26 @@ Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) { |
double rmax = rhs->Max(); |
// Or-ing any two values results in a value no smaller than their minimum. |
// Even no smaller than their maximum if both values are non-negative. |
- Handle<Object> min = f->NewNumber( |
- lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin)); |
+ double min = |
+ lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin); |
+ double max = Type::Signed32()->Max(); |
+ |
+ // Or-ing with 0 is essentially a conversion to int32. |
+ if (rmin == 0 && rmax == 0) { |
+ min = lmin; |
+ max = lmax; |
+ } |
+ if (lmin == 0 && lmax == 0) { |
+ min = rmin; |
+ max = rmax; |
+ } |
+ |
if (lmax < 0 || rmax < 0) { |
// Or-ing two values of which at least one is negative results in a negative |
// value. |
- Handle<Object> max = f->NewNumber(-1); |
- return Type::Range(min, max, t->zone()); |
+ max = std::min(max, -1.0); |
} |
- Handle<Object> max = f->NewNumber(Type::Signed32()->Max()); |
- return Type::Range(min, max, t->zone()); |
+ return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone()); |
// TODO(neis): Be precise for singleton inputs, here and elsewhere. |
} |
@@ -739,18 +749,22 @@ Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) { |
double rmin = rhs->Min(); |
double lmax = lhs->Max(); |
double rmax = rhs->Max(); |
+ double min = Type::Signed32()->Min(); |
// And-ing any two values results in a value no larger than their maximum. |
// Even no larger than their minimum if both values are non-negative. |
- Handle<Object> max = f->NewNumber( |
- lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax)); |
- if (lmin >= 0 || rmin >= 0) { |
- // And-ing two values of which at least one is non-negative results in a |
- // non-negative value. |
- Handle<Object> min = f->NewNumber(0); |
- return Type::Range(min, max, t->zone()); |
+ double max = |
+ lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax); |
+ // And-ing with a non-negative value x causes the result to be between |
+ // zero and x. |
+ if (lmin >= 0) { |
+ min = 0; |
+ max = std::min(max, lmax); |
} |
- Handle<Object> min = f->NewNumber(Type::Signed32()->Min()); |
- return Type::Range(min, max, t->zone()); |
+ if (rmin >= 0) { |
+ min = 0; |
+ max = std::min(max, rmax); |
+ } |
+ return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone()); |
} |
@@ -780,18 +794,31 @@ Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) { |
Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) { |
lhs = NumberToInt32(ToNumber(lhs, t), t); |
- Factory* f = t->isolate()->factory(); |
+ rhs = NumberToUint32(ToNumber(rhs, t), t); |
+ double min = kMinInt; |
+ double max = kMaxInt; |
if (lhs->Min() >= 0) { |
// Right-shifting a non-negative value cannot make it negative, nor larger. |
- Handle<Object> min = f->NewNumber(0); |
- Handle<Object> max = f->NewNumber(lhs->Max()); |
- return Type::Range(min, max, t->zone()); |
+ min = std::max(min, 0.0); |
+ max = std::min(max, lhs->Max()); |
} |
if (lhs->Max() < 0) { |
// Right-shifting a negative value cannot make it non-negative, nor smaller. |
- Handle<Object> min = f->NewNumber(lhs->Min()); |
- Handle<Object> max = f->NewNumber(-1); |
- return Type::Range(min, max, t->zone()); |
+ min = std::max(min, lhs->Min()); |
+ max = std::min(max, -1.0); |
+ } |
+ if (rhs->Min() > 0 && rhs->Max() <= 31) { |
+ // Right-shifting by a positive value yields a small integer value. |
+ double shift_min = kMinInt >> static_cast<int>(rhs->Min()); |
+ double shift_max = kMaxInt >> static_cast<int>(rhs->Min()); |
+ min = std::max(min, shift_min); |
+ max = std::min(max, shift_max); |
+ } |
+ // TODO(jarin) Ideally, the following micro-optimization should be performed |
+ // by the type constructor. |
+ if (max != Type::Signed32()->Max() || min != Type::Signed32()->Min()) { |
+ Factory* f = t->isolate()->factory(); |
+ return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone()); |
} |
return Type::Signed32(); |
} |