Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/operation-typer.h" | 5 #include "src/compiler/operation-typer.h" |
| 6 | 6 |
| 7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
| 8 #include "src/factory.h" | 8 #include "src/factory.h" |
| 9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
| 10 #include "src/type-cache.h" | 10 #include "src/type-cache.h" |
| 11 #include "src/types.h" | 11 #include "src/types.h" |
| 12 | 12 |
| 13 #include "src/objects-inl.h" | 13 #include "src/objects-inl.h" |
| 14 | 14 |
| 15 namespace v8 { | 15 namespace v8 { |
| 16 namespace internal { | 16 namespace internal { |
| 17 namespace compiler { | 17 namespace compiler { |
| 18 | 18 |
| 19 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) | 19 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) |
| 20 : zone_(zone), cache_(TypeCache::Get()) { | 20 : zone_(zone), cache_(TypeCache::Get()) { |
| 21 Factory* factory = isolate->factory(); | 21 Factory* factory = isolate->factory(); |
| 22 Type* infinity = Type::Constant(factory->infinity_value(), zone); | 22 infinity_ = Type::Constant(factory->infinity_value(), zone); |
| 23 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); | 23 minus_infinity_ = Type::Constant(factory->minus_infinity_value(), zone); |
| 24 // Unfortunately, the infinities created in other places might be different | 24 // Unfortunately, the infinities created in other places might be different |
| 25 // ones (eg the result of NewNumber in TypeNumberConstant). | 25 // ones (eg the result of NewNumber in TypeNumberConstant). |
| 26 Type* truncating_to_zero = | 26 Type* truncating_to_zero = |
| 27 Type::Union(Type::Union(infinity, minus_infinity, zone), | 27 Type::Union(Type::Union(infinity_, minus_infinity_, zone), |
| 28 Type::MinusZeroOrNaN(), zone); | 28 Type::MinusZeroOrNaN(), zone); |
| 29 DCHECK(!truncating_to_zero->Maybe(Type::Integral32())); | 29 DCHECK(!truncating_to_zero->Maybe(Type::Integral32())); |
| 30 | 30 |
| 31 singleton_false_ = Type::Constant(factory->false_value(), zone); | 31 singleton_false_ = Type::Constant(factory->false_value(), zone); |
| 32 singleton_true_ = Type::Constant(factory->true_value(), zone); | 32 singleton_true_ = Type::Constant(factory->true_value(), zone); |
| 33 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); | 33 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); |
| 34 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); | 34 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); |
| 35 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); | 35 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); |
| 36 } | 36 } |
| 37 | 37 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 | 167 |
| 168 Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min, | 168 Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min, |
| 169 double rhs_max) { | 169 double rhs_max) { |
| 170 double results[4]; | 170 double results[4]; |
| 171 results[0] = lhs_min + rhs_min; | 171 results[0] = lhs_min + rhs_min; |
| 172 results[1] = lhs_min + rhs_max; | 172 results[1] = lhs_min + rhs_max; |
| 173 results[2] = lhs_max + rhs_min; | 173 results[2] = lhs_max + rhs_min; |
| 174 results[3] = lhs_max + rhs_max; | 174 results[3] = lhs_max + rhs_max; |
| 175 // Since none of the inputs can be -0, the result cannot be -0 either. | 175 // Since none of the inputs can be -0, the result cannot be -0 either. |
| 176 // However, it can be nan (the sum of two infinities of opposite sign). | 176 // However, it can be nan (the sum of two infinities of opposite sign). |
| 177 // On the other hand, if none of the "results" above is nan, then the actual | 177 // On the other hand, if none of the "results" above is nan, then the |
| 178 // result cannot be nan either. | 178 // actual result cannot be nan either. |
| 179 int nans = 0; | 179 int nans = 0; |
| 180 for (int i = 0; i < 4; ++i) { | 180 for (int i = 0; i < 4; ++i) { |
| 181 if (std::isnan(results[i])) ++nans; | 181 if (std::isnan(results[i])) ++nans; |
| 182 } | 182 } |
| 183 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa | 183 if (nans == 4) return Type::NaN(); |
| 184 Type* range = | 184 Type* type = |
| 185 Type::Range(array_min(results, 4), array_max(results, 4), zone()); | 185 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
| 186 return nans == 0 ? range : Type::Union(range, Type::NaN(), zone()); | 186 if (nans > 0) type = Type::Union(type, Type::NaN(), zone()); |
| 187 // Examples: | 187 // Examples: |
| 188 // [-inf, -inf] + [+inf, +inf] = NaN | 188 // [-inf, -inf] + [+inf, +inf] = NaN |
| 189 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN | 189 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN |
| 190 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN | 190 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN |
| 191 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN | 191 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN |
| 192 return type; | |
| 192 } | 193 } |
| 193 | 194 |
| 194 Type* OperationTyper::SubtractRanger(RangeType* lhs, RangeType* rhs) { | 195 Type* OperationTyper::SubtractRanger(RangeType* lhs, RangeType* rhs) { |
| 195 double results[4]; | 196 double results[4]; |
| 196 results[0] = lhs->Min() - rhs->Min(); | 197 results[0] = lhs->Min() - rhs->Min(); |
| 197 results[1] = lhs->Min() - rhs->Max(); | 198 results[1] = lhs->Min() - rhs->Max(); |
| 198 results[2] = lhs->Max() - rhs->Min(); | 199 results[2] = lhs->Max() - rhs->Min(); |
| 199 results[3] = lhs->Max() - rhs->Max(); | 200 results[3] = lhs->Max() - rhs->Max(); |
| 200 // Since none of the inputs can be -0, the result cannot be -0. | 201 // Since none of the inputs can be -0, the result cannot be -0. |
| 201 // However, it can be nan (the subtraction of two infinities of same sign). | 202 // However, it can be nan (the subtraction of two infinities of same sign). |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 489 } | 490 } |
| 490 | 491 |
| 491 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { | 492 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { |
| 492 DCHECK(lhs->Is(Type::Number())); | 493 DCHECK(lhs->Is(Type::Number())); |
| 493 DCHECK(rhs->Is(Type::Number())); | 494 DCHECK(rhs->Is(Type::Number())); |
| 494 | 495 |
| 495 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 496 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 496 return Type::None(); | 497 return Type::None(); |
| 497 } | 498 } |
| 498 | 499 |
| 500 // Addition can return NaN if either input can be NaN or we try to compute | |
| 501 // the sum of two infinities of opposite sign. | |
| 502 bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN()); | |
| 503 | |
| 504 // Addition can yield minus zero only if both inputs can be minus zero. | |
| 505 bool maybe_minuszero = false; | |
| 506 if (lhs->Maybe(Type::MinusZero())) { | |
| 507 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); | |
| 508 maybe_minuszero = true; | |
| 509 } | |
| 510 if (rhs->Maybe(Type::MinusZero())) { | |
| 511 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); | |
| 512 maybe_minuszero = true; | |
| 513 } | |
|
Jarin
2016/08/08 06:43:59
This sets maybe_minuszero if one side can be minus
Benedikt Meurer
2016/08/08 06:59:33
Ah good point, thanks.
| |
| 514 | |
| 499 // We can give more precise types for integers. | 515 // We can give more precise types for integers. |
| 500 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || | 516 Type* type = Type::None(); |
| 501 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { | 517 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); |
| 502 return Type::Number(); | 518 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); |
| 519 if (lhs->IsInhabited() && rhs->IsInhabited()) { | |
| 520 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { | |
| 521 type = AddRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max()); | |
| 522 } else { | |
| 523 if ((lhs->Maybe(minus_infinity_) && rhs->Maybe(infinity_)) || | |
| 524 (rhs->Maybe(minus_infinity_) && lhs->Maybe(infinity_))) { | |
| 525 maybe_nan = true; | |
| 526 } | |
| 527 type = Type::PlainNumber(); | |
| 528 } | |
| 503 } | 529 } |
| 504 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); | 530 |
| 505 if (lhs->Maybe(Type::MinusZero())) { | 531 // Take into account the -0 and NaN information computed earlier. |
| 506 int_lhs = Type::Union(int_lhs, cache_.kSingletonZero, zone()); | 532 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
| 507 } | 533 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
| 508 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); | 534 return type; |
| 509 if (rhs->Maybe(Type::MinusZero())) { | |
| 510 int_rhs = Type::Union(int_rhs, cache_.kSingletonZero, zone()); | |
| 511 } | |
| 512 Type* result = | |
| 513 AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max()); | |
| 514 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { | |
| 515 result = Type::Union(result, Type::NaN(), zone()); | |
| 516 } | |
| 517 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { | |
| 518 result = Type::Union(result, Type::MinusZero(), zone()); | |
| 519 } | |
| 520 return result; | |
| 521 } | 535 } |
| 522 | 536 |
| 523 Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) { | 537 Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) { |
| 524 DCHECK(lhs->Is(Type::Number())); | 538 DCHECK(lhs->Is(Type::Number())); |
| 525 DCHECK(rhs->Is(Type::Number())); | 539 DCHECK(rhs->Is(Type::Number())); |
| 526 | 540 |
| 527 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 541 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
| 528 return Type::None(); | 542 return Type::None(); |
| 529 } | 543 } |
| 530 | 544 |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 return singleton_true(); | 926 return singleton_true(); |
| 913 } | 927 } |
| 914 | 928 |
| 915 Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) { | 929 Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) { |
| 916 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone()); | 930 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone()); |
| 917 } | 931 } |
| 918 | 932 |
| 919 } // namespace compiler | 933 } // namespace compiler |
| 920 } // namespace internal | 934 } // namespace internal |
| 921 } // namespace v8 | 935 } // namespace v8 |
| OLD | NEW |