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 = true; |
| 506 if (lhs->Maybe(Type::MinusZero())) { |
| 507 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); |
| 508 } else { |
| 509 maybe_minuszero = false; |
| 510 } |
| 511 if (rhs->Maybe(Type::MinusZero())) { |
| 512 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); |
| 513 } else { |
| 514 maybe_minuszero = false; |
| 515 } |
| 516 |
499 // We can give more precise types for integers. | 517 // We can give more precise types for integers. |
500 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || | 518 Type* type = Type::None(); |
501 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { | 519 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); |
502 return Type::Number(); | 520 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); |
| 521 if (lhs->IsInhabited() && rhs->IsInhabited()) { |
| 522 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { |
| 523 type = AddRanger(lhs->Min(), lhs->Max(), rhs->Min(), rhs->Max()); |
| 524 } else { |
| 525 if ((lhs->Maybe(minus_infinity_) && rhs->Maybe(infinity_)) || |
| 526 (rhs->Maybe(minus_infinity_) && lhs->Maybe(infinity_))) { |
| 527 maybe_nan = true; |
| 528 } |
| 529 type = Type::PlainNumber(); |
| 530 } |
503 } | 531 } |
504 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); | 532 |
505 if (lhs->Maybe(Type::MinusZero())) { | 533 // Take into account the -0 and NaN information computed earlier. |
506 int_lhs = Type::Union(int_lhs, cache_.kSingletonZero, zone()); | 534 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
507 } | 535 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
508 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); | 536 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 } | 537 } |
522 | 538 |
523 Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) { | 539 Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) { |
524 DCHECK(lhs->Is(Type::Number())); | 540 DCHECK(lhs->Is(Type::Number())); |
525 DCHECK(rhs->Is(Type::Number())); | 541 DCHECK(rhs->Is(Type::Number())); |
526 | 542 |
527 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 543 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
528 return Type::None(); | 544 return Type::None(); |
529 } | 545 } |
530 | 546 |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 return singleton_true(); | 928 return singleton_true(); |
913 } | 929 } |
914 | 930 |
915 Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) { | 931 Type* OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type* input) { |
916 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone()); | 932 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone()); |
917 } | 933 } |
918 | 934 |
919 } // namespace compiler | 935 } // namespace compiler |
920 } // namespace internal | 936 } // namespace internal |
921 } // namespace v8 | 937 } // namespace v8 |
OLD | NEW |