Changeset 244079 in webkit
- Timestamp:
- Apr 9, 2019 9:06:48 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r244069 r244079 1 2019-04-09 Saam barati <sbarati@apple.com> 2 3 Clean up Int52 code and some bugs in it 4 https://bugs.webkit.org/show_bug.cgi?id=196639 5 <rdar://problem/49515757> 6 7 Reviewed by Yusuke Suzuki. 8 9 * stress/spec-any-int-as-double-produces-any-int52-from-int52-rep.js: Added. 10 1 11 2019-04-09 Tadeu Zagallo <tzagallo@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r244069 r244079 1 2019-04-09 Saam barati <sbarati@apple.com> 2 3 Clean up Int52 code and some bugs in it 4 https://bugs.webkit.org/show_bug.cgi?id=196639 5 <rdar://problem/49515757> 6 7 Reviewed by Yusuke Suzuki. 8 9 This patch fixes bugs in our Int52 code. The primary change in this patch is 10 adopting a segregated type lattice for Int52. Previously, for Int52 values, 11 we represented them with SpecInt32Only and SpecInt52Only. For an Int52, 12 SpecInt32Only meant that the value is in int32 range. And SpecInt52Only meant 13 that the is outside of the int32 range. 14 15 However, this got confusing because we reused SpecInt32Only both for JSValue 16 representations and Int52 representations. This actually lead to some bugs. 17 18 1. It's possible that roundtripping through Int52 representation would say 19 it produces the wrong type. For example, consider this program and how we 20 used to annotate types in AI: 21 a: JSConstant(10.0) => m_type is SpecAnyIntAsDouble 22 b: Int52Rep(@a) => m_type is SpecInt52Only 23 c: ValueRep(@b) => m_type is SpecAnyIntAsDouble 24 25 In AI, for the above program, we'd say that @c produces SpecAnyIntAsDouble. 26 However, the execution semantics are such that it'd actually produce a boxed 27 Int32. This patch fixes the bug where we'd say that Int52Rep over SpecAnyIntAsDouble 28 would produce SpecInt52Only. This is clearly wrong, as SpecAnyIntAsDouble can 29 mean an int value in either int32 or int52 range. 30 31 2. AsbstractValue::validateTypeAcceptingBoxedInt52 was wrong in how it 32 accepted Int52 values. It was wrong in two different ways: 33 a: If the AbstractValue's type was SpecInt52Only, and the incoming value 34 was a boxed double, but represented a value in int32 range, the incoming 35 value would incorrectly validate as being acceptable. However, we should 36 have rejected this value. 37 b: If the AbstractValue's type was SpecInt32Only, and the incoming value 38 was an Int32 boxed in a double, this would not validate, even though 39 it should have validated. 40 41 Solving 2 was easiest if we segregated out the Int52 type into its own 42 lattice. This patch makes a new Int52 lattice, which is composed of 43 SpecInt32AsInt52 and SpecNonInt32AsInt52. 44 45 The conversion rules are now really simple. 46 47 Int52 rep => JSValue rep 48 SpecInt32AsInt52 => SpecInt32Only 49 SpecNonInt32AsInt52 => SpecAnyIntAsDouble 50 51 JSValue rep => Int52 rep 52 SpecInt32Only => SpecInt32AsInt52 53 SpecAnyIntAsDouble => SpecInt52Any 54 55 With these rules, the program in (1) will now correctly report that @c 56 returns SpecInt32Only | SpecAnyIntAsDouble. 57 58 * bytecode/SpeculatedType.cpp: 59 (JSC::dumpSpeculation): 60 (JSC::speculationToAbbreviatedString): 61 (JSC::int52AwareSpeculationFromValue): 62 (JSC::leastUpperBoundOfStrictlyEquivalentSpeculations): 63 (JSC::speculationFromString): 64 * bytecode/SpeculatedType.h: 65 (JSC::isInt32SpeculationForArithmetic): 66 (JSC::isInt32OrBooleanSpeculationForArithmetic): 67 (JSC::isAnyInt52Speculation): 68 (JSC::isIntAnyFormat): 69 (JSC::isInt52Speculation): Deleted. 70 (JSC::isAnyIntSpeculation): Deleted. 71 * dfg/DFGAbstractInterpreterInlines.h: 72 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 73 * dfg/DFGAbstractValue.cpp: 74 (JSC::DFG::AbstractValue::fixTypeForRepresentation): 75 (JSC::DFG::AbstractValue::checkConsistency const): 76 * dfg/DFGAbstractValue.h: 77 (JSC::DFG::AbstractValue::isInt52Any const): 78 (JSC::DFG::AbstractValue::validateTypeAcceptingBoxedInt52 const): 79 * dfg/DFGFixupPhase.cpp: 80 (JSC::DFG::FixupPhase::fixupArithMul): 81 (JSC::DFG::FixupPhase::fixupNode): 82 (JSC::DFG::FixupPhase::fixupGetPrototypeOf): 83 (JSC::DFG::FixupPhase::fixupToThis): 84 (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor): 85 (JSC::DFG::FixupPhase::observeUseKindOnNode): 86 (JSC::DFG::FixupPhase::fixIntConvertingEdge): 87 (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd): 88 (JSC::DFG::FixupPhase::fixupCompareStrictEqAndSameValue): 89 (JSC::DFG::FixupPhase::fixupChecksInBlock): 90 * dfg/DFGGraph.h: 91 (JSC::DFG::Graph::addShouldSpeculateInt52): 92 (JSC::DFG::Graph::binaryArithShouldSpeculateInt52): 93 (JSC::DFG::Graph::unaryArithShouldSpeculateInt52): 94 (JSC::DFG::Graph::addShouldSpeculateAnyInt): Deleted. 95 (JSC::DFG::Graph::binaryArithShouldSpeculateAnyInt): Deleted. 96 (JSC::DFG::Graph::unaryArithShouldSpeculateAnyInt): Deleted. 97 * dfg/DFGNode.h: 98 (JSC::DFG::Node::shouldSpeculateInt52): 99 (JSC::DFG::Node::shouldSpeculateAnyInt): Deleted. 100 * dfg/DFGPredictionPropagationPhase.cpp: 101 * dfg/DFGSpeculativeJIT.cpp: 102 (JSC::DFG::SpeculativeJIT::setIntTypedArrayLoadResult): 103 (JSC::DFG::SpeculativeJIT::compileArithAdd): 104 (JSC::DFG::SpeculativeJIT::compileArithSub): 105 (JSC::DFG::SpeculativeJIT::compileArithNegate): 106 * dfg/DFGSpeculativeJIT64.cpp: 107 (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal): 108 (JSC::DFG::SpeculativeJIT::fillSpeculateInt52): 109 * dfg/DFGUseKind.h: 110 (JSC::DFG::typeFilterFor): 111 * dfg/DFGVariableAccessData.cpp: 112 (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat): 113 (JSC::DFG::VariableAccessData::couldRepresentInt52Impl): 114 * ftl/FTLLowerDFGToB3.cpp: 115 (JSC::FTL::DFG::LowerDFGToB3::compileArithAddOrSub): 116 (JSC::FTL::DFG::LowerDFGToB3::compileArithNegate): 117 (JSC::FTL::DFG::LowerDFGToB3::setIntTypedArrayLoadResult): 118 1 119 2019-04-09 Tadeu Zagallo <tzagallo@apple.com> 2 120 -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r243277 r244079 250 250 } 251 251 252 if (value & SpecInt52Only) 253 strOut.print("Int52"); 252 if (value & SpecInt32AsInt52) 253 strOut.print("Int32AsInt52"); 254 255 if (value & SpecNonInt32AsInt52) 256 strOut.print("NonInt32AsInt52"); 254 257 255 258 if ((value & SpecBytecodeDouble) == SpecBytecodeDouble) … … 344 347 if (isAnyIntAsDoubleSpeculation(prediction)) 345 348 return "<AnyIntAsDouble>"; 346 if (isInt52Speculation(prediction)) 347 return "<Int52>"; 348 if (isAnyIntSpeculation(prediction)) 349 return "<AnyInt>"; 349 if (prediction == SpecNonInt32AsInt52) 350 return "<NonInt32AsInt52>"; 351 if (prediction == SpecInt32AsInt52) 352 return "<Int32AsInt52>"; 353 if (isAnyInt52Speculation(prediction)) 354 return "<Int52Any>"; 350 355 if (isDoubleSpeculation(prediction)) 351 356 return "<Double>"; … … 509 514 ASSERT(value.isUndefinedOrNull()); 510 515 return SpecOther; 516 } 517 518 SpeculatedType int52AwareSpeculationFromValue(JSValue value) 519 { 520 if (!value.isAnyInt()) 521 return speculationFromValue(value); 522 523 int64_t intValue = value.asAnyInt(); 524 bool isI32 = static_cast<int64_t>(static_cast<int32_t>(intValue)) == intValue; 525 if (isI32) 526 return SpecInt32AsInt52; 527 return SpecNonInt32AsInt52; 511 528 } 512 529 … … 579 596 { 580 597 // SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0 in the context of == and ===. 581 if (type & (Spec AnyInt | SpecAnyIntAsDouble| SpecNonIntAsDouble))582 type |= (Spec AnyInt | SpecAnyIntAsDouble| SpecNonIntAsDouble);598 if (type & (SpecIntAnyFormat | SpecNonIntAsDouble)) 599 type |= (SpecIntAnyFormat | SpecNonIntAsDouble); 583 600 584 601 if (type & SpecString) … … 804 821 if (!strncmp(speculation, "SpecInt32Only", strlen("SpecInt32Only"))) 805 822 return SpecInt32Only; 806 if (!strncmp(speculation, "SpecInt52Only", strlen("SpecInt52Only"))) 807 return SpecInt52Only; 808 if (!strncmp(speculation, "SpecAnyInt", strlen("SpecAnyInt"))) 809 return SpecAnyInt; 823 if (!strncmp(speculation, "SpecInt32AsInt52", strlen("SpecInt32AsInt52"))) 824 return SpecInt32AsInt52; 825 if (!strncmp(speculation, "SpecNonInt32AsInt52", strlen("SpecNonInt32AsInt52"))) 826 return SpecNonInt32AsInt52; 827 if (!strncmp(speculation, "SpecInt52Any", strlen("SpecInt52Any"))) 828 return SpecInt52Any; 829 if (!strncmp(speculation, "SpecIntAnyFormat", strlen("SpecIntAnyFormat"))) 830 return SpecIntAnyFormat; 810 831 if (!strncmp(speculation, "SpecAnyIntAsDouble", strlen("SpecAnyIntAsDouble"))) 811 832 return SpecAnyIntAsDouble; -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r243278 r244079 74 74 static const SpeculatedType SpecNonBoolInt32 = 1ull << 29; // It's definitely an Int32 with value other than 0 or 1. 75 75 static const SpeculatedType SpecInt32Only = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32. 76 static const SpeculatedType SpecInt52Only = 1ull << 30; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32. 77 static const SpeculatedType SpecAnyInt = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on. 78 static const SpeculatedType SpecAnyIntAsDouble = 1ull << 31; // It's definitely an Int52 and it's inside a double. 79 static const SpeculatedType SpecNonIntAsDouble = 1ull << 32; // It's definitely not an Int52 but it's a real number and it's a double. 76 77 static const SpeculatedType SpecInt32AsInt52 = 1ull << 30; // It's an Int52 and it can fit in an int32. 78 static const SpeculatedType SpecNonInt32AsInt52 = 1ull << 31; // It's an Int52 and it can't fit in an int32. 79 static const SpeculatedType SpecInt52Any = SpecInt32AsInt52 | SpecNonInt32AsInt52; // It's any kind of Int52. 80 81 static const SpeculatedType SpecAnyIntAsDouble = 1ull << 32; // It's definitely an Int52 and it's inside a double. 82 static const SpeculatedType SpecNonIntAsDouble = 1ull << 33; // It's definitely not an Int52 but it's a real number and it's a double. 80 83 static const SpeculatedType SpecDoubleReal = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double. 81 static const SpeculatedType SpecDoublePureNaN = 1ull << 3 3; // It's definitely a NaN that is safe to tag (i.e. pure).82 static const SpeculatedType SpecDoubleImpureNaN = 1ull << 3 4; // It's definitely a NaN that is unsafe to tag (i.e. impure).84 static const SpeculatedType SpecDoublePureNaN = 1ull << 34; // It's definitely a NaN that is safe to tag (i.e. pure). 85 static const SpeculatedType SpecDoubleImpureNaN = 1ull << 35; // It's definitely a NaN that is unsafe to tag (i.e. impure). 83 86 static const SpeculatedType SpecDoubleNaN = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN. 84 87 static const SpeculatedType SpecBytecodeDouble = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN. 85 88 static const SpeculatedType SpecFullDouble = SpecDoubleReal | SpecDoubleNaN; // It's either a non-NaN or a NaN double. 86 89 static const SpeculatedType SpecBytecodeRealNumber = SpecInt32Only | SpecDoubleReal; // It's either an Int32 or a DoubleReal. 87 static const SpeculatedType SpecFullRealNumber = Spec AnyInt | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or aInt52.90 static const SpeculatedType SpecFullRealNumber = SpecInt32Only | SpecInt52Any | SpecDoubleReal; // It's either an Int32 or a DoubleReal, or an Int52. 88 91 static const SpeculatedType SpecBytecodeNumber = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN. 89 static const SpeculatedType SpecFullNumber = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN. 90 static const SpeculatedType SpecBoolean = 1ull << 35; // It's definitely a Boolean. 91 static const SpeculatedType SpecOther = 1ull << 36; // It's definitely either Null or Undefined. 92 static const SpeculatedType SpecIntAnyFormat = SpecInt52Any | SpecInt32Only | SpecAnyIntAsDouble; 93 94 static const SpeculatedType SpecFullNumber = SpecIntAnyFormat | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN. 95 static const SpeculatedType SpecBoolean = 1ull << 36; // It's definitely a Boolean. 96 static const SpeculatedType SpecOther = 1ull << 37; // It's definitely either Null or Undefined. 92 97 static const SpeculatedType SpecMisc = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined. 93 static const SpeculatedType SpecEmpty = 1ull << 3 7; // It's definitely an empty value marker.94 static const SpeculatedType SpecBigInt = 1ull << 3 8; // It's definitely a BigInt.95 static const SpeculatedType SpecDataViewObject = 1ull << 39; // It's definitely a JSDataView.98 static const SpeculatedType SpecEmpty = 1ull << 38; // It's definitely an empty value marker. 99 static const SpeculatedType SpecBigInt = 1ull << 39; // It's definitely a BigInt. 100 static const SpeculatedType SpecDataViewObject = 1ull << 40; // It's definitely a JSDataView. 96 101 static const SpeculatedType SpecPrimitive = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc | SpecBigInt; // It's any non-Object JSValue. 97 102 static const SpeculatedType SpecObject = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecWeakMapObject | SpecWeakSetObject | SpecProxyObject | SpecDerivedArray | SpecObjectOther | SpecDataViewObject; // Bitmask used for testing for any kind of object prediction. … … 338 343 inline bool isInt32SpeculationForArithmetic(SpeculatedType value) 339 344 { 340 return !(value & (SpecFullDouble | SpecInt52 Only));345 return !(value & (SpecFullDouble | SpecInt52Any)); 341 346 } 342 347 343 348 inline bool isInt32OrBooleanSpeculationForArithmetic(SpeculatedType value) 344 349 { 345 return !(value & (SpecFullDouble | SpecInt52 Only));350 return !(value & (SpecFullDouble | SpecInt52Any)); 346 351 } 347 352 … … 351 356 } 352 357 353 inline bool is Int52Speculation(SpeculatedType value)354 { 355 return value == SpecInt52Only;356 } 357 358 inline bool is AnyIntSpeculation(SpeculatedType value)359 { 360 return !!value && (value & Spec AnyInt) == value;358 inline bool isAnyInt52Speculation(SpeculatedType value) 359 { 360 return !!value && (value & SpecInt52Any) == value; 361 } 362 363 inline bool isIntAnyFormat(SpeculatedType value) 364 { 365 return !!value && (value & SpecIntAnyFormat) == value; 361 366 } 362 367 … … 484 489 SpeculatedType speculationFromCell(JSCell*); 485 490 JS_EXPORT_PRIVATE SpeculatedType speculationFromValue(JSValue); 491 // If it's an anyInt(), it'll return speculated types from the Int52 lattice. 492 // Otherwise, it'll return types from the JSValue lattice. 493 JS_EXPORT_PRIVATE SpeculatedType int52AwareSpeculationFromValue(JSValue); 486 494 SpeculatedType speculationFromJSType(JSType); 487 495 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r244067 r244079 482 482 break; 483 483 } 484 setNonCellTypeForNode(node, Spec AnyInt);484 setNonCellTypeForNode(node, SpecInt52Any); 485 485 break; 486 486 } … … 608 608 break; 609 609 } 610 611 setNonCellTypeForNode(node, SpecAnyInt); 610 611 setTypeForNode(node, forNode(node->child1()).m_type); 612 forNode(node).fixTypeForRepresentation(m_graph, node); 612 613 break; 613 614 } … … 668 669 } 669 670 } 670 setNonCellTypeForNode(node, Spec AnyInt);671 setNonCellTypeForNode(node, SpecInt52Any); 671 672 break; 672 673 case DoubleRepUse: … … 768 769 } 769 770 } 770 setNonCellTypeForNode(node, Spec AnyInt);771 setNonCellTypeForNode(node, SpecInt52Any); 771 772 break; 772 773 case DoubleRepUse: … … 831 832 } 832 833 } 833 setNonCellTypeForNode(node, Spec AnyInt);834 setNonCellTypeForNode(node, SpecInt52Any); 834 835 break; 835 836 case DoubleRepUse: … … 891 892 } 892 893 } 893 setNonCellTypeForNode(node, Spec AnyInt);894 setNonCellTypeForNode(node, SpecInt52Any); 894 895 break; 895 896 case DoubleRepUse: … … 2131 2132 if (node->shouldSpeculateInt32()) 2132 2133 setNonCellTypeForNode(node, SpecInt32Only); 2133 else if ( enableInt52() && node->shouldSpeculateAnyInt())2134 setNonCellTypeForNode(node, Spec AnyInt);2134 else if (node->shouldSpeculateInt52()) 2135 setNonCellTypeForNode(node, SpecInt52Any); 2135 2136 else 2136 2137 setNonCellTypeForNode(node, SpecAnyIntAsDouble); … … 3876 3877 setNonCellTypeForNode(node, SpecInt32Only); 3877 3878 else 3878 setNonCellTypeForNode(node, Spec AnyInt);3879 setNonCellTypeForNode(node, SpecInt52Any); 3879 3880 } 3880 3881 break; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r242990 r244079 135 135 m_value = jsDoubleNumber(m_value.asNumber()); 136 136 } 137 if (m_type & Spec AnyInt) {138 m_type &= ~Spec AnyInt;137 if (m_type & SpecIntAnyFormat) { 138 m_type &= ~SpecIntAnyFormat; 139 139 m_type |= SpecAnyIntAsDouble; 140 140 } … … 143 143 } else if (representation == NodeResultInt52) { 144 144 if (m_type & SpecAnyIntAsDouble) { 145 // AnyIntAsDouble can produce i32 or i52. SpecAnyIntAsDouble doesn't bound the magnitude of the value. 145 146 m_type &= ~SpecAnyIntAsDouble; 146 m_type |= SpecInt52Only; 147 } 148 if (m_type & ~SpecAnyInt) 149 DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for int52 node has type outside SpecAnyInt.\n").data()); 147 m_type |= SpecInt52Any; 148 } 149 150 if (m_type & SpecInt32Only) { 151 m_type &= ~SpecInt32Only; 152 m_type |= SpecInt32AsInt52; 153 } 154 155 if (m_type & ~SpecInt52Any) 156 DFG_CRASH(graph, node, toCString("Abstract value ", *this, " for int52 node has type outside SpecInt52Any.\n").data()); 157 158 if (m_value) { 159 DFG_ASSERT(graph, node, m_value.isAnyInt()); 160 m_type = int52AwareSpeculationFromValue(m_value); 161 } 150 162 } else { 151 if (m_type & SpecInt52Only) { 152 m_type &= ~SpecInt52Only; 163 if (m_type & SpecInt32AsInt52) { 164 m_type &= ~SpecInt32AsInt52; 165 m_type |= SpecInt32Only; 166 } 167 if (m_type & SpecNonInt32AsInt52) { 168 m_type &= ~SpecNonInt32AsInt52; 153 169 m_type |= SpecAnyIntAsDouble; 154 170 } … … 416 432 { 417 433 if (!(m_type & SpecCell)) { 418 ASSERT(m_structure.isClear());419 ASSERT(!m_arrayModes);434 RELEASE_ASSERT(m_structure.isClear()); 435 RELEASE_ASSERT(!m_arrayModes); 420 436 } 421 437 422 438 if (isClear()) 423 ASSERT(!m_value); 424 425 if (!!m_value) { 426 SpeculatedType type = m_type; 427 // This relaxes the assertion below a bit, since we don't know the representation of the 428 // node. 429 if (type & SpecInt52Only) 430 type |= SpecAnyIntAsDouble; 431 ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type); 432 } 433 439 RELEASE_ASSERT(!m_value); 440 441 if (m_type & SpecInt52Any) { 442 if (m_type != SpecFullTop) 443 RELEASE_ASSERT(isAnyInt52Speculation(m_type)); 444 } 445 446 if (!!m_value) 447 RELEASE_ASSERT(validateTypeAcceptingBoxedInt52(m_value)); 448 434 449 // Note that it's possible for a prediction like (Final, []). This really means that 435 450 // the value is bottom and that any code that uses the value is unreachable. But … … 442 457 m_structure.assertIsRegistered(graph); 443 458 } 444 #endif 459 #endif // !ASSERT_DISABLED 445 460 446 461 ResultType AbstractValue::resultType() const -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r243278 r244079 202 202 return !m_value && m_type; 203 203 } 204 205 bool isInt52Any() const 206 { 207 return !(m_type & ~SpecInt52Any); 208 } 204 209 205 210 JSValue value() const … … 507 512 bool validateTypeAcceptingBoxedInt52(JSValue value) const 508 513 { 509 if (is HeapTop())514 if (isBytecodeTop()) 510 515 return true; 511 516 512 // Constant folding always represents Int52's in a double (i.e. AnyIntAsDouble). 513 // So speculationFromValue(value) for an Int52 value will return AnyIntAsDouble, 514 // and that's fine - the type validates just fine. 515 SpeculatedType type = m_type; 516 if (type & SpecInt52Only) 517 type |= SpecAnyIntAsDouble; 518 519 if (mergeSpeculations(type, speculationFromValue(value)) != type) 517 if (m_type & SpecInt52Any) { 518 ASSERT(!(m_type & ~SpecInt52Any)); 519 520 if (mergeSpeculations(m_type, int52AwareSpeculationFromValue(value)) != m_type) 521 return false; 522 return true; 523 } 524 525 if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type) 520 526 return false; 521 522 if (value.isEmpty()) {523 ASSERT(m_type & SpecEmpty);524 return true;525 }526 527 527 528 return true; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r244067 r244079 127 127 return; 128 128 } 129 if (m_graph.binaryArithShouldSpeculate AnyInt(node, FixupPass)) {129 if (m_graph.binaryArithShouldSpeculateInt52(node, FixupPass)) { 130 130 fixEdge<Int52RepUse>(leftChild); 131 131 fixEdge<Int52RepUse>(rightChild); … … 327 327 } 328 328 329 if (m_graph.unaryArithShouldSpeculate AnyInt(node, FixupPass)) {329 if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) { 330 330 node->setOp(ArithNegate); 331 331 fixEdge<Int52RepUse>(node->child1()); … … 451 451 break; 452 452 } 453 if (m_graph.unaryArithShouldSpeculate AnyInt(node, FixupPass)) {453 if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) { 454 454 fixEdge<Int52RepUse>(node->child1()); 455 455 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) … … 682 682 break; 683 683 } 684 if (enableInt52() 685 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) { 684 if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) { 686 685 fixEdge<Int52RepUse>(node->child1()); 687 686 fixEdge<Int52RepUse>(node->child2()); … … 937 936 if (node->shouldSpeculateInt32()) 938 937 break; 939 if (node->shouldSpeculate AnyInt() && enableInt52())938 if (node->shouldSpeculateInt52()) 940 939 node->setResult(NodeResultInt52); 941 940 else … … 1016 1015 if (child3->shouldSpeculateInt32()) 1017 1016 fixIntOrBooleanEdge(child3); 1018 else if (child3->shouldSpeculate AnyInt())1017 else if (child3->shouldSpeculateInt52()) 1019 1018 fixEdge<Int52RepUse>(child3); 1020 1019 else … … 1061 1060 // conversions. 1062 1061 if (!child->shouldSpeculateInt32() 1063 && !child->shouldSpeculate AnyInt()1062 && !child->shouldSpeculateInt52() 1064 1063 && !(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL())) 1065 1064 badNews = true; … … 1082 1081 if (child->shouldSpeculateInt32()) 1083 1082 fixIntOrBooleanEdge(child); 1084 else if (child->shouldSpeculate AnyInt())1083 else if (child->shouldSpeculateInt52()) 1085 1084 fixEdge<Int52RepUse>(child); 1086 1085 else { … … 1096 1095 if (node->arrayMode().type() == Array::Uint32Array) { 1097 1096 // NOTE: This means basically always doing Int52. 1098 if (node->shouldSpeculate AnyInt() && enableInt52())1097 if (node->shouldSpeculateInt52()) 1099 1098 node->setResult(NodeResultInt52); 1100 1099 else … … 1520 1519 } 1521 1520 1522 if ( enableInt52() && node->child1()->shouldSpeculateAnyInt()) {1521 if (node->child1()->shouldSpeculateInt52()) { 1523 1522 insertCheck<Int52RepUse>(node->child1().node()); 1524 1523 m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction())); … … 2181 2180 if (node->child1()->shouldSpeculateInt32()) 2182 2181 fixEdge<Int32Use>(node->child1()); 2183 else if ( enableInt52() && node->child1()->shouldSpeculateAnyInt())2182 else if (node->child1()->shouldSpeculateInt52()) 2184 2183 fixEdge<Int52RepUse>(node->child1()); 2185 2184 else … … 2615 2614 return; 2616 2615 } 2617 if ( enableInt52() && node->child1()->shouldSpeculateAnyInt()) {2616 if (node->child1()->shouldSpeculateInt52()) { 2618 2617 insertCheck<Int52RepUse>(node->child1().node()); 2619 2618 m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype())); … … 2671 2670 } 2672 2671 2673 if ( enableInt52() && node->child1()->shouldSpeculateAnyInt()) {2672 if (node->child1()->shouldSpeculateInt52()) { 2674 2673 fixEdge<Int52RepUse>(node->child1()); 2675 2674 node->convertToIdentity(); … … 2905 2904 } 2906 2905 2907 if ( enableInt52() && node->child1()->shouldSpeculateAnyInt()) {2906 if (node->child1()->shouldSpeculateInt52()) { 2908 2907 fixEdge<Int52RepUse>(node->child1()); 2909 2908 node->clearFlags(NodeMustGenerate); … … 3226 3225 break; 3227 3226 case Int52RepUse: 3228 if (isAnyInt Speculation(variable->prediction()))3227 if (isAnyInt52Speculation(variable->prediction())) 3229 3228 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); 3230 3229 break; … … 3317 3316 3318 3317 UseKind useKind; 3319 if (node->shouldSpeculate AnyInt())3318 if (node->shouldSpeculateInt52()) 3320 3319 useKind = Int52RepUse; 3321 3320 else if (node->shouldSpeculateNumber()) … … 3414 3413 } 3415 3414 3416 if (m_graph.addShouldSpeculate AnyInt(node)) {3415 if (m_graph.addShouldSpeculateInt52(node)) { 3417 3416 fixEdge<Int52RepUse>(node->child1()); 3418 3417 fixEdge<Int52RepUse>(node->child2()); … … 3733 3732 return; 3734 3733 } 3735 if (enableInt52() 3736 && Node::shouldSpeculateAnyInt(node->child1().node(), node->child2().node())) { 3734 if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) { 3737 3735 fixEdge<Int52RepUse>(node->child1()); 3738 3736 fixEdge<Int52RepUse>(node->child2()); … … 3974 3972 if (edge->isAnyIntConstant()) { 3975 3973 result = m_insertionSet.insertNode( 3976 indexForChecks, Spec AnyInt, Int52Constant, originForChecks,3974 indexForChecks, SpecInt52Any, Int52Constant, originForChecks, 3977 3975 OpInfo(edge->constant())); 3978 3976 } else if (edge->hasDoubleResult()) { 3979 3977 result = m_insertionSet.insertNode( 3980 indexForChecks, Spec AnyInt, Int52Rep, originForChecks,3978 indexForChecks, SpecInt52Any, Int52Rep, originForChecks, 3981 3979 Edge(edge.node(), DoubleRepAnyIntUse)); 3982 3980 } else if (edge->shouldSpeculateInt32ForArithmetic()) { … … 3986 3984 } else { 3987 3985 result = m_insertionSet.insertNode( 3988 indexForChecks, Spec AnyInt, Int52Rep, originForChecks,3986 indexForChecks, SpecInt52Any, Int52Rep, originForChecks, 3989 3987 Edge(edge.node(), AnyIntUse)); 3990 3988 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r243232 r244079 285 285 } 286 286 287 bool addShouldSpeculate AnyInt(Node* add)287 bool addShouldSpeculateInt52(Node* add) 288 288 { 289 289 if (!enableInt52()) … … 296 296 return false; 297 297 298 if (Node::shouldSpeculate AnyInt(left, right))298 if (Node::shouldSpeculateInt52(left, right)) 299 299 return true; 300 300 301 auto shouldSpeculateAnyIntForAdd = [](Node* node) { 302 auto isAnyIntSpeculationForAdd = [](SpeculatedType value) { 303 return !!value && (value & (SpecAnyInt | SpecAnyIntAsDouble)) == value; 304 }; 305 301 auto shouldSpeculateInt52ForAdd = [] (Node* node) { 306 302 // When DoubleConstant node appears, it means that users explicitly write a constant in their code with double form instead of integer form (1.0 instead of 1). 307 303 // In that case, we should honor this decision: using it as integer is not appropriate. 308 304 if (node->op() == DoubleConstant) 309 305 return false; 310 return is AnyIntSpeculationForAdd(node->prediction());306 return isIntAnyFormat(node->prediction()); 311 307 }; 312 308 313 // Allow AnyInt ArithAdd only when the one side of the binary operation should be speculated AnyInt. It is a bit conservative309 // Allow Int52 ArithAdd only when the one side of the binary operation should be speculated Int52. It is a bit conservative 314 310 // decision. This is because Double to Int52 conversion is not so cheap. Frequent back-and-forth conversions between Double and Int52 315 311 // rather hurt the performance. If the one side of the operation is already Int52, the cost for constructing ArithAdd becomes 316 312 // cheap since only one Double to Int52 conversion could be required. 317 313 // This recovers some regression in assorted tests while keeping kraken crypto improvements. 318 if (!left->shouldSpeculate AnyInt() && !right->shouldSpeculateAnyInt())314 if (!left->shouldSpeculateInt52() && !right->shouldSpeculateInt52()) 319 315 return false; 320 316 … … 330 326 return false; 331 327 332 return shouldSpeculate AnyIntForAdd(left) && shouldSpeculateAnyIntForAdd(right);328 return shouldSpeculateInt52ForAdd(left) && shouldSpeculateInt52ForAdd(right); 333 329 } 334 330 … … 342 338 } 343 339 344 bool binaryArithShouldSpeculate AnyInt(Node* node, PredictionPass pass)340 bool binaryArithShouldSpeculateInt52(Node* node, PredictionPass pass) 345 341 { 346 342 if (!enableInt52()) … … 350 346 Node* right = node->child2().node(); 351 347 352 return Node::shouldSpeculate AnyInt(left, right)348 return Node::shouldSpeculateInt52(left, right) 353 349 && node->canSpeculateInt52(pass) 354 350 && !hasExitSite(node, Int52Overflow); … … 361 357 } 362 358 363 bool unaryArithShouldSpeculate AnyInt(Node* node, PredictionPass pass)359 bool unaryArithShouldSpeculateInt52(Node* node, PredictionPass pass) 364 360 { 365 361 if (!enableInt52()) 366 362 return false; 367 return node->child1()->shouldSpeculate AnyInt()363 return node->child1()->shouldSpeculateInt52() 368 364 && node->canSpeculateInt52(pass) 369 365 && !hasExitSite(node, Int52Overflow); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r243448 r244079 2347 2347 } 2348 2348 2349 bool shouldSpeculate AnyInt()2350 { 2351 return isAnyIntSpeculation(prediction());2349 bool shouldSpeculateInt52() 2350 { 2351 return enableInt52() && isAnyInt52Speculation(prediction()); 2352 2352 } 2353 2353 … … 2610 2610 } 2611 2611 2612 static bool shouldSpeculate AnyInt(Node* op1, Node* op2)2613 { 2614 return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();2612 static bool shouldSpeculateInt52(Node* op1, Node* op2) 2613 { 2614 return enableInt52() && op1->shouldSpeculateInt52() && op2->shouldSpeculateInt52(); 2615 2615 } 2616 2616 -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r244067 r244079 157 157 VariableAccessData* variable = node->variableAccessData(); 158 158 SpeculatedType prediction = variable->prediction(); 159 if (!variable->couldRepresentInt52() && (prediction & Spec Int52Only))160 prediction = (prediction | SpecAnyIntAsDouble) & ~Spec Int52Only;159 if (!variable->couldRepresentInt52() && (prediction & SpecNonInt32AsInt52)) 160 prediction = (prediction | SpecAnyIntAsDouble) & ~SpecNonInt32AsInt52; 161 161 if (prediction) 162 162 changed |= mergePrediction(prediction); … … 174 174 changed |= mergePrediction(SpecInt32Only); 175 175 else if (enableInt52()) 176 changed |= mergePrediction(Spec AnyInt);176 changed |= mergePrediction(SpecInt52Any); 177 177 else 178 178 changed |= mergePrediction(SpecBytecodeNumber); … … 189 189 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 190 190 changed |= mergePrediction(SpecInt32Only); 191 else if (m_graph.addShouldSpeculate AnyInt(node))192 changed |= mergePrediction(SpecInt52 Only);191 else if (m_graph.addShouldSpeculateInt52(node)) 192 changed |= mergePrediction(SpecInt52Any); 193 193 else 194 194 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 218 218 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 219 219 changed |= mergePrediction(SpecInt32Only); 220 else if (m_graph.addShouldSpeculate AnyInt(node))221 changed |= mergePrediction(SpecInt52 Only);220 else if (m_graph.addShouldSpeculateInt52(node)) 221 changed |= mergePrediction(SpecInt52Any); 222 222 else if (isFullNumberOrBooleanSpeculation(left) && isFullNumberOrBooleanSpeculation(right)) 223 223 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 239 239 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 240 240 changed |= mergePrediction(SpecInt32Only); 241 else if (m_graph.addShouldSpeculate AnyInt(node))242 changed |= mergePrediction(SpecInt52 Only);241 else if (m_graph.addShouldSpeculateInt52(node)) 242 changed |= mergePrediction(SpecInt52Any); 243 243 else 244 244 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 260 260 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32) 261 261 changed |= mergePrediction(SpecInt32Only); 262 else if (m_graph.addShouldSpeculate AnyInt(node))263 changed |= mergePrediction(SpecInt52 Only);262 else if (m_graph.addShouldSpeculateInt52(node)) 263 changed |= mergePrediction(SpecInt52Any); 264 264 else 265 265 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 284 284 if (isInt32OrBooleanSpeculation(prediction) && node->canSpeculateInt32(m_pass)) 285 285 changed |= mergePrediction(SpecInt32Only); 286 else if (m_graph.unaryArithShouldSpeculate AnyInt(node, m_pass))287 changed |= mergePrediction(SpecInt52 Only);286 else if (m_graph.unaryArithShouldSpeculateInt52(node, m_pass)) 287 changed |= mergePrediction(SpecInt52Any); 288 288 else if (isBytecodeNumberSpeculation(prediction)) 289 289 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); … … 327 327 if (m_graph.binaryArithShouldSpeculateInt32(node, m_pass)) 328 328 changed |= mergePrediction(SpecInt32Only); 329 else if (m_graph.binaryArithShouldSpeculate AnyInt(node, m_pass))330 changed |= mergePrediction(SpecInt52 Only);329 else if (m_graph.binaryArithShouldSpeculateInt52(node, m_pass)) 330 changed |= mergePrediction(SpecInt52Any); 331 331 else 332 332 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 428 428 changed |= mergePrediction(SpecInt32Only); 429 429 else if (enableInt52()) 430 changed |= mergePrediction(Spec AnyInt);430 changed |= mergePrediction(SpecInt52Any); 431 431 else 432 432 changed |= mergePrediction(SpecInt32Only | SpecAnyIntAsDouble); … … 460 460 } 461 461 462 if ( enableInt52() && node->child1()->shouldSpeculateAnyInt()) {463 changed |= mergePrediction(Spec AnyInt);462 if (node->child1()->shouldSpeculateInt52()) { 463 changed |= mergePrediction(SpecInt52Any); 464 464 break; 465 465 } … … 568 568 && isFullNumberSpeculation(right) 569 569 && !m_graph.addShouldSpeculateInt32(node, m_pass) 570 && !m_graph.addShouldSpeculate AnyInt(node))570 && !m_graph.addShouldSpeculateInt52(node)) 571 571 ballot = VoteDouble; 572 572 else … … 588 588 && isFullNumberSpeculation(right) 589 589 && !m_graph.binaryArithShouldSpeculateInt32(node, m_pass) 590 && !m_graph.binaryArithShouldSpeculate AnyInt(node, m_pass))590 && !m_graph.binaryArithShouldSpeculateInt52(node, m_pass)) 591 591 ballot = VoteDouble; 592 592 else … … 644 644 node->variableAccessData()->vote(VoteDouble, weight); 645 645 else if (!isFullNumberSpeculation(prediction) 646 || isInt32Speculation(prediction) || isAnyInt Speculation(prediction))646 || isInt32Speculation(prediction) || isAnyInt52Speculation(prediction)) 647 647 node->variableAccessData()->vote(VoteValue, weight); 648 648 break; … … 735 735 switch (m_currentNode->op()) { 736 736 case JSConstant: { 737 SpeculatedType type = speculationFromValue(m_currentNode->asJSValue()); 738 if (type == SpecAnyIntAsDouble && enableInt52()) 739 type = SpecInt52Only; 740 setPrediction(type); 737 setPrediction(speculationFromValue(m_currentNode->asJSValue())); 741 738 break; 742 739 } … … 1049 1046 case FiatInt52: { 1050 1047 RELEASE_ASSERT(enableInt52()); 1051 setPrediction(Spec AnyInt);1048 setPrediction(SpecInt52Any); 1052 1049 break; 1053 1050 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r244067 r244079 2920 2920 2921 2921 #if USE(JSVALUE64) 2922 if (node->shouldSpeculateAnyInt()) { 2922 if (node->shouldSpeculateInt52()) { 2923 ASSERT(enableInt52()); 2923 2924 m_jit.zeroExtend32ToPtr(resultReg, resultReg); 2924 2925 strictInt52Result(resultReg, node); … … 4327 4328 // Will we need an overflow check? If we can prove that neither input can be 4328 4329 // Int52 then the overflow check will not be necessary. 4329 if (!m_state.forNode(node->child1()).couldBeType(Spec Int52Only)4330 && !m_state.forNode(node->child2()).couldBeType(Spec Int52Only)) {4330 if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52) 4331 && !m_state.forNode(node->child2()).couldBeType(SpecNonInt32AsInt52)) { 4331 4332 SpeculateWhicheverInt52Operand op1(this, node->child1()); 4332 4333 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); … … 4513 4514 // Will we need an overflow check? If we can prove that neither input can be 4514 4515 // Int52 then the overflow check will not be necessary. 4515 if (!m_state.forNode(node->child1()).couldBeType(Spec Int52Only)4516 && !m_state.forNode(node->child2()).couldBeType(Spec Int52Only)) {4516 if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52) 4517 && !m_state.forNode(node->child2()).couldBeType(SpecNonInt32AsInt52)) { 4517 4518 SpeculateWhicheverInt52Operand op1(this, node->child1()); 4518 4519 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); … … 4597 4598 ASSERT(shouldCheckOverflow(node->arithMode())); 4598 4599 4599 if (!m_state.forNode(node->child1()).couldBeType(Spec Int52Only)) {4600 if (!m_state.forNode(node->child1()).couldBeType(SpecNonInt32AsInt52)) { 4600 4601 SpeculateWhicheverInt52Operand op1(this, node->child1()); 4601 4602 GPRTemporary result(this); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r244067 r244079 943 943 944 944 case DataFormatJS: { 945 DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52 Only));945 DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Any)); 946 946 // Check the value is an integer. 947 947 GPRReg gpr = info.gpr(); … … 1028 1028 AbstractValue& value = m_state.forNode(edge); 1029 1029 1030 m_interpreter.filter(value, Spec AnyInt);1030 m_interpreter.filter(value, SpecInt52Any); 1031 1031 if (value.isClear()) { 1032 1032 if (mayHaveTypeCheck(edge.useKind())) -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.h
r240114 r244079 103 103 return SpecInt32Only; 104 104 case Int52RepUse: 105 return Spec AnyInt;105 return SpecInt52Any; 106 106 case AnyIntUse: 107 107 return SpecInt32Only | SpecAnyIntAsDouble; -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.cpp
r200034 r244079 157 157 if (type & ~SpecBytecodeNumber) 158 158 type |= SpecDoublePureNaN; 159 if (type & SpecAnyInt)159 if (type & (SpecInt32Only | SpecInt52Any)) 160 160 type |= SpecAnyIntAsDouble; 161 161 return checkAndSet(m_prediction, type); … … 181 181 182 182 // The argument-aware prediction -- which merges all of an (inlined or machine) 183 // argument's variable access datas' predictions -- must possibly be AnyInt.184 return !(argumentAwarePrediction() & ~SpecAnyInt);183 // argument's variable access datas' predictions -- must possibly be Int52Any. 184 return isAnyInt52Speculation(argumentAwarePrediction()); 185 185 } 186 186 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r244067 r244079 2327 2327 2328 2328 case Int52RepUse: { 2329 if (!abstractValue(m_node->child1()).couldBeType(Spec Int52Only)2330 && !abstractValue(m_node->child2()).couldBeType(Spec Int52Only)) {2329 if (!abstractValue(m_node->child1()).couldBeType(SpecNonInt32AsInt52) 2330 && !abstractValue(m_node->child2()).couldBeType(SpecNonInt32AsInt52)) { 2331 2331 Int52Kind kind; 2332 2332 LValue left = lowWhicheverInt52(m_node->child1(), kind); … … 3024 3024 3025 3025 case Int52RepUse: { 3026 if (!abstractValue(m_node->child1()).couldBeType(Spec Int52Only)) {3026 if (!abstractValue(m_node->child1()).couldBeType(SpecNonInt32AsInt52)) { 3027 3027 Int52Kind kind; 3028 3028 LValue value = lowWhicheverInt52(m_node->child1(), kind); … … 14638 14638 } 14639 14639 14640 if (m_node->shouldSpeculate AnyInt()) {14640 if (m_node->shouldSpeculateInt52()) { 14641 14641 setStrictInt52(m_out.zeroExt(result, Int64)); 14642 14642 return;
Note: See TracChangeset
for help on using the changeset viewer.