summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/operation-typer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/operation-typer.cc')
-rw-r--r--deps/v8/src/compiler/operation-typer.cc84
1 files changed, 52 insertions, 32 deletions
diff --git a/deps/v8/src/compiler/operation-typer.cc b/deps/v8/src/compiler/operation-typer.cc
index 9198f4b9a9..c422f0986b 100644
--- a/deps/v8/src/compiler/operation-typer.cc
+++ b/deps/v8/src/compiler/operation-typer.cc
@@ -366,8 +366,9 @@ Type* OperationTyper::NumberExpm1(Type* type) {
Type* OperationTyper::NumberFloor(Type* type) {
DCHECK(type->Is(Type::Number()));
if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type;
- // TODO(bmeurer): We could infer a more precise type here.
- return cache_.kIntegerOrMinusZeroOrNaN;
+ type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone());
+ type = Type::Union(type, cache_.kInteger, zone());
+ return type;
}
Type* OperationTyper::NumberFround(Type* type) {
@@ -624,12 +625,19 @@ Type* OperationTyper::NumberDivide(Type* lhs, Type* rhs) {
}
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
- // Division is tricky, so all we do is try ruling out nan.
+ // Division is tricky, so all we do is try ruling out -0 and NaN.
+ bool maybe_minuszero = !lhs->Is(cache_.kPositiveIntegerOrNaN) ||
+ !rhs->Is(cache_.kPositiveIntegerOrNaN);
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();
+
+ // Take into account the -0 and NaN information computed earlier.
+ Type* type = Type::PlainNumber();
+ if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone());
+ if (maybe_nan) type = Type::Union(type, Type::NaN(), zone());
+ return type;
}
Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) {
@@ -796,8 +804,35 @@ Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
- // TODO(turbofan): Infer a better type here.
- return Type::Signed32();
+ if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
+
+ lhs = NumberToInt32(lhs);
+ rhs = NumberToUint32(rhs);
+
+ int32_t min_lhs = lhs->Min();
+ int32_t max_lhs = lhs->Max();
+ uint32_t min_rhs = rhs->Min();
+ uint32_t max_rhs = rhs->Max();
+ if (max_rhs > 31) {
+ // rhs can be larger than the bitmask
+ max_rhs = 31;
+ min_rhs = 0;
+ }
+
+ if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) {
+ // overflow possible
+ return Type::Signed32();
+ }
+
+ double min =
+ std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs),
+ static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs));
+ double max =
+ std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs),
+ static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs));
+
+ if (max == kMaxInt && min == kMinInt) return Type::Signed32();
+ return Type::Range(min, max, zone());
}
Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
@@ -809,33 +844,18 @@ Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
lhs = NumberToInt32(lhs);
rhs = NumberToUint32(rhs);
- double min = kMinInt;
- double max = kMaxInt;
- if (lhs->Min() >= 0) {
- // Right-shifting a non-negative value cannot make it negative, nor larger.
- min = std::max(min, 0.0);
- max = std::min(max, lhs->Max());
- if (rhs->Min() > 0 && rhs->Max() <= 31) {
- max = static_cast<int>(max) >> static_cast<int>(rhs->Min());
- }
+ int32_t min_lhs = lhs->Min();
+ int32_t max_lhs = lhs->Max();
+ uint32_t min_rhs = rhs->Min();
+ uint32_t max_rhs = rhs->Max();
+ if (max_rhs > 31) {
+ // rhs can be larger than the bitmask
+ max_rhs = 31;
+ min_rhs = 0;
}
- if (lhs->Max() < 0) {
- // Right-shifting a negative value cannot make it non-negative, nor smaller.
- min = std::max(min, lhs->Min());
- max = std::min(max, -1.0);
- if (rhs->Min() > 0 && rhs->Max() <= 31) {
- min = static_cast<int>(min) >> static_cast<int>(rhs->Min());
- }
- }
- 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.
+ double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs);
+ double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs);
+
if (max == kMaxInt && min == kMinInt) return Type::Signed32();
return Type::Range(min, max, zone());
}