| 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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 Type* range = | 197 Type* range = |
| 198 Type::Range(array_min(results, 4), array_max(results, 4), zone()); | 198 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
| 199 return nans == 0 ? range : Type::Union(range, Type::NaN(), zone()); | 199 return nans == 0 ? range : Type::Union(range, Type::NaN(), zone()); |
| 200 // Examples: | 200 // Examples: |
| 201 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN | 201 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN |
| 202 // [-inf, -inf] - [-inf, -inf] = NaN | 202 // [-inf, -inf] - [-inf, -inf] = NaN |
| 203 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN | 203 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN |
| 204 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN | 204 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN |
| 205 } | 205 } |
| 206 | 206 |
| 207 Type* OperationTyper::ModulusRanger(RangeType* lhs, RangeType* rhs) { | |
| 208 double lmin = lhs->Min(); | |
| 209 double lmax = lhs->Max(); | |
| 210 double rmin = rhs->Min(); | |
| 211 double rmax = rhs->Max(); | |
| 212 | |
| 213 double labs = std::max(std::abs(lmin), std::abs(lmax)); | |
| 214 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; | |
| 215 double abs = std::min(labs, rabs); | |
| 216 bool maybe_minus_zero = false; | |
| 217 double omin = 0; | |
| 218 double omax = 0; | |
| 219 if (lmin >= 0) { // {lhs} positive. | |
| 220 omin = 0; | |
| 221 omax = abs; | |
| 222 } else if (lmax <= 0) { // {lhs} negative. | |
| 223 omin = 0 - abs; | |
| 224 omax = 0; | |
| 225 maybe_minus_zero = true; | |
| 226 } else { | |
| 227 omin = 0 - abs; | |
| 228 omax = abs; | |
| 229 maybe_minus_zero = true; | |
| 230 } | |
| 231 | |
| 232 Type* result = Type::Range(omin, omax, zone()); | |
| 233 if (maybe_minus_zero) result = Type::Union(result, Type::MinusZero(), zone()); | |
| 234 return result; | |
| 235 } | |
| 236 | |
| 237 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { | 207 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { |
| 238 double results[4]; | 208 double results[4]; |
| 239 double lmin = lhs->AsRange()->Min(); | 209 double lmin = lhs->AsRange()->Min(); |
| 240 double lmax = lhs->AsRange()->Max(); | 210 double lmax = lhs->AsRange()->Max(); |
| 241 double rmin = rhs->AsRange()->Min(); | 211 double rmin = rhs->AsRange()->Min(); |
| 242 double rmax = rhs->AsRange()->Max(); | 212 double rmax = rhs->AsRange()->Max(); |
| 243 results[0] = lmin * rmin; | 213 results[0] = lmin * rmin; |
| 244 results[1] = lmin * rmax; | 214 results[1] = lmin * rmax; |
| 245 results[2] = lmax * rmin; | 215 results[2] = lmax * rmin; |
| 246 results[3] = lmax * rmax; | 216 results[3] = lmax * rmax; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 336 lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 367 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && | 337 ((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) && |
| 368 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); | 338 (rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY)); |
| 369 return maybe_nan ? Type::Number() : Type::OrderedNumber(); | 339 return maybe_nan ? Type::Number() : Type::OrderedNumber(); |
| 370 } | 340 } |
| 371 | 341 |
| 372 Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) { | 342 Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) { |
| 373 DCHECK(lhs->Is(Type::Number())); | 343 DCHECK(lhs->Is(Type::Number())); |
| 374 DCHECK(rhs->Is(Type::Number())); | 344 DCHECK(rhs->Is(Type::Number())); |
| 375 | 345 |
| 376 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 346 // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or |
| 377 return Type::None(); | 347 // {lhs} is not finite, or the {rhs} is a zero value. |
| 348 bool maybe_nan = lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || |
| 349 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY; |
| 350 |
| 351 // Deal with -0 inputs, only the signbit of {lhs} matters for the result. |
| 352 bool maybe_minuszero = false; |
| 353 if (lhs->Maybe(Type::MinusZero())) { |
| 354 maybe_minuszero = true; |
| 355 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); |
| 356 } |
| 357 if (rhs->Maybe(Type::MinusZero())) { |
| 358 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); |
| 378 } | 359 } |
| 379 | 360 |
| 380 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN(); | 361 // Rule out NaN and -0, and check what we can do with the remaining type info. |
| 362 Type* type = Type::None(); |
| 363 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); |
| 364 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); |
| 381 | 365 |
| 382 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(cache_.kZeroish) || | 366 // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited, |
| 383 lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) { | 367 // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}. |
| 384 // Result maybe NaN. | 368 if (lhs->IsInhabited() && !rhs->Is(cache_.kSingletonZero)) { |
| 385 return Type::Number(); | 369 // Determine the bounds of {lhs} and {rhs}. |
| 370 double const lmin = lhs->Min(); |
| 371 double const lmax = lhs->Max(); |
| 372 double const rmin = rhs->Min(); |
| 373 double const rmax = rhs->Max(); |
| 374 |
| 375 // The sign of the result is the sign of the {lhs}. |
| 376 if (lmin < 0.0) maybe_minuszero = true; |
| 377 |
| 378 // For integer inputs {lhs} and {rhs} we can infer a precise type. |
| 379 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { |
| 380 double labs = std::max(std::abs(lmin), std::abs(lmax)); |
| 381 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; |
| 382 double abs = std::min(labs, rabs); |
| 383 double min = 0.0, max = 0.0; |
| 384 if (lmin >= 0.0) { |
| 385 // {lhs} positive. |
| 386 min = 0.0; |
| 387 max = abs; |
| 388 } else if (lmax <= 0.0) { |
| 389 // {lhs} negative. |
| 390 min = 0.0 - abs; |
| 391 max = 0.0; |
| 392 } else { |
| 393 // {lhs} positive or negative. |
| 394 min = 0.0 - abs; |
| 395 max = abs; |
| 396 } |
| 397 type = Type::Range(min, max, zone()); |
| 398 } else { |
| 399 type = Type::PlainNumber(); |
| 400 } |
| 386 } | 401 } |
| 387 | 402 |
| 388 lhs = Rangify(lhs); | 403 // Take into account the -0 and NaN information computed earlier. |
| 389 rhs = Rangify(rhs); | 404 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
| 390 if (lhs->IsRange() && rhs->IsRange()) { | 405 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
| 391 return ModulusRanger(lhs->AsRange(), rhs->AsRange()); | 406 return type; |
| 392 } | |
| 393 return Type::OrderedNumber(); | |
| 394 } | 407 } |
| 395 | 408 |
| 396 Type* OperationTyper::NumberAbs(Type* type) { | 409 Type* OperationTyper::NumberAbs(Type* type) { |
| 397 DCHECK(type->Is(Type::Number())); | 410 DCHECK(type->Is(Type::Number())); |
| 398 | 411 |
| 399 if (!type->IsInhabited()) { | 412 if (!type->IsInhabited()) { |
| 400 return Type::None(); | 413 return Type::None(); |
| 401 } | 414 } |
| 402 | 415 |
| 403 bool const maybe_nan = type->Maybe(Type::NaN()); | 416 bool const maybe_nan = type->Maybe(Type::NaN()); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 return NumberAdd(lhs, rhs); | 489 return NumberAdd(lhs, rhs); |
| 477 } | 490 } |
| 478 | 491 |
| 479 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | 492 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { |
| 480 return NumberSubtract(ToNumber(lhs), ToNumber(rhs)); | 493 return NumberSubtract(ToNumber(lhs), ToNumber(rhs)); |
| 481 } | 494 } |
| 482 | 495 |
| 483 } // namespace compiler | 496 } // namespace compiler |
| 484 } // namespace internal | 497 } // namespace internal |
| 485 } // namespace v8 | 498 } // namespace v8 |
| OLD | NEW |