Changeset 156019 in webkit
- Timestamp:
- Sep 17, 2013 6:31:04 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 12 added
- 69 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r156013 r156019 1 2013-09-17 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should support Int52 for local variables 4 https://bugs.webkit.org/show_bug.cgi?id=121064 5 6 Reviewed by Oliver Hunt. 7 8 * js/regress/large-int-captured-expected.txt: Added. 9 * js/regress/large-int-captured.html: Added. 10 * js/regress/large-int-expected.txt: Added. 11 * js/regress/large-int-neg-expected.txt: Added. 12 * js/regress/large-int-neg.html: Added. 13 * js/regress/large-int.html: Added. 14 * js/regress/marsaglia-larger-ints-expected.txt: Added. 15 * js/regress/marsaglia-larger-ints.html: Added. 16 * js/regress/script-tests/large-int-captured.js: Added. 17 (.bar): 18 (foo): 19 * js/regress/script-tests/large-int-neg.js: Added. 20 (foo): 21 * js/regress/script-tests/large-int.js: Added. 22 (foo): 23 * js/regress/script-tests/marsaglia-larger-ints.js: Added. 24 (uint): 25 (marsaglia): 26 1 27 2013-09-17 Alexey Proskuryakov <ap@apple.com> 2 28 -
trunk/Source/JavaScriptCore/ChangeLog
r156017 r156019 1 2013-09-16 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should support Int52 for local variables 4 https://bugs.webkit.org/show_bug.cgi?id=121064 5 6 Reviewed by Oliver Hunt. 7 8 This adds Int52 support for local variables to the DFG and FTL. It's a speed-up on 9 programs that have local int32 overflows but where a larger int representation can 10 prevent us from having to convert all the way up to double. 11 12 It's a small speed-up for now. But we're just supporting Int52 for a handful of 13 operations (add, sub, mul, neg, compare, bitops, typed array access) and this lays 14 the groundwork for adding Int52 to JSValue, which will probably be a bigger 15 speed-up. 16 17 The basic approach is: 18 19 - We have a notion of Int52 in our typesystem. Int52 doesn't belong to BytecodeTop 20 or HeapTop - i.e. it doesn't arise from JSValues. 21 22 - DFG treats Int52 as being part of its FullTop and will treat it as being a 23 subtype of double unless instructed otherwise. 24 25 - Prediction propagator creates Int52s whenever we have a node going doubly but due 26 to large values rather than fractional values, and that node is known to be able 27 to produce Int52 natively in the DFG backend. 28 29 - Fixup phase converts edges to MachineIntUses in nodes that are known to be able 30 to deal with Int52, and where we have a subtype of Int32|Int52 as the predicted 31 input. 32 33 - The DFG backend and FTL LLVM IR lowering have two notions of Int52s - ones that 34 are left-shifted by 16 (great for overflow checks) and ones that are 35 sign-extended. Both backends know how to convert between Int52s and the other 36 representations. 37 38 * assembler/MacroAssemblerX86_64.h: 39 (JSC::MacroAssemblerX86_64::rshift64): 40 (JSC::MacroAssemblerX86_64::mul64): 41 (JSC::MacroAssemblerX86_64::branchMul64): 42 (JSC::MacroAssemblerX86_64::branchNeg64): 43 (JSC::MacroAssemblerX86_64::convertInt64ToDouble): 44 * assembler/X86Assembler.h: 45 (JSC::X86Assembler::imulq_rr): 46 (JSC::X86Assembler::cvtsi2sdq_rr): 47 * bytecode/DataFormat.h: 48 (JSC::dataFormatToString): 49 * bytecode/OperandsInlines.h: 50 (JSC::::dumpInContext): 51 * bytecode/SpeculatedType.cpp: 52 (JSC::dumpSpeculation): 53 (JSC::speculationToAbbreviatedString): 54 (JSC::speculationFromValue): 55 * bytecode/SpeculatedType.h: 56 (JSC::isInt32SpeculationForArithmetic): 57 (JSC::isMachineIntSpeculationForArithmetic): 58 (JSC::isBytecodeRealNumberSpeculation): 59 (JSC::isFullRealNumberSpeculation): 60 (JSC::isBytecodeNumberSpeculation): 61 (JSC::isFullNumberSpeculation): 62 (JSC::isBytecodeNumberSpeculationExpectingDefined): 63 (JSC::isFullNumberSpeculationExpectingDefined): 64 * bytecode/ValueRecovery.h: 65 (JSC::ValueRecovery::alreadyInJSStackAsUnboxedInt52): 66 (JSC::ValueRecovery::inGPR): 67 (JSC::ValueRecovery::displacedInJSStack): 68 (JSC::ValueRecovery::isAlreadyInJSStack): 69 (JSC::ValueRecovery::gpr): 70 (JSC::ValueRecovery::virtualRegister): 71 (JSC::ValueRecovery::dumpInContext): 72 * dfg/DFGAbstractInterpreter.h: 73 (JSC::DFG::AbstractInterpreter::needsTypeCheck): 74 (JSC::DFG::AbstractInterpreter::filterByType): 75 * dfg/DFGAbstractInterpreterInlines.h: 76 (JSC::DFG::::executeEffects): 77 * dfg/DFGAbstractValue.cpp: 78 (JSC::DFG::AbstractValue::set): 79 (JSC::DFG::AbstractValue::checkConsistency): 80 * dfg/DFGAbstractValue.h: 81 (JSC::DFG::AbstractValue::couldBeType): 82 (JSC::DFG::AbstractValue::isType): 83 (JSC::DFG::AbstractValue::checkConsistency): 84 (JSC::DFG::AbstractValue::validateType): 85 * dfg/DFGArrayMode.cpp: 86 (JSC::DFG::ArrayMode::refine): 87 * dfg/DFGAssemblyHelpers.h: 88 (JSC::DFG::AssemblyHelpers::boxInt52): 89 * dfg/DFGCSEPhase.cpp: 90 (JSC::DFG::CSEPhase::pureCSE): 91 (JSC::DFG::CSEPhase::getByValLoadElimination): 92 (JSC::DFG::CSEPhase::performNodeCSE): 93 * dfg/DFGClobberize.h: 94 (JSC::DFG::clobberize): 95 * dfg/DFGCommon.h: 96 (JSC::DFG::enableInt52): 97 * dfg/DFGFixupPhase.cpp: 98 (JSC::DFG::FixupPhase::run): 99 (JSC::DFG::FixupPhase::fixupNode): 100 (JSC::DFG::FixupPhase::fixupSetLocalsInBlock): 101 (JSC::DFG::FixupPhase::fixupUntypedSetLocalsInBlock): 102 (JSC::DFG::FixupPhase::observeUseKindOnNode): 103 (JSC::DFG::FixupPhase::fixEdge): 104 (JSC::DFG::FixupPhase::injectInt32ToDoubleNode): 105 (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd): 106 * dfg/DFGFlushFormat.cpp: 107 (WTF::printInternal): 108 * dfg/DFGFlushFormat.h: 109 (JSC::DFG::resultFor): 110 (JSC::DFG::useKindFor): 111 * dfg/DFGGenerationInfo.h: 112 (JSC::DFG::GenerationInfo::initInt52): 113 (JSC::DFG::GenerationInfo::initStrictInt52): 114 (JSC::DFG::GenerationInfo::isFormat): 115 (JSC::DFG::GenerationInfo::isInt52): 116 (JSC::DFG::GenerationInfo::isStrictInt52): 117 (JSC::DFG::GenerationInfo::fillInt52): 118 (JSC::DFG::GenerationInfo::fillStrictInt52): 119 * dfg/DFGGraph.cpp: 120 (JSC::DFG::Graph::dump): 121 * dfg/DFGGraph.h: 122 (JSC::DFG::Graph::addShouldSpeculateMachineInt): 123 (JSC::DFG::Graph::mulShouldSpeculateMachineInt): 124 (JSC::DFG::Graph::negateShouldSpeculateMachineInt): 125 * dfg/DFGInPlaceAbstractState.cpp: 126 (JSC::DFG::InPlaceAbstractState::mergeStateAtTail): 127 * dfg/DFGJITCode.cpp: 128 (JSC::DFG::JITCode::reconstruct): 129 * dfg/DFGMinifiedNode.h: 130 (JSC::DFG::belongsInMinifiedGraph): 131 (JSC::DFG::MinifiedNode::hasChild): 132 * dfg/DFGNode.h: 133 (JSC::DFG::Node::shouldSpeculateNumber): 134 (JSC::DFG::Node::shouldSpeculateNumberExpectingDefined): 135 * dfg/DFGNodeFlags.h: 136 * dfg/DFGNodeType.h: 137 (JSC::DFG::forwardRewiringSelectionScore): 138 * dfg/DFGOSRExitCompiler.cpp: 139 * dfg/DFGOSRExitCompiler64.cpp: 140 (JSC::DFG::OSRExitCompiler::compileExit): 141 * dfg/DFGPredictionPropagationPhase.cpp: 142 (JSC::DFG::PredictionPropagationPhase::speculatedDoubleTypeForPrediction): 143 (JSC::DFG::PredictionPropagationPhase::propagate): 144 (JSC::DFG::PredictionPropagationPhase::doDoubleVoting): 145 * dfg/DFGSafeToExecute.h: 146 (JSC::DFG::SafeToExecuteEdge::operator()): 147 (JSC::DFG::safeToExecute): 148 * dfg/DFGSilentRegisterSavePlan.h: 149 * dfg/DFGSpeculativeJIT.cpp: 150 (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR): 151 (JSC::DFG::SpeculativeJIT::silentFill): 152 (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): 153 (JSC::DFG::SpeculativeJIT::compileInlineStart): 154 (JSC::DFG::SpeculativeJIT::compileDoublePutByVal): 155 (JSC::DFG::SpeculativeJIT::compileValueToInt32): 156 (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): 157 (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): 158 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 159 (JSC::DFG::SpeculativeJIT::compileAdd): 160 (JSC::DFG::SpeculativeJIT::compileArithSub): 161 (JSC::DFG::SpeculativeJIT::compileArithNegate): 162 (JSC::DFG::SpeculativeJIT::compileArithMul): 163 (JSC::DFG::SpeculativeJIT::compare): 164 (JSC::DFG::SpeculativeJIT::compileStrictEq): 165 (JSC::DFG::SpeculativeJIT::speculateMachineInt): 166 (JSC::DFG::SpeculativeJIT::speculateNumber): 167 (JSC::DFG::SpeculativeJIT::speculateRealNumber): 168 (JSC::DFG::SpeculativeJIT::speculate): 169 * dfg/DFGSpeculativeJIT.h: 170 (JSC::DFG::SpeculativeJIT::canReuse): 171 (JSC::DFG::SpeculativeJIT::isFilled): 172 (JSC::DFG::SpeculativeJIT::isFilledDouble): 173 (JSC::DFG::SpeculativeJIT::use): 174 (JSC::DFG::SpeculativeJIT::isKnownInteger): 175 (JSC::DFG::SpeculativeJIT::isKnownCell): 176 (JSC::DFG::SpeculativeJIT::isKnownNotNumber): 177 (JSC::DFG::SpeculativeJIT::int52Result): 178 (JSC::DFG::SpeculativeJIT::strictInt52Result): 179 (JSC::DFG::SpeculativeJIT::initConstantInfo): 180 (JSC::DFG::SpeculativeJIT::isInteger): 181 (JSC::DFG::SpeculativeJIT::betterUseStrictInt52): 182 (JSC::DFG::SpeculativeJIT::generationInfo): 183 (JSC::DFG::SpeculateInt52Operand::SpeculateInt52Operand): 184 (JSC::DFG::SpeculateInt52Operand::~SpeculateInt52Operand): 185 (JSC::DFG::SpeculateInt52Operand::edge): 186 (JSC::DFG::SpeculateInt52Operand::node): 187 (JSC::DFG::SpeculateInt52Operand::gpr): 188 (JSC::DFG::SpeculateInt52Operand::use): 189 (JSC::DFG::SpeculateStrictInt52Operand::SpeculateStrictInt52Operand): 190 (JSC::DFG::SpeculateStrictInt52Operand::~SpeculateStrictInt52Operand): 191 (JSC::DFG::SpeculateStrictInt52Operand::edge): 192 (JSC::DFG::SpeculateStrictInt52Operand::node): 193 (JSC::DFG::SpeculateStrictInt52Operand::gpr): 194 (JSC::DFG::SpeculateStrictInt52Operand::use): 195 (JSC::DFG::SpeculateWhicheverInt52Operand::SpeculateWhicheverInt52Operand): 196 (JSC::DFG::SpeculateWhicheverInt52Operand::~SpeculateWhicheverInt52Operand): 197 (JSC::DFG::SpeculateWhicheverInt52Operand::edge): 198 (JSC::DFG::SpeculateWhicheverInt52Operand::node): 199 (JSC::DFG::SpeculateWhicheverInt52Operand::gpr): 200 (JSC::DFG::SpeculateWhicheverInt52Operand::use): 201 (JSC::DFG::SpeculateWhicheverInt52Operand::format): 202 * dfg/DFGSpeculativeJIT32_64.cpp: 203 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 204 (JSC::DFG::SpeculativeJIT::compile): 205 * dfg/DFGSpeculativeJIT64.cpp: 206 (JSC::DFG::SpeculativeJIT::boxInt52): 207 (JSC::DFG::SpeculativeJIT::fillJSValue): 208 (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal): 209 (JSC::DFG::SpeculativeJIT::fillSpeculateInt52): 210 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 211 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 212 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 213 (JSC::DFG::SpeculativeJIT::compileInt52Compare): 214 (JSC::DFG::SpeculativeJIT::compilePeepHoleInt52Branch): 215 (JSC::DFG::SpeculativeJIT::compile): 216 * dfg/DFGUseKind.cpp: 217 (WTF::printInternal): 218 * dfg/DFGUseKind.h: 219 (JSC::DFG::typeFilterFor): 220 (JSC::DFG::isNumerical): 221 * dfg/DFGValueSource.cpp: 222 (JSC::DFG::ValueSource::dump): 223 * dfg/DFGValueSource.h: 224 (JSC::DFG::dataFormatToValueSourceKind): 225 (JSC::DFG::valueSourceKindToDataFormat): 226 (JSC::DFG::ValueSource::forFlushFormat): 227 (JSC::DFG::ValueSource::valueRecovery): 228 * dfg/DFGVariableAccessData.h: 229 (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote): 230 (JSC::DFG::VariableAccessData::flushFormat): 231 * ftl/FTLCArgumentGetter.cpp: 232 (JSC::FTL::CArgumentGetter::loadNextAndBox): 233 * ftl/FTLCArgumentGetter.h: 234 * ftl/FTLCapabilities.cpp: 235 (JSC::FTL::canCompile): 236 * ftl/FTLExitValue.cpp: 237 (JSC::FTL::ExitValue::dumpInContext): 238 * ftl/FTLExitValue.h: 239 (JSC::FTL::ExitValue::inJSStackAsInt52): 240 * ftl/FTLIntrinsicRepository.h: 241 * ftl/FTLLowerDFGToLLVM.cpp: 242 (JSC::FTL::LowerDFGToLLVM::createPhiVariables): 243 (JSC::FTL::LowerDFGToLLVM::compileNode): 244 (JSC::FTL::LowerDFGToLLVM::compileUpsilon): 245 (JSC::FTL::LowerDFGToLLVM::compilePhi): 246 (JSC::FTL::LowerDFGToLLVM::compileSetLocal): 247 (JSC::FTL::LowerDFGToLLVM::compileAdd): 248 (JSC::FTL::LowerDFGToLLVM::compileArithSub): 249 (JSC::FTL::LowerDFGToLLVM::compileArithMul): 250 (JSC::FTL::LowerDFGToLLVM::compileArithNegate): 251 (JSC::FTL::LowerDFGToLLVM::compilePutByVal): 252 (JSC::FTL::LowerDFGToLLVM::compileCompareEq): 253 (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq): 254 (JSC::FTL::LowerDFGToLLVM::compileCompareLess): 255 (JSC::FTL::LowerDFGToLLVM::compileCompareLessEq): 256 (JSC::FTL::LowerDFGToLLVM::compileCompareGreater): 257 (JSC::FTL::LowerDFGToLLVM::compileCompareGreaterEq): 258 (JSC::FTL::LowerDFGToLLVM::lowInt32): 259 (JSC::FTL::LowerDFGToLLVM::lowInt52): 260 (JSC::FTL::LowerDFGToLLVM::lowStrictInt52): 261 (JSC::FTL::LowerDFGToLLVM::betterUseStrictInt52): 262 (JSC::FTL::LowerDFGToLLVM::bestInt52Kind): 263 (JSC::FTL::LowerDFGToLLVM::opposite): 264 (JSC::FTL::LowerDFGToLLVM::Int52s::operator[]): 265 (JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52): 266 (JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52s): 267 (JSC::FTL::LowerDFGToLLVM::lowOpposingInt52s): 268 (JSC::FTL::LowerDFGToLLVM::lowCell): 269 (JSC::FTL::LowerDFGToLLVM::lowBoolean): 270 (JSC::FTL::LowerDFGToLLVM::lowDouble): 271 (JSC::FTL::LowerDFGToLLVM::lowJSValue): 272 (JSC::FTL::LowerDFGToLLVM::strictInt52ToInt32): 273 (JSC::FTL::LowerDFGToLLVM::strictInt52ToDouble): 274 (JSC::FTL::LowerDFGToLLVM::strictInt52ToJSValue): 275 (JSC::FTL::LowerDFGToLLVM::setInt52WithStrictValue): 276 (JSC::FTL::LowerDFGToLLVM::strictInt52ToInt52): 277 (JSC::FTL::LowerDFGToLLVM::int52ToStrictInt52): 278 (JSC::FTL::LowerDFGToLLVM::speculateRealNumber): 279 (JSC::FTL::LowerDFGToLLVM::initializeOSRExitStateForBlock): 280 (JSC::FTL::LowerDFGToLLVM::emitOSRExitCall): 281 (JSC::FTL::LowerDFGToLLVM::addExitArgumentForNode): 282 (JSC::FTL::LowerDFGToLLVM::setInt52): 283 (JSC::FTL::LowerDFGToLLVM::setStrictInt52): 284 * ftl/FTLOSRExitCompiler.cpp: 285 (JSC::FTL::compileStub): 286 * ftl/FTLOutput.h: 287 (JSC::FTL::Output::addWithOverflow64): 288 (JSC::FTL::Output::subWithOverflow64): 289 (JSC::FTL::Output::mulWithOverflow64): 290 * ftl/FTLValueFormat.cpp: 291 (WTF::printInternal): 292 * ftl/FTLValueFormat.h: 293 * ftl/FTLValueSource.cpp: 294 (JSC::FTL::ValueSource::dump): 295 * ftl/FTLValueSource.h: 296 * interpreter/Register.h: 297 (JSC::Register::unboxedInt52): 298 * runtime/Arguments.cpp: 299 (JSC::Arguments::tearOffForInlineCallFrame): 300 * runtime/IndexingType.cpp: 301 (JSC::leastUpperBoundOfIndexingTypeAndType): 302 * runtime/JSCJSValue.h: 303 * runtime/JSCJSValueInlines.h: 304 (JSC::JSValue::isMachineInt): 305 (JSC::JSValue::asMachineInt): 306 1 307 2013-09-17 Filip Pizlo <fpizlo@apple.com> 2 308 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h
r155711 r156019 231 231 } 232 232 233 void rshift64(TrustedImm32 imm, RegisterID dest) 234 { 235 m_assembler.sarq_i8r(imm.m_value, dest); 236 } 237 238 void mul64(RegisterID src, RegisterID dest) 239 { 240 m_assembler.imulq_rr(src, dest); 241 } 242 233 243 void neg64(RegisterID dest) 234 244 { … … 531 541 } 532 542 543 Jump branchMul64(ResultCondition cond, RegisterID src, RegisterID dest) 544 { 545 mul64(src, dest); 546 if (cond != Overflow) 547 m_assembler.testq_rr(dest, dest); 548 return Jump(m_assembler.jCC(x86Condition(cond))); 549 } 550 533 551 Jump branchSub64(ResultCondition cond, TrustedImm32 imm, RegisterID dest) 534 552 { … … 547 565 move(src1, dest); 548 566 return branchSub64(cond, src2, dest); 567 } 568 569 Jump branchNeg64(ResultCondition cond, RegisterID srcDest) 570 { 571 neg64(srcDest); 572 return Jump(m_assembler.jCC(x86Condition(cond))); 549 573 } 550 574 … … 594 618 MacroAssemblerX86Common::move(TrustedImmPtr(address.m_ptr), scratchRegister); 595 619 return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister), mask); 620 } 621 622 void convertInt64ToDouble(RegisterID src, FPRegisterID dest) 623 { 624 m_assembler.cvtsi2sdq_rr(src, dest); 596 625 } 597 626 -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r155711 r156019 830 830 } 831 831 } 832 #endif 832 #endif // CPU(X86_64) 833 833 834 834 void imull_rr(RegisterID src, RegisterID dst) … … 836 836 m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src); 837 837 } 838 839 #if CPU(X86_64) 840 void imulq_rr(RegisterID src, RegisterID dst) 841 { 842 m_formatter.twoByteOp64(OP2_IMUL_GvEv, dst, src); 843 } 844 #endif // CPU(X86_64) 838 845 839 846 void imull_mr(int offset, RegisterID base, RegisterID dst) … … 1611 1618 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); 1612 1619 } 1620 1621 #if CPU(X86_64) 1622 void cvtsi2sdq_rr(RegisterID src, XMMRegisterID dst) 1623 { 1624 m_formatter.prefix(PRE_SSE_F2); 1625 m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src); 1626 } 1627 #endif 1613 1628 1614 1629 void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst) -
trunk/Source/JavaScriptCore/bytecode/DataFormat.h
r155578 r156019 40 40 DataFormatNone = 0, 41 41 DataFormatInt32 = 1, 42 DataFormatDouble = 2, 43 DataFormatBoolean = 3, 44 DataFormatCell = 4, 45 DataFormatStorage = 5, 42 DataFormatInt52 = 2, // Int52's are left-shifted by 16 by default. 43 DataFormatStrictInt52 = 3, // "Strict" Int52 means it's not shifted. 44 DataFormatDouble = 4, 45 DataFormatBoolean = 5, 46 DataFormatCell = 6, 47 DataFormatStorage = 7, 46 48 DataFormatJS = 8, 47 49 DataFormatJSInt32 = DataFormatJS | DataFormatInt32, … … 65 67 case DataFormatInt32: 66 68 return "Int32"; 69 case DataFormatInt52: 70 return "Int52"; 71 case DataFormatStrictInt52: 72 return "StrictInt52"; 67 73 case DataFormatDouble: 68 74 return "Double"; -
trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp
r155499 r156019 53 53 case NegativeZero: 54 54 return "NegativeZero"; 55 case Int 48Overflow:56 return "Int 48Overflow";55 case Int52Overflow: 56 return "Int52Overflow"; 57 57 case StoreToHole: 58 58 return "StoreToHole"; -
trunk/Source/JavaScriptCore/bytecode/ExitKind.h
r155499 r156019 39 39 Overflow, // We exited because of overflow. 40 40 NegativeZero, // We exited because we encountered negative zero. 41 Int 48Overflow, // We exited because of an Int48overflow.41 Int52Overflow, // We exited because of an Int52 overflow. 42 42 StoreToHole, // We had a store to a hole. 43 43 LoadFromHole, // We had a load from a hole. -
trunk/Source/JavaScriptCore/bytecode/OperandsInlines.h
r153296 r156019 44 44 if (Traits::isEmptyForDump(local(localIndex))) 45 45 continue; 46 out.print(comma, " r", localIndex, ":", inContext(local(localIndex), context));46 out.print(comma, "loc", localIndex, ":", inContext(local(localIndex), context)); 47 47 } 48 48 } -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r155499 r156019 155 155 156 156 if (value & SpecInt32) 157 myOut.print("Int ");157 myOut.print("Int32"); 158 158 else 159 159 isTop = false; 160 160 161 if (value & SpecInt52) 162 myOut.print("Int52"); 163 161 164 if ((value & SpecDouble) == SpecDouble) 162 165 myOut.print("Double"); 163 166 else { 164 if (value & SpecInt48AsDouble) 165 myOut.print("Int48asdouble"); 166 else 167 isTop = false; 168 169 if (value & SpecInt48) 170 myOut.print("Int48"); 167 if (value & SpecInt52AsDouble) 168 myOut.print("Int52asdouble"); 171 169 else 172 170 isTop = false; … … 244 242 if (isInt32Speculation(prediction)) 245 243 return "<Int32>"; 246 if (isInt48AsDoubleSpeculation(prediction)) 247 return "<Int48AsDouble>"; 248 if (isInt48Speculation(prediction)) 249 return "<Int48>"; 244 if (isInt52AsDoubleSpeculation(prediction)) 245 return "<Int52AsDouble>"; 246 if (isInt52Speculation(prediction)) 247 return "<Int52>"; 248 if (isMachineIntSpeculation(prediction)) 249 return "<MachineInt>"; 250 250 if (isDoubleSpeculation(prediction)) 251 251 return "<Double>"; 252 if (is NumberSpeculation(prediction))252 if (isFullNumberSpeculation(prediction)) 253 253 return "<Number>"; 254 254 if (isBooleanSpeculation(prediction)) … … 346 346 if (value.isDouble()) { 347 347 double number = value.asNumber(); 348 if (number == number) { 349 int64_t asInt64 = static_cast<int64_t>(number); 350 if (asInt64 == number && (asInt64 || !std::signbit(number)) 351 && asInt64 < (static_cast<int64_t>(1) << 47) 352 && asInt64 >= -(static_cast<int64_t>(1) << 47)) { 353 return SpecInt48AsDouble; 354 } 355 return SpecNonIntAsDouble; 356 } 357 return SpecDoubleNaN; 348 if (number != number) 349 return SpecDoubleNaN; 350 if (value.isMachineInt()) 351 return SpecInt52AsDouble; 352 return SpecNonIntAsDouble; 358 353 } 359 354 if (value.isCell()) -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r155499 r156019 39 39 40 40 typedef uint32_t SpeculatedType; 41 static const SpeculatedType SpecNone = 0x00000000; // We don't know anything yet. 42 static const SpeculatedType SpecFinalObject = 0x00000001; // It's definitely a JSFinalObject. 43 static const SpeculatedType SpecArray = 0x00000002; // It's definitely a JSArray. 44 static const SpeculatedType SpecFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. 45 static const SpeculatedType SpecInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. 46 static const SpeculatedType SpecInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. 47 static const SpeculatedType SpecInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses. 48 static const SpeculatedType SpecUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses. 49 static const SpeculatedType SpecUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses. 50 static const SpeculatedType SpecUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses. 51 static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses. 52 static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. 53 static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses. 54 static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array; 55 static const SpeculatedType SpecArguments = 0x00002000; // It's definitely an Arguments object. 56 static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject. 57 static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. 58 static const SpeculatedType SpecObject = 0x0000ffff; // Bitmask used for testing for any kind of object prediction. 59 static const SpeculatedType SpecStringIdent = 0x00010000; // It's definitely a JSString, and it's an identifier. 60 static const SpeculatedType SpecStringVar = 0x00020000; // It's definitely a JSString, and it's not an identifier. 61 static const SpeculatedType SpecString = 0x00030000; // It's definitely a JSString. 62 static const SpeculatedType SpecCellOther = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. 63 static const SpeculatedType SpecCell = 0x0007ffff; // It's definitely a JSCell. 64 static const SpeculatedType SpecInt32 = 0x00800000; // It's definitely an Int32. 65 static const SpeculatedType SpecInt48 = 0x01000000; // It's definitely an Int48, it's inside a double, but it doesn't need to be. 66 static const SpeculatedType SpecMachineInt = 0x01800000; // It's something that we can do machine int arithmetic on. 67 static const SpeculatedType SpecInt48AsDouble = 0x02000000; // It's definitely an Int48 and it's inside a double. 68 static const SpeculatedType SpecInteger = 0x03800000; // It's definitely some kind of integer. 69 static const SpeculatedType SpecNonIntAsDouble = 0x04000000; // It's definitely not an Int48 but it's a real number and it's a double. 70 static const SpeculatedType SpecDoubleReal = 0x07000000; // It's definitely a non-NaN double. 71 static const SpeculatedType SpecDoubleNaN = 0x08000000; // It's definitely a NaN. 72 static const SpeculatedType SpecDouble = 0x0f000000; // It's either a non-NaN or a NaN double. 73 static const SpeculatedType SpecRealNumber = 0x07800000; // It's either an Int32 or a DoubleReal. 74 static const SpeculatedType SpecNumber = 0x0f800000; // It's either an Int32 or a Double. 75 static const SpeculatedType SpecBoolean = 0x10000000; // It's definitely a Boolean. 76 static const SpeculatedType SpecOther = 0x20000000; // It's definitely none of the above. 77 static const SpeculatedType SpecHeapTop = 0x3fffffff; // It can be any of the above. 78 static const SpeculatedType SpecEmpty = 0x40000000; // It's definitely an empty value marker. 79 static const SpeculatedType SpecBytecodeTop = 0x7fffffff; // It can be any of the above. 80 static const SpeculatedType SpecFullTop = 0x7fffffff; // It can be any of the above plus anything the DFG chooses. 41 static const SpeculatedType SpecNone = 0x00000000; // We don't know anything yet. 42 static const SpeculatedType SpecFinalObject = 0x00000001; // It's definitely a JSFinalObject. 43 static const SpeculatedType SpecArray = 0x00000002; // It's definitely a JSArray. 44 static const SpeculatedType SpecFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. 45 static const SpeculatedType SpecInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. 46 static const SpeculatedType SpecInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. 47 static const SpeculatedType SpecInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses. 48 static const SpeculatedType SpecUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses. 49 static const SpeculatedType SpecUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses. 50 static const SpeculatedType SpecUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses. 51 static const SpeculatedType SpecUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses. 52 static const SpeculatedType SpecFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. 53 static const SpeculatedType SpecFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses. 54 static const SpeculatedType SpecTypedArrayView = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array; 55 static const SpeculatedType SpecArguments = 0x00002000; // It's definitely an Arguments object. 56 static const SpeculatedType SpecStringObject = 0x00004000; // It's definitely a StringObject. 57 static const SpeculatedType SpecObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. 58 static const SpeculatedType SpecObject = 0x0000ffff; // Bitmask used for testing for any kind of object prediction. 59 static const SpeculatedType SpecStringIdent = 0x00010000; // It's definitely a JSString, and it's an identifier. 60 static const SpeculatedType SpecStringVar = 0x00020000; // It's definitely a JSString, and it's not an identifier. 61 static const SpeculatedType SpecString = 0x00030000; // It's definitely a JSString. 62 static const SpeculatedType SpecCellOther = 0x00040000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. 63 static const SpeculatedType SpecCell = 0x0007ffff; // It's definitely a JSCell. 64 static const SpeculatedType SpecInt32 = 0x00800000; // It's definitely an Int32. 65 static const SpeculatedType SpecInt52 = 0x01000000; // It's definitely an Int52 and we intend it to unbox it. 66 static const SpeculatedType SpecMachineInt = 0x01800000; // It's something that we can do machine int arithmetic on. 67 static const SpeculatedType SpecInt52AsDouble = 0x02000000; // It's definitely an Int52 and it's inside a double. 68 static const SpeculatedType SpecInteger = 0x03800000; // It's definitely some kind of integer. 69 static const SpeculatedType SpecNonIntAsDouble = 0x04000000; // It's definitely not an Int52 but it's a real number and it's a double. 70 static const SpeculatedType SpecDoubleReal = 0x06000000; // It's definitely a non-NaN double. 71 static const SpeculatedType SpecDoubleNaN = 0x08000000; // It's definitely a NaN. 72 static const SpeculatedType SpecDouble = 0x0e000000; // It's either a non-NaN or a NaN double. 73 static const SpeculatedType SpecBytecodeRealNumber = 0x06800000; // It's either an Int32 or a DoubleReal. 74 static const SpeculatedType SpecFullRealNumber = 0x07800000; // It's either an Int32 or a DoubleReal, or a Int52. 75 static const SpeculatedType SpecBytecodeNumber = 0x0e800000; // It's either an Int32 or a Double. 76 static const SpeculatedType SpecFullNumber = 0x0f800000; // It's either an Int32, Int52, or a Double. 77 static const SpeculatedType SpecBoolean = 0x10000000; // It's definitely a Boolean. 78 static const SpeculatedType SpecOther = 0x20000000; // It's definitely none of the above. 79 static const SpeculatedType SpecHeapTop = 0x3effffff; // It can be any of the above, except for SpecInt52. 80 static const SpeculatedType SpecEmpty = 0x40000000; // It's definitely an empty value marker. 81 static const SpeculatedType SpecBytecodeTop = 0x7effffff; // It can be any of the above, except for SpecInt52. 82 static const SpeculatedType SpecFullTop = 0x7fffffff; // It can be any of the above plus anything the DFG chooses. 81 83 82 84 typedef bool (*SpeculatedTypeChecker)(SpeculatedType); … … 241 243 inline bool isInt32SpeculationForArithmetic(SpeculatedType value) 242 244 { 245 return !(value & (SpecDouble | SpecInt52)); 246 } 247 248 inline bool isInt32SpeculationExpectingDefined(SpeculatedType value) 249 { 250 return isInt32Speculation(value & ~SpecOther); 251 } 252 253 inline bool isInt52Speculation(SpeculatedType value) 254 { 255 return value == SpecInt52; 256 } 257 258 inline bool isMachineIntSpeculation(SpeculatedType value) 259 { 260 return !!value && (value & SpecMachineInt) == value; 261 } 262 263 inline bool isMachineIntSpeculationExpectingDefined(SpeculatedType value) 264 { 265 return isMachineIntSpeculation(value & ~SpecOther); 266 } 267 268 inline bool isMachineIntSpeculationForArithmetic(SpeculatedType value) 269 { 243 270 return !(value & SpecDouble); 244 271 } 245 272 246 inline bool isInt32SpeculationExpectingDefined(SpeculatedType value) 247 { 248 return isInt32Speculation(value & ~SpecOther); 249 } 250 251 inline bool isInt48Speculation(SpeculatedType value) 252 { 253 return value == SpecInt48; 254 } 255 256 inline bool isMachineIntSpeculation(SpeculatedType value) 257 { 258 return !!value && (value & SpecMachineInt) == value; 259 } 260 261 inline bool isMachineIntSpeculationExpectingDefined(SpeculatedType value) 262 { 263 return isMachineIntSpeculation(value & ~SpecOther); 264 } 265 266 inline bool isMachineIntSpeculationForArithmetic(SpeculatedType value) 267 { 268 return !(value & (SpecDouble & ~SpecMachineInt)); 269 } 270 271 inline bool isInt48AsDoubleSpeculation(SpeculatedType value) 272 { 273 return value == SpecInt48AsDouble; 273 inline bool isInt52AsDoubleSpeculation(SpeculatedType value) 274 { 275 return value == SpecInt52AsDouble; 274 276 } 275 277 … … 294 296 } 295 297 296 inline bool isRealNumberSpeculation(SpeculatedType value) 297 { 298 return !!(value & SpecRealNumber) && !(value & ~SpecRealNumber); 299 } 300 301 inline bool isNumberSpeculation(SpeculatedType value) 302 { 303 return !!(value & SpecNumber) && !(value & ~SpecNumber); 304 } 305 306 inline bool isNumberSpeculationExpectingDefined(SpeculatedType value) 307 { 308 return isNumberSpeculation(value & ~SpecOther); 298 inline bool isBytecodeRealNumberSpeculation(SpeculatedType value) 299 { 300 return !!(value & SpecBytecodeRealNumber) && !(value & ~SpecBytecodeRealNumber); 301 } 302 303 inline bool isFullRealNumberSpeculation(SpeculatedType value) 304 { 305 return !!(value & SpecFullRealNumber) && !(value & ~SpecFullRealNumber); 306 } 307 308 inline bool isBytecodeNumberSpeculation(SpeculatedType value) 309 { 310 return !!(value & SpecBytecodeNumber) && !(value & ~SpecBytecodeNumber); 311 } 312 313 inline bool isFullNumberSpeculation(SpeculatedType value) 314 { 315 return !!(value & SpecFullNumber) && !(value & ~SpecFullNumber); 316 } 317 318 inline bool isBytecodeNumberSpeculationExpectingDefined(SpeculatedType value) 319 { 320 return isBytecodeNumberSpeculation(value & ~SpecOther); 321 } 322 323 inline bool isFullNumberSpeculationExpectingDefined(SpeculatedType value) 324 { 325 return isFullNumberSpeculation(value & ~SpecOther); 309 326 } 310 327 -
trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h
r155820 r156019 45 45 // It's already in the stack but unboxed. 46 46 AlreadyInJSStackAsUnboxedInt32, 47 AlreadyInJSStackAsUnboxedInt52, 47 48 AlreadyInJSStackAsUnboxedCell, 48 49 AlreadyInJSStackAsUnboxedBoolean, … … 51 52 InGPR, 52 53 UnboxedInt32InGPR, 54 UnboxedInt52InGPR, 55 UnboxedStrictInt52InGPR, 53 56 UnboxedBooleanInGPR, 54 57 #if USE(JSVALUE32_64) … … 61 64 // It's in the stack, at a different location, and it's unboxed. 62 65 Int32DisplacedInJSStack, 66 Int52DisplacedInJSStack, 67 StrictInt52DisplacedInJSStack, 63 68 DoubleDisplacedInJSStack, 64 69 CellDisplacedInJSStack, … … 96 101 } 97 102 103 static ValueRecovery alreadyInJSStackAsUnboxedInt52() 104 { 105 ValueRecovery result; 106 result.m_technique = AlreadyInJSStackAsUnboxedInt52; 107 return result; 108 } 109 98 110 static ValueRecovery alreadyInJSStackAsUnboxedCell() 99 111 { … … 126 138 if (dataFormat == DataFormatInt32) 127 139 result.m_technique = UnboxedInt32InGPR; 140 else if (dataFormat == DataFormatInt52) 141 result.m_technique = UnboxedInt52InGPR; 142 else if (dataFormat == DataFormatStrictInt52) 143 result.m_technique = UnboxedStrictInt52InGPR; 128 144 else if (dataFormat == DataFormatBoolean) 129 145 result.m_technique = UnboxedBooleanInGPR; … … 169 185 break; 170 186 187 case DataFormatInt52: 188 result.m_technique = Int52DisplacedInJSStack; 189 break; 190 191 case DataFormatStrictInt52: 192 result.m_technique = StrictInt52DisplacedInJSStack; 193 break; 194 171 195 case DataFormatDouble: 172 196 result.m_technique = DoubleDisplacedInJSStack; … … 230 254 case AlreadyInJSStack: 231 255 case AlreadyInJSStackAsUnboxedInt32: 256 case AlreadyInJSStackAsUnboxedInt52: 232 257 case AlreadyInJSStackAsUnboxedCell: 233 258 case AlreadyInJSStackAsUnboxedBoolean: … … 241 266 MacroAssembler::RegisterID gpr() const 242 267 { 243 ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR );268 ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR); 244 269 return m_source.gpr; 245 270 } … … 267 292 VirtualRegister virtualRegister() const 268 293 { 269 ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack );294 ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack); 270 295 return m_source.virtualReg; 271 296 } … … 286 311 out.printf("(int32)"); 287 312 return; 313 case AlreadyInJSStackAsUnboxedInt52: 314 out.printf("(int52)"); 315 return; 288 316 case AlreadyInJSStackAsUnboxedCell: 289 317 out.printf("(cell)"); … … 301 329 out.printf("int32(%%r%d)", gpr()); 302 330 return; 331 case UnboxedInt52InGPR: 332 out.printf("int52(%%r%d)", gpr()); 333 return; 334 case UnboxedStrictInt52InGPR: 335 out.printf("strictInt52(%%r%d)", gpr()); 336 return; 303 337 case UnboxedBooleanInGPR: 304 338 out.printf("bool(%%r%d)", gpr()); … … 320 354 case Int32DisplacedInJSStack: 321 355 out.printf("*int32(%d)", virtualRegister()); 356 return; 357 case Int52DisplacedInJSStack: 358 out.printf("*int52(%d)", virtualRegister()); 359 return; 360 case StrictInt52DisplacedInJSStack: 361 out.printf("*strictInt52(%d)", virtualRegister()); 322 362 return; 323 363 case DoubleDisplacedInJSStack: -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r155567 r156019 61 61 bool needsTypeCheck(Node* node, SpeculatedType typesPassedThrough) 62 62 { 63 return forNode(node).m_type & ~typesPassedThrough;63 return !forNode(node).isType(typesPassedThrough); 64 64 } 65 65 … … 169 169 { 170 170 AbstractValue& value = forNode(edge); 171 if ( value.m_type & ~type) {171 if (!value.isType(type)) { 172 172 node->setCanExit(true); 173 173 edge.setProofStatus(NeedsCheck); -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r155730 r156019 311 311 } 312 312 313 case Int52ToDouble: { 314 JSValue child = forNode(node->child1()).value(); 315 if (child && child.isNumber()) { 316 setConstant(node, child); 317 break; 318 } 319 forNode(node).setType(SpecDouble); 320 break; 321 } 322 323 case Int52ToValue: { 324 JSValue child = forNode(node->child1()).value(); 325 if (child && child.isNumber()) { 326 setConstant(node, child); 327 break; 328 } 329 SpeculatedType type = forNode(node->child1()).m_type; 330 if (type & SpecInt52) 331 type = (type | SpecInt32 | SpecInt52AsDouble) & ~SpecInt52; 332 forNode(node).setType(type); 333 break; 334 } 335 313 336 case ValueAdd: 314 337 case ArithAdd: { … … 325 348 node->setCanExit(true); 326 349 break; 350 case MachineIntUse: 351 forNode(node).setType(SpecInt52); 352 if (!forNode(node->child1()).isType(SpecInt32) 353 || !forNode(node->child2()).isType(SpecInt32)) 354 node->setCanExit(true); 355 break; 327 356 case NumberUse: 328 if (is RealNumberSpeculation(forNode(node->child1()).m_type)329 && is RealNumberSpeculation(forNode(node->child2()).m_type))357 if (isFullRealNumberSpeculation(forNode(node->child1()).m_type) 358 && isFullRealNumberSpeculation(forNode(node->child2()).m_type)) 330 359 forNode(node).setType(SpecDoubleReal); 331 360 else … … 335 364 RELEASE_ASSERT(node->op() == ValueAdd); 336 365 clobberWorld(node->codeOrigin, clobberLimit); 337 forNode(node).setType(SpecString | Spec Int32 | SpecNumber);366 forNode(node).setType(SpecString | SpecBytecodeNumber); 338 367 break; 339 368 } … … 359 388 node->setCanExit(true); 360 389 break; 390 case MachineIntUse: 391 forNode(node).setType(SpecInt52); 392 if (!forNode(node->child1()).isType(SpecInt32) 393 || !forNode(node->child2()).isType(SpecInt32)) 394 node->setCanExit(true); 395 break; 361 396 case NumberUse: 362 397 forNode(node).setType(SpecDouble); … … 379 414 forNode(node).setType(SpecInt32); 380 415 if (!bytecodeCanTruncateInteger(node->arithNodeFlags())) 416 node->setCanExit(true); 417 break; 418 case MachineIntUse: 419 forNode(node).setType(SpecInt52); 420 if (m_state.forNode(node->child1()).couldBeType(SpecInt52)) 421 node->setCanExit(true); 422 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 381 423 node->setCanExit(true); 382 424 break; … … 405 447 node->setCanExit(true); 406 448 break; 449 case MachineIntUse: 450 forNode(node).setType(SpecInt52); 451 node->setCanExit(true); 452 break; 407 453 case NumberUse: 408 if (is RealNumberSpeculation(forNode(node->child1()).m_type)409 || is RealNumberSpeculation(forNode(node->child2()).m_type))454 if (isFullRealNumberSpeculation(forNode(node->child1()).m_type) 455 || isFullRealNumberSpeculation(forNode(node->child2()).m_type)) 410 456 forNode(node).setType(SpecDoubleReal); 411 457 else … … 587 633 } 588 634 589 if (is NumberSpeculation(abstractChild.m_type)) {635 if (isFullNumberSpeculation(abstractChild.m_type)) { 590 636 setConstant(node, vm->smallStrings.numberString()); 591 637 break; … … 812 858 if (node->shouldSpeculateInt32()) 813 859 forNode(node).setType(SpecInt32); 860 else if (enableInt52() && node->shouldSpeculateMachineInt()) 861 forNode(node).setType(SpecInt52); 814 862 else 815 863 forNode(node).setType(SpecDouble); … … 864 912 node->setCanExit(true); 865 913 clobberWorld(node->codeOrigin, clobberLimit); 866 forNode(node).setType(Spec Number);914 forNode(node).setType(SpecBytecodeNumber); 867 915 break; 868 916 … … 935 983 // 936 984 // destination = source; 937 // if (destination.m_type & !(Spec Number | SpecString | SpecBoolean)) {938 // destination.filter(Spec Number | SpecString | SpecBoolean);985 // if (destination.m_type & !(SpecFullNumber | SpecString | SpecBoolean)) { 986 // destination.filter(SpecFullNumber | SpecString | SpecBoolean); 939 987 // AbstractValue string; 940 988 // string.set(vm->stringStructure); … … 956 1004 957 1005 SpeculatedType type = source.m_type; 958 if (type & ~(Spec Number | SpecString | SpecBoolean))1006 if (type & ~(SpecFullNumber | SpecString | SpecBoolean)) 959 1007 type = (SpecHeapTop & ~SpecCell) | SpecString; 960 1008 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r155480 r156019 68 68 69 69 m_type = speculationFromValue(value); 70 if (m_type == SpecInt52AsDouble) 71 m_type = SpecInt52; 70 72 m_value = value; 71 73 … … 228 230 } 229 231 232 #if !ASSERT_DISABLED 230 233 void AbstractValue::checkConsistency() const 231 234 { … … 239 242 ASSERT(!m_value); 240 243 241 if (!!m_value) 242 ASSERT(mergeSpeculations(m_type, speculationFromValue(m_value)) == m_type); 244 if (!!m_value) { 245 SpeculatedType type = m_type; 246 if (type & SpecInt52) 247 type |= SpecInt52AsDouble; 248 ASSERT(mergeSpeculations(type, speculationFromValue(m_value)) == type); 249 } 243 250 244 251 // Note that it's possible for a prediction like (Final, []). This really means that … … 247 254 // complexity of the code. 248 255 } 256 #endif 249 257 250 258 void AbstractValue::dump(PrintStream& out) const -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r155480 r156019 186 186 } 187 187 188 bool couldBeType(SpeculatedType desiredType) 189 { 190 return !!(m_type & desiredType); 191 } 192 193 bool isType(SpeculatedType desiredType) 194 { 195 return !(m_type & ~desiredType); 196 } 197 188 198 FiltrationResult filter(Graph&, const StructureSet&); 189 199 … … 193 203 194 204 FiltrationResult filterByValue(JSValue value); 195 196 bool validateType(JSValue value) const197 {198 if (isHeapTop())199 return true;200 201 if (mergeSpeculations(m_type, speculationFromValue(value)) != m_type)202 return false;203 204 if (value.isEmpty()) {205 ASSERT(m_type & SpecEmpty);206 return true;207 }208 209 return true;210 }211 205 212 206 bool validate(JSValue value) const … … 252 246 } 253 247 248 #if ASSERT_DISABLED 249 void checkConsistency() const { } 250 #else 254 251 void checkConsistency() const; 252 #endif 255 253 256 254 void dumpInContext(PrintStream&, DumpContext*) const; … … 364 362 } 365 363 364 bool validateType(JSValue value) const 365 { 366 if (isHeapTop()) 367 return true; 368 369 // Constant folding always represents Int52's in a double (i.e. Int52AsDouble). 370 // So speculationFromValue(value) for an Int52 value will return Int52AsDouble, 371 // and that's fine - the type validates just fine. 372 SpeculatedType type = m_type; 373 if (type & SpecInt52) 374 type |= SpecInt52AsDouble; 375 376 if (mergeSpeculations(type, speculationFromValue(value)) != type) 377 return false; 378 379 if (value.isEmpty()) { 380 ASSERT(m_type & SpecEmpty); 381 return true; 382 } 383 384 return true; 385 } 386 366 387 void makeTop(SpeculatedType top) 367 388 { -
trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp
r156017 r156019 164 164 if (isInt32Speculation(value)) 165 165 return withTypeAndConversion(Array::Int32, Array::Convert); 166 if (is NumberSpeculation(value))166 if (isFullNumberSpeculation(value)) 167 167 return withTypeAndConversion(Array::Double, Array::Convert); 168 168 return withTypeAndConversion(Array::Contiguous, Array::Convert); … … 171 171 if (!value || isInt32Speculation(value)) 172 172 return *this; 173 if (is NumberSpeculation(value))173 if (isFullNumberSpeculation(value)) 174 174 return withTypeAndConversion(Array::Double, Array::Convert); 175 175 return withTypeAndConversion(Array::Contiguous, Array::Convert); … … 178 178 if (flags & NodeBytecodeUsesAsInt) 179 179 return withTypeAndConversion(Array::Contiguous, Array::RageConvert); 180 if (!value || is NumberSpeculation(value))180 if (!value || isFullNumberSpeculation(value)) 181 181 return *this; 182 182 return withTypeAndConversion(Array::Contiguous, Array::Convert); -
trunk/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h
r154797 r156019 294 294 return fpr; 295 295 } 296 297 void boxInt52(GPRReg source, GPRReg target, GPRReg scratch, FPRReg fpScratch) 298 { 299 // Is it an int32? 300 signExtend32ToPtr(source, scratch); 301 Jump isInt32 = branch64(Equal, source, scratch); 302 303 // Nope, it's not, but regT0 contains the int64 value. 304 convertInt64ToDouble(source, fpScratch); 305 boxDouble(fpScratch, target); 306 Jump done = jump(); 307 308 isInt32.link(this); 309 zeroExtend32ToPtr(source, target); 310 or64(GPRInfo::tagTypeNumberRegister, target); 311 312 done.link(this); 313 } 296 314 #endif 297 315 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r156003 r156019 875 875 case ArithAdd: 876 876 case ArithSub: 877 case ArithNegate:878 877 case ValueAdd: 879 878 case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. … … 881 880 break; 882 881 882 case ArithNegate: 883 // Currently we can't tell the difference between a negation overflowing 884 // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow 885 // path then we assume that it did both of those things. 886 node->mergeFlags(NodeMayOverflow); 887 node->mergeFlags(NodeMayNegZero); 888 break; 889 883 890 case ArithMul: 884 891 if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex) -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r155564 r156019 64 64 private: 65 65 66 Node* canonicalize(Node* node)67 {68 if (!node)69 return 0;70 71 if (node->op() == ValueToInt32)72 node = node->child1().node();73 74 return node;75 }76 Node* canonicalize(Edge edge)77 {78 return canonicalize(edge.node());79 }80 81 66 unsigned endIndexForPureCSE() 82 67 { … … 95 80 Node* pureCSE(Node* node) 96 81 { 97 Node* child1 = canonicalize(node->child1());98 Node* child2 = canonicalize(node->child2());99 Node* child3 = canonicalize(node->child3());82 Edge child1 = node->child1(); 83 Edge child2 = node->child2(); 84 Edge child3 = node->child3(); 100 85 101 86 for (unsigned i = endIndexForPureCSE(); i--;) { … … 110 95 continue; 111 96 112 Node* otherChild = canonicalize(otherNode->child1());97 Edge otherChild = otherNode->child1(); 113 98 if (!otherChild) 114 99 return otherNode; … … 116 101 continue; 117 102 118 otherChild = canonicalize(otherNode->child2());103 otherChild = otherNode->child2(); 119 104 if (!otherChild) 120 105 return otherNode; … … 122 107 continue; 123 108 124 otherChild = canonicalize(otherNode->child3());109 otherChild = otherNode->child3(); 125 110 if (!otherChild) 126 111 return otherNode; … … 378 363 for (unsigned i = m_indexInBlock; i--;) { 379 364 Node* node = m_currentBlock->at(i); 380 if (node == child1 || node == c anonicalize(child2))365 if (node == child1 || node == child2) 381 366 break; 382 367 … … 385 370 if (!m_graph.byValIsPure(node)) 386 371 return 0; 387 if (node->child1() == child1 && canonicalize(node->child2()) == canonicalize(child2))372 if (node->child1() == child1 && node->child2() == child2) 388 373 return node; 389 374 break; … … 392 377 if (!m_graph.byValIsPure(node)) 393 378 return 0; 394 if (m_graph.varArgChild(node, 0) == child1 && canonicalize(m_graph.varArgChild(node, 1)) == canonicalize(child2))379 if (m_graph.varArgChild(node, 0) == child1 && m_graph.varArgChild(node, 1) == child2) 395 380 return m_graph.varArgChild(node, 2).node(); 396 381 // We must assume that the PutByVal will clobber the location we're getting from. … … 1091 1076 case ValueToInt32: 1092 1077 case MakeRope: 1078 case Int52ToDouble: 1079 case Int52ToValue: 1093 1080 if (cseMode == StoreElimination) 1094 1081 break; -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r155023 r156019 113 113 case Int32ToDouble: 114 114 case ExtractOSREntryLocal: 115 case Int52ToDouble: 116 case Int52ToValue: 115 117 return; 116 118 … … 181 183 case Int32Use: 182 184 case NumberUse: 185 case MachineIntUse: 183 186 return; 184 187 case UntypedUse: -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r153296 r156019 139 139 #if ENABLE(CONCURRENT_JIT) 140 140 return Options::enableConcurrentJIT() && Options::numberOfCompilerThreads(); 141 #else 142 return false; 143 #endif 144 } 145 146 inline bool enableInt52() 147 { 148 #if USE(JSVALUE64) 149 return true; 141 150 #else 142 151 return false; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r155593 r156019 65 65 } 66 66 67 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) 68 fixupUntypedSetLocalsInBlock(m_graph.block(blockIndex)); 69 67 70 return true; 68 71 } … … 93 96 case SetLocal: { 94 97 // This gets handled by fixupSetLocalsInBlock(). 95 break;98 return; 96 99 } 97 100 … … 125 128 } 126 129 130 if (node->child1()->shouldSpeculateMachineInt()) { 131 fixEdge<MachineIntUse>(node->child1()); 132 break; 133 } 134 127 135 if (node->child1()->shouldSpeculateNumber()) { 128 136 fixEdge<NumberUse>(node->child1()); … … 198 206 break; 199 207 } 208 if (m_graph.negateShouldSpeculateMachineInt(node)) { 209 fixEdge<MachineIntUse>(node->child1()); 210 break; 211 } 200 212 fixEdge<NumberUse>(node->child1()); 201 213 break; … … 206 218 fixEdge<Int32Use>(node->child1()); 207 219 fixEdge<Int32Use>(node->child2()); 220 break; 221 } 222 if (m_graph.mulShouldSpeculateMachineInt(node)) { 223 fixEdge<MachineIntUse>(node->child1()); 224 fixEdge<MachineIntUse>(node->child2()); 208 225 break; 209 226 } … … 301 318 break; 302 319 } 320 if (enableInt52() 321 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) { 322 fixEdge<MachineIntUse>(node->child1()); 323 fixEdge<MachineIntUse>(node->child2()); 324 break; 325 } 303 326 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) { 304 327 fixEdge<NumberUse>(node->child1()); … … 354 377 fixEdge<Int32Use>(node->child1()); 355 378 fixEdge<Int32Use>(node->child2()); 379 break; 380 } 381 if (enableInt52() 382 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) { 383 fixEdge<MachineIntUse>(node->child1()); 384 fixEdge<MachineIntUse>(node->child2()); 356 385 break; 357 386 } … … 477 506 fixEdge<Int32Use>(child2); 478 507 fixEdge<Int32Use>(child3); 508 if (child3->prediction() & SpecInt52) 509 fixEdge<MachineIntUse>(child3); 510 else 511 fixEdge<Int32Use>(child3); 479 512 break; 480 513 case Array::Double: … … 494 527 if (child3->shouldSpeculateInt32()) 495 528 fixEdge<Int32Use>(child3); 529 else if (child3->shouldSpeculateMachineInt()) 530 fixEdge<MachineIntUse>(child3); 496 531 else 497 532 fixEdge<NumberUse>(child3); … … 848 883 case CheckTierUpAtReturn: 849 884 case CheckTierUpAndOSREnter: 885 case Int52ToDouble: 886 case Int52ToValue: 850 887 RELEASE_ASSERT_NOT_REACHED(); 851 888 break; … … 1190 1227 fixEdge<Int32Use>(node->child1()); 1191 1228 break; 1229 case FlushedInt52: 1230 fixEdge<MachineIntUse>(node->child1()); 1231 break; 1192 1232 case FlushedCell: 1193 1233 fixEdge<CellUse>(node->child1()); … … 1200 1240 break; 1201 1241 } 1242 } 1243 m_insertionSet.execute(block); 1244 } 1245 1246 void fixupUntypedSetLocalsInBlock(BasicBlock* block) 1247 { 1248 if (!block) 1249 return; 1250 ASSERT(block->isReachable); 1251 m_block = block; 1252 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { 1253 Node* node = m_currentNode = block->at(m_indexInBlock); 1254 if (node->op() != SetLocal) 1255 continue; 1256 1257 if (node->child1().useKind() == UntypedUse) 1258 fixEdge<UntypedUse>(node->child1()); 1202 1259 } 1203 1260 m_insertionSet.execute(block); … … 1305 1362 return; 1306 1363 1364 // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious. 1365 // https://bugs.webkit.org/show_bug.cgi?id=121518 1366 1307 1367 VariableAccessData* variable = node->variableAccessData(); 1308 1368 switch (useKind) { … … 1320 1380 if (alwaysUnboxSimplePrimitives() 1321 1381 || isBooleanSpeculation(variable->prediction())) 1382 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); 1383 break; 1384 case MachineIntUse: 1385 if (isMachineIntSpeculation(variable->prediction())) 1322 1386 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); 1323 1387 break; … … 1348 1412 void fixEdge(Edge& edge, SpeculationDirection direction = BackwardSpeculation) 1349 1413 { 1350 if (isDouble(useKind) && edge->shouldSpeculateInt32ForArithmetic()) { 1351 injectInt32ToDoubleNode(edge, useKind, direction); 1414 if (isDouble(useKind)) { 1415 if (edge->shouldSpeculateInt32ForArithmetic()) { 1416 injectInt32ToDoubleNode(edge, useKind, direction); 1417 return; 1418 } 1419 1420 if (enableInt52() && edge->shouldSpeculateMachineInt()) { 1421 // Make all double uses of int52 values have an intermediate Int52ToDouble. 1422 // This is for the same reason as Int52ToValue (see below) except that 1423 // Int8ToDouble will convert int52's that fit in an int32 into a double 1424 // rather than trying to create a boxed int32 like Int52ToValue does. 1425 1426 Node* result = m_insertionSet.insertNode( 1427 m_indexInBlock, SpecInt52AsDouble, Int52ToDouble, 1428 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); 1429 edge = Edge(result, useKind); 1430 return; 1431 } 1432 } 1433 1434 if (enableInt52() && useKind != MachineIntUse 1435 && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) { 1436 // We make all non-int52 uses of int52 values have an intermediate Int52ToValue 1437 // node to ensure that we handle this properly: 1438 // 1439 // a: SomeInt52 1440 // b: ArithAdd(@a, ...) 1441 // c: Call(..., @a) 1442 // d: ArithAdd(@a, ...) 1443 // 1444 // Without an intermediate node and just labeling the uses, we will get: 1445 // 1446 // a: SomeInt52 1447 // b: ArithAdd(Int52:@a, ...) 1448 // c: Call(..., Untyped:@a) 1449 // d: ArithAdd(Int52:@a, ...) 1450 // 1451 // And now the c->Untyped:@a edge will box the value of @a into a double. This 1452 // is bad, because now the d->Int52:@a edge will either have to do double-to-int 1453 // conversions, or will have to OSR exit unconditionally. Alternatively we could 1454 // have the c->Untyped:@a edge box the value by copying rather than in-place. 1455 // But these boxings are also costly so this wouldn't be great. 1456 // 1457 // The solution we use is to always have non-Int52 uses of predicted Int52's use 1458 // an intervening Int52ToValue node: 1459 // 1460 // a: SomeInt52 1461 // b: ArithAdd(Int52:@a, ...) 1462 // x: Int52ToValue(Int52:@a) 1463 // c: Call(..., Untyped:@x) 1464 // d: ArithAdd(Int52:@a, ...) 1465 // 1466 // Note that even if we had multiple non-int52 uses of @a, the multiple 1467 // Int52ToValue's would get CSE'd together. So the boxing would only happen once. 1468 // At the same time, @a would continue to be represented as a native int52. 1469 // 1470 // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of 1471 // int52's. This would have handled the above example but would fall over for: 1472 // 1473 // a: SomeInt52 1474 // b: Call(..., @a) 1475 // c: ArithAdd(@a, ...) 1476 // 1477 // But the solution we use handles the above gracefully. 1478 1479 Node* result = m_insertionSet.insertNode( 1480 m_indexInBlock, SpecInt52, Int52ToValue, 1481 m_currentNode->codeOrigin, Edge(edge.node(), UntypedUse)); 1482 edge = Edge(result, useKind); 1352 1483 return; 1353 1484 } 1354 1485 1355 1486 observeUseKindOnNode<useKind>(edge.node()); 1487 1356 1488 edge.setUseKind(useKind); 1357 1489 } … … 1379 1511 { 1380 1512 Node* result = m_insertionSet.insertNode( 1381 m_indexInBlock, SpecInt 48, Int32ToDouble,1513 m_indexInBlock, SpecInt52AsDouble, Int32ToDouble, 1382 1514 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); 1383 1515 if (direction == ForwardSpeculation) … … 1435 1567 { 1436 1568 AddSpeculationMode mode = m_graph.addSpeculationMode(node); 1437 if (mode == DontSpeculateInt32) 1438 return false; 1439 1440 truncateConstantsIfNecessary(node, mode); 1441 fixEdge<Int32Use>(node->child1()); 1442 fixEdge<Int32Use>(node->child2()); 1443 return true; 1569 if (mode != DontSpeculateInt32) { 1570 truncateConstantsIfNecessary(node, mode); 1571 fixEdge<Int32Use>(node->child1()); 1572 fixEdge<Int32Use>(node->child2()); 1573 return true; 1574 } 1575 1576 if (m_graph.addShouldSpeculateMachineInt(node)) { 1577 fixEdge<MachineIntUse>(node->child1()); 1578 fixEdge<MachineIntUse>(node->child2()); 1579 return true; 1580 } 1581 1582 return false; 1444 1583 } 1445 1584 -
trunk/Source/JavaScriptCore/dfg/DFGFlushFormat.cpp
r153274 r156019 42 42 out.print("FlushedInt32"); 43 43 return; 44 case FlushedInt52: 45 out.print("FlushedInt52"); 46 return; 44 47 case FlushedDouble: 45 48 out.print("FlushedDouble"); -
trunk/Source/JavaScriptCore/dfg/DFGFlushFormat.h
r153296 r156019 41 41 DeadFlush, 42 42 FlushedInt32, 43 FlushedInt52, 43 44 FlushedDouble, 44 45 FlushedCell, … … 56 57 case FlushedInt32: 57 58 return NodeResultInt32; 59 case FlushedInt52: 60 return NodeResultInt52; 58 61 case FlushedDouble: 59 62 return NodeResultNumber; … … 75 78 case FlushedInt32: 76 79 return Int32Use; 80 case FlushedInt52: 81 return MachineIntUse; 77 82 case FlushedDouble: 78 83 return NumberUse; -
trunk/Source/JavaScriptCore/dfg/DFGGenerationInfo.h
r155645 r156019 87 87 initGPR(node, useCount, gpr, DataFormatInt32); 88 88 } 89 void initInt52(Node* node, uint32_t useCount, GPRReg reg, DataFormat format) 90 { 91 ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52); 92 initGPR(node, useCount, reg, format); 93 } 94 void initInt52(Node* node, uint32_t useCount, GPRReg reg) 95 { 96 initGPR(node, useCount, reg, DataFormatInt52); 97 } 98 void initStrictInt52(Node* node, uint32_t useCount, GPRReg reg) 99 { 100 initGPR(node, useCount, reg, DataFormatStrictInt52); 101 } 89 102 #if USE(JSVALUE64) 90 103 void initJSValue(Node* node, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS) … … 188 201 DataFormat spillFormat() { return m_spillFormat; } 189 202 203 bool isFormat(DataFormat expectedFormat) 204 { 205 return registerFormat() == expectedFormat || spillFormat() == expectedFormat; 206 } 207 190 208 bool isJSFormat(DataFormat expectedFormat) 191 209 { … … 196 214 { 197 215 return isJSFormat(DataFormatJSInt32); 216 } 217 218 bool isInt52() 219 { 220 return isFormat(DataFormatInt52); 221 } 222 223 bool isStrictInt52() 224 { 225 return isFormat(DataFormatStrictInt52); 198 226 } 199 227 … … 314 342 { 315 343 fillGPR(stream, gpr, DataFormatInt32); 344 } 345 void fillInt52(VariableEventStream& stream, GPRReg gpr, DataFormat format) 346 { 347 ASSERT(format == DataFormatInt52 || format == DataFormatStrictInt52); 348 fillGPR(stream, gpr, format); 349 } 350 void fillInt52(VariableEventStream& stream, GPRReg gpr) 351 { 352 fillGPR(stream, gpr, DataFormatInt52); 353 } 354 void fillStrictInt52(VariableEventStream& stream, GPRReg gpr) 355 { 356 fillGPR(stream, gpr, DataFormatStrictInt52); 316 357 } 317 358 void fillBoolean(VariableEventStream& stream, GPRReg gpr) -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r155564 r156019 237 237 out.print(comma, "arg", operandToArgument(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")"); 238 238 else 239 out.print(comma, " r", operand, "(", VariableAccessDataDump(*this, variableAccessData), ")");239 out.print(comma, "loc", operandToLocal(operand), "(", VariableAccessDataDump(*this, variableAccessData), ")"); 240 240 } 241 241 if (node->hasUnlinkedLocal()) { … … 244 244 out.print(comma, "arg", operandToArgument(operand)); 245 245 else 246 out.print(comma, " r", operand);246 out.print(comma, "loc", operandToLocal(operand)); 247 247 } 248 248 if (node->hasConstantBuffer()) { -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r155499 r156019 231 231 bool addShouldSpeculateMachineInt(Node* add) 232 232 { 233 if (!enableInt52()) 234 return false; 235 233 236 Node* left = add->child1().node(); 234 237 Node* right = add->child2().node(); … … 236 239 bool speculation; 237 240 if (add->op() == ValueAdd) 238 speculation = Node::shouldSpeculateMachineInt ExpectingDefined(left, right);241 speculation = Node::shouldSpeculateMachineInt(left, right); 239 242 else 240 speculation = Node::shouldSpeculateMachineInt ForArithmetic(left, right);241 242 return speculation && !hasExitSite(add, Int 48Overflow);243 speculation = Node::shouldSpeculateMachineInt(left, right); 244 245 return speculation && !hasExitSite(add, Int52Overflow); 243 246 } 244 247 … … 258 261 ASSERT(mul->op() == ArithMul); 259 262 263 if (!enableInt52()) 264 return false; 265 260 266 Node* left = mul->child1().node(); 261 267 Node* right = mul->child2().node(); 262 268 263 return Node::shouldSpeculateMachineInt ForArithmetic(left, right)264 && mul->canSpeculateInt 48()265 && !hasExitSite(mul, Int 48Overflow);269 return Node::shouldSpeculateMachineInt(left, right) 270 && mul->canSpeculateInt52() 271 && !hasExitSite(mul, Int52Overflow); 266 272 } 267 273 … … 275 281 { 276 282 ASSERT(negate->op() == ArithNegate); 277 return negate->child1()->shouldSpeculateMachineIntForArithmetic() 278 && !hasExitSite(negate, Int48Overflow) 279 && negate->canSpeculateInt48(); 283 if (!enableInt52()) 284 return false; 285 return negate->child1()->shouldSpeculateMachineInt() 286 && !hasExitSite(negate, Int52Overflow) 287 && negate->canSpeculateInt52(); 280 288 } 281 289 -
trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
r155564 r156019 314 314 source = forNode(node->child1()); 315 315 if (node->variableAccessData()->flushFormat() == FlushedDouble) { 316 ASSERT(!(source.m_type & ~Spec Number));317 ASSERT(!!(source.m_type & ~SpecDouble) == !!(source.m_type & Spec Int32));316 ASSERT(!(source.m_type & ~SpecFullNumber)); 317 ASSERT(!!(source.m_type & ~SpecDouble) == !!(source.m_type & SpecMachineInt)); 318 318 if (!(source.m_type & ~SpecDouble)) { 319 source.merge(SpecInt 48AsDouble);319 source.merge(SpecInt52AsDouble); 320 320 source.filter(SpecDouble); 321 321 } -
trunk/Source/JavaScriptCore/dfg/DFGJITCode.cpp
r155023 r156019 104 104 value = jsNumber(exec->r(operand).unboxedInt32()); 105 105 break; 106 case AlreadyInJSStackAsUnboxedInt52: 107 value = jsNumber(exec->r(operand).unboxedInt52()); 108 break; 106 109 case AlreadyInJSStackAsUnboxedDouble: 107 110 value = jsDoubleNumber(exec->r(operand).unboxedDouble()); -
trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h
r155793 r156019 49 49 case DoubleAsInt32: 50 50 case PhantomArguments: 51 case Int52ToValue: 52 case Int52ToDouble: 51 53 return true; 52 54 default: … … 105 107 case UInt32ToNumber: 106 108 case DoubleAsInt32: 109 case Int52ToDouble: 110 case Int52ToValue: 107 111 return true; 108 112 default: -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r155499 r156019 1242 1242 bool shouldSpeculateNumber() 1243 1243 { 1244 return is NumberSpeculation(prediction());1244 return isFullNumberSpeculation(prediction()); 1245 1245 } 1246 1246 1247 1247 bool shouldSpeculateNumberExpectingDefined() 1248 1248 { 1249 return is NumberSpeculationExpectingDefined(prediction());1249 return isFullNumberSpeculationExpectingDefined(prediction()); 1250 1250 } 1251 1251 … … 1425 1425 } 1426 1426 1427 bool canSpeculateInt 48()1428 { 1429 return nodeCanSpeculateInt 48(arithNodeFlags());1427 bool canSpeculateInt52() 1428 { 1429 return nodeCanSpeculateInt52(arithNodeFlags()); 1430 1430 } 1431 1431 -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h
r155499 r156019 42 42 #define NodeResultNumber 0x0002 43 43 #define NodeResultInt32 0x0003 44 #define NodeResultBoolean 0x0004 45 #define NodeResultStorage 0x0005 44 #define NodeResultInt52 0x0004 45 #define NodeResultBoolean 0x0005 46 #define NodeResultStorage 0x0006 46 47 47 48 #define NodeMustGenerate 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE. … … 108 109 } 109 110 110 static inline bool nodeCanSpeculateInt 48(NodeFlags flags)111 static inline bool nodeCanSpeculateInt52(NodeFlags flags) 111 112 { 112 113 if (nodeMayNegZero(flags)) -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r155793 r156019 115 115 /* Used to speculate that a double value is actually an integer. */\ 116 116 macro(DoubleAsInt32, NodeResultInt32 | NodeExitsForward) \ 117 /* Used to separate representation and register allocation of Int52's represented */\ 118 /* as values. */\ 119 macro(Int52ToValue, NodeResultJS) \ 120 macro(Int52ToDouble, NodeResultNumber) \ 117 121 \ 118 122 /* Nodes for arithmetic operations. */\ … … 357 361 return 25; 358 362 363 case Int52ToValue: 364 // Loses no information. It just boxes the value, which is what OSR wants 365 // to do anyway. 366 return 100; 367 368 case Int52ToDouble: 369 // This is like Int32ToDouble; we can use it because it gives a semantically 370 // equivalent value but that value may be an int32 in a double, so we'd 371 // rather not if we can avoid it. 372 return 75; 373 359 374 default: 360 375 return 0; -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
r155995 r156019 40 40 41 41 namespace JSC { namespace DFG { 42 43 static CString shortOperandsDump(const Operands<ValueRecovery>& operands)44 {45 DumpContext context;46 StringPrintStream out;47 out.print(inContext(operands, &context));48 return out.toCString();49 }50 42 51 43 extern "C" { … … 118 110 exitIndex, toCString(exit.m_codeOrigin).data(), 119 111 exitKindToString(exit.m_kind), toCString(*codeBlock).data(), 120 shortOperandsDump(operands).data()));112 toCString(ignoringContext<DumpContext>(operands)).data())); 121 113 } 122 114 -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
r155820 r156019 196 196 case UnboxedInt32InGPR: 197 197 case UInt32InGPR: 198 case UnboxedInt52InGPR: 199 case UnboxedStrictInt52InGPR: 198 200 m_jit.store64(recovery.gpr(), scratch + index); 199 201 break; … … 236 238 case Int32DisplacedInJSStack: 237 239 case DoubleDisplacedInJSStack: 240 case Int52DisplacedInJSStack: 241 case StrictInt52DisplacedInJSStack: 238 242 m_jit.load64(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0); 239 243 m_jit.store64(GPRInfo::regT0, scratch + index); … … 242 246 case AlreadyInJSStackAsUnboxedInt32: 243 247 case AlreadyInJSStackAsUnboxedDouble: 248 case AlreadyInJSStackAsUnboxedInt52: 244 249 m_jit.load64(AssemblyHelpers::addressFor(operand), GPRInfo::regT0); 245 250 m_jit.store64(GPRInfo::regT0, scratch + index); … … 275 280 break; 276 281 282 case AlreadyInJSStackAsUnboxedInt52: 283 case UnboxedInt52InGPR: 284 case Int52DisplacedInJSStack: 285 m_jit.load64(scratch + index, GPRInfo::regT0); 286 m_jit.rshift64( 287 AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), GPRInfo::regT0); 288 m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0); 289 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand)); 290 break; 291 292 case UnboxedStrictInt52InGPR: 293 case StrictInt52DisplacedInJSStack: 294 m_jit.load64(scratch + index, GPRInfo::regT0); 295 m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0); 296 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand)); 297 break; 298 299 case UInt32InGPR: 300 m_jit.load64(scratch + index, GPRInfo::regT0); 301 m_jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0); 302 m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0); 303 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand)); 304 break; 305 277 306 case AlreadyInJSStackAsUnboxedDouble: 278 307 case InFPR: … … 283 312 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand)); 284 313 break; 285 286 case UInt32InGPR: {287 m_jit.load64(scratch + index, GPRInfo::regT0);288 m_jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0);289 AssemblyHelpers::Jump positive = m_jit.branch32(290 AssemblyHelpers::GreaterThanOrEqual,291 GPRInfo::regT0, AssemblyHelpers::TrustedImm32(0));292 m_jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0);293 m_jit.addDouble(294 AssemblyHelpers::AbsoluteAddress(&AssemblyHelpers::twoToThe32),295 FPRInfo::fpRegT0);296 m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0);297 AssemblyHelpers::Jump done = m_jit.jump();298 positive.link(&m_jit);299 m_jit.or64(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);300 done.link(&m_jit);301 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));302 break;303 }304 314 305 315 case Constant: -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r155499 r156019 117 117 SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value) 118 118 { 119 if (!is NumberSpeculation(value))119 if (!isFullNumberSpeculation(value)) 120 120 return SpecDouble; 121 121 if (value & SpecDoubleNaN) … … 143 143 case WeakJSConstant: { 144 144 SpeculatedType type = speculationFromValue(m_graph.valueOfJSConstant(node)); 145 if (type == SpecInt 48AsDouble)146 type = SpecInt 48;145 if (type == SpecInt52AsDouble) 146 type = SpecInt52; 147 147 changed |= setPrediction(type); 148 148 break; … … 150 150 151 151 case GetLocal: { 152 VariableAccessData* variableAccessData = node->variableAccessData(); 153 SpeculatedType prediction = variableAccessData->prediction(); 152 VariableAccessData* variable = node->variableAccessData(); 153 SpeculatedType prediction = variable->prediction(); 154 if (variable->shouldNeverUnbox() && (prediction & SpecInt52)) 155 prediction = (prediction | SpecInt52AsDouble) & ~SpecInt52; 154 156 if (prediction) 155 157 changed |= mergePrediction(prediction); … … 204 206 changed |= mergePrediction(SpecInt32); 205 207 else 206 changed |= mergePrediction(Spec Number);208 changed |= mergePrediction(SpecBytecodeNumber); 207 209 break; 208 210 } … … 213 215 214 216 if (left && right) { 215 if (is NumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {217 if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right)) { 216 218 if (m_graph.addSpeculationMode(node) != DontSpeculateInt32) 217 219 changed |= mergePrediction(SpecInt32); 218 220 else if (m_graph.addShouldSpeculateMachineInt(node)) 219 changed |= mergePrediction(SpecInt 48);221 changed |= mergePrediction(SpecInt52); 220 222 else 221 223 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 222 } else if (!(left & Spec Number) || !(right & SpecNumber)) {224 } else if (!(left & SpecFullNumber) || !(right & SpecFullNumber)) { 223 225 // left or right is definitely something other than a number. 224 226 changed |= mergePrediction(SpecString); … … 237 239 changed |= mergePrediction(SpecInt32); 238 240 else if (m_graph.addShouldSpeculateMachineInt(node)) 239 changed |= mergePrediction(SpecInt 48);241 changed |= mergePrediction(SpecInt52); 240 242 else 241 243 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 252 254 changed |= mergePrediction(SpecInt32); 253 255 else if (m_graph.addShouldSpeculateMachineInt(node)) 254 changed |= mergePrediction(SpecInt 48);256 changed |= mergePrediction(SpecInt52); 255 257 else 256 258 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 264 266 changed |= mergePrediction(SpecInt32); 265 267 else if (m_graph.negateShouldSpeculateMachineInt(node)) 266 changed |= mergePrediction(SpecInt 48);268 changed |= mergePrediction(SpecInt52); 267 269 else 268 270 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); … … 293 295 changed |= mergePrediction(SpecInt32); 294 296 else if (m_graph.mulShouldSpeculateMachineInt(node)) 295 changed |= mergePrediction(SpecInt 48);297 changed |= mergePrediction(SpecInt52); 296 298 else 297 299 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); … … 369 371 370 372 case GetByVal: { 373 if (!node->child1()->prediction()) 374 break; 375 if (!node->getHeapPrediction()) 376 break; 377 371 378 if (node->child1()->shouldSpeculateFloat32Array() 372 379 || node->child1()->shouldSpeculateFloat64Array()) 373 380 changed |= mergePrediction(SpecDouble); 374 else 381 else if (node->child1()->shouldSpeculateUint32Array()) { 382 if (isInt32Speculation(node->getHeapPrediction())) 383 changed |= mergePrediction(SpecInt32); 384 else 385 changed |= mergePrediction(SpecInt52); 386 } else 375 387 changed |= mergePrediction(node->getHeapPrediction()); 376 388 break; … … 567 579 case Unreachable: 568 580 case LoopHint: 581 case Int52ToValue: 582 case Int52ToDouble: 569 583 break; 570 584 … … 641 655 DoubleBallot ballot; 642 656 643 if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right) 644 && !m_graph.addShouldSpeculateInt32(node)) 657 if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right) 658 && !m_graph.addShouldSpeculateInt32(node) 659 && !m_graph.addShouldSpeculateMachineInt(node)) 645 660 ballot = VoteDouble; 646 661 else … … 658 673 DoubleBallot ballot; 659 674 660 if (isNumberSpeculation(left) && isNumberSpeculation(right) 661 && !m_graph.mulShouldSpeculateInt32(node)) 675 if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right) 676 && !m_graph.mulShouldSpeculateInt32(node) 677 && !m_graph.mulShouldSpeculateMachineInt(node)) 662 678 ballot = VoteDouble; 663 679 else … … 678 694 DoubleBallot ballot; 679 695 680 if (is NumberSpeculation(left) && isNumberSpeculation(right)696 if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right) 681 697 && !(Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32())) 682 698 ballot = VoteDouble; … … 707 723 if (isDoubleSpeculation(prediction)) 708 724 node->variableAccessData()->vote(VoteDouble); 709 else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction)) 725 else if ( 726 !isFullNumberSpeculation(prediction) 727 || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction)) 710 728 node->variableAccessData()->vote(VoteValue); 711 729 break; -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r155201 r156019 62 62 case NotCellUse: 63 63 case OtherUse: 64 case MachineIntUse: 64 65 return; 65 66 … … 70 71 71 72 case KnownNumberUse: 72 if (m_state.forNode(edge).m_type & ~Spec Number)73 if (m_state.forNode(edge).m_type & ~SpecFullNumber) 73 74 m_result = false; 74 75 return; … … 240 241 case CheckTierUpAndOSREnter: 241 242 case LoopHint: 243 case Int52ToDouble: 244 case Int52ToValue: 242 245 return true; 243 246 -
trunk/Source/JavaScriptCore/dfg/DFGSilentRegisterSavePlan.h
r141069 r156019 49 49 DoNothingForFill, 50 50 SetInt32Constant, 51 SetInt52Constant, 52 SetStrictInt52Constant, 51 53 SetBooleanConstant, 52 54 SetCellConstant, … … 62 64 Load32Payload, 63 65 Load32PayloadBoxInt, 66 Load32PayloadConvertToInt52, 67 Load32PayloadSignExtend, 64 68 LoadPtr, 65 69 Load64, 70 Load64ShiftInt52Right, 71 Load64ShiftInt52Left, 66 72 LoadDouble, 67 73 LoadDoubleBoxDouble, -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r156016 r156019 336 336 else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage) 337 337 spillAction = StorePtr; 338 else if (registerFormat == DataFormatInt52 || registerFormat == DataFormatStrictInt52) 339 spillAction = Store64; 338 340 else { 339 341 ASSERT(registerFormat & DataFormatJS); … … 387 389 ASSERT(info.gpr() == source); 388 390 fillAction = LoadPtr; 391 } else if (registerFormat == DataFormatInt52) { 392 if (node->hasConstant()) 393 fillAction = SetInt52Constant; 394 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS) 395 fillAction = Load32PayloadConvertToInt52; 396 else if (info.spillFormat() == DataFormatInt52) 397 fillAction = Load64; 398 else if (info.spillFormat() == DataFormatStrictInt52) 399 fillAction = Load64ShiftInt52Left; 400 else if (info.spillFormat() == DataFormatNone) 401 fillAction = Load64; 402 else { 403 // Should never happen. Anything that qualifies as an int32 will never 404 // be turned into a cell (immediate spec fail) or a double (to-double 405 // conversions involve a separate node). 406 RELEASE_ASSERT_NOT_REACHED(); 407 fillAction = Load64; // Make GCC happy. 408 } 409 } else if (registerFormat == DataFormatStrictInt52) { 410 if (node->hasConstant()) 411 fillAction = SetStrictInt52Constant; 412 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS) 413 fillAction = Load32PayloadSignExtend; 414 else if (info.spillFormat() == DataFormatInt52) 415 fillAction = Load64ShiftInt52Right; 416 else if (info.spillFormat() == DataFormatStrictInt52) 417 fillAction = Load64; 418 else if (info.spillFormat() == DataFormatNone) 419 fillAction = Load64; 420 else { 421 // Should never happen. Anything that qualifies as an int32 will never 422 // be turned into a cell (immediate spec fail) or a double (to-double 423 // conversions involve a separate node). 424 RELEASE_ASSERT_NOT_REACHED(); 425 fillAction = Load64; // Make GCC happy. 426 } 389 427 } else { 390 428 ASSERT(registerFormat & DataFormatJS); … … 394 432 if (valueOfJSConstant(node).isCell()) 395 433 fillAction = SetTrustedJSConstant; 396 else397 434 fillAction = SetJSConstant; 398 435 } else if (info.spillFormat() == DataFormatInt32) { … … 513 550 m_jit.move(Imm32(valueOfInt32Constant(plan.node())), plan.gpr()); 514 551 break; 552 #if USE(JSVALUE64) 553 case SetInt52Constant: 554 m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt() << JSValue::int52ShiftAmount), plan.gpr()); 555 break; 556 case SetStrictInt52Constant: 557 m_jit.move(Imm64(valueOfJSConstant(plan.node()).asMachineInt()), plan.gpr()); 558 break; 559 #endif // USE(JSVALUE64) 515 560 case SetBooleanConstant: 516 561 m_jit.move(TrustedImm32(valueOfBooleanConstant(plan.node())), plan.gpr()); … … 534 579 m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr()); 535 580 break; 581 case Load32PayloadConvertToInt52: 582 m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr()); 583 m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr()); 584 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 585 break; 586 case Load32PayloadSignExtend: 587 m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr()); 588 m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr()); 589 break; 536 590 case LoadDoubleBoxDouble: 537 591 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); … … 574 628 case Load64: 575 629 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 630 break; 631 case Load64ShiftInt52Right: 632 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 633 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 634 break; 635 case Load64ShiftInt52Left: 636 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr()); 637 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), plan.gpr()); 576 638 break; 577 639 #endif … … 1417 1479 if (node->isBinaryUseKind(Int32Use)) 1418 1480 compilePeepHoleInt32Branch(node, branchNode, condition); 1481 #if USE(JSVALUE64) 1482 else if (node->isBinaryUseKind(MachineIntUse)) 1483 compilePeepHoleInt52Branch(node, branchNode, condition); 1484 #endif // USE(JSVALUE64) 1419 1485 else if (node->isBinaryUseKind(NumberUse)) 1420 1486 compilePeepHoleDoubleBranch(node, branchNode, doubleCondition); … … 1507 1573 case FlushedInt32: 1508 1574 valueSource = ValueSource(Int32InJSStack); 1575 break; 1576 case FlushedInt52: 1577 valueSource = ValueSource(Int52InJSStack); 1509 1578 break; 1510 1579 case FlushedCell: … … 1874 1943 1875 1944 DFG_TYPE_CHECK( 1876 JSValueRegs(), child3, Spec RealNumber,1945 JSValueRegs(), child3, SpecFullRealNumber, 1877 1946 m_jit.branchDouble( 1878 1947 MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg)); … … 2150 2219 return; 2151 2220 } 2221 2222 #if USE(JSVALUE64) 2223 case MachineIntUse: { 2224 SpeculateStrictInt52Operand op1(this, node->child1()); 2225 GPRTemporary result(this, Reuse, op1); 2226 GPRReg op1GPR = op1.gpr(); 2227 GPRReg resultGPR = result.gpr(); 2228 m_jit.zeroExtend32ToPtr(op1GPR, resultGPR); 2229 int32Result(resultGPR, node, DataFormatInt32); 2230 return; 2231 } 2232 #endif // USE(JSVALUE64) 2152 2233 2153 2234 case NumberUse: … … 2188 2269 if (node->child1().useKind() == NumberUse) { 2189 2270 DFG_TYPE_CHECK( 2190 JSValueRegs(gpr), node->child1(), Spec Number,2271 JSValueRegs(gpr), node->child1(), SpecFullNumber, 2191 2272 m_jit.branchTest64( 2192 2273 MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); … … 2244 2325 if (node->child1().useKind() == NumberUse) { 2245 2326 DFG_TYPE_CHECK( 2246 JSValueRegs(tagGPR, payloadGPR), node->child1(), Spec Number,2327 JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecFullNumber, 2247 2328 m_jit.branch32( 2248 2329 MacroAssembler::AboveOrEqual, tagGPR, … … 2390 2471 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2391 2472 2392 if (needsTypeCheck(node->child1(), Spec Number)) {2473 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2393 2474 if (node->flags() & NodeExitsForward) { 2394 2475 forwardTypeCheck( 2395 JSValueRegs(op1GPR), node->child1(), Spec Number,2476 JSValueRegs(op1GPR), node->child1(), SpecFullNumber, 2396 2477 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister), 2397 2478 ValueRecovery::inGPR(op1GPR, DataFormatJS)); 2398 2479 } else { 2399 2480 backwardTypeCheck( 2400 JSValueRegs(op1GPR), node->child1(), Spec Number,2481 JSValueRegs(op1GPR), node->child1(), SpecFullNumber, 2401 2482 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2402 2483 } … … 2421 2502 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2422 2503 2423 if (needsTypeCheck(node->child1(), Spec Number)) {2504 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2424 2505 if (node->flags() & NodeExitsForward) { 2425 2506 forwardTypeCheck( 2426 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec Number,2507 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, 2427 2508 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)), 2428 2509 ValueRecovery::inPair(op1TagGPR, op1PayloadGPR)); 2429 2510 } else { 2430 2511 backwardTypeCheck( 2431 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), Spec Number,2512 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, 2432 2513 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2433 2514 } … … 2549 2630 return; 2550 2631 } 2632 2633 #if USE(JSVALUE64) 2634 if (node->shouldSpeculateMachineInt()) { 2635 m_jit.zeroExtend32ToPtr(resultReg, resultReg); 2636 strictInt52Result(resultReg, node); 2637 return; 2638 } 2639 #endif 2551 2640 2552 2641 FPRTemporary fresult(this); … … 2602 2691 break; 2603 2692 } 2693 2694 #if USE(JSVALUE64) 2695 case MachineIntUse: { 2696 SpeculateStrictInt52Operand valueOp(this, valueUse); 2697 GPRTemporary scratch(this); 2698 GPRReg scratchReg = scratch.gpr(); 2699 m_jit.move(valueOp.gpr(), scratchReg); 2700 if (isClamped(type)) { 2701 ASSERT(elementSize(type) == 1); 2702 MacroAssembler::Jump inBounds = m_jit.branch64( 2703 MacroAssembler::BelowOrEqual, scratchReg, JITCompiler::TrustedImm64(0xff)); 2704 MacroAssembler::Jump tooBig = m_jit.branch64( 2705 MacroAssembler::GreaterThan, scratchReg, JITCompiler::TrustedImm64(0xff)); 2706 m_jit.move(TrustedImm32(0), scratchReg); 2707 MacroAssembler::Jump clamped = m_jit.jump(); 2708 tooBig.link(&m_jit); 2709 m_jit.move(JITCompiler::TrustedImm32(255), scratchReg); 2710 clamped.link(&m_jit); 2711 inBounds.link(&m_jit); 2712 } 2713 value.adopt(scratch); 2714 valueGPR = scratchReg; 2715 break; 2716 } 2717 #endif // USE(JSVALUE64) 2604 2718 2605 2719 case NumberUse: { … … 2871 2985 return; 2872 2986 } 2873 2987 2874 2988 if (isNumberConstant(node->child2().node())) { 2875 2989 SpeculateInt32Operand op1(this, node->child1()); … … 2916 3030 return; 2917 3031 } 3032 3033 #if USE(JSVALUE64) 3034 case MachineIntUse: { 3035 // Will we need an overflow check? If we can prove that neither input can be 3036 // Int52 then the overflow check will not be necessary. 3037 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52) 3038 && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) { 3039 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3040 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 3041 GPRTemporary result(this, Reuse, op1); 3042 m_jit.move(op1.gpr(), result.gpr()); 3043 m_jit.add64(op2.gpr(), result.gpr()); 3044 int52Result(result.gpr(), node, op1.format()); 3045 return; 3046 } 3047 3048 SpeculateInt52Operand op1(this, node->child1()); 3049 SpeculateInt52Operand op2(this, node->child2()); 3050 GPRTemporary result(this, Reuse, op1, op2); 3051 m_jit.move(op1.gpr(), result.gpr()); 3052 speculationCheck( 3053 Int52Overflow, JSValueRegs(), 0, 3054 m_jit.branchAdd64(MacroAssembler::Overflow, op2.gpr(), result.gpr())); 3055 int52Result(result.gpr(), node); 3056 return; 3057 } 3058 #endif // USE(JSVALUE64) 2918 3059 2919 3060 case NumberUse: { … … 3061 3202 } 3062 3203 3204 #if USE(JSVALUE64) 3205 case MachineIntUse: { 3206 // Will we need an overflow check? If we can prove that neither input can be 3207 // Int52 then the overflow check will not be necessary. 3208 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52) 3209 && !m_state.forNode(node->child2()).couldBeType(SpecInt52)) { 3210 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3211 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 3212 GPRTemporary result(this, Reuse, op1); 3213 m_jit.move(op1.gpr(), result.gpr()); 3214 m_jit.sub64(op2.gpr(), result.gpr()); 3215 int52Result(result.gpr(), node, op1.format()); 3216 return; 3217 } 3218 3219 SpeculateInt52Operand op1(this, node->child1()); 3220 SpeculateInt52Operand op2(this, node->child2()); 3221 GPRTemporary result(this, Reuse, op1, op2); 3222 m_jit.move(op1.gpr(), result.gpr()); 3223 speculationCheck( 3224 Int52Overflow, JSValueRegs(), 0, 3225 m_jit.branchSub64(MacroAssembler::Overflow, op2.gpr(), result.gpr())); 3226 int52Result(result.gpr(), node); 3227 return; 3228 } 3229 #endif // USE(JSVALUE64) 3230 3063 3231 case NumberUse: { 3064 3232 SpeculateDoubleOperand op1(this, node->child1()); … … 3089 3257 m_jit.move(op1.gpr(), result.gpr()); 3090 3258 3259 // Note: there is no notion of being not used as a number, but someone 3260 // caring about negative zero. 3261 3091 3262 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 3092 3263 m_jit.neg32(result.gpr()); … … 3101 3272 return; 3102 3273 } 3274 3275 #if USE(JSVALUE64) 3276 case MachineIntUse: { 3277 if (!m_state.forNode(node->child1()).couldBeType(SpecInt52)) { 3278 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3279 GPRTemporary result(this); 3280 GPRReg op1GPR = op1.gpr(); 3281 GPRReg resultGPR = result.gpr(); 3282 m_jit.move(op1GPR, resultGPR); 3283 m_jit.neg64(resultGPR); 3284 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3285 speculationCheck( 3286 NegativeZero, JSValueRegs(), 0, 3287 m_jit.branchTest64(MacroAssembler::Zero, resultGPR)); 3288 } 3289 int52Result(resultGPR, node, op1.format()); 3290 return; 3291 } 3292 3293 SpeculateInt52Operand op1(this, node->child1()); 3294 GPRTemporary result(this); 3295 GPRReg op1GPR = op1.gpr(); 3296 GPRReg resultGPR = result.gpr(); 3297 m_jit.move(op1GPR, resultGPR); 3298 speculationCheck( 3299 Int52Overflow, JSValueRegs(), 0, 3300 m_jit.branchNeg64(MacroAssembler::Overflow, resultGPR)); 3301 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3302 speculationCheck( 3303 NegativeZero, JSValueRegs(), 0, 3304 m_jit.branchTest64(MacroAssembler::Zero, resultGPR)); 3305 } 3306 int52Result(resultGPR, node); 3307 return; 3308 } 3309 #endif // USE(JSVALUE64) 3103 3310 3104 3311 case NumberUse: { … … 3166 3373 return; 3167 3374 } 3375 3376 #if USE(JSVALUE64) 3377 case MachineIntUse: { 3378 // This is super clever. We want to do an int52 multiplication and check the 3379 // int52 overflow bit. There is no direct hardware support for this, but we do 3380 // have the ability to do an int64 multiplication and check the int64 overflow 3381 // bit. We leverage that. Consider that a, b are int52 numbers inside int64 3382 // registers, with the high 12 bits being sign-extended. We can do: 3383 // 3384 // (a * (b << 12)) 3385 // 3386 // This will give us a left-shifted int52 (value is in high 52 bits, low 16 3387 // bits are zero) plus the int52 overflow bit. I.e. whether this 64-bit 3388 // multiplication overflows is identical to whether the 'a * b' 52-bit 3389 // multiplication overflows. 3390 // 3391 // In our nomenclature, this is: 3392 // 3393 // strictInt52(a) * int52(b) => int52 3394 // 3395 // That is "strictInt52" means unshifted and "int52" means left-shifted by 16 3396 // bits. 3397 // 3398 // We don't care which of op1 or op2 serves as the left-shifted operand, so 3399 // we just do whatever is more convenient for op1 and have op2 do the 3400 // opposite. This ensures that we do at most one shift. 3401 3402 SpeculateWhicheverInt52Operand op1(this, node->child1()); 3403 SpeculateWhicheverInt52Operand op2(this, node->child2(), OppositeShift, op1); 3404 GPRTemporary result(this); 3405 3406 GPRReg op1GPR = op1.gpr(); 3407 GPRReg op2GPR = op2.gpr(); 3408 GPRReg resultGPR = result.gpr(); 3409 3410 m_jit.move(op1GPR, resultGPR); 3411 speculationCheck( 3412 Int52Overflow, JSValueRegs(), 0, 3413 m_jit.branchMul64(MacroAssembler::Overflow, op2GPR, resultGPR)); 3414 3415 if (!bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) { 3416 MacroAssembler::Jump resultNonZero = m_jit.branchTest64( 3417 MacroAssembler::NonZero, resultGPR); 3418 speculationCheck( 3419 NegativeZero, JSValueRegs(), 0, 3420 m_jit.branch64(MacroAssembler::LessThan, op1GPR, TrustedImm64(0))); 3421 speculationCheck( 3422 NegativeZero, JSValueRegs(), 0, 3423 m_jit.branch64(MacroAssembler::LessThan, op2GPR, TrustedImm64(0))); 3424 resultNonZero.link(&m_jit); 3425 } 3426 3427 int52Result(resultGPR, node); 3428 return; 3429 } 3430 #endif // USE(JSVALUE64) 3168 3431 3169 3432 case NumberUse: { … … 3589 3852 return false; 3590 3853 } 3591 3854 3855 #if USE(JSVALUE64) 3856 if (node->isBinaryUseKind(MachineIntUse)) { 3857 compileInt52Compare(node, condition); 3858 return false; 3859 } 3860 #endif // USE(JSVALUE64) 3861 3592 3862 if (node->isBinaryUseKind(NumberUse)) { 3593 3863 compileDoubleCompare(node, doubleCondition); … … 3739 4009 return false; 3740 4010 } 4011 4012 #if USE(JSVALUE64) 4013 case MachineIntUse: { 4014 unsigned branchIndexInBlock = detectPeepHoleBranch(); 4015 if (branchIndexInBlock != UINT_MAX) { 4016 Node* branchNode = m_block->at(branchIndexInBlock); 4017 compilePeepHoleInt52Branch(node, branchNode, MacroAssembler::Equal); 4018 use(node->child1()); 4019 use(node->child2()); 4020 m_indexInBlock = branchIndexInBlock; 4021 m_currentNode = branchNode; 4022 return true; 4023 } 4024 compileInt52Compare(node, MacroAssembler::Equal); 4025 return false; 4026 } 4027 #endif // USE(JSVALUE64) 3741 4028 3742 4029 case NumberUse: { … … 4494 4781 } 4495 4782 4783 void SpeculativeJIT::speculateMachineInt(Edge edge) 4784 { 4785 #if USE(JSVALUE64) 4786 if (!needsTypeCheck(edge, SpecMachineInt)) 4787 return; 4788 4789 (SpeculateWhicheverInt52Operand(this, edge)).gpr(); 4790 #else // USE(JSVALUE64) 4791 UNUSED_PARAM(edge); 4792 UNREACHABLE_FOR_PLATFORM(); 4793 #endif // USE(JSVALUE64) 4794 } 4795 4496 4796 void SpeculativeJIT::speculateNumber(Edge edge) 4497 4797 { 4498 if (!needsTypeCheck(edge, Spec Number))4798 if (!needsTypeCheck(edge, SpecFullNumber)) 4499 4799 return; 4500 4800 … … 4504 4804 void SpeculativeJIT::speculateRealNumber(Edge edge) 4505 4805 { 4506 if (!needsTypeCheck(edge, Spec RealNumber))4806 if (!needsTypeCheck(edge, SpecFullRealNumber)) 4507 4807 return; 4508 4808 … … 4510 4810 FPRReg fpr = operand.fpr(); 4511 4811 DFG_TYPE_CHECK( 4512 JSValueRegs(), edge, Spec RealNumber,4812 JSValueRegs(), edge, SpecFullRealNumber, 4513 4813 m_jit.branchDouble( 4514 4814 MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr)); … … 4772 5072 break; 4773 5073 case KnownNumberUse: 4774 ASSERT(!needsTypeCheck(edge, Spec Number));5074 ASSERT(!needsTypeCheck(edge, SpecFullNumber)); 4775 5075 break; 4776 5076 case KnownCellUse: … … 4782 5082 case Int32Use: 4783 5083 speculateInt32(edge); 5084 break; 5085 case MachineIntUse: 5086 speculateMachineInt(edge); 4784 5087 break; 4785 5088 case RealNumberUse: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r155783 r156019 160 160 bool canReuse(Node* node) 161 161 { 162 VirtualRegister virtualRegister = node->virtualRegister(); 163 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 164 return info.canReuse(); 162 return generationInfo(node).canReuse(); 165 163 } 166 164 bool canReuse(Edge nodeUse) … … 238 236 bool isFilled(Node* node) 239 237 { 240 VirtualRegister virtualRegister = node->virtualRegister(); 241 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 242 return info.registerFormat() != DataFormatNone; 238 return generationInfo(node).registerFormat() != DataFormatNone; 243 239 } 244 240 bool isFilledDouble(Node* node) 245 241 { 246 VirtualRegister virtualRegister = node->virtualRegister(); 247 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 248 return info.registerFormat() == DataFormatDouble; 242 return generationInfo(node).registerFormat() == DataFormatDouble; 249 243 } 250 244 … … 254 248 if (!node->hasResult()) 255 249 return; 256 VirtualRegister virtualRegister = node->virtualRegister(); 257 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 250 GenerationInfo& info = generationInfo(node); 258 251 259 252 // use() returns true when the value becomes dead, and any … … 334 327 GPRReg fillSpeculateInt32(Edge, DataFormat& returnFormat); 335 328 GPRReg fillSpeculateInt32Strict(Edge); 329 GPRReg fillSpeculateInt52(Edge, DataFormat desiredFormat); 336 330 FPRReg fillSpeculateDouble(Edge); 337 331 GPRReg fillSpeculateCell(Edge); … … 469 463 return boxDouble(fpr, allocate()); 470 464 } 465 466 void boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat); 471 467 #elif USE(JSVALUE32_64) 472 468 void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR) … … 560 556 } 561 557 562 bool isKnownInteger(Node* node) { return !(m_state.forNode(node).m_type & ~SpecInt32); }563 bool isKnownCell(Node* node) { return !(m_state.forNode(node).m_type & ~SpecCell); }558 bool isKnownInteger(Node* node) { return m_state.forNode(node).isType(SpecInt32); } 559 bool isKnownCell(Node* node) { return m_state.forNode(node).isType(SpecCell); } 564 560 565 561 bool isKnownNotInteger(Node* node) { return !(m_state.forNode(node).m_type & SpecInt32); } 566 bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & Spec Number); }562 bool isKnownNotNumber(Node* node) { return !(m_state.forNode(node).m_type & SpecFullNumber); } 567 563 bool isKnownNotCell(Node* node) { return !(m_state.forNode(node).m_type & SpecCell); } 568 564 … … 817 813 int32Result(reg, node, DataFormatInt32, mode); 818 814 } 815 void int52Result(GPRReg reg, Node* node, DataFormat format, UseChildrenMode mode = CallUseChildren) 816 { 817 if (mode == CallUseChildren) 818 useChildren(node); 819 820 VirtualRegister virtualRegister = node->virtualRegister(); 821 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 822 823 m_gprs.retain(reg, virtualRegister, SpillOrderJS); 824 info.initInt52(node, node->refCount(), reg, format); 825 } 826 void int52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren) 827 { 828 int52Result(reg, node, DataFormatInt52, mode); 829 } 830 void strictInt52Result(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren) 831 { 832 int52Result(reg, node, DataFormatStrictInt52, mode); 833 } 819 834 void noResult(Node* node, UseChildrenMode mode = CallUseChildren) 820 835 { … … 901 916 { 902 917 ASSERT(isInt32Constant(node) || isNumberConstant(node) || isJSConstant(node)); 903 generationInfo FromVirtualRegister(node->virtualRegister()).initConstant(node, node->refCount());918 generationInfo(node).initConstant(node, node->refCount()); 904 919 } 905 920 … … 1890 1905 return true; 1891 1906 1892 VirtualRegister virtualRegister = node->virtualRegister(); 1893 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 1894 1895 return info.isJSInt32(); 1907 return generationInfo(node).isJSInt32(); 1908 } 1909 1910 bool betterUseStrictInt52(Node* node) 1911 { 1912 return !generationInfo(node).isInt52(); 1913 } 1914 bool betterUseStrictInt52(Edge edge) 1915 { 1916 return betterUseStrictInt52(edge.node()); 1896 1917 } 1897 1918 … … 1899 1920 bool compilePeepHoleBranch(Node*, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ); 1900 1921 void compilePeepHoleInt32Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition); 1922 void compilePeepHoleInt52Branch(Node*, Node* branchNode, JITCompiler::RelationalCondition); 1901 1923 void compilePeepHoleBooleanBranch(Node*, Node* branchNode, JITCompiler::RelationalCondition); 1902 1924 void compilePeepHoleDoubleBranch(Node*, Node* branchNode, JITCompiler::DoubleCondition); … … 1946 1968 1947 1969 void compileInt32Compare(Node*, MacroAssembler::RelationalCondition); 1970 void compileInt52Compare(Node*, MacroAssembler::RelationalCondition); 1948 1971 void compileBooleanCompare(Node*, MacroAssembler::RelationalCondition); 1949 1972 void compileDoubleCompare(Node*, MacroAssembler::DoubleCondition); … … 2119 2142 2120 2143 void speculateInt32(Edge); 2144 void speculateMachineInt(Edge); 2121 2145 void speculateNumber(Edge); 2122 2146 void speculateRealNumber(Edge); … … 2196 2220 return m_generationInfo[operandToLocal(virtualRegister)]; 2197 2221 } 2222 2223 GenerationInfo& generationInfo(Node* node) 2224 { 2225 return generationInfoFromVirtualRegister(node->virtualRegister()); 2226 } 2227 2228 GenerationInfo& generationInfo(Edge edge) 2229 { 2230 return generationInfo(edge.node()); 2231 } 2198 2232 2199 2233 // The JIT, while also provides MacroAssembler functionality. … … 2677 2711 }; 2678 2712 2713 // Gives you a canonical Int52 (i.e. it's left-shifted by 16, low bits zero). 2714 class SpeculateInt52Operand { 2715 public: 2716 explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2717 : m_jit(jit) 2718 , m_edge(edge) 2719 , m_gprOrInvalid(InvalidGPRReg) 2720 { 2721 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2722 if (jit->isFilled(node())) 2723 gpr(); 2724 } 2725 2726 ~SpeculateInt52Operand() 2727 { 2728 ASSERT(m_gprOrInvalid != InvalidGPRReg); 2729 m_jit->unlock(m_gprOrInvalid); 2730 } 2731 2732 Edge edge() const 2733 { 2734 return m_edge; 2735 } 2736 2737 Node* node() const 2738 { 2739 return edge().node(); 2740 } 2741 2742 GPRReg gpr() 2743 { 2744 if (m_gprOrInvalid == InvalidGPRReg) 2745 m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatInt52); 2746 return m_gprOrInvalid; 2747 } 2748 2749 void use() 2750 { 2751 m_jit->use(node()); 2752 } 2753 2754 private: 2755 SpeculativeJIT* m_jit; 2756 Edge m_edge; 2757 GPRReg m_gprOrInvalid; 2758 }; 2759 2760 // Gives you a strict Int52 (i.e. the payload is in the low 48 bits, high 16 bits are sign-extended). 2761 class SpeculateStrictInt52Operand { 2762 public: 2763 explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2764 : m_jit(jit) 2765 , m_edge(edge) 2766 , m_gprOrInvalid(InvalidGPRReg) 2767 { 2768 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2769 if (jit->isFilled(node())) 2770 gpr(); 2771 } 2772 2773 ~SpeculateStrictInt52Operand() 2774 { 2775 ASSERT(m_gprOrInvalid != InvalidGPRReg); 2776 m_jit->unlock(m_gprOrInvalid); 2777 } 2778 2779 Edge edge() const 2780 { 2781 return m_edge; 2782 } 2783 2784 Node* node() const 2785 { 2786 return edge().node(); 2787 } 2788 2789 GPRReg gpr() 2790 { 2791 if (m_gprOrInvalid == InvalidGPRReg) 2792 m_gprOrInvalid = m_jit->fillSpeculateInt52(edge(), DataFormatStrictInt52); 2793 return m_gprOrInvalid; 2794 } 2795 2796 void use() 2797 { 2798 m_jit->use(node()); 2799 } 2800 2801 private: 2802 SpeculativeJIT* m_jit; 2803 Edge m_edge; 2804 GPRReg m_gprOrInvalid; 2805 }; 2806 2807 enum OppositeShiftTag { OppositeShift }; 2808 2809 class SpeculateWhicheverInt52Operand { 2810 public: 2811 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2812 : m_jit(jit) 2813 , m_edge(edge) 2814 , m_gprOrInvalid(InvalidGPRReg) 2815 , m_strict(jit->betterUseStrictInt52(edge)) 2816 { 2817 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2818 if (jit->isFilled(node())) 2819 gpr(); 2820 } 2821 2822 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2823 : m_jit(jit) 2824 , m_edge(edge) 2825 , m_gprOrInvalid(InvalidGPRReg) 2826 , m_strict(other.m_strict) 2827 { 2828 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2829 if (jit->isFilled(node())) 2830 gpr(); 2831 } 2832 2833 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2834 : m_jit(jit) 2835 , m_edge(edge) 2836 , m_gprOrInvalid(InvalidGPRReg) 2837 , m_strict(!other.m_strict) 2838 { 2839 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2840 if (jit->isFilled(node())) 2841 gpr(); 2842 } 2843 2844 ~SpeculateWhicheverInt52Operand() 2845 { 2846 ASSERT(m_gprOrInvalid != InvalidGPRReg); 2847 m_jit->unlock(m_gprOrInvalid); 2848 } 2849 2850 Edge edge() const 2851 { 2852 return m_edge; 2853 } 2854 2855 Node* node() const 2856 { 2857 return edge().node(); 2858 } 2859 2860 GPRReg gpr() 2861 { 2862 if (m_gprOrInvalid == InvalidGPRReg) { 2863 m_gprOrInvalid = m_jit->fillSpeculateInt52( 2864 edge(), m_strict ? DataFormatStrictInt52 : DataFormatInt52); 2865 } 2866 return m_gprOrInvalid; 2867 } 2868 2869 void use() 2870 { 2871 m_jit->use(node()); 2872 } 2873 2874 DataFormat format() const 2875 { 2876 return m_strict ? DataFormatStrictInt52 : DataFormatInt52; 2877 } 2878 2879 private: 2880 SpeculativeJIT* m_jit; 2881 Edge m_edge; 2882 GPRReg m_gprOrInvalid; 2883 bool m_strict; 2884 }; 2885 2679 2886 class SpeculateDoubleOperand { 2680 2887 public: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r155783 r156019 889 889 AbstractValue& value = m_state.forNode(edge); 890 890 SpeculatedType type = value.m_type; 891 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~Spec Number));892 m_interpreter.filter(value, Spec Number);891 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber)); 892 m_interpreter.filter(value, SpecFullNumber); 893 893 VirtualRegister virtualRegister = edge->virtualRegister(); 894 894 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); … … 929 929 if (spillFormat != DataFormatJSInt32 && spillFormat != DataFormatInt32) { 930 930 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)); 931 if (type & ~Spec Number)931 if (type & ~SpecFullNumber) 932 932 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag))); 933 933 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); … … 964 964 FPRTemporary scratch(this); 965 965 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 966 if (type & ~Spec Number)966 if (type & ~SpecFullNumber) 967 967 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 968 968 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); … … 2924 2924 2925 2925 DFG_TYPE_CHECK( 2926 JSValueRegs(), node->child2(), Spec RealNumber,2926 JSValueRegs(), node->child2(), SpecFullRealNumber, 2927 2927 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2928 2928 … … 3188 3188 op1.use(); 3189 3189 3190 if (!(m_state.forNode(node->child1()).m_type & ~(Spec Number | SpecBoolean))) {3190 if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean))) { 3191 3191 m_jit.move(op1TagGPR, resultTagGPR); 3192 3192 m_jit.move(op1PayloadGPR, resultPayloadGPR); … … 3290 3290 FPRReg opFPR = operand.fpr(); 3291 3291 DFG_TYPE_CHECK( 3292 JSValueRegs(), use, Spec RealNumber,3292 JSValueRegs(), use, SpecFullRealNumber, 3293 3293 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3294 3294 … … 3355 3355 FPRReg opFPR = operand.fpr(); 3356 3356 DFG_TYPE_CHECK( 3357 JSValueRegs(), use, Spec RealNumber,3357 JSValueRegs(), use, SpecFullRealNumber, 3358 3358 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); 3359 3359 … … 4798 4798 case CheckTierUpAtReturn: 4799 4799 case CheckTierUpAndOSREnter: 4800 case Int52ToDouble: 4801 case Int52ToValue: 4800 4802 RELEASE_ASSERT_NOT_REACHED(); 4801 4803 break; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r155783 r156019 41 41 #if USE(JSVALUE64) 42 42 43 void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format) 44 { 45 GPRReg tempGPR; 46 if (sourceGPR == targetGPR) 47 tempGPR = allocate(); 48 else 49 tempGPR = targetGPR; 50 51 FPRReg fpr = fprAllocate(); 52 53 if (format == DataFormatInt52) 54 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR); 55 else 56 ASSERT(format == DataFormatStrictInt52); 57 58 m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr); 59 60 if (tempGPR != targetGPR) 61 unlock(tempGPR); 62 63 unlock(fpr); 64 } 65 43 66 GPRReg SpeculativeJIT::fillJSValue(Edge edge) 44 67 { … … 70 93 DataFormat spillFormat = info.spillFormat(); 71 94 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 72 if (spillFormat == DataFormatInt32) { 95 switch (spillFormat) { 96 case DataFormatInt32: { 73 97 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 74 98 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr); 75 99 spillFormat = DataFormatJSInt32; 76 } else { 100 break; 101 } 102 103 case DataFormatInt52: 104 case DataFormatStrictInt52: { 105 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 106 boxInt52(gpr, gpr, spillFormat); 107 return gpr; 108 } 109 110 default: 77 111 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 78 112 if (spillFormat == DataFormatDouble) { … … 82 116 } else 83 117 RELEASE_ASSERT(spillFormat & DataFormatJS); 118 break; 84 119 } 85 120 info.fillJSValue(*m_stream, gpr, spillFormat); … … 113 148 114 149 return gpr; 150 } 151 152 case DataFormatInt52: 153 case DataFormatStrictInt52: { 154 GPRReg gpr = info.gpr(); 155 lock(gpr); 156 GPRReg resultGPR = allocate(); 157 boxInt52(gpr, resultGPR, info.registerFormat()); 158 unlock(gpr); 159 return resultGPR; 115 160 } 116 161 … … 769 814 DataFormat spillFormat = info.spillFormat(); 770 815 771 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 );816 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52); 772 817 773 818 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 790 835 return gpr; 791 836 } 837 if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) { 838 // Generally, this can only happen if we've already proved that the 839 // value is an int32. That's because if a value originated as a JSValue 840 // then we would speculate that it's an int32 before representing it as 841 // an int52. Otherwise, if we knowingly produced an int52, then we would 842 // be boxing it into a value using Int52ToValue. This assertion is valid 843 // only because Int52 is something that we introduce at prediction time. 844 // However: we may have an int32-producing node replaced by an 845 // int52-producing node due to CSE. So we must do a check. 846 RELEASE_ASSERT(!(type & ~SpecMachineInt)); 847 if (type & SpecInt52) { 848 GPRReg temp = allocate(); 849 m_jit.signExtend32ToPtr(gpr, temp); 850 // Currently, we can't supply value profiling information here. :-/ 851 speculationCheck( 852 BadType, JSValueRegs(), 0, 853 m_jit.branch64(MacroAssembler::NotEqual, gpr, temp)); 854 unlock(temp); 855 } 856 if (spillFormat == DataFormatStrictInt52) 857 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 858 else { 859 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 860 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 861 m_jit.zeroExtend32ToPtr(gpr, gpr); 862 } 863 info.fillInt32(*m_stream, gpr); 864 returnFormat = DataFormatInt32; 865 return gpr; 866 } 792 867 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 793 868 … … 798 873 799 874 case DataFormatJS: { 875 RELEASE_ASSERT(!(type & SpecInt52)); 800 876 // Check the value is an integer. 801 877 GPRReg gpr = info.gpr(); … … 844 920 return gpr; 845 921 } 922 923 case DataFormatStrictInt52: 924 case DataFormatInt52: { 925 GPRReg gpr = info.gpr(); 926 GPRReg result; 927 if (m_gprs.isLocked(gpr)) { 928 result = allocate(); 929 m_jit.move(gpr, result); 930 } else { 931 lock(gpr); 932 info.fillInt32(*m_stream, gpr); 933 result = gpr; 934 } 935 RELEASE_ASSERT(!(type & ~SpecMachineInt)); 936 if (info.registerFormat() == DataFormatInt52) 937 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 938 if (type & SpecInt52) { 939 GPRReg temp = allocate(); 940 m_jit.signExtend32ToPtr(result, temp); 941 // Currently, we can't supply value profiling information here. :-/ 942 speculationCheck( 943 BadType, JSValueRegs(), 0, 944 m_jit.branch64(MacroAssembler::NotEqual, result, temp)); 945 unlock(temp); 946 } 947 m_jit.zeroExtend32ToPtr(result, result); 948 returnFormat = DataFormatInt32; 949 return gpr; 950 } 846 951 847 952 case DataFormatDouble: … … 886 991 } 887 992 993 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat) 994 { 995 ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52); 996 AbstractValue& value = m_state.forNode(edge); 997 SpeculatedType type = value.m_type; 998 m_interpreter.filter(value, SpecMachineInt); 999 VirtualRegister virtualRegister = edge->virtualRegister(); 1000 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); 1001 1002 switch (info.registerFormat()) { 1003 case DataFormatNone: { 1004 if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) { 1005 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1006 return allocate(); 1007 } 1008 1009 GPRReg gpr = allocate(); 1010 1011 if (edge->hasConstant()) { 1012 JSValue jsValue = valueOfJSConstant(edge.node()); 1013 ASSERT(jsValue.isMachineInt()); 1014 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 1015 int64_t value = jsValue.asMachineInt(); 1016 if (desiredFormat == DataFormatInt52) 1017 value = value << JSValue::int52ShiftAmount; 1018 m_jit.move(MacroAssembler::Imm64(value), gpr); 1019 info.fillGPR(*m_stream, gpr, desiredFormat); 1020 return gpr; 1021 } 1022 1023 DataFormat spillFormat = info.spillFormat(); 1024 1025 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52); 1026 1027 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1028 1029 if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) { 1030 // If we know this was spilled as an integer we can fill without checking. 1031 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 1032 m_jit.signExtend32ToPtr(gpr, gpr); 1033 if (desiredFormat == DataFormatStrictInt52) { 1034 info.fillStrictInt52(*m_stream, gpr); 1035 return gpr; 1036 } 1037 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1038 info.fillInt52(*m_stream, gpr); 1039 return gpr; 1040 } 1041 if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) { 1042 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1043 if (desiredFormat == DataFormatStrictInt52) { 1044 if (spillFormat == DataFormatInt52) 1045 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1046 info.fillStrictInt52(*m_stream, gpr); 1047 return gpr; 1048 } 1049 if (spillFormat == DataFormatStrictInt52) 1050 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1051 info.fillInt52(*m_stream, gpr); 1052 return gpr; 1053 } 1054 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1055 1056 // Fill as JSValue, and fall through. 1057 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32); 1058 m_gprs.unlock(gpr); 1059 } 1060 1061 case DataFormatJS: { 1062 // Check the value is an integer. Note that we would *like* to unbox an Int52 1063 // at this point but this is too costly. We only *prove* that this is an Int52 1064 // even though we check if it's an int32. 1065 GPRReg gpr = info.gpr(); 1066 GPRReg result; 1067 if (m_gprs.isLocked(gpr)) { 1068 result = allocate(); 1069 m_jit.move(gpr, result); 1070 } else { 1071 m_gprs.lock(gpr); 1072 result = gpr; 1073 } 1074 if (type & ~SpecInt32) 1075 speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister)); 1076 if (result == gpr) // The not-already-locked, so fill in-place, case. 1077 info.fillInt52(*m_stream, gpr, desiredFormat); 1078 m_jit.signExtend32ToPtr(result, result); 1079 if (desiredFormat == DataFormatInt52) 1080 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 1081 return result; 1082 } 1083 1084 case DataFormatInt32: 1085 case DataFormatJSInt32: { 1086 GPRReg gpr = info.gpr(); 1087 GPRReg result; 1088 if (m_gprs.isLocked(gpr)) { 1089 result = allocate(); 1090 m_jit.move(gpr, result); 1091 } else { 1092 m_gprs.lock(gpr); 1093 info.fillInt52(*m_stream, gpr, desiredFormat); 1094 result = gpr; 1095 } 1096 m_jit.signExtend32ToPtr(result, result); 1097 if (desiredFormat == DataFormatInt52) 1098 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 1099 return result; 1100 } 1101 1102 case DataFormatStrictInt52: { 1103 GPRReg gpr = info.gpr(); 1104 bool wasLocked = m_gprs.isLocked(gpr); 1105 lock(gpr); 1106 if (desiredFormat == DataFormatStrictInt52) 1107 return gpr; 1108 if (wasLocked) { 1109 GPRReg result = allocate(); 1110 m_jit.move(gpr, result); 1111 unlock(gpr); 1112 gpr = result; 1113 } else 1114 info.fillStrictInt52(*m_stream, gpr); 1115 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1116 return gpr; 1117 } 1118 1119 case DataFormatInt52: { 1120 GPRReg gpr = info.gpr(); 1121 bool wasLocked = m_gprs.isLocked(gpr); 1122 lock(gpr); 1123 if (desiredFormat == DataFormatInt52) 1124 return gpr; 1125 if (wasLocked) { 1126 GPRReg result = allocate(); 1127 m_jit.move(gpr, result); 1128 unlock(gpr); 1129 gpr = result; 1130 } else 1131 info.fillInt52(*m_stream, gpr); 1132 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1133 return gpr; 1134 } 1135 1136 case DataFormatDouble: 1137 case DataFormatJSDouble: 1138 if (edge->hasConstant()) { 1139 JSValue jsValue = valueOfJSConstant(edge.node()); 1140 if (jsValue.isMachineInt()) { 1141 int64_t value = jsValue.asMachineInt(); 1142 if (desiredFormat == DataFormatInt52) 1143 value = value << JSValue::int52ShiftAmount; 1144 GPRReg gpr = allocate(); 1145 m_jit.move(MacroAssembler::Imm64(value), gpr); 1146 return gpr; 1147 } 1148 } 1149 1150 case DataFormatCell: 1151 case DataFormatBoolean: 1152 case DataFormatJSCell: 1153 case DataFormatJSBoolean: { 1154 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1155 return allocate(); 1156 } 1157 1158 case DataFormatStorage: 1159 RELEASE_ASSERT_NOT_REACHED(); 1160 1161 default: 1162 RELEASE_ASSERT_NOT_REACHED(); 1163 return InvalidGPRReg; 1164 } 1165 } 1166 888 1167 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge) 889 1168 { … … 893 1172 AbstractValue& value = m_state.forNode(edge); 894 1173 SpeculatedType type = value.m_type; 895 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~Spec Number));896 m_interpreter.filter(value, Spec Number);1174 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber)); 1175 m_interpreter.filter(value, SpecFullNumber); 897 1176 VirtualRegister virtualRegister = edge->virtualRegister(); 898 1177 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); … … 946 1225 break; 947 1226 } 1227 1228 case DataFormatInt52: { 1229 GPRReg gpr = allocate(); 1230 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1231 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1232 info.fillInt52(*m_stream, gpr); 1233 unlock(gpr); 1234 break; 1235 } 1236 1237 case DataFormatStrictInt52: { 1238 GPRReg gpr = allocate(); 1239 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1240 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1241 info.fillStrictInt52(*m_stream, gpr); 1242 unlock(gpr); 1243 break; 1244 } 948 1245 949 1246 default: … … 979 1276 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); 980 1277 981 if (type & ~Spec Number)1278 if (type & ~SpecFullNumber) 982 1279 speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister)); 983 1280 … … 1007 1304 m_gprs.lock(gpr); 1008 1305 m_jit.convertInt32ToDouble(gpr, fpr); 1306 m_gprs.unlock(gpr); 1307 return fpr; 1308 } 1309 1310 case DataFormatInt52: { 1311 FPRReg fpr = fprAllocate(); 1312 GPRReg gpr = info.gpr(); 1313 m_gprs.lock(gpr); 1314 GPRReg temp = allocate(); 1315 m_jit.move(gpr, temp); 1316 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp); 1317 m_jit.convertInt64ToDouble(temp, fpr); 1318 unlock(temp); 1319 m_gprs.unlock(gpr); 1320 return fpr; 1321 } 1322 1323 case DataFormatStrictInt52: { 1324 FPRReg fpr = fprAllocate(); 1325 GPRReg gpr = info.gpr(); 1326 m_gprs.lock(gpr); 1327 m_jit.convertInt64ToDouble(gpr, fpr); 1009 1328 m_gprs.unlock(gpr); 1010 1329 return fpr; … … 1112 1431 case DataFormatDouble: 1113 1432 case DataFormatJSBoolean: 1114 case DataFormatBoolean: { 1433 case DataFormatBoolean: 1434 case DataFormatInt52: 1435 case DataFormatStrictInt52: { 1115 1436 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1116 1437 return allocate(); … … 1195 1516 case DataFormatDouble: 1196 1517 case DataFormatJSCell: 1197 case DataFormatCell: { 1518 case DataFormatCell: 1519 case DataFormatInt52: 1520 case DataFormatStrictInt52: { 1198 1521 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1199 1522 return allocate(); … … 1502 1825 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 1503 1826 jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean); 1827 } 1828 1829 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition) 1830 { 1831 SpeculateWhicheverInt52Operand op1(this, node->child1()); 1832 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 1833 GPRTemporary result(this, Reuse, op1, op2); 1834 1835 m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr()); 1836 1837 // If we add a DataFormatBool, we should use it here. 1838 m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); 1839 jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean); 1840 } 1841 1842 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition) 1843 { 1844 BasicBlock* taken = branchNode->takenBlock(); 1845 BasicBlock* notTaken = branchNode->notTakenBlock(); 1846 1847 // The branch instruction will branch to the taken block. 1848 // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through. 1849 if (taken == nextBlock()) { 1850 condition = JITCompiler::invert(condition); 1851 BasicBlock* tmp = taken; 1852 taken = notTaken; 1853 notTaken = tmp; 1854 } 1855 1856 SpeculateWhicheverInt52Operand op1(this, node->child1()); 1857 SpeculateWhicheverInt52Operand op2(this, node->child2(), op1); 1858 1859 branch64(condition, op1.gpr(), op2.gpr(), taken); 1860 jump(notTaken); 1504 1861 } 1505 1862 … … 1907 2264 } 1908 2265 2266 case FlushedInt52: { 2267 GPRTemporary result(this); 2268 m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr()); 2269 2270 VirtualRegister virtualRegister = node->virtualRegister(); 2271 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS); 2272 generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr()); 2273 break; 2274 } 2275 1909 2276 default: 1910 2277 GPRTemporary result(this); … … 1982 2349 } 1983 2350 2351 case FlushedInt52: { 2352 SpeculateInt52Operand value(this, node->child1()); 2353 m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local())); 2354 noResult(node); 2355 recordSetLocal(node->local(), ValueSource(Int52InJSStack)); 2356 break; 2357 } 2358 1984 2359 case FlushedCell: { 1985 2360 SpeculateCellOperand cell(this, node->child1()); … … 2102 2477 case Int32ToDouble: { 2103 2478 compileInt32ToDouble(node); 2479 break; 2480 } 2481 2482 case Int52ToValue: { 2483 JSValueOperand operand(this, node->child1()); 2484 GPRTemporary result(this, Reuse, operand); 2485 m_jit.move(operand.gpr(), result.gpr()); 2486 jsValueResult(result.gpr(), node); 2487 break; 2488 } 2489 2490 case Int52ToDouble: { 2491 SpeculateDoubleOperand operand(this, node->child1()); 2492 FPRTemporary result(this, operand); 2493 m_jit.moveDouble(operand.fpr(), result.fpr()); 2494 doubleResult(result.fpr(), node); 2104 2495 break; 2105 2496 } … … 2890 3281 2891 3282 DFG_TYPE_CHECK( 2892 JSValueRegs(), node->child2(), Spec RealNumber,3283 JSValueRegs(), node->child2(), SpecFullRealNumber, 2893 3284 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR)); 2894 3285 … … 3106 3497 op1.use(); 3107 3498 3108 if (!(m_state.forNode(node->child1()).m_type & ~(Spec Number | SpecBoolean)))3499 if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean))) 3109 3500 m_jit.move(op1GPR, resultGPR); 3110 3501 else { … … 3203 3594 FPRReg opFPR = operand.fpr(); 3204 3595 DFG_TYPE_CHECK( 3205 JSValueRegs(), use, Spec RealNumber,3596 JSValueRegs(), use, SpecFullRealNumber, 3206 3597 m_jit.branchDouble( 3207 3598 MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); … … 3268 3659 GPRReg scratchGPR = scratch.gpr(); 3269 3660 DFG_TYPE_CHECK( 3270 JSValueRegs(), use, Spec RealNumber,3661 JSValueRegs(), use, SpecFullRealNumber, 3271 3662 m_jit.branchDouble( 3272 3663 MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR)); -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp
r155201 r156019 44 44 case KnownInt32Use: 45 45 out.print("KnownInt32"); 46 break; 47 case MachineIntUse: 48 out.print("MachineInt"); 46 49 break; 47 50 case RealNumberUse: -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.h
r155590 r156019 40 40 Int32Use, 41 41 KnownInt32Use, 42 MachineIntUse, 42 43 RealNumberUse, 43 44 NumberUse, … … 67 68 case KnownInt32Use: 68 69 return SpecInt32; 70 case MachineIntUse: 71 return SpecMachineInt; 69 72 case RealNumberUse: 70 return Spec RealNumber;73 return SpecFullRealNumber; 71 74 case NumberUse: 72 75 case KnownNumberUse: 73 return Spec Number;76 return SpecFullNumber; 74 77 case BooleanUse: 75 78 return SpecBoolean; … … 126 129 case Int32Use: 127 130 case KnownInt32Use: 131 case MachineIntUse: 128 132 case RealNumberUse: 129 133 case NumberUse: -
trunk/Source/JavaScriptCore/dfg/DFGValueSource.cpp
r141069 r156019 46 46 out.print("Int32"); 47 47 break; 48 case Int52InJSStack: 49 out.print("Int52"); 50 break; 48 51 case CellInJSStack: 49 52 out.print("Cell"); -
trunk/Source/JavaScriptCore/dfg/DFGValueSource.h
r155575 r156019 44 44 ValueInJSStack, 45 45 Int32InJSStack, 46 Int52InJSStack, 46 47 CellInJSStack, 47 48 BooleanInJSStack, … … 57 58 case DataFormatInt32: 58 59 return Int32InJSStack; 60 case DataFormatInt52: 61 return Int52InJSStack; 59 62 case DataFormatDouble: 60 63 return DoubleInJSStack; … … 80 83 case Int32InJSStack: 81 84 return DataFormatInt32; 85 case Int52InJSStack: 86 return DataFormatInt52; 82 87 case CellInJSStack: 83 88 return DataFormatCell; … … 140 145 case FlushedInt32: 141 146 return ValueSource(Int32InJSStack); 147 case FlushedInt52: 148 return ValueSource(Int52InJSStack); 142 149 case FlushedCell: 143 150 return ValueSource(CellInJSStack); … … 182 189 return ValueRecovery::alreadyInJSStackAsUnboxedInt32(); 183 190 191 case Int52InJSStack: 192 return ValueRecovery::alreadyInJSStackAsUnboxedInt52(); 193 184 194 case CellInJSStack: 185 195 return ValueRecovery::alreadyInJSStackAsUnboxedCell(); -
trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h
r155497 r156019 236 236 // If the variable is not a number prediction, then this doesn't 237 237 // make any sense. 238 if (!is NumberSpeculation(prediction())) {238 if (!isFullNumberSpeculation(prediction())) { 239 239 // FIXME: we may end up forcing a local in inlined argument position to be a double even 240 240 // if it is sometimes not even numeric, since this never signals the fact that it doesn't … … 333 333 if (isInt32Speculation(prediction)) 334 334 return FlushedInt32; 335 336 if (enableInt52() && !operandIsArgument(m_local) && isMachineIntSpeculation(prediction)) 337 return FlushedInt52; 335 338 336 339 if (isCellSpeculation(prediction)) -
trunk/Source/JavaScriptCore/ftl/FTLCArgumentGetter.cpp
r153121 r156019 33 33 using namespace DFG; 34 34 35 void CArgumentGetter::loadNextAndBox(ValueFormat format, GPRReg destination, GPRReg scratch) 35 void CArgumentGetter::loadNextAndBox( 36 ValueFormat format, GPRReg destination, GPRReg scratch1, GPRReg scratch2) 36 37 { 37 if (scratch == InvalidGPRReg) { 38 if (scratch1 == InvalidGPRReg) { 39 ASSERT(scratch2 == InvalidGPRReg); 38 40 if (destination == GPRInfo::nonArgGPR0) 39 scratch = GPRInfo::nonArgGPR1;41 scratch1 = GPRInfo::nonArgGPR1; 40 42 else 41 scratch = GPRInfo::nonArgGPR0; 43 scratch1 = GPRInfo::nonArgGPR0; 44 } 45 if (scratch2 == InvalidGPRReg) { 46 if (destination != GPRInfo::nonArgGPR0 && scratch1 != GPRInfo::nonArgGPR0) 47 scratch2 = GPRInfo::nonArgGPR0; 48 else if (destination != GPRInfo::nonArgGPR1 && scratch1 != GPRInfo::nonArgGPR1) 49 scratch2 = GPRInfo::nonArgGPR1; 50 else 51 scratch2 = GPRInfo::nonArgGPR2; 42 52 } 43 53 … … 51 61 case ValueFormatUInt32: { 52 62 loadNext32(destination); 53 MacroAssembler::Jump isInt = m_jit.branch32( 54 MacroAssembler::GreaterThanOrEqual, 55 destination, MacroAssembler::TrustedImm32(0)); 63 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2); 64 m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0); 65 m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0); 66 break; 67 } 68 69 case ValueFormatInt52: { 70 loadNext64(destination); 71 m_jit.rshift64(AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), destination); 72 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2); 73 m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0); 74 m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0); 75 break; 76 } 56 77 57 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch); 58 m_jit.convertInt32ToDouble(destination, FPRInfo::fpRegT0); 59 m_jit.boxDouble(FPRInfo::fpRegT0, destination); 60 m_jit.move64ToDouble(scratch, FPRInfo::fpRegT0); 61 62 MacroAssembler::Jump done = m_jit.jump(); 63 64 isInt.link(&m_jit); 65 m_jit.or64(GPRInfo::tagTypeNumberRegister, destination); 66 67 done.link(&m_jit); 78 case ValueFormatStrictInt52: { 79 loadNext64(destination); 80 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2); 81 m_jit.boxInt52(destination, destination, scratch1, FPRInfo::fpRegT0); 82 m_jit.move64ToDouble(scratch2, FPRInfo::fpRegT0); 68 83 break; 69 84 } … … 81 96 82 97 case ValueFormatDouble: { 83 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch );98 m_jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch1); 84 99 loadNextDouble(FPRInfo::fpRegT0); 85 100 m_jit.boxDouble(FPRInfo::fpRegT0, destination); 86 m_jit.move64ToDouble(scratch , FPRInfo::fpRegT0);101 m_jit.move64ToDouble(scratch1, FPRInfo::fpRegT0); 87 102 break; 88 103 } -
trunk/Source/JavaScriptCore/ftl/FTLCArgumentGetter.h
r153121 r156019 116 116 117 117 void loadNextAndBox( 118 ValueFormat format, DFG::GPRReg destination, DFG::GPRReg scratch = InvalidGPRReg); 118 ValueFormat, DFG::GPRReg destination, 119 DFG::GPRReg scratch1 = InvalidGPRReg, DFG::GPRReg scratch2 = InvalidGPRReg); 119 120 120 121 private: -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r155281 r156019 165 165 if (node->isBinaryUseKind(Int32Use)) 166 166 break; 167 if (node->isBinaryUseKind(MachineIntUse)) 168 break; 167 169 if (node->isBinaryUseKind(NumberUse)) 168 170 break; … … 175 177 case CompareGreaterEq: 176 178 if (node->isBinaryUseKind(Int32Use)) 179 break; 180 if (node->isBinaryUseKind(MachineIntUse)) 177 181 break; 178 182 if (node->isBinaryUseKind(NumberUse)) … … 237 241 case Int32Use: 238 242 case KnownInt32Use: 243 case MachineIntUse: 239 244 case NumberUse: 240 245 case KnownNumberUse: -
trunk/Source/JavaScriptCore/ftl/FTLExitValue.cpp
r153296 r156019 54 54 out.print("InJSStackAsInt32"); 55 55 return; 56 case ExitValueInJSStackAsInt52: 57 out.print("InJSStackAsInt52"); 58 return; 56 59 case ExitValueInJSStackAsDouble: 57 60 out.print("InJSStackAsDouble"); -
trunk/Source/JavaScriptCore/ftl/FTLExitValue.h
r153296 r156019 50 50 ExitValueInJSStack, 51 51 ExitValueInJSStackAsInt32, 52 ExitValueInJSStackAsInt52, 52 53 ExitValueInJSStackAsDouble 53 54 }; … … 80 81 ExitValue result; 81 82 result.m_kind = ExitValueInJSStackAsInt32; 83 return result; 84 } 85 86 static ExitValue inJSStackAsInt52() 87 { 88 ExitValue result; 89 result.m_kind = ExitValueInJSStackAsInt52; 82 90 return result; 83 91 } -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r155281 r156019 39 39 #define FOR_EACH_FTL_INTRINSIC(macro) \ 40 40 macro(addWithOverflow32, "llvm.sadd.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ 41 macro(addWithOverflow64, "llvm.sadd.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \ 41 42 macro(doubleAbs, "llvm.fabs.f64", functionType(doubleType, doubleType)) \ 42 43 macro(mulWithOverflow32, "llvm.smul.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ 44 macro(mulWithOverflow64, "llvm.smul.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \ 43 45 macro(subWithOverflow32, "llvm.ssub.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ 46 macro(subWithOverflow64, "llvm.ssub.with.overflow.i64", functionType(structType(m_context, int64, boolean), int64, int64)) \ 44 47 macro(trap, "llvm.trap", functionType(voidType)) \ 45 48 macro(osrExit, "webkit_osr_exit", functionType(voidType, boolean, int32, Variadic)) -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r156016 r156019 152 152 type = m_out.int32; 153 153 break; 154 case NodeResultInt52: 155 type = m_out.int64; 156 break; 154 157 case NodeResultBoolean: 155 158 type = m_out.boolean; … … 240 243 break; 241 244 case JSConstant: 242 compileJSConstant();243 245 break; 244 246 case WeakJSConstant: … … 462 464 m_out.set(lowInt32(m_node->child1()), destination); 463 465 break; 466 case MachineIntUse: 467 m_out.set(lowInt52(m_node->child1()), destination); 468 break; 464 469 case BooleanUse: 465 470 m_out.set(lowBoolean(m_node->child1()), destination); … … 487 492 case NodeResultInt32: 488 493 setInt32(m_out.get(source)); 494 break; 495 case NodeResultInt52: 496 setInt52(m_out.get(source)); 489 497 break; 490 498 case NodeResultBoolean: … … 592 600 } 593 601 602 case FlushedInt52: { 603 LValue value = lowInt52(m_node->child1()); 604 m_out.store64(value, addressFor(variable->local())); 605 m_valueSources.operand(variable->local()) = ValueSource(Int52InJSStack); 606 return; 607 } 608 594 609 case FlushedCell: { 595 610 LValue value = lowCell(m_node->child1()); … … 656 671 } 657 672 673 case MachineIntUse: { 674 if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52) 675 && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) { 676 Int52Kind kind; 677 LValue left = lowWhicheverInt52(m_node->child1(), kind); 678 LValue right = lowInt52(m_node->child2(), kind); 679 setInt52(m_out.add(left, right), kind); 680 break; 681 } 682 683 LValue left = lowInt52(m_node->child1()); 684 LValue right = lowInt52(m_node->child2()); 685 LValue result = m_out.addWithOverflow64(left, right); 686 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1)); 687 setInt52(m_out.extractValue(result, 0)); 688 break; 689 } 690 658 691 case NumberUse: { 659 692 setDouble( … … 683 716 speculate(Overflow, noValue(), 0, m_out.extractValue(result, 1)); 684 717 setInt32(m_out.extractValue(result, 0)); 718 break; 719 } 720 721 case MachineIntUse: { 722 if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52) 723 && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) { 724 Int52Kind kind; 725 LValue left = lowWhicheverInt52(m_node->child1(), kind); 726 LValue right = lowInt52(m_node->child2(), kind); 727 setInt52(m_out.sub(left, right), kind); 728 break; 729 } 730 731 LValue left = lowInt52(m_node->child1()); 732 LValue right = lowInt52(m_node->child2()); 733 LValue result = m_out.subWithOverflow64(left, right); 734 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(result, 1)); 735 setInt52(m_out.extractValue(result, 0)); 685 736 break; 686 737 } … … 728 779 729 780 setInt32(result); 781 break; 782 } 783 784 case MachineIntUse: { 785 Int52Kind kind; 786 LValue left = lowWhicheverInt52(m_node->child1(), kind); 787 LValue right = lowInt52(m_node->child2(), opposite(kind)); 788 789 LValue overflowResult = m_out.mulWithOverflow64(left, right); 790 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 791 LValue result = m_out.extractValue(overflowResult, 0); 792 793 if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) { 794 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("ArithMul slow case")); 795 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMul continuation")); 796 797 m_out.branch(m_out.notZero64(result), continuation, slowCase); 798 799 LBasicBlock lastNext = m_out.appendTo(slowCase, continuation); 800 speculate(NegativeZero, noValue(), 0, m_out.lessThan(left, m_out.int64Zero)); 801 speculate(NegativeZero, noValue(), 0, m_out.lessThan(right, m_out.int64Zero)); 802 m_out.jump(continuation); 803 m_out.appendTo(continuation, lastNext); 804 } 805 806 setInt52(result); 730 807 break; 731 808 } … … 1030 1107 1031 1108 setInt32(result); 1109 break; 1110 } 1111 1112 case MachineIntUse: { 1113 if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) { 1114 Int52Kind kind; 1115 LValue value = lowWhicheverInt52(m_node->child1(), kind); 1116 LValue result = m_out.neg(value); 1117 if (!bytecodeCanIgnoreNegativeZero(m_node->arithNodeFlags())) 1118 speculate(NegativeZero, noValue(), 0, m_out.isZero64(result)); 1119 setInt52(result, kind); 1120 break; 1121 } 1122 1123 LValue value = lowInt52(m_node->child1()); 1124 LValue overflowResult = m_out.subWithOverflow64(m_out.int64Zero, value); 1125 speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1)); 1126 LValue result = m_out.extractValue(overflowResult, 0); 1127 speculate(NegativeZero, noValue(), 0, m_out.isZero64(result)); 1128 setInt52(result); 1032 1129 break; 1033 1130 } … … 1474 1571 1475 1572 FTL_TYPE_CHECK( 1476 doubleValue(value), child3, Spec RealNumber,1573 doubleValue(value), child3, SpecFullRealNumber, 1477 1574 m_out.doubleNotEqualOrUnordered(value, value)); 1478 1575 … … 1709 1806 { 1710 1807 if (m_node->isBinaryUseKind(Int32Use) 1808 || m_node->isBinaryUseKind(MachineIntUse) 1711 1809 || m_node->isBinaryUseKind(NumberUse) 1712 1810 || m_node->isBinaryUseKind(ObjectUse)) { … … 1732 1830 setBoolean( 1733 1831 m_out.equal(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 1832 return; 1833 } 1834 1835 if (m_node->isBinaryUseKind(MachineIntUse)) { 1836 Int52Kind kind; 1837 LValue left = lowWhicheverInt52(m_node->child1(), kind); 1838 LValue right = lowInt52(m_node->child2(), kind); 1839 setBoolean(m_out.equal(left, right)); 1734 1840 return; 1735 1841 } … … 1783 1889 } 1784 1890 1891 if (m_node->isBinaryUseKind(MachineIntUse)) { 1892 Int52Kind kind; 1893 LValue left = lowWhicheverInt52(m_node->child1(), kind); 1894 LValue right = lowInt52(m_node->child2(), kind); 1895 setBoolean(m_out.lessThan(left, right)); 1896 return; 1897 } 1898 1785 1899 if (m_node->isBinaryUseKind(NumberUse)) { 1786 1900 setBoolean( … … 1797 1911 setBoolean( 1798 1912 m_out.lessThanOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 1913 return; 1914 } 1915 1916 if (m_node->isBinaryUseKind(MachineIntUse)) { 1917 Int52Kind kind; 1918 LValue left = lowWhicheverInt52(m_node->child1(), kind); 1919 LValue right = lowInt52(m_node->child2(), kind); 1920 setBoolean(m_out.lessThanOrEqual(left, right)); 1799 1921 return; 1800 1922 } … … 1818 1940 } 1819 1941 1942 if (m_node->isBinaryUseKind(MachineIntUse)) { 1943 Int52Kind kind; 1944 LValue left = lowWhicheverInt52(m_node->child1(), kind); 1945 LValue right = lowInt52(m_node->child2(), kind); 1946 setBoolean(m_out.greaterThan(left, right)); 1947 return; 1948 } 1949 1820 1950 if (m_node->isBinaryUseKind(NumberUse)) { 1821 1951 setBoolean( … … 1834 1964 m_out.greaterThanOrEqual( 1835 1965 lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 1966 return; 1967 } 1968 1969 if (m_node->isBinaryUseKind(MachineIntUse)) { 1970 Int52Kind kind; 1971 LValue left = lowWhicheverInt52(m_node->child1(), kind); 1972 LValue right = lowInt52(m_node->child2(), kind); 1973 setBoolean(m_out.greaterThanOrEqual(left, right)); 1836 1974 return; 1837 1975 } … … 2353 2491 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || (edge.useKind() == Int32Use || edge.useKind() == KnownInt32Use)); 2354 2492 2493 if (edge->hasConstant()) { 2494 JSValue value = m_graph.valueOfJSConstant(edge.node()); 2495 if (!value.isInt32()) { 2496 terminate(Uncountable); 2497 return m_out.int32Zero; 2498 } 2499 return m_out.constInt32(value.asInt32()); 2500 } 2501 2355 2502 LoweredNodeValue value = m_int32Values.get(edge.node()); 2356 2503 if (isValid(value)) 2357 2504 return value.value(); 2505 2506 value = m_strictInt52Values.get(edge.node()); 2507 if (isValid(value)) 2508 return strictInt52ToInt32(edge, value.value()); 2509 2510 value = m_int52Values.get(edge.node()); 2511 if (isValid(value)) 2512 return strictInt52ToInt32(edge, int52ToStrictInt52(value.value())); 2358 2513 2359 2514 value = m_jsValueValues.get(edge.node()); … … 2372 2527 } 2373 2528 2529 enum Int52Kind { StrictInt52, Int52 }; 2530 LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2531 { 2532 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 2533 2534 if (edge->hasConstant()) { 2535 JSValue value = m_graph.valueOfJSConstant(edge.node()); 2536 if (!value.isMachineInt()) { 2537 terminate(Uncountable); 2538 return m_out.int64Zero; 2539 } 2540 int64_t result = value.asMachineInt(); 2541 if (kind == Int52) 2542 result <<= JSValue::int52ShiftAmount; 2543 return m_out.constInt64(result); 2544 } 2545 2546 LoweredNodeValue value; 2547 2548 switch (kind) { 2549 case Int52: 2550 value = m_int52Values.get(edge.node()); 2551 if (isValid(value)) 2552 return value.value(); 2553 2554 value = m_strictInt52Values.get(edge.node()); 2555 if (isValid(value)) 2556 return strictInt52ToInt52(value.value()); 2557 break; 2558 2559 case StrictInt52: 2560 value = m_strictInt52Values.get(edge.node()); 2561 if (isValid(value)) 2562 return value.value(); 2563 2564 value = m_int52Values.get(edge.node()); 2565 if (isValid(value)) 2566 return int52ToStrictInt52(value.value()); 2567 break; 2568 } 2569 2570 value = m_int32Values.get(edge.node()); 2571 if (isValid(value)) { 2572 return setInt52WithStrictValue( 2573 edge.node(), m_out.signExt(value.value(), m_out.int64), kind); 2574 } 2575 2576 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52)); 2577 2578 value = m_jsValueValues.get(edge.node()); 2579 if (isValid(value)) { 2580 LValue boxedResult = value.value(); 2581 FTL_TYPE_CHECK( 2582 jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult)); 2583 return setInt52WithStrictValue( 2584 edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind); 2585 } 2586 2587 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt)); 2588 terminate(Uncountable); 2589 return m_out.int64Zero; 2590 } 2591 2592 LValue lowInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2593 { 2594 return lowInt52(edge, Int52, mode); 2595 } 2596 2597 LValue lowStrictInt52(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2598 { 2599 return lowInt52(edge, StrictInt52, mode); 2600 } 2601 2602 bool betterUseStrictInt52(Node* node) 2603 { 2604 return !isValid(m_int52Values.get(node)); 2605 } 2606 bool betterUseStrictInt52(Edge edge) 2607 { 2608 return betterUseStrictInt52(edge.node()); 2609 } 2610 template<typename T> 2611 Int52Kind bestInt52Kind(T node) 2612 { 2613 return betterUseStrictInt52(node) ? StrictInt52 : Int52; 2614 } 2615 Int52Kind opposite(Int52Kind kind) 2616 { 2617 switch (kind) { 2618 case Int52: 2619 return StrictInt52; 2620 case StrictInt52: 2621 return Int52; 2622 } 2623 RELEASE_ASSERT_NOT_REACHED(); 2624 } 2625 2626 LValue lowWhicheverInt52(Edge edge, Int52Kind& kind, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2627 { 2628 kind = bestInt52Kind(edge); 2629 return lowInt52(edge, kind, mode); 2630 } 2631 2374 2632 LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 2375 2633 { 2376 2634 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isCell(edge.useKind())); 2635 2636 if (edge->op() == JSConstant) { 2637 JSValue value = m_graph.valueOfJSConstant(edge.node()); 2638 if (!value.isCell()) { 2639 terminate(Uncountable); 2640 return m_out.intPtrZero; 2641 } 2642 return m_out.constIntPtr(value.asCell()); 2643 } 2377 2644 2378 2645 LoweredNodeValue value = m_jsValueValues.get(edge.node()); … … 2419 2686 { 2420 2687 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == BooleanUse); 2688 2689 if (edge->hasConstant()) { 2690 JSValue value = m_graph.valueOfJSConstant(edge.node()); 2691 if (!value.isBoolean()) { 2692 terminate(Uncountable); 2693 return m_out.booleanFalse; 2694 } 2695 return m_out.constBool(value.asBoolean()); 2696 } 2421 2697 2422 2698 LoweredNodeValue value = m_booleanValues.get(edge.node()); … … 2443 2719 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind())); 2444 2720 2721 if (edge->hasConstant()) { 2722 JSValue value = m_graph.valueOfJSConstant(edge.node()); 2723 if (!value.isNumber()) { 2724 terminate(Uncountable); 2725 return m_out.doubleZero; 2726 } 2727 return m_out.constDouble(value.asNumber()); 2728 } 2729 2445 2730 LoweredNodeValue value = m_doubleValues.get(edge.node()); 2446 2731 if (isValid(value)) … … 2454 2739 } 2455 2740 2741 value = m_strictInt52Values.get(edge.node()); 2742 if (isValid(value)) 2743 return strictInt52ToDouble(edge, value.value()); 2744 2745 value = m_int52Values.get(edge.node()); 2746 if (isValid(value)) 2747 return strictInt52ToDouble(edge, int52ToStrictInt52(value.value())); 2748 2456 2749 value = m_jsValueValues.get(edge.node()); 2457 2750 if (isValid(value)) { … … 2473 2766 2474 2767 FTL_TYPE_CHECK( 2475 jsValueValue(boxedResult), edge, Spec Number, isCellOrMisc(boxedResult));2768 jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult)); 2476 2769 2477 2770 ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult)); … … 2486 2779 } 2487 2780 2488 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & Spec Number));2781 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber)); 2489 2782 terminate(Uncountable); 2490 2783 return m_out.doubleZero; … … 2494 2787 { 2495 2788 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse); 2789 2790 if (edge->hasConstant()) 2791 return m_out.constInt64(JSValue::encode(m_graph.valueOfJSConstant(edge.node()))); 2496 2792 2497 2793 LoweredNodeValue value = m_jsValueValues.get(edge.node()); … … 2506 2802 } 2507 2803 2804 value = m_strictInt52Values.get(edge.node()); 2805 if (isValid(value)) 2806 return strictInt52ToJSValue(value.value()); 2807 2808 value = m_int52Values.get(edge.node()); 2809 if (isValid(value)) 2810 return strictInt52ToJSValue(int52ToStrictInt52(value.value())); 2811 2508 2812 value = m_booleanValues.get(edge.node()); 2509 2813 if (isValid(value)) { … … 2533 2837 setStorage(edge.node(), result); 2534 2838 return result; 2839 } 2840 2841 LValue strictInt52ToInt32(Edge edge, LValue value) 2842 { 2843 LValue result = m_out.castToInt32(value); 2844 FTL_TYPE_CHECK( 2845 noValue(), edge, SpecInt32, 2846 m_out.notEqual(m_out.signExt(result, m_out.int64), value)); 2847 setInt32(edge.node(), result); 2848 return result; 2849 } 2850 2851 LValue strictInt52ToDouble(Edge edge, LValue value) 2852 { 2853 LValue result = m_out.intToDouble(value); 2854 setDouble(edge.node(), result); 2855 return result; 2856 } 2857 2858 LValue strictInt52ToJSValue(LValue value) 2859 { 2860 LBasicBlock isInt32 = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isInt32 case")); 2861 LBasicBlock isDouble = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue isDouble case")); 2862 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("strictInt52ToJSValue continuation")); 2863 2864 Vector<ValueFromBlock, 2> results; 2865 2866 LValue int32Value = m_out.castToInt32(value); 2867 m_out.branch( 2868 m_out.equal(m_out.signExt(int32Value, m_out.int64), value), 2869 isInt32, isDouble); 2870 2871 LBasicBlock lastNext = m_out.appendTo(isInt32, isDouble); 2872 2873 results.append(m_out.anchor(boxInt32(int32Value))); 2874 m_out.jump(continuation); 2875 2876 m_out.appendTo(isDouble, continuation); 2877 2878 results.append(m_out.anchor(boxDouble(m_out.intToDouble(value)))); 2879 m_out.jump(continuation); 2880 2881 m_out.appendTo(continuation, lastNext); 2882 return m_out.phi(m_out.int64, results); 2883 } 2884 2885 LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind) 2886 { 2887 switch (kind) { 2888 case StrictInt52: 2889 setStrictInt52(node, value); 2890 return value; 2891 2892 case Int52: 2893 value = strictInt52ToInt52(value); 2894 setInt52(node, value); 2895 return value; 2896 } 2897 2898 RELEASE_ASSERT_NOT_REACHED(); 2899 return 0; 2900 } 2901 2902 LValue strictInt52ToInt52(LValue value) 2903 { 2904 return m_out.shl(value, m_out.constInt64(JSValue::int52ShiftAmount)); 2905 } 2906 2907 LValue int52ToStrictInt52(LValue value) 2908 { 2909 return m_out.aShr(value, m_out.constInt64(JSValue::int52ShiftAmount)); 2535 2910 } 2536 2911 … … 2795 3170 LValue value = lowDouble(edge); 2796 3171 FTL_TYPE_CHECK( 2797 doubleValue(value), edge, Spec RealNumber,3172 doubleValue(value), edge, SpecFullRealNumber, 2798 3173 m_out.doubleNotEqualOrUnordered(value, value)); 2799 3174 } … … 2803 3178 lowBoolean(edge); 2804 3179 } 2805 3180 2806 3181 bool masqueradesAsUndefinedWatchpointIsStillValid() 2807 3182 { … … 2934 3309 break; 2935 3310 3311 case FlushedInt52: 3312 m_valueSources[i] = ValueSource(Int52InJSStack); 3313 break; 3314 2936 3315 case FlushedDouble: 2937 3316 m_valueSources[i] = ValueSource(DoubleInJSStack); … … 3036 3415 case Int32InJSStack: 3037 3416 exit.m_values[i] = ExitValue::inJSStackAsInt32(); 3417 break; 3418 case Int52InJSStack: 3419 exit.m_values[i] = ExitValue::inJSStackAsInt52(); 3038 3420 break; 3039 3421 case DoubleInJSStack: … … 3140 3522 } 3141 3523 3524 value = m_int52Values.get(node); 3525 if (isValid(value)) { 3526 addExitArgument(exit, arguments, index, ValueFormatInt52, value.value()); 3527 return; 3528 } 3529 3530 value = m_strictInt52Values.get(node); 3531 if (isValid(value)) { 3532 addExitArgument(exit, arguments, index, ValueFormatStrictInt52, value.value()); 3533 return; 3534 } 3535 3142 3536 value = m_booleanValues.get(node); 3143 3537 if (isValid(value)) { … … 3243 3637 m_int32Values.set(node, LoweredNodeValue(value, m_highBlock)); 3244 3638 } 3639 void setInt52(Node* node, LValue value) 3640 { 3641 m_int52Values.set(node, LoweredNodeValue(value, m_highBlock)); 3642 } 3643 void setStrictInt52(Node* node, LValue value) 3644 { 3645 m_strictInt52Values.set(node, LoweredNodeValue(value, m_highBlock)); 3646 } 3647 void setInt52(Node* node, LValue value, Int52Kind kind) 3648 { 3649 switch (kind) { 3650 case Int52: 3651 setInt52(node, value); 3652 return; 3653 3654 case StrictInt52: 3655 setStrictInt52(node, value); 3656 return; 3657 } 3658 3659 RELEASE_ASSERT_NOT_REACHED(); 3660 } 3245 3661 void setJSValue(Node* node, LValue value) 3246 3662 { … … 3263 3679 { 3264 3680 setInt32(m_node, value); 3681 } 3682 void setInt52(LValue value) 3683 { 3684 setInt52(m_node, value); 3685 } 3686 void setStrictInt52(LValue value) 3687 { 3688 setStrictInt52(m_node, value); 3689 } 3690 void setInt52(LValue value, Int52Kind kind) 3691 { 3692 setInt52(m_node, value, kind); 3265 3693 } 3266 3694 void setJSValue(LValue value) … … 3343 3771 3344 3772 HashMap<Node*, LoweredNodeValue> m_int32Values; 3773 HashMap<Node*, LoweredNodeValue> m_strictInt52Values; 3774 HashMap<Node*, LoweredNodeValue> m_int52Values; 3345 3775 HashMap<Node*, LoweredNodeValue> m_jsValueValues; 3346 3776 HashMap<Node*, LoweredNodeValue> m_booleanValues; -
trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
r155995 r156019 105 105 } 106 106 107 // All temp registers are free at this point. 108 107 109 // Box anything that is already on the stack, or that is a constant. 108 110 … … 129 131 jit.store64(GPRInfo::regT0, address); 130 132 break; 133 case ExitValueInJSStackAsInt52: 134 jit.load64(address, GPRInfo::regT0); 135 jit.rshift64( 136 AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), GPRInfo::regT0); 137 jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0); 138 jit.store64(GPRInfo::regT0, address); 139 break; 131 140 case ExitValueInJSStackAsDouble: 132 141 jit.loadDouble(address, FPRInfo::fpRegT0); … … 161 170 shouldShowDisassembly(), 162 171 patchBuffer, 163 ("FTL OSR exit #%u (bc#%u, %s) from %s ",172 ("FTL OSR exit #%u (bc#%u, %s) from %s, with operands = %s", 164 173 exitID, exit.m_codeOrigin.bytecodeIndex, 165 exitKindToString(exit.m_kind), toCString(*codeBlock).data())); 174 exitKindToString(exit.m_kind), toCString(*codeBlock).data(), 175 toCString(ignoringContext<DumpContext>(exit.m_values)).data())); 166 176 } 167 177 -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r155281 r156019 167 167 return call(mulWithOverflow32Intrinsic(), left, right); 168 168 } 169 LValue addWithOverflow64(LValue left, LValue right) 170 { 171 return call(addWithOverflow64Intrinsic(), left, right); 172 } 173 LValue subWithOverflow64(LValue left, LValue right) 174 { 175 return call(subWithOverflow64Intrinsic(), left, right); 176 } 177 LValue mulWithOverflow64(LValue left, LValue right) 178 { 179 return call(mulWithOverflow64Intrinsic(), left, right); 180 } 169 181 LValue doubleAbs(LValue value) 170 182 { -
trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp
r153121 r156019 45 45 out.print("UInt32"); 46 46 return; 47 case ValueFormatInt52: 48 out.print("Int52"); 49 return; 50 case ValueFormatStrictInt52: 51 out.print("StrictInt52"); 52 return; 47 53 case ValueFormatBoolean: 48 54 out.print("Boolean"); -
trunk/Source/JavaScriptCore/ftl/FTLValueFormat.h
r153121 r156019 42 42 ValueFormatInt32, 43 43 ValueFormatUInt32, 44 ValueFormatInt52, 45 ValueFormatStrictInt52, 44 46 ValueFormatBoolean, 45 47 ValueFormatJSValue, -
trunk/Source/JavaScriptCore/ftl/FTLValueSource.cpp
r153296 r156019 43 43 out.print("Int32InJSStack"); 44 44 return; 45 case Int52InJSStack: 46 out.print("Int52InJSStack"); 47 return; 45 48 case DoubleInJSStack: 46 49 out.print("DoubleInJSStack"); -
trunk/Source/JavaScriptCore/ftl/FTLValueSource.h
r153296 r156019 41 41 ValueInJSStack, 42 42 Int32InJSStack, 43 Int52InJSStack, 43 44 DoubleInJSStack, 44 45 SourceIsDead, -
trunk/Source/JavaScriptCore/interpreter/Register.h
r155023 r156019 74 74 InlineCallFrame* asInlineCallFrame() const; 75 75 int32_t unboxedInt32() const; 76 int64_t unboxedInt52() const; 76 77 bool unboxedBoolean() const; 77 78 double unboxedDouble() const; … … 99 100 EncodedValueDescriptor encodedValue; 100 101 double number; 102 int64_t integer; 101 103 } u; 102 104 }; … … 184 186 { 185 187 return payload(); 188 } 189 190 ALWAYS_INLINE int64_t Register::unboxedInt52() const 191 { 192 return u.integer >> JSValue::int52ShiftAmount; 186 193 } 187 194 -
trunk/Source/JavaScriptCore/runtime/Arguments.cpp
r155711 r156019 384 384 value = jsNumber(location->unboxedInt32()); 385 385 break; 386 case AlreadyInJSStackAsUnboxedInt52: 387 value = jsNumber(location->unboxedInt52()); 388 break; 386 389 case AlreadyInJSStackAsUnboxedCell: 387 390 value = location->unboxedCell(); -
trunk/Source/JavaScriptCore/runtime/IndexingType.cpp
r138073 r156019 51 51 if (isInt32Speculation(type)) 52 52 return (indexingType & ~IndexingShapeMask) | Int32Shape; 53 if (is NumberSpeculation(type))53 if (isFullNumberSpeculation(type)) 54 54 return (indexingType & ~IndexingShapeMask) | DoubleShape; 55 55 return (indexingType & ~IndexingShapeMask) | ContiguousShape; 56 56 case ALL_DOUBLE_INDEXING_TYPES: 57 if (is NumberSpeculation(type))57 if (isFullNumberSpeculation(type)) 58 58 return indexingType; 59 59 return (indexingType & ~IndexingShapeMask) | ContiguousShape; -
trunk/Source/JavaScriptCore/runtime/JSCJSValue.h
r155643 r156019 192 192 int32_t asInt32() const; 193 193 uint32_t asUInt32() const; 194 int64_t asMachineInt() const; 194 195 double asDouble() const; 195 196 bool asBoolean() const; … … 203 204 bool isUndefinedOrNull() const; 204 205 bool isBoolean() const; 206 bool isMachineInt() const; 205 207 bool isNumber() const; 206 208 bool isString() const; … … 274 276 275 277 JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; 278 279 #if USE(JSVALUE64) 280 // Constants used for Int52. Int52 isn't part of JSValue right now, but JSValues may be 281 // converted to Int52s and back again. 282 static const unsigned numberOfInt52Bits = 52; 283 static const unsigned int52ShiftAmount = 12; 284 #endif 276 285 277 286 private: -
trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h
r154902 r156019 495 495 #endif // USE(JSVALUE64) 496 496 497 inline bool JSValue::isMachineInt() const 498 { 499 if (isInt32()) 500 return true; 501 if (!isNumber()) 502 return false; 503 double number = asDouble(); 504 if (number != number) 505 return false; 506 int64_t asInt64 = static_cast<int64_t>(number); 507 if (asInt64 != number) 508 return false; 509 if (!asInt64 && std::signbit(number)) 510 return false; 511 if (asInt64 >= (static_cast<int64_t>(1) << (numberOfInt52Bits - 1))) 512 return false; 513 if (asInt64 < -(static_cast<int64_t>(1) << (numberOfInt52Bits - 1))) 514 return false; 515 return true; 516 } 517 518 inline int64_t JSValue::asMachineInt() const 519 { 520 ASSERT(isMachineInt()); 521 if (isInt32()) 522 return asInt32(); 523 return static_cast<int64_t>(asDouble()); 524 } 525 497 526 inline bool JSValue::isString() const 498 527 { -
trunk/Source/WTF/ChangeLog
r156004 r156019 1 2013-09-16 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should support Int52 for local variables 4 https://bugs.webkit.org/show_bug.cgi?id=121064 5 6 Reviewed by Oliver Hunt. 7 8 * wtf/PrintStream.h: 9 (WTF::ValueIgnoringContext::ValueIgnoringContext): 10 (WTF::ValueIgnoringContext::dump): 11 (WTF::ignoringContext): 12 1 13 2013-09-17 Anders Carlsson <andersca@apple.com> 2 14 -
trunk/Source/WTF/wtf/PrintStream.h
r155251 r156019 361 361 } 362 362 363 template<typename T, typename U> 364 class ValueIgnoringContext { 365 public: 366 ValueIgnoringContext(const U& value) 367 : m_value(&value) 368 { 369 } 370 371 void dump(PrintStream& out) const 372 { 373 T context; 374 m_value->dumpInContext(out, &context); 375 } 376 377 private: 378 const U* m_value; 379 }; 380 381 template<typename T, typename U> 382 ValueIgnoringContext<T, U> ignoringContext(const U& value) 383 { 384 return ValueIgnoringContext<T, U>(value); 385 } 386 363 387 } // namespace WTF 364 388 … … 366 390 using WTF::PointerDump; 367 391 using WTF::PrintStream; 392 using WTF::ignoringContext; 368 393 using WTF::inContext; 369 394 using WTF::pointerDump; -
trunk/Tools/ChangeLog
r156018 r156019 1 2013-09-17 Filip Pizlo <fpizlo@apple.com> 2 3 DFG should support Int52 for local variables 4 https://bugs.webkit.org/show_bug.cgi?id=121064 5 6 Reviewed by Oliver Hunt. 7 8 * Scripts/run-jsc-stress-tests: 9 1 10 2013-09-17 Alex Christensen <alex.christensen@flexsim.com> 2 11 -
trunk/Tools/Scripts/run-jsc-stress-tests
r155489 r156019 215 215 runAlwaysTriggerCopyPhase 216 216 runNoCJIT 217 runDFGEager 217 218 if $enableFTL 218 219 runDefaultFTL 219 220 runFTLNoCJIT 220 221 runFTLEager 221 else222 runDFGEager223 222 end 224 223 end
Note: See TracChangeset
for help on using the changeset viewer.