| 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/factory.h" | 7 #include "src/factory.h" |
| 8 #include "src/isolate.h" | 8 #include "src/isolate.h" |
| 9 #include "src/type-cache.h" | 9 #include "src/type-cache.h" |
| 10 #include "src/types.h" | 10 #include "src/types.h" |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 if (!std::isnan(a[i])) { | 146 if (!std::isnan(a[i])) { |
| 147 x = std::max(a[i], x); | 147 x = std::max(a[i], x); |
| 148 } | 148 } |
| 149 } | 149 } |
| 150 DCHECK(!std::isnan(x)); | 150 DCHECK(!std::isnan(x)); |
| 151 return x == 0 ? 0 : x; // -0 -> 0 | 151 return x == 0 ? 0 : x; // -0 -> 0 |
| 152 } | 152 } |
| 153 | 153 |
| 154 } // namespace | 154 } // namespace |
| 155 | 155 |
| 156 Type* OperationTyper::AddRanger(RangeType* lhs, RangeType* rhs) { | 156 Type* OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min, |
| 157 double rhs_max) { |
| 157 double results[4]; | 158 double results[4]; |
| 158 results[0] = lhs->Min() + rhs->Min(); | 159 results[0] = lhs_min + rhs_min; |
| 159 results[1] = lhs->Min() + rhs->Max(); | 160 results[1] = lhs_min + rhs_max; |
| 160 results[2] = lhs->Max() + rhs->Min(); | 161 results[2] = lhs_max + rhs_min; |
| 161 results[3] = lhs->Max() + rhs->Max(); | 162 results[3] = lhs_max + rhs_max; |
| 162 // Since none of the inputs can be -0, the result cannot be -0 either. | 163 // Since none of the inputs can be -0, the result cannot be -0 either. |
| 163 // However, it can be nan (the sum of two infinities of opposite sign). | 164 // However, it can be nan (the sum of two infinities of opposite sign). |
| 164 // On the other hand, if none of the "results" above is nan, then the actual | 165 // On the other hand, if none of the "results" above is nan, then the actual |
| 165 // result cannot be nan either. | 166 // result cannot be nan either. |
| 166 int nans = 0; | 167 int nans = 0; |
| 167 for (int i = 0; i < 4; ++i) { | 168 for (int i = 0; i < 4; ++i) { |
| 168 if (std::isnan(results[i])) ++nans; | 169 if (std::isnan(results[i])) ++nans; |
| 169 } | 170 } |
| 170 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa | 171 if (nans == 4) return Type::NaN(); // [-inf..-inf] + [inf..inf] or vice versa |
| 171 Type* range = | 172 Type* range = |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 282 return Type::Union(Type::Intersect(type, Type::Number(), zone()), |
| 282 cache_.kZeroOrOne, zone()); | 283 cache_.kZeroOrOne, zone()); |
| 283 } | 284 } |
| 284 return Type::Number(); | 285 return Type::Number(); |
| 285 } | 286 } |
| 286 | 287 |
| 287 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { | 288 Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) { |
| 288 DCHECK(lhs->Is(Type::Number())); | 289 DCHECK(lhs->Is(Type::Number())); |
| 289 DCHECK(rhs->Is(Type::Number())); | 290 DCHECK(rhs->Is(Type::Number())); |
| 290 | 291 |
| 291 lhs = Rangify(lhs); | 292 // We can give more precise types for integers. |
| 292 rhs = Rangify(rhs); | 293 if (!lhs->Is(cache_.kIntegerOrMinusZeroOrNaN) || |
| 293 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 294 !rhs->Is(cache_.kIntegerOrMinusZeroOrNaN)) { |
| 294 if (lhs->IsRange() && rhs->IsRange()) { | 295 return Type::Number(); |
| 295 return AddRanger(lhs->AsRange(), rhs->AsRange()); | |
| 296 } | 296 } |
| 297 // TODO(neis): Deal with numeric bitsets here and elsewhere. | 297 Type* int_lhs = Type::Intersect(lhs, cache_.kInteger, zone()); |
| 298 return Type::Number(); | 298 Type* int_rhs = Type::Intersect(rhs, cache_.kInteger, zone()); |
| 299 Type* result = |
| 300 AddRanger(int_lhs->Min(), int_lhs->Max(), int_rhs->Min(), int_rhs->Max()); |
| 301 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
| 302 result = Type::Union(result, Type::NaN(), zone()); |
| 303 } |
| 304 if (lhs->Maybe(Type::MinusZero()) && rhs->Maybe(Type::MinusZero())) { |
| 305 result = Type::Union(result, Type::MinusZero(), zone()); |
| 306 } |
| 307 return result; |
| 299 } | 308 } |
| 300 | 309 |
| 301 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { | 310 Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) { |
| 302 DCHECK(lhs->Is(Type::Number())); | 311 DCHECK(lhs->Is(Type::Number())); |
| 303 DCHECK(rhs->Is(Type::Number())); | 312 DCHECK(rhs->Is(Type::Number())); |
| 304 | 313 |
| 305 lhs = Rangify(lhs); | 314 lhs = Rangify(lhs); |
| 306 rhs = Rangify(rhs); | 315 rhs = Rangify(rhs); |
| 307 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 316 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); |
| 308 if (lhs->IsRange() && rhs->IsRange()) { | 317 if (lhs->IsRange() && rhs->IsRange()) { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 406 return NumericAdd(lhs, rhs); | 415 return NumericAdd(lhs, rhs); |
| 407 } | 416 } |
| 408 | 417 |
| 409 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 418 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
| 410 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); | 419 return NumericSubtract(ToNumber(lhs), ToNumber(rhs)); |
| 411 } | 420 } |
| 412 | 421 |
| 413 } // namespace compiler | 422 } // namespace compiler |
| 414 } // namespace internal | 423 } // namespace internal |
| 415 } // namespace v8 | 424 } // namespace v8 |
| OLD | NEW |