SpeculatedType.cpp
1 /* 2 * Copyright (C) 2011-2020 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "SpeculatedType.h" 31 32 #include "DateInstance.h" 33 #include "DirectArguments.h" 34 #include "JSArray.h" 35 #include "JSBigInt.h" 36 #include "JSBoundFunction.h" 37 #include "JSDataView.h" 38 #include "JSFunction.h" 39 #include "JSMap.h" 40 #include "JSSet.h" 41 #include "JSWeakMap.h" 42 #include "JSWeakSet.h" 43 #include "ProxyObject.h" 44 #include "RegExpObject.h" 45 #include "ScopedArguments.h" 46 #include "StringObject.h" 47 #include <wtf/CommaPrinter.h> 48 #include <wtf/StringPrintStream.h> 49 50 namespace JSC { 51 52 struct PrettyPrinter { 53 PrettyPrinter(PrintStream& out) 54 : out(out) 55 , separator("|") 56 { } 57 58 template<typename T> 59 void print(const T& value) 60 { 61 out.print(separator, value); 62 } 63 64 PrintStream& out; 65 CommaPrinter separator; 66 }; 67 68 void dumpSpeculation(PrintStream& outStream, SpeculatedType value) 69 { 70 StringPrintStream strStream; 71 PrettyPrinter out(outStream); 72 PrettyPrinter strOut(strStream); 73 74 if (value == SpecNone) { 75 out.print("None"); 76 return; 77 } 78 79 bool isTop = true; 80 81 if ((value & SpecCell) == SpecCell) 82 strOut.print("Cell"); 83 else { 84 if ((value & SpecObject) == SpecObject) 85 strOut.print("Object"); 86 else { 87 if (value & SpecCellOther) 88 strOut.print("OtherCell"); 89 else 90 isTop = false; 91 92 if (value & SpecObjectOther) 93 strOut.print("OtherObj"); 94 else 95 isTop = false; 96 97 if (value & SpecFinalObject) 98 strOut.print("Final"); 99 else 100 isTop = false; 101 102 if (value & SpecArray) 103 strOut.print("Array"); 104 else 105 isTop = false; 106 107 if (value & SpecInt8Array) 108 strOut.print("Int8Array"); 109 else 110 isTop = false; 111 112 if (value & SpecInt16Array) 113 strOut.print("Int16Array"); 114 else 115 isTop = false; 116 117 if (value & SpecInt32Array) 118 strOut.print("Int32Array"); 119 else 120 isTop = false; 121 122 if (value & SpecUint8Array) 123 strOut.print("Uint8Array"); 124 else 125 isTop = false; 126 127 if (value & SpecUint8ClampedArray) 128 strOut.print("Uint8ClampedArray"); 129 else 130 isTop = false; 131 132 if (value & SpecUint16Array) 133 strOut.print("Uint16Array"); 134 else 135 isTop = false; 136 137 if (value & SpecUint32Array) 138 strOut.print("Uint32Array"); 139 else 140 isTop = false; 141 142 if (value & SpecFloat32Array) 143 strOut.print("Float32array"); 144 else 145 isTop = false; 146 147 if (value & SpecFloat64Array) 148 strOut.print("Float64Array"); 149 else 150 isTop = false; 151 152 if (value & SpecFunction) 153 strOut.print("Function"); 154 else 155 isTop = false; 156 157 if (value & SpecDirectArguments) 158 strOut.print("DirectArguments"); 159 else 160 isTop = false; 161 162 if (value & SpecScopedArguments) 163 strOut.print("ScopedArguments"); 164 else 165 isTop = false; 166 167 if (value & SpecStringObject) 168 strOut.print("StringObject"); 169 else 170 isTop = false; 171 172 if (value & SpecRegExpObject) 173 strOut.print("RegExpObject"); 174 else 175 isTop = false; 176 177 if (value & SpecDateObject) 178 strOut.print("DateObject"); 179 else 180 isTop = false; 181 182 if (value & SpecPromiseObject) 183 strOut.print("PromiseObject"); 184 else 185 isTop = false; 186 187 if (value & SpecMapObject) 188 strOut.print("MapObject"); 189 else 190 isTop = false; 191 192 if (value & SpecSetObject) 193 strOut.print("SetObject"); 194 else 195 isTop = false; 196 197 if (value & SpecWeakMapObject) 198 strOut.print("WeakMapObject"); 199 else 200 isTop = false; 201 202 if (value & SpecWeakSetObject) 203 strOut.print("WeakSetObject"); 204 else 205 isTop = false; 206 207 if (value & SpecProxyObject) 208 strOut.print("ProxyObject"); 209 else 210 isTop = false; 211 212 if (value & SpecDerivedArray) 213 strOut.print("DerivedArray"); 214 else 215 isTop = false; 216 217 if (value & SpecDataViewObject) 218 strOut.print("DataView"); 219 else 220 isTop = false; 221 } 222 223 if ((value & SpecString) == SpecString) 224 strOut.print("String"); 225 else { 226 if (value & SpecStringIdent) 227 strOut.print("StringIdent"); 228 else 229 isTop = false; 230 231 if (value & SpecStringVar) 232 strOut.print("StringVar"); 233 else 234 isTop = false; 235 } 236 237 if (value & SpecSymbol) 238 strOut.print("Symbol"); 239 else 240 isTop = false; 241 } 242 243 if (value == SpecInt32Only) 244 strOut.print("Int32"); 245 else { 246 if (value & SpecBoolInt32) 247 strOut.print("BoolInt32"); 248 else 249 isTop = false; 250 251 if (value & SpecNonBoolInt32) 252 strOut.print("NonBoolInt32"); 253 else 254 isTop = false; 255 } 256 257 if ((value & SpecBytecodeDouble) == SpecBytecodeDouble) 258 strOut.print("BytecodeDouble"); 259 else { 260 if (value & SpecAnyIntAsDouble) 261 strOut.print("AnyIntAsDouble"); 262 else 263 isTop = false; 264 265 if (value & SpecNonIntAsDouble) 266 strOut.print("NonIntAsDouble"); 267 else 268 isTop = false; 269 270 if (value & SpecDoublePureNaN) 271 strOut.print("DoublePureNaN"); 272 else 273 isTop = false; 274 } 275 276 if ((value & SpecBigInt) == SpecBigInt) 277 strOut.print("BigInt"); 278 #if USE(BIGINT32) 279 else { 280 if (value & SpecBigInt32) 281 strOut.print("BigInt32"); 282 else 283 isTop = false; 284 285 if (value & SpecHeapBigInt) 286 strOut.print("HeapBigInt"); 287 else 288 isTop = false; 289 } 290 #endif 291 292 if (value & SpecDoubleImpureNaN) 293 strOut.print("DoubleImpureNaN"); 294 295 if (value & SpecBoolean) 296 strOut.print("Bool"); 297 else 298 isTop = false; 299 300 if (value & SpecOther) 301 strOut.print("Other"); 302 else 303 isTop = false; 304 305 if (value & SpecEmpty) 306 strOut.print("Empty"); 307 else 308 isTop = false; 309 310 if (value & SpecInt52Any) { 311 if ((value & SpecInt52Any) == SpecInt52Any) 312 strOut.print("Int52Any"); 313 else if (value & SpecInt32AsInt52) 314 strOut.print("Int32AsInt52"); 315 else if (value & SpecNonInt32AsInt52) 316 strOut.print("NonInt32AsInt52"); 317 } else 318 isTop = false; 319 320 if (value == SpecBytecodeTop) 321 out.print("BytecodeTop"); 322 else if (value == SpecHeapTop) 323 out.print("HeapTop"); 324 else if (value == SpecFullTop) 325 out.print("FullTop"); 326 else if (isTop) 327 out.print("Top"); 328 else 329 out.print(strStream.toCString()); 330 } 331 332 // We don't expose this because we don't want anyone relying on the fact that this method currently 333 // just returns string constants. 334 static const char* speculationToAbbreviatedString(SpeculatedType prediction) 335 { 336 if (isFinalObjectSpeculation(prediction)) 337 return "<Final>"; 338 if (isArraySpeculation(prediction)) 339 return "<Array>"; 340 if (isStringIdentSpeculation(prediction)) 341 return "<StringIdent>"; 342 if (isStringSpeculation(prediction)) 343 return "<String>"; 344 if (isFunctionSpeculation(prediction)) 345 return "<Function>"; 346 if (isInt8ArraySpeculation(prediction)) 347 return "<Int8array>"; 348 if (isInt16ArraySpeculation(prediction)) 349 return "<Int16array>"; 350 if (isInt32ArraySpeculation(prediction)) 351 return "<Int32array>"; 352 if (isUint8ArraySpeculation(prediction)) 353 return "<Uint8array>"; 354 if (isUint16ArraySpeculation(prediction)) 355 return "<Uint16array>"; 356 if (isUint32ArraySpeculation(prediction)) 357 return "<Uint32array>"; 358 if (isFloat32ArraySpeculation(prediction)) 359 return "<Float32array>"; 360 if (isFloat64ArraySpeculation(prediction)) 361 return "<Float64array>"; 362 if (isDirectArgumentsSpeculation(prediction)) 363 return "<DirectArguments>"; 364 if (isScopedArgumentsSpeculation(prediction)) 365 return "<ScopedArguments>"; 366 if (isStringObjectSpeculation(prediction)) 367 return "<StringObject>"; 368 if (isRegExpObjectSpeculation(prediction)) 369 return "<RegExpObject>"; 370 if (isStringOrStringObjectSpeculation(prediction)) 371 return "<StringOrStringObject>"; 372 if (isObjectSpeculation(prediction)) 373 return "<Object>"; 374 if (isCellSpeculation(prediction)) 375 return "<Cell>"; 376 if (isBoolInt32Speculation(prediction)) 377 return "<BoolInt32>"; 378 if (isInt32Speculation(prediction)) 379 return "<Int32>"; 380 if (isAnyIntAsDoubleSpeculation(prediction)) 381 return "<AnyIntAsDouble>"; 382 if (prediction == SpecNonInt32AsInt52) 383 return "<NonInt32AsInt52>"; 384 if (prediction == SpecInt32AsInt52) 385 return "<Int32AsInt52>"; 386 if (isAnyInt52Speculation(prediction)) 387 return "<Int52Any>"; 388 if (isDoubleSpeculation(prediction)) 389 return "<Double>"; 390 if (isFullNumberSpeculation(prediction)) 391 return "<Number>"; 392 if (isBooleanSpeculation(prediction)) 393 return "<Boolean>"; 394 if (isOtherSpeculation(prediction)) 395 return "<Other>"; 396 if (isMiscSpeculation(prediction)) 397 return "<Misc>"; 398 return ""; 399 } 400 401 void dumpSpeculationAbbreviated(PrintStream& out, SpeculatedType value) 402 { 403 out.print(speculationToAbbreviatedString(value)); 404 } 405 406 SpeculatedType speculationFromTypedArrayType(TypedArrayType type) 407 { 408 switch (type) { 409 case TypeInt8: 410 return SpecInt8Array; 411 case TypeInt16: 412 return SpecInt16Array; 413 case TypeInt32: 414 return SpecInt32Array; 415 case TypeUint8: 416 return SpecUint8Array; 417 case TypeUint8Clamped: 418 return SpecUint8ClampedArray; 419 case TypeUint16: 420 return SpecUint16Array; 421 case TypeUint32: 422 return SpecUint32Array; 423 case TypeFloat32: 424 return SpecFloat32Array; 425 case TypeFloat64: 426 return SpecFloat64Array; 427 case NotTypedArray: 428 case TypeDataView: 429 break; 430 } 431 RELEASE_ASSERT_NOT_REACHED(); 432 return SpecNone; 433 } 434 435 SpeculatedType speculationFromClassInfoInheritance(const ClassInfo* classInfo) 436 { 437 if (classInfo == JSString::info()) 438 return SpecString; 439 ASSERT_WITH_MESSAGE(!classInfo->isSubClassOf(JSString::info()), "Rope strings should still have JSString's ClassInfo"); 440 441 static_assert(std::is_final_v<Symbol>); 442 if (classInfo == Symbol::info()) 443 return SpecSymbol; 444 445 static_assert(std::is_final_v<JSBigInt>); 446 if (classInfo == JSBigInt::info()) 447 return SpecHeapBigInt; 448 449 static_assert(std::is_final_v<JSFinalObject>); 450 if (classInfo == JSFinalObject::info()) 451 return SpecFinalObject; 452 453 static_assert(std::is_final_v<DirectArguments>); 454 if (classInfo == DirectArguments::info()) 455 return SpecDirectArguments; 456 457 static_assert(std::is_final_v<ScopedArguments>); 458 if (classInfo == ScopedArguments::info()) 459 return SpecScopedArguments; 460 461 static_assert(std::is_final_v<RegExpObject>); 462 if (classInfo == RegExpObject::info()) 463 return SpecRegExpObject; 464 465 static_assert(std::is_final_v<DateInstance>); 466 if (classInfo == DateInstance::info()) 467 return SpecDateObject; 468 469 static_assert(std::is_final_v<JSMap>); 470 if (classInfo == JSMap::info()) 471 return SpecMapObject; 472 473 static_assert(std::is_final_v<JSSet>); 474 if (classInfo == JSSet::info()) 475 return SpecSetObject; 476 477 static_assert(std::is_final_v<JSWeakMap>); 478 if (classInfo == JSWeakMap::info()) 479 return SpecWeakMapObject; 480 481 static_assert(std::is_final_v<JSWeakSet>); 482 if (classInfo == JSWeakSet::info()) 483 return SpecWeakSetObject; 484 485 static_assert(std::is_final_v<ProxyObject>); 486 if (classInfo == ProxyObject::info()) 487 return SpecProxyObject; 488 489 static_assert(std::is_final_v<JSDataView>); 490 if (classInfo == JSDataView::info()) 491 return SpecDataViewObject; 492 493 if (classInfo->isSubClassOf(StringObject::info())) 494 return SpecStringObject | SpecObjectOther; 495 496 if (classInfo->isSubClassOf(JSArray::info())) 497 return SpecArray | SpecDerivedArray; 498 499 if (classInfo->isSubClassOf(JSFunction::info())) { 500 if (classInfo == JSBoundFunction::info()) 501 return SpecFunctionWithNonDefaultHasInstance; 502 return SpecFunctionWithDefaultHasInstance; 503 } 504 505 if (classInfo->isSubClassOf(JSPromise::info())) 506 return SpecPromiseObject; 507 508 if (isTypedView(classInfo->typedArrayStorageType)) 509 return speculationFromTypedArrayType(classInfo->typedArrayStorageType); 510 511 if (classInfo->isSubClassOf(JSObject::info())) 512 return SpecObjectOther; 513 514 return SpecCellOther; 515 } 516 517 SpeculatedType speculationFromStructure(Structure* structure) 518 { 519 SpeculatedType filteredResult = SpecNone; 520 switch (structure->typeInfo().type()) { 521 case StringType: 522 filteredResult = SpecString; 523 break; 524 case SymbolType: 525 filteredResult = SpecSymbol; 526 break; 527 case HeapBigIntType: 528 filteredResult = SpecHeapBigInt; 529 break; 530 case DerivedArrayType: 531 filteredResult = SpecDerivedArray; 532 break; 533 case ArrayType: 534 filteredResult = SpecArray; 535 break; 536 case StringObjectType: 537 filteredResult = SpecStringObject; 538 break; 539 // We do not want to accept String.prototype in StringObjectUse, so that we do not include it as SpecStringObject. 540 case DerivedStringObjectType: 541 filteredResult = SpecObjectOther; 542 break; 543 default: 544 return speculationFromClassInfoInheritance(structure->classInfo()); 545 } 546 ASSERT(filteredResult); 547 ASSERT(isSubtypeSpeculation(filteredResult, speculationFromClassInfoInheritance(structure->classInfo()))); 548 return filteredResult; 549 } 550 551 ALWAYS_INLINE static bool isSanePointer(const void* pointer) 552 { 553 // FIXME: rdar://69036888: remove this when no longer needed. 554 #if CPU(ADDRESS64) 555 uintptr_t pointerAsInt = bitwise_cast<uintptr_t>(pointer); 556 uintptr_t canonicalPointerBits = pointerAsInt << (64 - OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH)); 557 uintptr_t nonCanonicalPointerBits = pointerAsInt >> OS_CONSTANT(EFFECTIVE_ADDRESS_WIDTH); 558 return !nonCanonicalPointerBits && canonicalPointerBits; 559 #else 560 UNUSED_PARAM(pointer); 561 return true; 562 #endif 563 } 564 565 SpeculatedType speculationFromCell(JSCell* cell) 566 { 567 if (UNLIKELY(!isSanePointer(cell))) { 568 ASSERT_NOT_REACHED(); 569 return SpecNone; 570 } 571 if (cell->isString()) { 572 JSString* string = jsCast<JSString*>(cell); 573 if (const StringImpl* impl = string->tryGetValueImpl()) { 574 if (UNLIKELY(!isSanePointer(impl))) { 575 ASSERT_NOT_REACHED(); 576 return SpecNone; 577 } 578 if (impl->isAtom()) 579 return SpecStringIdent; 580 } 581 return SpecString; 582 } 583 // FIXME: rdar://69036888: undo this when no longer needed. 584 auto* structure = cell->vm().tryGetStructure(cell->structureID()); 585 if (UNLIKELY(!isSanePointer(structure))) { 586 ASSERT_NOT_REACHED(); 587 return SpecNone; 588 } 589 return speculationFromStructure(structure); 590 } 591 592 SpeculatedType speculationFromValue(JSValue value) 593 { 594 if (value.isEmpty()) 595 return SpecEmpty; 596 if (value.isInt32()) { 597 if (value.asInt32() & ~1) 598 return SpecNonBoolInt32; 599 return SpecBoolInt32; 600 } 601 if (value.isDouble()) { 602 double number = value.asNumber(); 603 if (number != number) 604 return SpecDoublePureNaN; 605 if (value.isAnyInt()) 606 return SpecAnyIntAsDouble; 607 return SpecNonIntAsDouble; 608 } 609 if (value.isBigInt32()) 610 return SpecBigInt32; 611 if (value.isCell()) 612 return speculationFromCell(value.asCell()); 613 if (value.isBoolean()) 614 return SpecBoolean; 615 ASSERT(value.isUndefinedOrNull()); 616 return SpecOther; 617 } 618 619 SpeculatedType int52AwareSpeculationFromValue(JSValue value) 620 { 621 if (!value.isAnyInt()) 622 return speculationFromValue(value); 623 624 int64_t intValue = value.asAnyInt(); 625 bool isI32 = static_cast<int64_t>(static_cast<int32_t>(intValue)) == intValue; 626 if (isI32) 627 return SpecInt32AsInt52; 628 return SpecNonInt32AsInt52; 629 } 630 631 TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType type) 632 { 633 if (isInt8ArraySpeculation(type)) 634 return TypeInt8; 635 636 if (isInt16ArraySpeculation(type)) 637 return TypeInt16; 638 639 if (isInt32ArraySpeculation(type)) 640 return TypeInt32; 641 642 if (isUint8ArraySpeculation(type)) 643 return TypeUint8; 644 645 if (isUint8ClampedArraySpeculation(type)) 646 return TypeUint8Clamped; 647 648 if (isUint16ArraySpeculation(type)) 649 return TypeUint16; 650 651 if (isUint32ArraySpeculation(type)) 652 return TypeUint32; 653 654 if (isFloat32ArraySpeculation(type)) 655 return TypeFloat32; 656 657 if (isFloat64ArraySpeculation(type)) 658 return TypeFloat64; 659 660 return NotTypedArray; 661 } 662 663 Optional<SpeculatedType> speculationFromJSType(JSType type) 664 { 665 switch (type) { 666 case StringType: 667 return SpecString; 668 case SymbolType: 669 return SpecSymbol; 670 case HeapBigIntType: 671 return SpecHeapBigInt; 672 case ArrayType: 673 return SpecArray; 674 case DerivedArrayType: 675 return SpecDerivedArray; 676 case RegExpObjectType: 677 return SpecRegExpObject; 678 case JSDateType: 679 return SpecDateObject; 680 case ProxyObjectType: 681 return SpecProxyObject; 682 case JSPromiseType: 683 return SpecPromiseObject; 684 case JSMapType: 685 return SpecMapObject; 686 case JSSetType: 687 return SpecSetObject; 688 case JSWeakMapType: 689 return SpecWeakMapObject; 690 case JSWeakSetType: 691 return SpecWeakSetObject; 692 case DataViewType: 693 return SpecDataViewObject; 694 default: 695 return WTF::nullopt; 696 } 697 } 698 699 SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type) 700 { 701 // SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0 in the context of == and ===. 702 if (type & (SpecIntAnyFormat | SpecNonIntAsDouble)) 703 type |= (SpecIntAnyFormat | SpecNonIntAsDouble); 704 705 if (type & SpecString) 706 type |= SpecString; 707 708 if (type & SpecBigInt) 709 type |= SpecBigInt; 710 711 return type; 712 } 713 714 static inline SpeculatedType leastUpperBoundOfEquivalentSpeculations(SpeculatedType type) 715 { 716 type = leastUpperBoundOfStrictlyEquivalentSpeculations(type); 717 718 // Boolean or BigInt can be converted to Number when performing non-strict equal. 719 if (type & (SpecIntAnyFormat | SpecNonIntAsDouble | SpecBoolean | SpecBigInt)) 720 type |= (SpecIntAnyFormat | SpecNonIntAsDouble | SpecBoolean | SpecBigInt); 721 722 return type; 723 } 724 725 bool valuesCouldBeEqual(SpeculatedType a, SpeculatedType b) 726 { 727 a = leastUpperBoundOfEquivalentSpeculations(a); 728 b = leastUpperBoundOfEquivalentSpeculations(b); 729 730 // Anything could be equal to a string. 731 if (a & SpecString) 732 return true; 733 if (b & SpecString) 734 return true; 735 736 // If both sides are definitely only objects, then equality is fairly sane. 737 if (isObjectSpeculation(a) && isObjectSpeculation(b)) 738 return !!(a & b); 739 740 // If either side could be an object or not, then we could call toString or 741 // valueOf, which could return anything. 742 if (a & SpecObject) 743 return true; 744 if (b & SpecObject) 745 return true; 746 747 // Neither side is an object or string, so the world is relatively sane. 748 return !!(a & b); 749 } 750 751 static SpeculatedType typeOfDoubleSumOrDifferenceOrProduct(SpeculatedType a, SpeculatedType b) 752 { 753 SpeculatedType result = a | b; 754 755 if (result & SpecNonIntAsDouble) { 756 // NaN can be produced by: 757 // Infinity - Infinity 758 // Infinity + (-Infinity) 759 // Infinity * 0 760 result |= SpecDoublePureNaN; 761 } 762 763 // Impure NaN could become pure NaN during addition because addition may clear bits. 764 if (result & SpecDoubleImpureNaN) 765 result |= SpecDoublePureNaN; 766 // Values could overflow, or fractions could become integers. 767 if (result & SpecDoubleReal) 768 result |= SpecDoubleReal; 769 return result; 770 } 771 772 SpeculatedType typeOfDoubleSum(SpeculatedType a, SpeculatedType b) 773 { 774 return typeOfDoubleSumOrDifferenceOrProduct(a, b); 775 } 776 777 SpeculatedType typeOfDoubleDifference(SpeculatedType a, SpeculatedType b) 778 { 779 return typeOfDoubleSumOrDifferenceOrProduct(a, b); 780 } 781 782 SpeculatedType typeOfDoubleIncOrDec(SpeculatedType t) 783 { 784 // Impure NaN could become pure NaN during addition because addition may clear bits. 785 if (t & SpecDoubleImpureNaN) 786 t |= SpecDoublePureNaN; 787 // Values could overflow, or fractions could become integers. 788 if (t & SpecDoubleReal) 789 t |= SpecDoubleReal; 790 return t; 791 } 792 793 SpeculatedType typeOfDoubleProduct(SpeculatedType a, SpeculatedType b) 794 { 795 return typeOfDoubleSumOrDifferenceOrProduct(a, b); 796 } 797 798 static SpeculatedType polluteDouble(SpeculatedType value) 799 { 800 // Impure NaN could become pure NaN because the operation could clear some bits. 801 if (value & SpecDoubleImpureNaN) 802 value |= SpecDoubleNaN; 803 // Values could overflow, fractions could become integers, or an error could produce 804 // PureNaN. 805 if (value & SpecDoubleReal) 806 value |= SpecDoubleReal | SpecDoublePureNaN; 807 return value; 808 } 809 810 SpeculatedType typeOfDoubleQuotient(SpeculatedType a, SpeculatedType b) 811 { 812 return polluteDouble(a | b); 813 } 814 815 SpeculatedType typeOfDoubleMinMax(SpeculatedType a, SpeculatedType b) 816 { 817 SpeculatedType result = a | b; 818 // Impure NaN could become pure NaN during addition because addition may clear bits. 819 if (result & SpecDoubleImpureNaN) 820 result |= SpecDoublePureNaN; 821 return result; 822 } 823 824 SpeculatedType typeOfDoubleNegation(SpeculatedType value) 825 { 826 // Changing bits can make pure NaN impure and vice versa: 827 // 0xefff000000000000 (pure) - 0xffff000000000000 (impure) 828 if (value & SpecDoubleNaN) 829 value |= SpecDoubleNaN; 830 // We could get negative zero, which mixes SpecAnyIntAsDouble and SpecNotIntAsDouble. 831 // We could also overflow a large negative int into something that is no longer 832 // representable as an int. 833 if (value & SpecDoubleReal) 834 value |= SpecDoubleReal; 835 return value; 836 } 837 838 SpeculatedType typeOfDoubleAbs(SpeculatedType value) 839 { 840 return typeOfDoubleNegation(value); 841 } 842 843 SpeculatedType typeOfDoubleRounding(SpeculatedType value) 844 { 845 // Double Pure NaN can becomes impure when converted back from Float. 846 // and vice versa. 847 if (value & SpecDoubleNaN) 848 value |= SpecDoubleNaN; 849 // We might lose bits, which leads to a value becoming integer-representable. 850 if (value & SpecNonIntAsDouble) 851 value |= SpecAnyIntAsDouble; 852 return value; 853 } 854 855 SpeculatedType typeOfDoublePow(SpeculatedType xValue, SpeculatedType yValue) 856 { 857 // Math.pow() always return NaN if the exponent is NaN, unlike std::pow(). 858 // We always set a pure NaN in that case. 859 if (yValue & SpecDoubleNaN) 860 xValue |= SpecDoublePureNaN; 861 // Handle the wierd case of NaN ^ 0, which returns 1. See https://tc39.github.io/ecma262/#sec-applying-the-exp-operator 862 if (xValue & SpecDoubleNaN) 863 xValue |= SpecFullDouble; 864 return polluteDouble(xValue); 865 } 866 867 SpeculatedType typeOfDoubleBinaryOp(SpeculatedType a, SpeculatedType b) 868 { 869 return polluteDouble(a | b); 870 } 871 872 SpeculatedType typeOfDoubleUnaryOp(SpeculatedType value) 873 { 874 return polluteDouble(value); 875 } 876 877 SpeculatedType speculationFromString(const char* speculation) 878 { 879 if (!strncmp(speculation, "SpecNone", strlen("SpecNone"))) 880 return SpecNone; 881 if (!strncmp(speculation, "SpecFinalObject", strlen("SpecFinalObject"))) 882 return SpecFinalObject; 883 if (!strncmp(speculation, "SpecArray", strlen("SpecArray"))) 884 return SpecArray; 885 if (!strncmp(speculation, "SpecFunction", strlen("SpecFunction"))) 886 return SpecFunction; 887 if (!strncmp(speculation, "SpecInt8Array", strlen("SpecInt8Array"))) 888 return SpecInt8Array; 889 if (!strncmp(speculation, "SpecInt16Array", strlen("SpecInt16Array"))) 890 return SpecInt16Array; 891 if (!strncmp(speculation, "SpecInt32Array", strlen("SpecInt32Array"))) 892 return SpecInt32Array; 893 if (!strncmp(speculation, "SpecUint8Array", strlen("SpecUint8Array"))) 894 return SpecUint8Array; 895 if (!strncmp(speculation, "SpecUint8ClampedArray", strlen("SpecUint8ClampedArray"))) 896 return SpecUint8ClampedArray; 897 if (!strncmp(speculation, "SpecUint16Array", strlen("SpecUint16Array"))) 898 return SpecUint16Array; 899 if (!strncmp(speculation, "SpecUint32Array", strlen("SpecUint32Array"))) 900 return SpecUint32Array; 901 if (!strncmp(speculation, "SpecFloat32Array", strlen("SpecFloat32Array"))) 902 return SpecFloat32Array; 903 if (!strncmp(speculation, "SpecFloat64Array", strlen("SpecFloat64Array"))) 904 return SpecFloat64Array; 905 if (!strncmp(speculation, "SpecTypedArrayView", strlen("SpecTypedArrayView"))) 906 return SpecTypedArrayView; 907 if (!strncmp(speculation, "SpecDirectArguments", strlen("SpecDirectArguments"))) 908 return SpecDirectArguments; 909 if (!strncmp(speculation, "SpecScopedArguments", strlen("SpecScopedArguments"))) 910 return SpecScopedArguments; 911 if (!strncmp(speculation, "SpecStringObject", strlen("SpecStringObject"))) 912 return SpecStringObject; 913 if (!strncmp(speculation, "SpecRegExpObject", strlen("SpecRegExpObject"))) 914 return SpecRegExpObject; 915 if (!strncmp(speculation, "SpecDateObject", strlen("SpecDateObject"))) 916 return SpecDateObject; 917 if (!strncmp(speculation, "SpecPromiseObject", strlen("SpecPromiseObject"))) 918 return SpecPromiseObject; 919 if (!strncmp(speculation, "SpecMapObject", strlen("SpecMapObject"))) 920 return SpecMapObject; 921 if (!strncmp(speculation, "SpecSetObject", strlen("SpecSetObject"))) 922 return SpecSetObject; 923 if (!strncmp(speculation, "SpecWeakMapObject", strlen("SpecWeakMapObject"))) 924 return SpecWeakMapObject; 925 if (!strncmp(speculation, "SpecWeakSetObject", strlen("SpecWeakSetObject"))) 926 return SpecWeakSetObject; 927 if (!strncmp(speculation, "SpecProxyObject", strlen("SpecProxyObject"))) 928 return SpecProxyObject; 929 if (!strncmp(speculation, "SpecDerivedArray", strlen("SpecDerivedArray"))) 930 return SpecDerivedArray; 931 if (!strncmp(speculation, "SpecDataViewObject", strlen("SpecDataViewObject"))) 932 return SpecDataViewObject; 933 if (!strncmp(speculation, "SpecObjectOther", strlen("SpecObjectOther"))) 934 return SpecObjectOther; 935 if (!strncmp(speculation, "SpecObject", strlen("SpecObject"))) 936 return SpecObject; 937 if (!strncmp(speculation, "SpecStringIdent", strlen("SpecStringIdent"))) 938 return SpecStringIdent; 939 if (!strncmp(speculation, "SpecStringVar", strlen("SpecStringVar"))) 940 return SpecStringVar; 941 if (!strncmp(speculation, "SpecString", strlen("SpecString"))) 942 return SpecString; 943 if (!strncmp(speculation, "SpecSymbol", strlen("SpecSymbol"))) 944 return SpecSymbol; 945 if (!strncmp(speculation, "SpecBigInt", strlen("SpecBigInt"))) 946 return SpecBigInt; 947 if (!strncmp(speculation, "SpecCellOther", strlen("SpecCellOther"))) 948 return SpecCellOther; 949 if (!strncmp(speculation, "SpecCell", strlen("SpecCell"))) 950 return SpecCell; 951 if (!strncmp(speculation, "SpecBoolInt32", strlen("SpecBoolInt32"))) 952 return SpecBoolInt32; 953 if (!strncmp(speculation, "SpecNonBoolInt32", strlen("SpecNonBoolInt32"))) 954 return SpecNonBoolInt32; 955 if (!strncmp(speculation, "SpecInt32Only", strlen("SpecInt32Only"))) 956 return SpecInt32Only; 957 if (!strncmp(speculation, "SpecInt32AsInt52", strlen("SpecInt32AsInt52"))) 958 return SpecInt32AsInt52; 959 if (!strncmp(speculation, "SpecNonInt32AsInt52", strlen("SpecNonInt32AsInt52"))) 960 return SpecNonInt32AsInt52; 961 if (!strncmp(speculation, "SpecInt52Any", strlen("SpecInt52Any"))) 962 return SpecInt52Any; 963 if (!strncmp(speculation, "SpecIntAnyFormat", strlen("SpecIntAnyFormat"))) 964 return SpecIntAnyFormat; 965 if (!strncmp(speculation, "SpecAnyIntAsDouble", strlen("SpecAnyIntAsDouble"))) 966 return SpecAnyIntAsDouble; 967 if (!strncmp(speculation, "SpecNonIntAsDouble", strlen("SpecNonIntAsDouble"))) 968 return SpecNonIntAsDouble; 969 if (!strncmp(speculation, "SpecDoubleReal", strlen("SpecDoubleReal"))) 970 return SpecDoubleReal; 971 if (!strncmp(speculation, "SpecDoublePureNaN", strlen("SpecDoublePureNaN"))) 972 return SpecDoublePureNaN; 973 if (!strncmp(speculation, "SpecDoubleImpureNaN", strlen("SpecDoubleImpureNaN"))) 974 return SpecDoubleImpureNaN; 975 if (!strncmp(speculation, "SpecDoubleNaN", strlen("SpecDoubleNaN"))) 976 return SpecDoubleNaN; 977 if (!strncmp(speculation, "SpecBytecodeDouble", strlen("SpecBytecodeDouble"))) 978 return SpecBytecodeDouble; 979 if (!strncmp(speculation, "SpecFullDouble", strlen("SpecFullDouble"))) 980 return SpecFullDouble; 981 if (!strncmp(speculation, "SpecBytecodeRealNumber", strlen("SpecBytecodeRealNumber"))) 982 return SpecBytecodeRealNumber; 983 if (!strncmp(speculation, "SpecFullRealNumber", strlen("SpecFullRealNumber"))) 984 return SpecFullRealNumber; 985 if (!strncmp(speculation, "SpecBytecodeNumber", strlen("SpecBytecodeNumber"))) 986 return SpecBytecodeNumber; 987 if (!strncmp(speculation, "SpecFullNumber", strlen("SpecFullNumber"))) 988 return SpecFullNumber; 989 if (!strncmp(speculation, "SpecBoolean", strlen("SpecBoolean"))) 990 return SpecBoolean; 991 if (!strncmp(speculation, "SpecOther", strlen("SpecOther"))) 992 return SpecOther; 993 if (!strncmp(speculation, "SpecMisc", strlen("SpecMisc"))) 994 return SpecMisc; 995 if (!strncmp(speculation, "SpecHeapTop", strlen("SpecHeapTop"))) 996 return SpecHeapTop; 997 if (!strncmp(speculation, "SpecPrimitive", strlen("SpecPrimitive"))) 998 return SpecPrimitive; 999 if (!strncmp(speculation, "SpecEmpty", strlen("SpecEmpty"))) 1000 return SpecEmpty; 1001 if (!strncmp(speculation, "SpecBytecodeTop", strlen("SpecBytecodeTop"))) 1002 return SpecBytecodeTop; 1003 if (!strncmp(speculation, "SpecFullTop", strlen("SpecFullTop"))) 1004 return SpecFullTop; 1005 if (!strncmp(speculation, "SpecCellCheck", strlen("SpecCellCheck"))) 1006 return SpecCellCheck; 1007 RELEASE_ASSERT_NOT_REACHED(); 1008 } 1009 1010 } // namespace JSC 1011