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 3 // found in the LICENSE file. 4 5 #include "src/compiler/operation-typer.h" 6 7 #include "src/compiler/common-operator.h" 8 #include "src/compiler/type-cache.h" 9 #include "src/compiler/types.h" 10 #include "src/heap/factory.h" 11 #include "src/isolate.h" 12 13 #include "src/objects-inl.h" 14 15 namespace v8 { 16 namespace internal { 17 namespace compiler { 18 19 OperationTyper::OperationTyper(Isolate* isolate, JSHeapBroker* js_heap_broker, 20 Zone* zone) 21 : zone_(zone), cache_(TypeCache::Get()) { 22 Factory* factory = isolate->factory(); 23 infinity_ = 24 Type::NewConstant(js_heap_broker, factory->infinity_value(), zone); 25 minus_infinity_ = 26 Type::NewConstant(js_heap_broker, factory->minus_infinity_value(), zone); 27 Type truncating_to_zero = Type::MinusZeroOrNaN(); 28 DCHECK(!truncating_to_zero.Maybe(Type::Integral32())); 29 30 singleton_empty_string_ = 31 Type::HeapConstant(js_heap_broker, factory->empty_string(), zone); 32 singleton_NaN_string_ = 33 Type::HeapConstant(js_heap_broker, factory->NaN_string(), zone); 34 singleton_zero_string_ = 35 Type::HeapConstant(js_heap_broker, factory->zero_string(), zone); 36 singleton_false_ = 37 Type::HeapConstant(js_heap_broker, factory->false_value(), zone); 38 singleton_true_ = 39 Type::HeapConstant(js_heap_broker, factory->true_value(), zone); 40 singleton_the_hole_ = 41 Type::HeapConstant(js_heap_broker, factory->the_hole_value(), zone); 42 signed32ish_ = Type::Union(Type::Signed32(), truncating_to_zero, zone); 43 unsigned32ish_ = Type::Union(Type::Unsigned32(), truncating_to_zero, zone); 44 45 falsish_ = Type::Union( 46 Type::Undetectable(), 47 Type::Union(Type::Union(singleton_false_, cache_.kZeroish, zone), 48 Type::Union(singleton_empty_string_, Type::Hole(), zone), 49 zone), 50 zone); 51 truish_ = Type::Union( 52 singleton_true_, 53 Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone), zone); 54 } 55 56 Type OperationTyper::Merge(Type left, Type right) { 57 return Type::Union(left, right, zone()); 58 } 59 60 Type OperationTyper::WeakenRange(Type previous_range, Type current_range) { 61 static const double kWeakenMinLimits[] = {0.0, 62 -1073741824.0, 63 -2147483648.0, 64 -4294967296.0, 65 -8589934592.0, 66 -17179869184.0, 67 -34359738368.0, 68 -68719476736.0, 69 -137438953472.0, 70 -274877906944.0, 71 -549755813888.0, 72 -1099511627776.0, 73 -2199023255552.0, 74 -4398046511104.0, 75 -8796093022208.0, 76 -17592186044416.0, 77 -35184372088832.0, 78 -70368744177664.0, 79 -140737488355328.0, 80 -281474976710656.0, 81 -562949953421312.0}; 82 static const double kWeakenMaxLimits[] = {0.0, 83 1073741823.0, 84 2147483647.0, 85 4294967295.0, 86 8589934591.0, 87 17179869183.0, 88 34359738367.0, 89 68719476735.0, 90 137438953471.0, 91 274877906943.0, 92 549755813887.0, 93 1099511627775.0, 94 2199023255551.0, 95 4398046511103.0, 96 8796093022207.0, 97 17592186044415.0, 98 35184372088831.0, 99 70368744177663.0, 100 140737488355327.0, 101 281474976710655.0, 102 562949953421311.0}; 103 STATIC_ASSERT(arraysize(kWeakenMinLimits) == arraysize(kWeakenMaxLimits)); 104 105 double current_min = current_range.Min(); 106 double new_min = current_min; 107 // Find the closest lower entry in the list of allowed 108 // minima (or negative infinity if there is no such entry). 109 if (current_min != previous_range.Min()) { 110 new_min = -V8_INFINITY; 111 for (double const min : kWeakenMinLimits) { 112 if (min <= current_min) { 113 new_min = min; 114 break; 115 } 116 } 117 } 118 119 double current_max = current_range.Max(); 120 double new_max = current_max; 121 // Find the closest greater entry in the list of allowed 122 // maxima (or infinity if there is no such entry). 123 if (current_max != previous_range.Max()) { 124 new_max = V8_INFINITY; 125 for (double const max : kWeakenMaxLimits) { 126 if (max >= current_max) { 127 new_max = max; 128 break; 129 } 130 } 131 } 132 133 return Type::Range(new_min, new_max, zone()); 134 } 135 136 Type OperationTyper::Rangify(Type type) { 137 if (type.IsRange()) return type; // Shortcut. 138 if (!type.Is(cache_.kInteger)) { 139 return type; // Give up on non-integer types. 140 } 141 return Type::Range(type.Min(), type.Max(), zone()); 142 } 143 144 namespace { 145 146 // Returns the array's least element, ignoring NaN. 147 // There must be at least one non-NaN element. 148 // Any -0 is converted to 0. 149 double array_min(double a[], size_t n) { 150 DCHECK_NE(0, n); 151 double x = +V8_INFINITY; 152 for (size_t i = 0; i < n; ++i) { 153 if (!std::isnan(a[i])) { 154 x = std::min(a[i], x); 155 } 156 } 157 DCHECK(!std::isnan(x)); 158 return x == 0 ? 0 : x; // -0 -> 0 159 } 160 161 // Returns the array's greatest element, ignoring NaN. 162 // There must be at least one non-NaN element. 163 // Any -0 is converted to 0. 164 double array_max(double a[], size_t n) { 165 DCHECK_NE(0, n); 166 double x = -V8_INFINITY; 167 for (size_t i = 0; i < n; ++i) { 168 if (!std::isnan(a[i])) { 169 x = std::max(a[i], x); 170 } 171 } 172 DCHECK(!std::isnan(x)); 173 return x == 0 ? 0 : x; // -0 -> 0 174 } 175 176 } // namespace 177 178 Type OperationTyper::AddRanger(double lhs_min, double lhs_max, double rhs_min, 179 double rhs_max) { 180 double results[4]; 181 results[0] = lhs_min + rhs_min; 182 results[1] = lhs_min + rhs_max; 183 results[2] = lhs_max + rhs_min; 184 results[3] = lhs_max + rhs_max; 185 // Since none of the inputs can be -0, the result cannot be -0 either. 186 // However, it can be nan (the sum of two infinities of opposite sign). 187 // On the other hand, if none of the "results" above is nan, then the 188 // actual result cannot be nan either. 189 int nans = 0; 190 for (int i = 0; i < 4; ++i) { 191 if (std::isnan(results[i])) ++nans; 192 } 193 if (nans == 4) return Type::NaN(); 194 Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone()); 195 if (nans > 0) type = Type::Union(type, Type::NaN(), zone()); 196 // Examples: 197 // [-inf, -inf] + [+inf, +inf] = NaN 198 // [-inf, -inf] + [n, +inf] = [-inf, -inf] \/ NaN 199 // [-inf, +inf] + [n, +inf] = [-inf, +inf] \/ NaN 200 // [-inf, m] + [n, +inf] = [-inf, +inf] \/ NaN 201 return type; 202 } 203 204 Type OperationTyper::SubtractRanger(double lhs_min, double lhs_max, 205 double rhs_min, double rhs_max) { 206 double results[4]; 207 results[0] = lhs_min - rhs_min; 208 results[1] = lhs_min - rhs_max; 209 results[2] = lhs_max - rhs_min; 210 results[3] = lhs_max - rhs_max; 211 // Since none of the inputs can be -0, the result cannot be -0. 212 // However, it can be nan (the subtraction of two infinities of same sign). 213 // On the other hand, if none of the "results" above is nan, then the actual 214 // result cannot be nan either. 215 int nans = 0; 216 for (int i = 0; i < 4; ++i) { 217 if (std::isnan(results[i])) ++nans; 218 } 219 if (nans == 4) return Type::NaN(); // [inf..inf] - [inf..inf] (all same sign) 220 Type type = Type::Range(array_min(results, 4), array_max(results, 4), zone()); 221 return nans == 0 ? type : Type::Union(type, Type::NaN(), zone()); 222 // Examples: 223 // [-inf, +inf] - [-inf, +inf] = [-inf, +inf] \/ NaN 224 // [-inf, -inf] - [-inf, -inf] = NaN 225 // [-inf, -inf] - [n, +inf] = [-inf, -inf] \/ NaN 226 // [m, +inf] - [-inf, n] = [-inf, +inf] \/ NaN 227 } 228 229 Type OperationTyper::MultiplyRanger(Type lhs, Type rhs) { 230 double results[4]; 231 double lmin = lhs.AsRange()->Min(); 232 double lmax = lhs.AsRange()->Max(); 233 double rmin = rhs.AsRange()->Min(); 234 double rmax = rhs.AsRange()->Max(); 235 results[0] = lmin * rmin; 236 results[1] = lmin * rmax; 237 results[2] = lmax * rmin; 238 results[3] = lmax * rmax; 239 // If the result may be nan, we give up on calculating a precise type, because 240 // the discontinuity makes it too complicated. Note that even if none of the 241 // "results" above is nan, the actual result may still be, so we have to do a 242 // different check: 243 bool maybe_nan = (lhs.Maybe(cache_.kSingletonZero) && 244 (rmin == -V8_INFINITY || rmax == +V8_INFINITY)) || 245 (rhs.Maybe(cache_.kSingletonZero) && 246 (lmin == -V8_INFINITY || lmax == +V8_INFINITY)); 247 if (maybe_nan) return cache_.kIntegerOrMinusZeroOrNaN; // Giving up. 248 bool maybe_minuszero = (lhs.Maybe(cache_.kSingletonZero) && rmin < 0) || 249 (rhs.Maybe(cache_.kSingletonZero) && lmin < 0); 250 Type range = 251 Type::Range(array_min(results, 4), array_max(results, 4), zone()); 252 return maybe_minuszero ? Type::Union(range, Type::MinusZero(), zone()) 253 : range; 254 } 255 256 Type OperationTyper::ConvertReceiver(Type type) { 257 if (type.Is(Type::Receiver())) return type; 258 bool const maybe_primitive = type.Maybe(Type::Primitive()); 259 type = Type::Intersect(type, Type::Receiver(), zone()); 260 if (maybe_primitive) { 261 // ConvertReceiver maps null and undefined to the JSGlobalProxy of the 262 // target function, and all other primitives are wrapped into a JSValue. 263 type = Type::Union(type, Type::OtherObject(), zone()); 264 } 265 return type; 266 } 267 268 // Returns the result type of converting {type} to number, if the 269 // result does not depend on conversion options. 270 base::Optional<Type> OperationTyper::ToNumberCommon(Type type) { 271 if (type.Is(Type::Number())) return type; 272 if (type.Is(Type::NullOrUndefined())) { 273 if (type.Is(Type::Null())) return cache_.kSingletonZero; 274 if (type.Is(Type::Undefined())) return Type::NaN(); 275 return Type::Union(Type::NaN(), cache_.kSingletonZero, zone()); 276 } 277 if (type.Is(Type::Boolean())) { 278 if (type.Is(singleton_false_)) return cache_.kSingletonZero; 279 if (type.Is(singleton_true_)) return cache_.kSingletonOne; 280 return cache_.kZeroOrOne; 281 } 282 if (type.Is(Type::NumberOrOddball())) { 283 if (type.Is(Type::NumberOrUndefined())) { 284 type = Type::Union(type, Type::NaN(), zone()); 285 } else if (type.Is(Type::NullOrNumber())) { 286 type = Type::Union(type, cache_.kSingletonZero, zone()); 287 } else if (type.Is(Type::BooleanOrNullOrNumber())) { 288 type = Type::Union(type, cache_.kZeroOrOne, zone()); 289 } else { 290 type = Type::Union(type, cache_.kZeroOrOneOrNaN, zone()); 291 } 292 return Type::Intersect(type, Type::Number(), zone()); 293 } 294 return base::Optional<Type>(); 295 } 296 297 Type OperationTyper::ToNumberOrNumeric(Object::Conversion mode, Type type) { 298 if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) { 299 return *maybe_result_type; 300 } 301 if (type.Is(Type::BigInt())) { 302 return mode == Object::Conversion::kToNumber ? Type::None() : type; 303 } 304 return mode == Object::Conversion::kToNumber ? Type::Number() 305 : Type::Numeric(); 306 } 307 308 Type OperationTyper::ToNumber(Type type) { 309 return ToNumberOrNumeric(Object::Conversion::kToNumber, type); 310 } 311 312 Type OperationTyper::ToNumberConvertBigInt(Type type) { 313 if (base::Optional<Type> maybe_result_type = ToNumberCommon(type)) { 314 return *maybe_result_type; 315 } 316 return Type::Number(); 317 } 318 319 Type OperationTyper::ToNumeric(Type type) { 320 return ToNumberOrNumeric(Object::Conversion::kToNumeric, type); 321 } 322 323 Type OperationTyper::NumberAbs(Type type) { 324 DCHECK(type.Is(Type::Number())); 325 if (type.IsNone()) return type; 326 327 bool const maybe_nan = type.Maybe(Type::NaN()); 328 bool const maybe_minuszero = type.Maybe(Type::MinusZero()); 329 330 type = Type::Intersect(type, Type::PlainNumber(), zone()); 331 if (!type.IsNone()) { 332 double const max = type.Max(); 333 double const min = type.Min(); 334 if (min < 0) { 335 if (type.Is(cache_.kInteger)) { 336 type = 337 Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone()); 338 } else { 339 type = Type::PlainNumber(); 340 } 341 } 342 } 343 344 if (maybe_minuszero) { 345 type = Type::Union(type, cache_.kSingletonZero, zone()); 346 } 347 if (maybe_nan) { 348 type = Type::Union(type, Type::NaN(), zone()); 349 } 350 return type; 351 } 352 353 Type OperationTyper::NumberAcos(Type type) { 354 DCHECK(type.Is(Type::Number())); 355 return Type::Number(); 356 } 357 358 Type OperationTyper::NumberAcosh(Type type) { 359 DCHECK(type.Is(Type::Number())); 360 return Type::Number(); 361 } 362 363 Type OperationTyper::NumberAsin(Type type) { 364 DCHECK(type.Is(Type::Number())); 365 return Type::Number(); 366 } 367 368 Type OperationTyper::NumberAsinh(Type type) { 369 DCHECK(type.Is(Type::Number())); 370 return Type::Number(); 371 } 372 373 Type OperationTyper::NumberAtan(Type type) { 374 DCHECK(type.Is(Type::Number())); 375 return Type::Number(); 376 } 377 378 Type OperationTyper::NumberAtanh(Type type) { 379 DCHECK(type.Is(Type::Number())); 380 return Type::Number(); 381 } 382 383 Type OperationTyper::NumberCbrt(Type type) { 384 DCHECK(type.Is(Type::Number())); 385 return Type::Number(); 386 } 387 388 Type OperationTyper::NumberCeil(Type type) { 389 DCHECK(type.Is(Type::Number())); 390 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; 391 type = Type::Intersect(type, Type::NaN(), zone()); 392 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone()); 393 return type; 394 } 395 396 Type OperationTyper::NumberClz32(Type type) { 397 DCHECK(type.Is(Type::Number())); 398 return cache_.kZeroToThirtyTwo; 399 } 400 401 Type OperationTyper::NumberCos(Type type) { 402 DCHECK(type.Is(Type::Number())); 403 return Type::Number(); 404 } 405 406 Type OperationTyper::NumberCosh(Type type) { 407 DCHECK(type.Is(Type::Number())); 408 return Type::Number(); 409 } 410 411 Type OperationTyper::NumberExp(Type type) { 412 DCHECK(type.Is(Type::Number())); 413 return Type::Union(Type::PlainNumber(), Type::NaN(), zone()); 414 } 415 416 Type OperationTyper::NumberExpm1(Type type) { 417 DCHECK(type.Is(Type::Number())); 418 return Type::Union(Type::PlainNumber(), Type::NaN(), zone()); 419 } 420 421 Type OperationTyper::NumberFloor(Type type) { 422 DCHECK(type.Is(Type::Number())); 423 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; 424 type = Type::Intersect(type, Type::MinusZeroOrNaN(), zone()); 425 type = Type::Union(type, cache_.kInteger, zone()); 426 return type; 427 } 428 429 Type OperationTyper::NumberFround(Type type) { 430 DCHECK(type.Is(Type::Number())); 431 return Type::Number(); 432 } 433 434 Type OperationTyper::NumberLog(Type type) { 435 DCHECK(type.Is(Type::Number())); 436 return Type::Number(); 437 } 438 439 Type OperationTyper::NumberLog1p(Type type) { 440 DCHECK(type.Is(Type::Number())); 441 return Type::Number(); 442 } 443 444 Type OperationTyper::NumberLog2(Type type) { 445 DCHECK(type.Is(Type::Number())); 446 return Type::Number(); 447 } 448 449 Type OperationTyper::NumberLog10(Type type) { 450 DCHECK(type.Is(Type::Number())); 451 return Type::Number(); 452 } 453 454 Type OperationTyper::NumberRound(Type type) { 455 DCHECK(type.Is(Type::Number())); 456 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; 457 type = Type::Intersect(type, Type::NaN(), zone()); 458 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone()); 459 return type; 460 } 461 462 Type OperationTyper::NumberSign(Type type) { 463 DCHECK(type.Is(Type::Number())); 464 if (type.Is(cache_.kZeroish)) return type; 465 bool maybe_minuszero = type.Maybe(Type::MinusZero()); 466 bool maybe_nan = type.Maybe(Type::NaN()); 467 type = Type::Intersect(type, Type::PlainNumber(), zone()); 468 if (type.IsNone()) { 469 // Do nothing. 470 } else if (type.Max() < 0.0) { 471 type = cache_.kSingletonMinusOne; 472 } else if (type.Max() <= 0.0) { 473 type = cache_.kMinusOneOrZero; 474 } else if (type.Min() > 0.0) { 475 type = cache_.kSingletonOne; 476 } else if (type.Min() >= 0.0) { 477 type = cache_.kZeroOrOne; 478 } else { 479 type = Type::Range(-1.0, 1.0, zone()); 480 } 481 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 482 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 483 DCHECK(!type.IsNone()); 484 return type; 485 } 486 487 Type OperationTyper::NumberSin(Type type) { 488 DCHECK(type.Is(Type::Number())); 489 return Type::Number(); 490 } 491 492 Type OperationTyper::NumberSinh(Type type) { 493 DCHECK(type.Is(Type::Number())); 494 return Type::Number(); 495 } 496 497 Type OperationTyper::NumberSqrt(Type type) { 498 DCHECK(type.Is(Type::Number())); 499 return Type::Number(); 500 } 501 502 Type OperationTyper::NumberTan(Type type) { 503 DCHECK(type.Is(Type::Number())); 504 return Type::Number(); 505 } 506 507 Type OperationTyper::NumberTanh(Type type) { 508 DCHECK(type.Is(Type::Number())); 509 return Type::Number(); 510 } 511 512 Type OperationTyper::NumberTrunc(Type type) { 513 DCHECK(type.Is(Type::Number())); 514 if (type.Is(cache_.kIntegerOrMinusZeroOrNaN)) return type; 515 type = Type::Intersect(type, Type::NaN(), zone()); 516 type = Type::Union(type, cache_.kIntegerOrMinusZero, zone()); 517 return type; 518 } 519 520 Type OperationTyper::NumberToBoolean(Type type) { 521 DCHECK(type.Is(Type::Number())); 522 if (type.IsNone()) return type; 523 if (type.Is(cache_.kZeroish)) return singleton_false_; 524 if (type.Is(Type::PlainNumber()) && (type.Max() < 0 || 0 < type.Min())) { 525 return singleton_true_; // Ruled out nan, -0 and +0. 526 } 527 return Type::Boolean(); 528 } 529 530 Type OperationTyper::NumberToInt32(Type type) { 531 DCHECK(type.Is(Type::Number())); 532 533 if (type.Is(Type::Signed32())) return type; 534 if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero; 535 if (type.Is(signed32ish_)) { 536 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()), 537 Type::Signed32(), zone()); 538 } 539 return Type::Signed32(); 540 } 541 542 Type OperationTyper::NumberToString(Type type) { 543 DCHECK(type.Is(Type::Number())); 544 if (type.IsNone()) return type; 545 if (type.Is(Type::NaN())) return singleton_NaN_string_; 546 if (type.Is(cache_.kZeroOrMinusZero)) return singleton_zero_string_; 547 return Type::String(); 548 } 549 550 Type OperationTyper::NumberToUint32(Type type) { 551 DCHECK(type.Is(Type::Number())); 552 553 if (type.Is(Type::Unsigned32())) return type; 554 if (type.Is(cache_.kZeroish)) return cache_.kSingletonZero; 555 if (type.Is(unsigned32ish_)) { 556 return Type::Intersect(Type::Union(type, cache_.kSingletonZero, zone()), 557 Type::Unsigned32(), zone()); 558 } 559 return Type::Unsigned32(); 560 } 561 562 Type OperationTyper::NumberToUint8Clamped(Type type) { 563 DCHECK(type.Is(Type::Number())); 564 565 if (type.Is(cache_.kUint8)) return type; 566 return cache_.kUint8; 567 } 568 569 Type OperationTyper::NumberSilenceNaN(Type type) { 570 DCHECK(type.Is(Type::Number())); 571 // TODO(jarin): This is a terrible hack; we definitely need a dedicated type 572 // for the hole (tagged and/or double). Otherwise if the input is the hole 573 // NaN constant, we'd just eliminate this node in JSTypedLowering. 574 if (type.Maybe(Type::NaN())) return Type::Number(); 575 return type; 576 } 577 578 Type OperationTyper::NumberAdd(Type lhs, Type rhs) { 579 DCHECK(lhs.Is(Type::Number())); 580 DCHECK(rhs.Is(Type::Number())); 581 582 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 583 584 // Addition can return NaN if either input can be NaN or we try to compute 585 // the sum of two infinities of opposite sign. 586 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()); 587 588 // Addition can yield minus zero only if both inputs can be minus zero. 589 bool maybe_minuszero = true; 590 if (lhs.Maybe(Type::MinusZero())) { 591 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); 592 } else { 593 maybe_minuszero = false; 594 } 595 if (rhs.Maybe(Type::MinusZero())) { 596 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); 597 } else { 598 maybe_minuszero = false; 599 } 600 601 // We can give more precise types for integers. 602 Type type = Type::None(); 603 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); 604 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); 605 if (!lhs.IsNone() && !rhs.IsNone()) { 606 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) { 607 type = AddRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max()); 608 } else { 609 if ((lhs.Maybe(minus_infinity_) && rhs.Maybe(infinity_)) || 610 (rhs.Maybe(minus_infinity_) && lhs.Maybe(infinity_))) { 611 maybe_nan = true; 612 } 613 type = Type::PlainNumber(); 614 } 615 } 616 617 // Take into account the -0 and NaN information computed earlier. 618 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 619 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 620 return type; 621 } 622 623 Type OperationTyper::NumberSubtract(Type lhs, Type rhs) { 624 DCHECK(lhs.Is(Type::Number())); 625 DCHECK(rhs.Is(Type::Number())); 626 627 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 628 629 // Subtraction can return NaN if either input can be NaN or we try to 630 // compute the sum of two infinities of opposite sign. 631 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN()); 632 633 // Subtraction can yield minus zero if {lhs} can be minus zero and {rhs} 634 // can be zero. 635 bool maybe_minuszero = false; 636 if (lhs.Maybe(Type::MinusZero())) { 637 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); 638 maybe_minuszero = rhs.Maybe(cache_.kSingletonZero); 639 } 640 if (rhs.Maybe(Type::MinusZero())) { 641 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); 642 } 643 644 // We can give more precise types for integers. 645 Type type = Type::None(); 646 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); 647 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); 648 if (!lhs.IsNone() && !rhs.IsNone()) { 649 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) { 650 type = SubtractRanger(lhs.Min(), lhs.Max(), rhs.Min(), rhs.Max()); 651 } else { 652 if ((lhs.Maybe(infinity_) && rhs.Maybe(infinity_)) || 653 (rhs.Maybe(minus_infinity_) && lhs.Maybe(minus_infinity_))) { 654 maybe_nan = true; 655 } 656 type = Type::PlainNumber(); 657 } 658 } 659 660 // Take into account the -0 and NaN information computed earlier. 661 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 662 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 663 return type; 664 } 665 666 Type OperationTyper::SpeculativeSafeIntegerAdd(Type lhs, Type rhs) { 667 Type result = SpeculativeNumberAdd(lhs, rhs); 668 // If we have a Smi or Int32 feedback, the representation selection will 669 // either truncate or it will check the inputs (i.e., deopt if not int32). 670 // In either case the result will be in the safe integer range, so we 671 // can bake in the type here. This needs to be in sync with 672 // SimplifiedLowering::VisitSpeculativeAdditiveOp. 673 return Type::Intersect(result, cache_.kSafeIntegerOrMinusZero, zone()); 674 } 675 676 Type OperationTyper::SpeculativeSafeIntegerSubtract(Type lhs, Type rhs) { 677 Type result = SpeculativeNumberSubtract(lhs, rhs); 678 // If we have a Smi or Int32 feedback, the representation selection will 679 // either truncate or it will check the inputs (i.e., deopt if not int32). 680 // In either case the result will be in the safe integer range, so we 681 // can bake in the type here. This needs to be in sync with 682 // SimplifiedLowering::VisitSpeculativeAdditiveOp. 683 return result = Type::Intersect(result, cache_.kSafeInteger, zone()); 684 } 685 686 Type OperationTyper::NumberMultiply(Type lhs, Type rhs) { 687 DCHECK(lhs.Is(Type::Number())); 688 DCHECK(rhs.Is(Type::Number())); 689 690 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 691 692 lhs = Rangify(lhs); 693 rhs = Rangify(rhs); 694 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN(); 695 if (lhs.IsRange() && rhs.IsRange()) { 696 return MultiplyRanger(lhs, rhs); 697 } 698 return Type::Number(); 699 } 700 701 Type OperationTyper::NumberDivide(Type lhs, Type rhs) { 702 DCHECK(lhs.Is(Type::Number())); 703 DCHECK(rhs.Is(Type::Number())); 704 705 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 706 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN(); 707 708 // Division is tricky, so all we do is try ruling out -0 and NaN. 709 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) || 710 ((lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY) && 711 (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY)); 712 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone()); 713 DCHECK(!lhs.IsNone()); 714 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone()); 715 DCHECK(!rhs.IsNone()); 716 717 // Try to rule out -0. 718 bool maybe_minuszero = 719 !lhs.Is(cache_.kInteger) || 720 (lhs.Maybe(cache_.kZeroish) && rhs.Min() < 0.0) || 721 (rhs.Min() == -V8_INFINITY || rhs.Max() == +V8_INFINITY); 722 723 // Take into account the -0 and NaN information computed earlier. 724 Type type = Type::PlainNumber(); 725 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 726 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 727 return type; 728 } 729 730 Type OperationTyper::NumberModulus(Type lhs, Type rhs) { 731 DCHECK(lhs.Is(Type::Number())); 732 DCHECK(rhs.Is(Type::Number())); 733 734 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 735 736 // Modulus can yield NaN if either {lhs} or {rhs} are NaN, or 737 // {lhs} is not finite, or the {rhs} is a zero value. 738 bool maybe_nan = lhs.Maybe(Type::NaN()) || rhs.Maybe(cache_.kZeroish) || 739 lhs.Min() == -V8_INFINITY || lhs.Max() == +V8_INFINITY; 740 741 // Deal with -0 inputs, only the signbit of {lhs} matters for the result. 742 bool maybe_minuszero = false; 743 if (lhs.Maybe(Type::MinusZero())) { 744 maybe_minuszero = true; 745 lhs = Type::Union(lhs, cache_.kSingletonZero, zone()); 746 } 747 if (rhs.Maybe(Type::MinusZero())) { 748 rhs = Type::Union(rhs, cache_.kSingletonZero, zone()); 749 } 750 751 // Rule out NaN and -0, and check what we can do with the remaining type info. 752 Type type = Type::None(); 753 lhs = Type::Intersect(lhs, Type::PlainNumber(), zone()); 754 rhs = Type::Intersect(rhs, Type::PlainNumber(), zone()); 755 756 // We can only derive a meaningful type if both {lhs} and {rhs} are inhabited, 757 // and the {rhs} is not 0, otherwise the result is NaN independent of {lhs}. 758 if (!lhs.IsNone() && !rhs.Is(cache_.kSingletonZero)) { 759 // Determine the bounds of {lhs} and {rhs}. 760 double const lmin = lhs.Min(); 761 double const lmax = lhs.Max(); 762 double const rmin = rhs.Min(); 763 double const rmax = rhs.Max(); 764 765 // The sign of the result is the sign of the {lhs}. 766 if (lmin < 0.0) maybe_minuszero = true; 767 768 // For integer inputs {lhs} and {rhs} we can infer a precise type. 769 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) { 770 double labs = std::max(std::abs(lmin), std::abs(lmax)); 771 double rabs = std::max(std::abs(rmin), std::abs(rmax)) - 1; 772 double abs = std::min(labs, rabs); 773 double min = 0.0, max = 0.0; 774 if (lmin >= 0.0) { 775 // {lhs} positive. 776 min = 0.0; 777 max = abs; 778 } else if (lmax <= 0.0) { 779 // {lhs} negative. 780 min = 0.0 - abs; 781 max = 0.0; 782 } else { 783 // {lhs} positive or negative. 784 min = 0.0 - abs; 785 max = abs; 786 } 787 type = Type::Range(min, max, zone()); 788 } else { 789 type = Type::PlainNumber(); 790 } 791 } 792 793 // Take into account the -0 and NaN information computed earlier. 794 if (maybe_minuszero) type = Type::Union(type, Type::MinusZero(), zone()); 795 if (maybe_nan) type = Type::Union(type, Type::NaN(), zone()); 796 return type; 797 } 798 799 Type OperationTyper::NumberBitwiseOr(Type lhs, Type rhs) { 800 DCHECK(lhs.Is(Type::Number())); 801 DCHECK(rhs.Is(Type::Number())); 802 803 lhs = NumberToInt32(lhs); 804 rhs = NumberToInt32(rhs); 805 806 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 807 808 double lmin = lhs.Min(); 809 double rmin = rhs.Min(); 810 double lmax = lhs.Max(); 811 double rmax = rhs.Max(); 812 // Or-ing any two values results in a value no smaller than their minimum. 813 // Even no smaller than their maximum if both values are non-negative. 814 double min = 815 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin); 816 double max = kMaxInt; 817 818 // Or-ing with 0 is essentially a conversion to int32. 819 if (rmin == 0 && rmax == 0) { 820 min = lmin; 821 max = lmax; 822 } 823 if (lmin == 0 && lmax == 0) { 824 min = rmin; 825 max = rmax; 826 } 827 828 if (lmax < 0 || rmax < 0) { 829 // Or-ing two values of which at least one is negative results in a negative 830 // value. 831 max = std::min(max, -1.0); 832 } 833 return Type::Range(min, max, zone()); 834 } 835 836 Type OperationTyper::NumberBitwiseAnd(Type lhs, Type rhs) { 837 DCHECK(lhs.Is(Type::Number())); 838 DCHECK(rhs.Is(Type::Number())); 839 840 lhs = NumberToInt32(lhs); 841 rhs = NumberToInt32(rhs); 842 843 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 844 845 double lmin = lhs.Min(); 846 double rmin = rhs.Min(); 847 double lmax = lhs.Max(); 848 double rmax = rhs.Max(); 849 double min = kMinInt; 850 // And-ing any two values results in a value no larger than their maximum. 851 // Even no larger than their minimum if both values are non-negative. 852 double max = 853 lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax); 854 // And-ing with a non-negative value x causes the result to be between 855 // zero and x. 856 if (lmin >= 0) { 857 min = 0; 858 max = std::min(max, lmax); 859 } 860 if (rmin >= 0) { 861 min = 0; 862 max = std::min(max, rmax); 863 } 864 return Type::Range(min, max, zone()); 865 } 866 867 Type OperationTyper::NumberBitwiseXor(Type lhs, Type rhs) { 868 DCHECK(lhs.Is(Type::Number())); 869 DCHECK(rhs.Is(Type::Number())); 870 871 lhs = NumberToInt32(lhs); 872 rhs = NumberToInt32(rhs); 873 874 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 875 876 double lmin = lhs.Min(); 877 double rmin = rhs.Min(); 878 double lmax = lhs.Max(); 879 double rmax = rhs.Max(); 880 if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) { 881 // Xor-ing negative or non-negative values results in a non-negative value. 882 return Type::Unsigned31(); 883 } 884 if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) { 885 // Xor-ing a negative and a non-negative value results in a negative value. 886 // TODO(jarin) Use a range here. 887 return Type::Negative32(); 888 } 889 return Type::Signed32(); 890 } 891 892 Type OperationTyper::NumberShiftLeft(Type lhs, Type rhs) { 893 DCHECK(lhs.Is(Type::Number())); 894 DCHECK(rhs.Is(Type::Number())); 895 896 lhs = NumberToInt32(lhs); 897 rhs = NumberToUint32(rhs); 898 899 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 900 901 int32_t min_lhs = lhs.Min(); 902 int32_t max_lhs = lhs.Max(); 903 uint32_t min_rhs = rhs.Min(); 904 uint32_t max_rhs = rhs.Max(); 905 if (max_rhs > 31) { 906 // rhs can be larger than the bitmask 907 max_rhs = 31; 908 min_rhs = 0; 909 } 910 911 if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) { 912 // overflow possible 913 return Type::Signed32(); 914 } 915 916 double min = 917 std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs), 918 static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs)); 919 double max = 920 std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs), 921 static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs)); 922 923 if (max == kMaxInt && min == kMinInt) return Type::Signed32(); 924 return Type::Range(min, max, zone()); 925 } 926 927 Type OperationTyper::NumberShiftRight(Type lhs, Type rhs) { 928 DCHECK(lhs.Is(Type::Number())); 929 DCHECK(rhs.Is(Type::Number())); 930 931 lhs = NumberToInt32(lhs); 932 rhs = NumberToUint32(rhs); 933 934 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 935 936 int32_t min_lhs = lhs.Min(); 937 int32_t max_lhs = lhs.Max(); 938 uint32_t min_rhs = rhs.Min(); 939 uint32_t max_rhs = rhs.Max(); 940 if (max_rhs > 31) { 941 // rhs can be larger than the bitmask 942 max_rhs = 31; 943 min_rhs = 0; 944 } 945 double min = std::min(min_lhs >> min_rhs, min_lhs >> max_rhs); 946 double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs); 947 948 if (max == kMaxInt && min == kMinInt) return Type::Signed32(); 949 return Type::Range(min, max, zone()); 950 } 951 952 Type OperationTyper::NumberShiftRightLogical(Type lhs, Type rhs) { 953 DCHECK(lhs.Is(Type::Number())); 954 DCHECK(rhs.Is(Type::Number())); 955 956 lhs = NumberToUint32(lhs); 957 rhs = NumberToUint32(rhs); 958 959 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 960 961 uint32_t min_lhs = lhs.Min(); 962 uint32_t max_lhs = lhs.Max(); 963 uint32_t min_rhs = rhs.Min(); 964 uint32_t max_rhs = rhs.Max(); 965 if (max_rhs > 31) { 966 // rhs can be larger than the bitmask 967 max_rhs = 31; 968 min_rhs = 0; 969 } 970 971 double min = min_lhs >> max_rhs; 972 double max = max_lhs >> min_rhs; 973 DCHECK_LE(0, min); 974 DCHECK_LE(max, kMaxUInt32); 975 976 if (min == 0 && max == kMaxInt) return Type::Unsigned31(); 977 if (min == 0 && max == kMaxUInt32) return Type::Unsigned32(); 978 return Type::Range(min, max, zone()); 979 } 980 981 Type OperationTyper::NumberAtan2(Type lhs, Type rhs) { 982 DCHECK(lhs.Is(Type::Number())); 983 DCHECK(rhs.Is(Type::Number())); 984 return Type::Number(); 985 } 986 987 Type OperationTyper::NumberImul(Type lhs, Type rhs) { 988 DCHECK(lhs.Is(Type::Number())); 989 DCHECK(rhs.Is(Type::Number())); 990 // TODO(turbofan): We should be able to do better here. 991 return Type::Signed32(); 992 } 993 994 Type OperationTyper::NumberMax(Type lhs, Type rhs) { 995 DCHECK(lhs.Is(Type::Number())); 996 DCHECK(rhs.Is(Type::Number())); 997 998 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 999 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN(); 1000 1001 Type type = Type::None(); 1002 // TODO(turbofan): Improve minus zero handling here. 1003 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) { 1004 type = Type::Union(type, Type::NaN(), zone()); 1005 } 1006 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone()); 1007 DCHECK(!lhs.IsNone()); 1008 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone()); 1009 DCHECK(!rhs.IsNone()); 1010 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) { 1011 double max = std::max(lhs.Max(), rhs.Max()); 1012 double min = std::max(lhs.Min(), rhs.Min()); 1013 type = Type::Union(type, Type::Range(min, max, zone()), zone()); 1014 } else { 1015 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone()); 1016 } 1017 return type; 1018 } 1019 1020 Type OperationTyper::NumberMin(Type lhs, Type rhs) { 1021 DCHECK(lhs.Is(Type::Number())); 1022 DCHECK(rhs.Is(Type::Number())); 1023 1024 if (lhs.IsNone() || rhs.IsNone()) return Type::None(); 1025 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return Type::NaN(); 1026 1027 Type type = Type::None(); 1028 // TODO(turbofan): Improve minus zero handling here. 1029 if (lhs.Maybe(Type::NaN()) || rhs.Maybe(Type::NaN())) { 1030 type = Type::Union(type, Type::NaN(), zone()); 1031 } 1032 lhs = Type::Intersect(lhs, Type::OrderedNumber(), zone()); 1033 DCHECK(!lhs.IsNone()); 1034 rhs = Type::Intersect(rhs, Type::OrderedNumber(), zone()); 1035 DCHECK(!rhs.IsNone()); 1036 if (lhs.Is(cache_.kInteger) && rhs.Is(cache_.kInteger)) { 1037 double max = std::min(lhs.Max(), rhs.Max()); 1038 double min = std::min(lhs.Min(), rhs.Min()); 1039 type = Type::Union(type, Type::Range(min, max, zone()), zone()); 1040 } else { 1041 type = Type::Union(type, Type::Union(lhs, rhs, zone()), zone()); 1042 } 1043 return type; 1044 } 1045 1046 Type OperationTyper::NumberPow(Type lhs, Type rhs) { 1047 DCHECK(lhs.Is(Type::Number())); 1048 DCHECK(rhs.Is(Type::Number())); 1049 // TODO(turbofan): We should be able to do better here. 1050 return Type::Number(); 1051 } 1052 1053 #define SPECULATIVE_NUMBER_BINOP(Name) \ 1054 Type OperationTyper::Speculative##Name(Type lhs, Type rhs) { \ 1055 lhs = SpeculativeToNumber(lhs); \ 1056 rhs = SpeculativeToNumber(rhs); \ 1057 return Name(lhs, rhs); \ 1058 } 1059 SPECULATIVE_NUMBER_BINOP(NumberAdd) 1060 SPECULATIVE_NUMBER_BINOP(NumberSubtract) 1061 SPECULATIVE_NUMBER_BINOP(NumberMultiply) 1062 SPECULATIVE_NUMBER_BINOP(NumberDivide) 1063 SPECULATIVE_NUMBER_BINOP(NumberModulus) 1064 SPECULATIVE_NUMBER_BINOP(NumberBitwiseOr) 1065 SPECULATIVE_NUMBER_BINOP(NumberBitwiseAnd) 1066 SPECULATIVE_NUMBER_BINOP(NumberBitwiseXor) 1067 SPECULATIVE_NUMBER_BINOP(NumberShiftLeft) 1068 SPECULATIVE_NUMBER_BINOP(NumberShiftRight) 1069 SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical) 1070 #undef SPECULATIVE_NUMBER_BINOP 1071 1072 Type OperationTyper::SpeculativeToNumber(Type type) { 1073 return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone())); 1074 } 1075 1076 Type OperationTyper::ToPrimitive(Type type) { 1077 if (type.Is(Type::Primitive())) { 1078 return type; 1079 } 1080 return Type::Primitive(); 1081 } 1082 1083 Type OperationTyper::Invert(Type type) { 1084 DCHECK(type.Is(Type::Boolean())); 1085 DCHECK(!type.IsNone()); 1086 if (type.Is(singleton_false())) return singleton_true(); 1087 if (type.Is(singleton_true())) return singleton_false(); 1088 return type; 1089 } 1090 1091 OperationTyper::ComparisonOutcome OperationTyper::Invert( 1092 ComparisonOutcome outcome) { 1093 ComparisonOutcome result(0); 1094 if ((outcome & kComparisonUndefined) != 0) result |= kComparisonUndefined; 1095 if ((outcome & kComparisonTrue) != 0) result |= kComparisonFalse; 1096 if ((outcome & kComparisonFalse) != 0) result |= kComparisonTrue; 1097 return result; 1098 } 1099 1100 Type OperationTyper::FalsifyUndefined(ComparisonOutcome outcome) { 1101 if ((outcome & kComparisonFalse) != 0 || 1102 (outcome & kComparisonUndefined) != 0) { 1103 return (outcome & kComparisonTrue) != 0 ? Type::Boolean() 1104 : singleton_false(); 1105 } 1106 // Type should be non empty, so we know it should be true. 1107 DCHECK_NE(0, outcome & kComparisonTrue); 1108 return singleton_true(); 1109 } 1110 1111 namespace { 1112 1113 Type JSType(Type type) { 1114 if (type.Is(Type::Boolean())) return Type::Boolean(); 1115 if (type.Is(Type::String())) return Type::String(); 1116 if (type.Is(Type::Number())) return Type::Number(); 1117 if (type.Is(Type::BigInt())) return Type::BigInt(); 1118 if (type.Is(Type::Undefined())) return Type::Undefined(); 1119 if (type.Is(Type::Null())) return Type::Null(); 1120 if (type.Is(Type::Symbol())) return Type::Symbol(); 1121 if (type.Is(Type::Receiver())) return Type::Receiver(); // JS "Object" 1122 return Type::Any(); 1123 } 1124 1125 } // namespace 1126 1127 Type OperationTyper::SameValue(Type lhs, Type rhs) { 1128 if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false(); 1129 if (lhs.Is(Type::NaN())) { 1130 if (rhs.Is(Type::NaN())) return singleton_true(); 1131 if (!rhs.Maybe(Type::NaN())) return singleton_false(); 1132 } else if (rhs.Is(Type::NaN())) { 1133 if (!lhs.Maybe(Type::NaN())) return singleton_false(); 1134 } 1135 if (lhs.Is(Type::MinusZero())) { 1136 if (rhs.Is(Type::MinusZero())) return singleton_true(); 1137 if (!rhs.Maybe(Type::MinusZero())) return singleton_false(); 1138 } else if (rhs.Is(Type::MinusZero())) { 1139 if (!lhs.Maybe(Type::MinusZero())) return singleton_false(); 1140 } 1141 if (lhs.Is(Type::OrderedNumber()) && rhs.Is(Type::OrderedNumber()) && 1142 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) { 1143 return singleton_false(); 1144 } 1145 return Type::Boolean(); 1146 } 1147 1148 Type OperationTyper::StrictEqual(Type lhs, Type rhs) { 1149 if (!JSType(lhs).Maybe(JSType(rhs))) return singleton_false(); 1150 if (lhs.Is(Type::NaN()) || rhs.Is(Type::NaN())) return singleton_false(); 1151 if (lhs.Is(Type::Number()) && rhs.Is(Type::Number()) && 1152 (lhs.Max() < rhs.Min() || lhs.Min() > rhs.Max())) { 1153 return singleton_false(); 1154 } 1155 if ((lhs.Is(Type::Hole()) || rhs.Is(Type::Hole())) && !lhs.Maybe(rhs)) { 1156 return singleton_false(); 1157 } 1158 if (lhs.IsHeapConstant() && rhs.Is(lhs)) { 1159 // Types are equal and are inhabited only by a single semantic value, 1160 // which is not nan due to the earlier check. 1161 return singleton_true(); 1162 } 1163 return Type::Boolean(); 1164 } 1165 1166 Type OperationTyper::CheckFloat64Hole(Type type) { 1167 if (type.Maybe(Type::Hole())) { 1168 // Turn "the hole" into undefined. 1169 type = Type::Intersect(type, Type::Number(), zone()); 1170 type = Type::Union(type, Type::Undefined(), zone()); 1171 } 1172 return type; 1173 } 1174 1175 Type OperationTyper::CheckNumber(Type type) { 1176 return Type::Intersect(type, Type::Number(), zone()); 1177 } 1178 1179 Type OperationTyper::TypeTypeGuard(const Operator* sigma_op, Type input) { 1180 return Type::Intersect(input, TypeGuardTypeOf(sigma_op), zone()); 1181 } 1182 1183 Type OperationTyper::ConvertTaggedHoleToUndefined(Type input) { 1184 if (input.Maybe(Type::Hole())) { 1185 // Turn "the hole" into undefined. 1186 Type type = Type::Intersect(input, Type::NonInternal(), zone()); 1187 return Type::Union(type, Type::Undefined(), zone()); 1188 } 1189 return input; 1190 } 1191 1192 Type OperationTyper::ToBoolean(Type type) { 1193 if (type.Is(Type::Boolean())) return type; 1194 if (type.Is(falsish_)) return singleton_false_; 1195 if (type.Is(truish_)) return singleton_true_; 1196 if (type.Is(Type::Number())) { 1197 return NumberToBoolean(type); 1198 } 1199 return Type::Boolean(); 1200 } 1201 1202 } // namespace compiler 1203 } // namespace internal 1204 } // namespace v8 1205