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" |
11 | 11 |
12 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) | 18 OperationTyper::OperationTyper(Isolate* isolate, Zone* zone) |
19 : zone_(zone), cache_(TypeCache::Get()) { | 19 : zone_(zone), cache_(TypeCache::Get()) { |
20 Factory* factory = isolate->factory(); | 20 Factory* factory = isolate->factory(); |
| 21 Type* infinity = Type::Constant(factory->infinity_value(), zone); |
| 22 Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone); |
| 23 // Unfortunately, the infinities created in other places might be different |
| 24 // ones (eg the result of NewNumber in TypeNumberConstant). |
| 25 Type* truncating_to_zero = |
| 26 Type::Union(Type::Union(infinity, minus_infinity, zone), |
| 27 Type::MinusZeroOrNaN(), zone); |
| 28 DCHECK(!truncating_to_zero->Maybe(Type::Integral32())); |
| 29 |
21 singleton_false_ = Type::Constant(factory->false_value(), zone); | 30 singleton_false_ = Type::Constant(factory->false_value(), zone); |
22 singleton_true_ = Type::Constant(factory->true_value(), zone); | 31 singleton_true_ = Type::Constant(factory->true_value(), zone); |
23 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); | 32 singleton_the_hole_ = Type::Constant(factory->the_hole_value(), zone); |
| 33 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); |
| 34 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); |
24 } | 35 } |
25 | 36 |
26 Type* OperationTyper::Merge(Type* left, Type* right) { | 37 Type* OperationTyper::Merge(Type* left, Type* right) { |
27 return Type::Union(left, right, zone()); | 38 return Type::Union(left, right, zone()); |
28 } | 39 } |
29 | 40 |
30 Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) { | 41 Type* OperationTyper::WeakenRange(Type* previous_range, Type* current_range) { |
31 static const double kWeakenMinLimits[] = {0.0, | 42 static const double kWeakenMinLimits[] = {0.0, |
32 -1073741824.0, | 43 -1073741824.0, |
33 -2147483648.0, | 44 -2147483648.0, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { | 218 Type* OperationTyper::MultiplyRanger(Type* lhs, Type* rhs) { |
208 double results[4]; | 219 double results[4]; |
209 double lmin = lhs->AsRange()->Min(); | 220 double lmin = lhs->AsRange()->Min(); |
210 double lmax = lhs->AsRange()->Max(); | 221 double lmax = lhs->AsRange()->Max(); |
211 double rmin = rhs->AsRange()->Min(); | 222 double rmin = rhs->AsRange()->Min(); |
212 double rmax = rhs->AsRange()->Max(); | 223 double rmax = rhs->AsRange()->Max(); |
213 results[0] = lmin * rmin; | 224 results[0] = lmin * rmin; |
214 results[1] = lmin * rmax; | 225 results[1] = lmin * rmax; |
215 results[2] = lmax * rmin; | 226 results[2] = lmax * rmin; |
216 results[3] = lmax * rmax; | 227 results[3] = lmax * rmax; |
217 // If the result may be nan, we give up on calculating a precise type, | 228 // If the result may be nan, we give up on calculating a precise type, because |
218 // because | 229 // the discontinuity makes it too complicated. Note that even if none of the |
219 // the discontinuity makes it too complicated. Note that even if none of | 230 // "results" above is nan, the actual result may still be, so we have to do a |
220 // the | |
221 // "results" above is nan, the actual result may still be, so we have to do | |
222 // a | |
223 // different check: | 231 // different check: |
224 bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) && | 232 bool maybe_nan = (lhs->Maybe(cache_.kSingletonZero) && |
225 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || | 233 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || |
226 (rhs->Maybe(cache_.kSingletonZero) && | 234 (rhs->Maybe(cache_.kSingletonZero) && |
227 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); | 235 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); |
228 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. | 236 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. |
229 bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) || | 237 bool maybe_minuszero = (lhs->Maybe(cache_.kSingletonZero) && rmin < 0) || |
230 (rhs->Maybe(cache_.kSingletonZero) && lmin < 0); | 238 (rhs->Maybe(cache_.kSingletonZero) && lmin < 0); |
231 Type* range = | 239 Type* range = |
232 Type::Range(array_min(results, 4), array_max(results, 4), zone()); | 240 Type::Range(array_min(results, 4), array_max(results, 4), zone()); |
233 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) | 241 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) |
234 : range; | 242 : range; |
235 } | 243 } |
236 | 244 |
237 Type* OperationTyper::ToNumber(Type* type) { | 245 Type* OperationTyper::ToNumber(Type* type) { |
238 if (type->Is(Type::Number())) return type; | 246 if (type->Is(Type::Number())) return type; |
239 if (type->Is(Type::NullOrUndefined())) { | 247 if (type->Is(Type::NullOrUndefined())) { |
240 if (type->Is(Type::Null())) return cache_.kSingletonZero; | 248 if (type->Is(Type::Null())) return cache_.kSingletonZero; |
241 if (type->Is(Type::Undefined())) return Type::NaN(); | 249 if (type->Is(Type::Undefined())) return Type::NaN(); |
242 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); | 250 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); |
243 } | 251 } |
244 if (type->Is(Type::NumberOrUndefined())) { | 252 if (type->Is(Type::Boolean())) { |
245 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 253 if (type->Is(singleton_false_)) return cache_.kSingletonZero; |
246 Type::NaN(), zone()); | 254 if (type->Is(singleton_true_)) return cache_.kSingletonOne; |
247 } | 255 return cache_.kZeroOrOne; |
248 if (type->Is(singleton_false_)) return cache_.kSingletonZero; | 256 } |
249 if (type->Is(singleton_true_)) return cache_.kSingletonOne; | 257 if (type->Is(Type::NumberOrOddball())) { |
250 if (type->Is(Type::Boolean())) return cache_.kZeroOrOne; | 258 if (type->Is(Type::NumberOrUndefined())) { |
251 if (type->Is(Type::BooleanOrNumber())) { | 259 type = Type::Union(type, Type::NaN(), zone()); |
252 return Type::Union(Type::Intersect(type, Type::Number(), zone()), | 260 } else if (type->Is(Type::NullOrNumber())) { |
253 cache_.kZeroOrOne, zone()); | 261 type = Type::Union(type, cache_.kSingletonZero, zone()); |
254 } | 262 } else if (type->Is(Type::BooleanOrNullOrNumber())) { |
255 return Type::Number(); | 263 type = Type::Union(type, cache_.kZeroOrOne, zone()); |
| 264 } else { |
| 265 type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone()); |
| 266 } |
| 267 return Type::Intersect(type, Type::Number(), zone()); |
| 268 } |
| 269 return Type::Number(); |
| 270 } |
| 271 |
| 272 Type* OperationTyper::NumberAbs(Type* type) { |
| 273 DCHECK(type->Is(Type::Number())); |
| 274 |
| 275 if (!type->IsInhabited()) { |
| 276 return Type::None(); |
| 277 } |
| 278 |
| 279 bool const maybe_nan = type->Maybe(Type::NaN()); |
| 280 bool const maybe_minuszero = type->Maybe(Type::MinusZero()); |
| 281 type = Type::Intersect(type, Type::PlainNumber(), zone()); |
| 282 double const max = type->Max(); |
| 283 double const min = type->Min(); |
| 284 if (min < 0) { |
| 285 if (type->Is(cache_.kInteger)) { |
| 286 type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone()); |
| 287 } else { |
| 288 type = Type::PlainNumber(); |
| 289 } |
| 290 } |
| 291 if (maybe_minuszero) { |
| 292 type = Type::Union(type, cache_.kSingletonZero, zone()); |
| 293 } |
| 294 if (maybe_nan) { |
| 295 type = Type::Union(type, Type::NaN(), zone()); |
| 296 } |
| 297 return type; |
| 298 } |
| 299 |
| 300 Type* OperationTyper::NumberAcos(Type* type) { |
| 301 DCHECK(type->Is(Type::Number())); |
| 302 return Type::Number(); |
| 303 } |
| 304 |
| 305 Type* OperationTyper::NumberAcosh(Type* type) { |
| 306 DCHECK(type->Is(Type::Number())); |
| 307 return Type::Number(); |
| 308 } |
| 309 |
| 310 Type* OperationTyper::NumberAsin(Type* type) { |
| 311 DCHECK(type->Is(Type::Number())); |
| 312 return Type::Number(); |
| 313 } |
| 314 |
| 315 Type* OperationTyper::NumberAsinh(Type* type) { |
| 316 DCHECK(type->Is(Type::Number())); |
| 317 return Type::Number(); |
| 318 } |
| 319 |
| 320 Type* OperationTyper::NumberAtan(Type* type) { |
| 321 DCHECK(type->Is(Type::Number())); |
| 322 return Type::Number(); |
| 323 } |
| 324 |
| 325 Type* OperationTyper::NumberAtanh(Type* type) { |
| 326 DCHECK(type->Is(Type::Number())); |
| 327 return Type::Number(); |
| 328 } |
| 329 |
| 330 Type* OperationTyper::NumberCbrt(Type* type) { |
| 331 DCHECK(type->Is(Type::Number())); |
| 332 return Type::Number(); |
| 333 } |
| 334 |
| 335 Type* OperationTyper::NumberCeil(Type* type) { |
| 336 DCHECK(type->Is(Type::Number())); |
| 337 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; |
| 338 // TODO(bmeurer): We could infer a more precise type here. |
| 339 return cache_.kIntegerOrMinusZeroOrNaN; |
| 340 } |
| 341 |
| 342 Type* OperationTyper::NumberClz32(Type* type) { |
| 343 DCHECK(type->Is(Type::Number())); |
| 344 return cache_.kZeroToThirtyTwo; |
| 345 } |
| 346 |
| 347 Type* OperationTyper::NumberCos(Type* type) { |
| 348 DCHECK(type->Is(Type::Number())); |
| 349 return Type::Number(); |
| 350 } |
| 351 |
| 352 Type* OperationTyper::NumberCosh(Type* type) { |
| 353 DCHECK(type->Is(Type::Number())); |
| 354 return Type::Number(); |
| 355 } |
| 356 |
| 357 Type* OperationTyper::NumberExp(Type* type) { |
| 358 DCHECK(type->Is(Type::Number())); |
| 359 return Type::Union(Type::PlainNumber(), Type::NaN(), zone()); |
| 360 } |
| 361 |
| 362 Type* OperationTyper::NumberExpm1(Type* type) { |
| 363 DCHECK(type->Is(Type::Number())); |
| 364 return Type::Union(Type::PlainNumber(), Type::NaN(), zone()); |
| 365 } |
| 366 |
| 367 Type* OperationTyper::NumberFloor(Type* type) { |
| 368 DCHECK(type->Is(Type::Number())); |
| 369 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; |
| 370 // TODO(bmeurer): We could infer a more precise type here. |
| 371 return cache_.kIntegerOrMinusZeroOrNaN; |
| 372 } |
| 373 |
| 374 Type* OperationTyper::NumberFround(Type* type) { |
| 375 DCHECK(type->Is(Type::Number())); |
| 376 return Type::Number(); |
| 377 } |
| 378 |
| 379 Type* OperationTyper::NumberLog(Type* type) { |
| 380 DCHECK(type->Is(Type::Number())); |
| 381 return Type::Number(); |
| 382 } |
| 383 |
| 384 Type* OperationTyper::NumberLog1p(Type* type) { |
| 385 DCHECK(type->Is(Type::Number())); |
| 386 return Type::Number(); |
| 387 } |
| 388 |
| 389 Type* OperationTyper::NumberLog2(Type* type) { |
| 390 DCHECK(type->Is(Type::Number())); |
| 391 return Type::Number(); |
| 392 } |
| 393 |
| 394 Type* OperationTyper::NumberLog10(Type* type) { |
| 395 DCHECK(type->Is(Type::Number())); |
| 396 return Type::Number(); |
| 397 } |
| 398 |
| 399 Type* OperationTyper::NumberRound(Type* type) { |
| 400 DCHECK(type->Is(Type::Number())); |
| 401 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; |
| 402 // TODO(bmeurer): We could infer a more precise type here. |
| 403 return cache_.kIntegerOrMinusZeroOrNaN; |
| 404 } |
| 405 |
| 406 Type* OperationTyper::NumberSign(Type* type) { |
| 407 DCHECK(type->Is(Type::Number())); |
| 408 if (type->Is(cache_.kZeroish)) return type; |
| 409 bool maybe_minuszero = type->Maybe(Type::MinusZero()); |
| 410 bool maybe_nan = type->Maybe(Type::NaN()); |
| 411 type = Type::Intersect(type, Type::PlainNumber(), zone()); |
| 412 if (type->Max() < 0.0) { |
| 413 type = cache_.kSingletonMinusOne; |
| 414 } else if (type->Max() <= 0.0) { |
| 415 type = cache_.kMinusOneOrZero; |
| 416 } else if (type->Min() > 0.0) { |
| 417 type = cache_.kSingletonOne; |
| 418 } else if (type->Min() >= 0.0) { |
| 419 type = cache_.kZeroOrOne; |
| 420 } else { |
| 421 type = Type::Range(-1.0, 1.0, zone()); |
| 422 } |
| 423 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
| 424 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
| 425 return type; |
| 426 } |
| 427 |
| 428 Type* OperationTyper::NumberSin(Type* type) { |
| 429 DCHECK(type->Is(Type::Number())); |
| 430 return Type::Number(); |
| 431 } |
| 432 |
| 433 Type* OperationTyper::NumberSinh(Type* type) { |
| 434 DCHECK(type->Is(Type::Number())); |
| 435 return Type::Number(); |
| 436 } |
| 437 |
| 438 Type* OperationTyper::NumberSqrt(Type* type) { |
| 439 DCHECK(type->Is(Type::Number())); |
| 440 return Type::Number(); |
| 441 } |
| 442 |
| 443 Type* OperationTyper::NumberTan(Type* type) { |
| 444 DCHECK(type->Is(Type::Number())); |
| 445 return Type::Number(); |
| 446 } |
| 447 |
| 448 Type* OperationTyper::NumberTanh(Type* type) { |
| 449 DCHECK(type->Is(Type::Number())); |
| 450 return Type::Number(); |
| 451 } |
| 452 |
| 453 Type* OperationTyper::NumberTrunc(Type* type) { |
| 454 DCHECK(type->Is(Type::Number())); |
| 455 if (type->Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; |
| 456 // TODO(bmeurer): We could infer a more precise type here. |
| 457 return cache_.kIntegerOrMinusZeroOrNaN; |
| 458 } |
| 459 |
| 460 Type* OperationTyper::NumberToInt32(Type* type) { |
| 461 DCHECK(type->Is(Type::Number())); |
| 462 |
| 463 if (type->Is(Type::Signed32())) return type; |
| 464 if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero; |
| 465 if (type->Is(signed32ish_)) { |
| 466 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()), |
| 467 Type::Signed32(), zone()); |
| 468 } |
| 469 return Type::Signed32(); |
| 470 } |
| 471 |
| 472 Type* OperationTyper::NumberToUint32(Type* type) { |
| 473 DCHECK(type->Is(Type::Number())); |
| 474 |
| 475 if (type->Is(Type::Unsigned32())) return type; |
| 476 if (type->Is(cache_.kZeroish)) return cache_.kSingletonZero; |
| 477 if (type->Is(unsigned32ish_)) { |
| 478 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()), |
| 479 Type::Unsigned32(), zone()); |
| 480 } |
| 481 return Type::Unsigned32(); |
| 482 } |
| 483 |
| 484 Type* OperationTyper::NumberSilenceNaN(Type* type) { |
| 485 DCHECK(type->Is(Type::Number())); |
| 486 // TODO(turbofan): We should have a dedicated type for the signaling NaN. |
| 487 return type; |
256 } | 488 } |
257 | 489 |
258 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { | 490 Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) { |
259 DCHECK(lhs->Is(Type::Number())); | 491 DCHECK(lhs->Is(Type::Number())); |
260 DCHECK(rhs->Is(Type::Number())); | 492 DCHECK(rhs->Is(Type::Number())); |
261 | 493 |
262 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | 494 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { |
263 return Type::None(); | 495 return Type::None(); |
264 } | 496 } |
265 | 497 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 type = Type::PlainNumber(); | 631 type = Type::PlainNumber(); |
400 } | 632 } |
401 } | 633 } |
402 | 634 |
403 // Take into account the -0 and NaN information computed earlier. | 635 // Take into account the -0 and NaN information computed earlier. |
404 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); | 636 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); |
405 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); | 637 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); |
406 return type; | 638 return type; |
407 } | 639 } |
408 | 640 |
409 Type* OperationTyper::NumberAbs(Type* type) { | 641 Type* OperationTyper::NumberBitwiseOr(Type* lhs, Type* rhs) { |
410 DCHECK(type->Is(Type::Number())); | 642 DCHECK(lhs->Is(Type::Number())); |
411 | 643 DCHECK(rhs->Is(Type::Number())); |
412 if (!type->IsInhabited()) { | 644 |
413 return Type::None(); | 645 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None(); |
414 } | 646 |
415 | 647 lhs = NumberToInt32(lhs); |
416 bool const maybe_nan = type->Maybe(Type::NaN()); | 648 rhs = NumberToInt32(rhs); |
417 bool const maybe_minuszero = type->Maybe(Type::MinusZero()); | 649 |
418 type = Type::Intersect(type, Type::PlainNumber(), zone()); | 650 double lmin = lhs->Min(); |
419 double const max = type->Max(); | 651 double rmin = rhs->Min(); |
420 double const min = type->Min(); | 652 double lmax = lhs->Max(); |
421 if (min < 0) { | 653 double rmax = rhs->Max(); |
422 if (type->Is(cache_.kInteger)) { | 654 // Or-ing any two values results in a value no smaller than their minimum. |
423 type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone()); | 655 // Even no smaller than their maximum if both values are non-negative. |
424 } else { | 656 double min = |
425 type = Type::PlainNumber(); | 657 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin); |
| 658 double max = kMaxInt; |
| 659 |
| 660 // Or-ing with 0 is essentially a conversion to int32. |
| 661 if (rmin == 0 && rmax == 0) { |
| 662 min = lmin; |
| 663 max = lmax; |
| 664 } |
| 665 if (lmin == 0 && lmax == 0) { |
| 666 min = rmin; |
| 667 max = rmax; |
| 668 } |
| 669 |
| 670 if (lmax < 0 || rmax < 0) { |
| 671 // Or-ing two values of which at least one is negative results in a negative |
| 672 // value. |
| 673 max = std::min(max, -1.0); |
| 674 } |
| 675 return Type::Range(min, max, zone()); |
| 676 } |
| 677 |
| 678 Type* OperationTyper::NumberBitwiseAnd(Type* lhs, Type* rhs) { |
| 679 DCHECK(lhs->Is(Type::Number())); |
| 680 DCHECK(rhs->Is(Type::Number())); |
| 681 |
| 682 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None(); |
| 683 |
| 684 lhs = NumberToInt32(lhs); |
| 685 rhs = NumberToInt32(rhs); |
| 686 |
| 687 double lmin = lhs->Min(); |
| 688 double rmin = rhs->Min(); |
| 689 double lmax = lhs->Max(); |
| 690 double rmax = rhs->Max(); |
| 691 double min = kMinInt; |
| 692 // And-ing any two values results in a value no larger than their maximum. |
| 693 // Even no larger than their minimum if both values are non-negative. |
| 694 double max = |
| 695 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax); |
| 696 // And-ing with a non-negative value x causes the result to be between |
| 697 // zero and x. |
| 698 if (lmin >= 0) { |
| 699 min = 0; |
| 700 max = std::min(max, lmax); |
| 701 } |
| 702 if (rmin >= 0) { |
| 703 min = 0; |
| 704 max = std::min(max, rmax); |
| 705 } |
| 706 return Type::Range(min, max, zone()); |
| 707 } |
| 708 |
| 709 Type* OperationTyper::NumberBitwiseXor(Type* lhs, Type* rhs) { |
| 710 DCHECK(lhs->Is(Type::Number())); |
| 711 DCHECK(rhs->Is(Type::Number())); |
| 712 |
| 713 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None(); |
| 714 |
| 715 lhs = NumberToInt32(lhs); |
| 716 rhs = NumberToInt32(rhs); |
| 717 |
| 718 double lmin = lhs->Min(); |
| 719 double rmin = rhs->Min(); |
| 720 double lmax = lhs->Max(); |
| 721 double rmax = rhs->Max(); |
| 722 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) { |
| 723 // Xor-ing negative or non-negative values results in a non-negative value. |
| 724 return Type::Unsigned31(); |
| 725 } |
| 726 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) { |
| 727 // Xor-ing a negative and a non-negative value results in a negative value. |
| 728 // TODO(jarin) Use a range here. |
| 729 return Type::Negative32(); |
| 730 } |
| 731 return Type::Signed32(); |
| 732 } |
| 733 |
| 734 Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) { |
| 735 DCHECK(lhs->Is(Type::Number())); |
| 736 DCHECK(rhs->Is(Type::Number())); |
| 737 |
| 738 // TODO(turbofan): Infer a better type here. |
| 739 return Type::Signed32(); |
| 740 } |
| 741 |
| 742 Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) { |
| 743 DCHECK(lhs->Is(Type::Number())); |
| 744 DCHECK(rhs->Is(Type::Number())); |
| 745 |
| 746 if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None(); |
| 747 |
| 748 lhs = NumberToInt32(lhs); |
| 749 rhs = NumberToUint32(rhs); |
| 750 |
| 751 double min = kMinInt; |
| 752 double max = kMaxInt; |
| 753 if (lhs->Min() >= 0) { |
| 754 // Right-shifting a non-negative value cannot make it negative, nor larger. |
| 755 min = std::max(min, 0.0); |
| 756 max = std::min(max, lhs->Max()); |
| 757 if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| 758 max = static_cast<int>(max) >> static_cast<int>(rhs->Min()); |
426 } | 759 } |
427 } | 760 } |
428 if (maybe_minuszero) { | 761 if (lhs->Max() < 0) { |
429 type = Type::Union(type, cache_.kSingletonZero, zone()); | 762 // Right-shifting a negative value cannot make it non-negative, nor smaller. |
430 } | 763 min = std::max(min, lhs->Min()); |
431 if (maybe_nan) { | 764 max = std::min(max, -1.0); |
| 765 if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| 766 min = static_cast<int>(min) >> static_cast<int>(rhs->Min()); |
| 767 } |
| 768 } |
| 769 if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| 770 // Right-shifting by a positive value yields a small integer value. |
| 771 double shift_min = kMinInt >> static_cast<int>(rhs->Min()); |
| 772 double shift_max = kMaxInt >> static_cast<int>(rhs->Min()); |
| 773 min = std::max(min, shift_min); |
| 774 max = std::min(max, shift_max); |
| 775 } |
| 776 // TODO(jarin) Ideally, the following micro-optimization should be performed |
| 777 // by the type constructor. |
| 778 if (max == kMaxInt && min == kMinInt) return Type::Signed32(); |
| 779 return Type::Range(min, max, zone()); |
| 780 } |
| 781 |
| 782 Type* OperationTyper::NumberShiftRightLogical(Type* lhs, Type* rhs) { |
| 783 DCHECK(lhs->Is(Type::Number())); |
| 784 DCHECK(rhs->Is(Type::Number())); |
| 785 |
| 786 if (!lhs->IsInhabited()) return Type::None(); |
| 787 |
| 788 lhs = NumberToUint32(lhs); |
| 789 |
| 790 // Logical right-shifting any value cannot make it larger. |
| 791 return Type::Range(0.0, lhs->Max(), zone()); |
| 792 } |
| 793 |
| 794 Type* OperationTyper::NumberAtan2(Type* lhs, Type* rhs) { |
| 795 DCHECK(lhs->Is(Type::Number())); |
| 796 DCHECK(rhs->Is(Type::Number())); |
| 797 return Type::Number(); |
| 798 } |
| 799 |
| 800 Type* OperationTyper::NumberImul(Type* lhs, Type* rhs) { |
| 801 DCHECK(lhs->Is(Type::Number())); |
| 802 DCHECK(rhs->Is(Type::Number())); |
| 803 // TODO(turbofan): We should be able to do better here. |
| 804 return Type::Signed32(); |
| 805 } |
| 806 |
| 807 Type* OperationTyper::NumberMax(Type* lhs, Type* rhs) { |
| 808 DCHECK(lhs->Is(Type::Number())); |
| 809 DCHECK(rhs->Is(Type::Number())); |
| 810 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) { |
| 811 return Type::NaN(); |
| 812 } |
| 813 Type* type = Type::None(); |
| 814 // TODO(turbofan): Improve minus zero handling here. |
| 815 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
432 type = Type::Union(type, Type::NaN(), zone()); | 816 type = Type::Union(type, Type::NaN(), zone()); |
433 } | 817 } |
| 818 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone()); |
| 819 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone()); |
| 820 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { |
| 821 double max = std::max(lhs->Max(), rhs->Max()); |
| 822 double min = std::max(lhs->Min(), rhs->Min()); |
| 823 type = Type::Union(type, Type::Range(min, max, zone()), zone()); |
| 824 } else { |
| 825 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone()); |
| 826 } |
434 return type; | 827 return type; |
435 } | 828 } |
436 | 829 |
| 830 Type* OperationTyper::NumberMin(Type* lhs, Type* rhs) { |
| 831 DCHECK(lhs->Is(Type::Number())); |
| 832 DCHECK(rhs->Is(Type::Number())); |
| 833 if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) { |
| 834 return Type::NaN(); |
| 835 } |
| 836 Type* type = Type::None(); |
| 837 // TODO(turbofan): Improve minus zero handling here. |
| 838 if (lhs->Maybe(Type::NaN()) || rhs->Maybe(Type::NaN())) { |
| 839 type = Type::Union(type, Type::NaN(), zone()); |
| 840 } |
| 841 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone()); |
| 842 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone()); |
| 843 if (lhs->Is(cache_.kInteger) && rhs->Is(cache_.kInteger)) { |
| 844 double max = std::min(lhs->Max(), rhs->Max()); |
| 845 double min = std::min(lhs->Min(), rhs->Min()); |
| 846 type = Type::Union(type, Type::Range(min, max, zone()), zone()); |
| 847 } else { |
| 848 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone()); |
| 849 } |
| 850 return type; |
| 851 } |
| 852 |
| 853 Type* OperationTyper::NumberPow(Type* lhs, Type* rhs) { |
| 854 DCHECK(lhs->Is(Type::Number())); |
| 855 DCHECK(rhs->Is(Type::Number())); |
| 856 // TODO(turbofan): We should be able to do better here. |
| 857 return Type::Number(); |
| 858 } |
| 859 |
| 860 #define SPECULATIVE_NUMBER_BINOP(Name) \ |
| 861 Type* OperationTyper::Speculative##Name(Type* lhs, Type* rhs) { \ |
| 862 lhs = ToNumber(Type::Intersect(lhs, Type::NumberOrOddball(), zone())); \ |
| 863 rhs = ToNumber(Type::Intersect(rhs, Type::NumberOrOddball(), zone())); \ |
| 864 return Name(lhs, rhs); \ |
| 865 } |
| 866 SPECULATIVE_NUMBER_BINOP(NumberAdd) |
| 867 SPECULATIVE_NUMBER_BINOP(NumberSubtract) |
| 868 SPECULATIVE_NUMBER_BINOP(NumberMultiply) |
| 869 SPECULATIVE_NUMBER_BINOP(NumberDivide) |
| 870 SPECULATIVE_NUMBER_BINOP(NumberModulus) |
| 871 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr) |
| 872 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd) |
| 873 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor) |
| 874 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft) |
| 875 SPECULATIVE_NUMBER_BINOP(NumberShiftRight) |
| 876 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical) |
| 877 #undef SPECULATIVE_NUMBER_BINOP |
| 878 |
437 Type* OperationTyper::ToPrimitive(Type* type) { | 879 Type* OperationTyper::ToPrimitive(Type* type) { |
438 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { | 880 if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { |
439 return type; | 881 return type; |
440 } | 882 } |
441 return Type::Primitive(); | 883 return Type::Primitive(); |
442 } | 884 } |
443 | 885 |
444 Type* OperationTyper::Invert(Type* type) { | 886 Type* OperationTyper::Invert(Type* type) { |
445 DCHECK(type->Is(Type::Boolean())); | 887 DCHECK(type->Is(Type::Boolean())); |
446 DCHECK(type->IsInhabited()); | 888 DCHECK(type->IsInhabited()); |
(...skipping 15 matching lines...) Expand all Loading... |
462 if ((outcome & kComparisonFalse) != 0 || | 904 if ((outcome & kComparisonFalse) != 0 || |
463 (outcome & kComparisonUndefined) != 0) { | 905 (outcome & kComparisonUndefined) != 0) { |
464 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() | 906 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() |
465 : singleton_false(); | 907 : singleton_false(); |
466 } | 908 } |
467 // Type should be non empty, so we know it should be true. | 909 // Type should be non empty, so we know it should be true. |
468 DCHECK((outcome & kComparisonTrue) != 0); | 910 DCHECK((outcome & kComparisonTrue) != 0); |
469 return singleton_true(); | 911 return singleton_true(); |
470 } | 912 } |
471 | 913 |
472 Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) { | |
473 lhs = ToPrimitive(lhs); | |
474 rhs = ToPrimitive(rhs); | |
475 | |
476 if (!lhs->IsInhabited() || !rhs->IsInhabited()) { | |
477 return Type::None(); | |
478 } | |
479 | |
480 if (lhs->Maybe(Type::String()) || rhs->Maybe(Type::String())) { | |
481 if (lhs->Is(Type::String()) || rhs->Is(Type::String())) { | |
482 return Type::String(); | |
483 } else { | |
484 return Type::NumberOrString(); | |
485 } | |
486 } | |
487 lhs = ToNumber(lhs); | |
488 rhs = ToNumber(rhs); | |
489 return NumberAdd(lhs, rhs); | |
490 } | |
491 | |
492 Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) { | |
493 return NumberSubtract(ToNumber(lhs), ToNumber(rhs)); | |
494 } | |
495 | |
496 } // namespace compiler | 914 } // namespace compiler |
497 } // namespace internal | 915 } // namespace internal |
498 } // namespace v8 | 916 } // namespace v8 |
OLD | NEW |