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 |