Changeset 167325 in webkit
- Timestamp:
- Apr 15, 2014 1:26:16 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 deleted
- 50 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r167313 r167325 1 2014-04-15 Filip Pizlo <fpizlo@apple.com> 2 3 DFG IR should keep the data flow of doubles and int52's separate from the data flow of JSValue's 4 https://bugs.webkit.org/show_bug.cgi?id=131423 5 6 Reviewed by Geoffrey Garen. 7 8 This introduces more static typing into DFG IR. Previously we just had the notion of 9 JSValues and Storage. This was weird because doubles weren't always convertible to 10 JSValues, and Int52s weren't always convertible to either doubles or JSValues. We would 11 sort of insert explicit conversion nodes just for the places where we knew that an 12 implicit conversion wouldn't have been possible -- but there was no hard and fast rule so 13 we'd get bugs from forgetting to do the right conversion. 14 15 This patch introduces a hard and fast rule: doubles can never be implicitly converted to 16 anything but doubles, and likewise Int52's can never be implicitly converted. Conversion 17 nodes are used for all of the conversions. Int52Rep, DoubleRep, and ValueRep are the 18 conversions. They are like Identity but return the same value using a different 19 representation. Likewise, constants may now be represented using either JSConstant, 20 Int52Constant, or DoubleConstant. UseKinds have been adjusted accordingly, as well. 21 Int52RepUse and DoubleRepUse are node uses that mean "the node must be of Int52 (or 22 Double) type". They don't imply checks. There is also DoubleRepRealUse, which means that 23 we speculate DoubleReal and expect Double representation. 24 25 In addition to simplifying a bunch of rules in the IR and making the IR more verifiable, 26 this also makes it easier to introduce optimizations in the future. It's now possible for 27 AI to model when/how conversion take place. For example if doing a conversion results in 28 NaN sanitization, then AI can model this and can allow us to sink sanitizations. That's 29 what https://bugs.webkit.org/show_bug.cgi?id=131419 will be all about. 30 31 This was a big change, so I had to do some interesting things, like finally get rid of 32 the DFG's weird variadic template macro hacks and use real C++11 variadic templates. Also 33 the ByteCodeParser no longer emits Identity nodes since that was always pointless. 34 35 No performance change because this mostly just rationalizes preexisting behavior. 36 37 * JavaScriptCore.xcodeproj/project.pbxproj: 38 * assembler/MacroAssemblerX86.h: 39 * bytecode/CodeBlock.cpp: 40 * bytecode/CodeBlock.h: 41 * dfg/DFGAbstractInterpreter.h: 42 (JSC::DFG::AbstractInterpreter::setBuiltInConstant): 43 (JSC::DFG::AbstractInterpreter::setConstant): 44 * dfg/DFGAbstractInterpreterInlines.h: 45 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 46 * dfg/DFGAbstractValue.cpp: 47 (JSC::DFG::AbstractValue::set): 48 (JSC::DFG::AbstractValue::fixTypeForRepresentation): 49 (JSC::DFG::AbstractValue::checkConsistency): 50 * dfg/DFGAbstractValue.h: 51 * dfg/DFGBackwardsPropagationPhase.cpp: 52 (JSC::DFG::BackwardsPropagationPhase::propagate): 53 * dfg/DFGBasicBlock.h: 54 * dfg/DFGBasicBlockInlines.h: 55 (JSC::DFG::BasicBlock::appendNode): 56 (JSC::DFG::BasicBlock::appendNonTerminal): 57 * dfg/DFGByteCodeParser.cpp: 58 (JSC::DFG::ByteCodeParser::parseBlock): 59 * dfg/DFGCSEPhase.cpp: 60 (JSC::DFG::CSEPhase::constantCSE): 61 (JSC::DFG::CSEPhase::performNodeCSE): 62 (JSC::DFG::CSEPhase::int32ToDoubleCSE): Deleted. 63 * dfg/DFGCapabilities.h: 64 * dfg/DFGClobberize.h: 65 (JSC::DFG::clobberize): 66 * dfg/DFGConstantFoldingPhase.cpp: 67 (JSC::DFG::ConstantFoldingPhase::foldConstants): 68 * dfg/DFGDCEPhase.cpp: 69 (JSC::DFG::DCEPhase::fixupBlock): 70 * dfg/DFGEdge.h: 71 (JSC::DFG::Edge::willNotHaveCheck): 72 * dfg/DFGFixupPhase.cpp: 73 (JSC::DFG::FixupPhase::run): 74 (JSC::DFG::FixupPhase::fixupNode): 75 (JSC::DFG::FixupPhase::fixupGetAndSetLocalsInBlock): 76 (JSC::DFG::FixupPhase::observeUseKindOnNode): 77 (JSC::DFG::FixupPhase::fixIntEdge): 78 (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd): 79 (JSC::DFG::FixupPhase::injectTypeConversionsInBlock): 80 (JSC::DFG::FixupPhase::tryToRelaxRepresentation): 81 (JSC::DFG::FixupPhase::fixEdgeRepresentation): 82 (JSC::DFG::FixupPhase::injectTypeConversionsForEdge): 83 (JSC::DFG::FixupPhase::addRequiredPhantom): 84 (JSC::DFG::FixupPhase::addPhantomsIfNecessary): 85 (JSC::DFG::FixupPhase::clearPhantomsAtEnd): 86 (JSC::DFG::FixupPhase::fixupSetLocalsInBlock): Deleted. 87 * dfg/DFGFlushFormat.h: 88 (JSC::DFG::resultFor): 89 (JSC::DFG::useKindFor): 90 * dfg/DFGGraph.cpp: 91 (JSC::DFG::Graph::dump): 92 * dfg/DFGGraph.h: 93 (JSC::DFG::Graph::addNode): 94 * dfg/DFGInPlaceAbstractState.cpp: 95 (JSC::DFG::InPlaceAbstractState::initialize): 96 * dfg/DFGInsertionSet.h: 97 (JSC::DFG::InsertionSet::insertNode): 98 (JSC::DFG::InsertionSet::insertConstant): 99 (JSC::DFG::InsertionSet::insertConstantForUse): 100 * dfg/DFGIntegerCheckCombiningPhase.cpp: 101 (JSC::DFG::IntegerCheckCombiningPhase::insertAdd): 102 (JSC::DFG::IntegerCheckCombiningPhase::insertMustAdd): 103 * dfg/DFGNode.cpp: 104 (JSC::DFG::Node::convertToIdentity): 105 (WTF::printInternal): 106 * dfg/DFGNode.h: 107 (JSC::DFG::Node::Node): 108 (JSC::DFG::Node::setResult): 109 (JSC::DFG::Node::result): 110 (JSC::DFG::Node::isConstant): 111 (JSC::DFG::Node::hasConstant): 112 (JSC::DFG::Node::convertToConstant): 113 (JSC::DFG::Node::valueOfJSConstant): 114 (JSC::DFG::Node::hasResult): 115 (JSC::DFG::Node::hasInt32Result): 116 (JSC::DFG::Node::hasInt52Result): 117 (JSC::DFG::Node::hasNumberResult): 118 (JSC::DFG::Node::hasDoubleResult): 119 (JSC::DFG::Node::hasJSResult): 120 (JSC::DFG::Node::hasBooleanResult): 121 (JSC::DFG::Node::hasStorageResult): 122 (JSC::DFG::Node::defaultUseKind): 123 (JSC::DFG::Node::defaultEdge): 124 (JSC::DFG::Node::convertToIdentity): Deleted. 125 * dfg/DFGNodeFlags.cpp: 126 (JSC::DFG::dumpNodeFlags): 127 * dfg/DFGNodeFlags.h: 128 (JSC::DFG::canonicalResultRepresentation): 129 * dfg/DFGNodeType.h: 130 * dfg/DFGOSRExitCompiler32_64.cpp: 131 (JSC::DFG::OSRExitCompiler::compileExit): 132 * dfg/DFGOSRExitCompiler64.cpp: 133 (JSC::DFG::OSRExitCompiler::compileExit): 134 * dfg/DFGPredictionPropagationPhase.cpp: 135 (JSC::DFG::PredictionPropagationPhase::propagate): 136 * dfg/DFGResurrectionForValidationPhase.cpp: 137 (JSC::DFG::ResurrectionForValidationPhase::run): 138 * dfg/DFGSSAConversionPhase.cpp: 139 (JSC::DFG::SSAConversionPhase::run): 140 * dfg/DFGSafeToExecute.h: 141 (JSC::DFG::SafeToExecuteEdge::operator()): 142 (JSC::DFG::safeToExecute): 143 * dfg/DFGSpeculativeJIT.cpp: 144 (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR): 145 (JSC::DFG::SpeculativeJIT::silentSavePlanForFPR): 146 (JSC::DFG::SpeculativeJIT::silentFill): 147 (JSC::DFG::JSValueRegsTemporary::JSValueRegsTemporary): 148 (JSC::DFG::JSValueRegsTemporary::~JSValueRegsTemporary): 149 (JSC::DFG::JSValueRegsTemporary::regs): 150 (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): 151 (JSC::DFG::SpeculativeJIT::checkGeneratedTypeForToInt32): 152 (JSC::DFG::SpeculativeJIT::compileValueToInt32): 153 (JSC::DFG::SpeculativeJIT::compileDoubleRep): 154 (JSC::DFG::SpeculativeJIT::compileValueRep): 155 (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): 156 (JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray): 157 (JSC::DFG::SpeculativeJIT::compileAdd): 158 (JSC::DFG::SpeculativeJIT::compileArithSub): 159 (JSC::DFG::SpeculativeJIT::compileArithNegate): 160 (JSC::DFG::SpeculativeJIT::compileArithMul): 161 (JSC::DFG::SpeculativeJIT::compileArithDiv): 162 (JSC::DFG::SpeculativeJIT::compileArithMod): 163 (JSC::DFG::SpeculativeJIT::compare): 164 (JSC::DFG::SpeculativeJIT::compileStrictEq): 165 (JSC::DFG::SpeculativeJIT::speculateNumber): 166 (JSC::DFG::SpeculativeJIT::speculateDoubleReal): 167 (JSC::DFG::SpeculativeJIT::speculate): 168 (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): Deleted. 169 (JSC::DFG::SpeculativeJIT::speculateMachineInt): Deleted. 170 (JSC::DFG::SpeculativeJIT::speculateRealNumber): Deleted. 171 * dfg/DFGSpeculativeJIT.h: 172 (JSC::DFG::SpeculativeJIT::allocate): 173 (JSC::DFG::SpeculativeJIT::use): 174 (JSC::DFG::SpeculativeJIT::boxDouble): 175 (JSC::DFG::SpeculativeJIT::spill): 176 (JSC::DFG::SpeculativeJIT::jsValueResult): 177 (JSC::DFG::SpeculateInt52Operand::SpeculateInt52Operand): 178 (JSC::DFG::SpeculateStrictInt52Operand::SpeculateStrictInt52Operand): 179 (JSC::DFG::SpeculateWhicheverInt52Operand::SpeculateWhicheverInt52Operand): 180 (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand): 181 * dfg/DFGSpeculativeJIT32_64.cpp: 182 (JSC::DFG::SpeculativeJIT::fillJSValue): 183 (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal): 184 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 185 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 186 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 187 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 188 (JSC::DFG::SpeculativeJIT::emitBranch): 189 (JSC::DFG::SpeculativeJIT::compile): 190 (JSC::DFG::SpeculativeJIT::convertToDouble): Deleted. 191 * dfg/DFGSpeculativeJIT64.cpp: 192 (JSC::DFG::SpeculativeJIT::fillJSValue): 193 (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal): 194 (JSC::DFG::SpeculativeJIT::fillSpeculateInt52): 195 (JSC::DFG::SpeculativeJIT::fillSpeculateDouble): 196 (JSC::DFG::SpeculativeJIT::fillSpeculateCell): 197 (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): 198 (JSC::DFG::SpeculativeJIT::compileLogicalNot): 199 (JSC::DFG::SpeculativeJIT::emitBranch): 200 (JSC::DFG::SpeculativeJIT::compile): 201 (JSC::DFG::SpeculativeJIT::convertToDouble): Deleted. 202 * dfg/DFGStrengthReductionPhase.cpp: 203 (JSC::DFG::StrengthReductionPhase::handleNode): 204 * dfg/DFGUseKind.cpp: 205 (WTF::printInternal): 206 * dfg/DFGUseKind.h: 207 (JSC::DFG::typeFilterFor): 208 (JSC::DFG::shouldNotHaveTypeCheck): 209 (JSC::DFG::mayHaveTypeCheck): 210 (JSC::DFG::isNumerical): 211 (JSC::DFG::isDouble): 212 (JSC::DFG::isCell): 213 (JSC::DFG::usesStructure): 214 (JSC::DFG::useKindForResult): 215 * dfg/DFGValidate.cpp: 216 (JSC::DFG::Validate::validate): 217 * dfg/DFGVariadicFunction.h: Removed. 218 * ftl/FTLCapabilities.cpp: 219 (JSC::FTL::canCompile): 220 * ftl/FTLLowerDFGToLLVM.cpp: 221 (JSC::FTL::LowerDFGToLLVM::createPhiVariables): 222 (JSC::FTL::LowerDFGToLLVM::compileNode): 223 (JSC::FTL::LowerDFGToLLVM::compileUpsilon): 224 (JSC::FTL::LowerDFGToLLVM::compilePhi): 225 (JSC::FTL::LowerDFGToLLVM::compileDoubleConstant): 226 (JSC::FTL::LowerDFGToLLVM::compileInt52Constant): 227 (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant): 228 (JSC::FTL::LowerDFGToLLVM::compileDoubleRep): 229 (JSC::FTL::LowerDFGToLLVM::compileValueRep): 230 (JSC::FTL::LowerDFGToLLVM::compileInt52Rep): 231 (JSC::FTL::LowerDFGToLLVM::compileValueToInt32): 232 (JSC::FTL::LowerDFGToLLVM::compileArithAddOrSub): 233 (JSC::FTL::LowerDFGToLLVM::compileArithMul): 234 (JSC::FTL::LowerDFGToLLVM::compileArithDiv): 235 (JSC::FTL::LowerDFGToLLVM::compileArithMod): 236 (JSC::FTL::LowerDFGToLLVM::compileArithMinOrMax): 237 (JSC::FTL::LowerDFGToLLVM::compileArithAbs): 238 (JSC::FTL::LowerDFGToLLVM::compileArithNegate): 239 (JSC::FTL::LowerDFGToLLVM::compilePutByVal): 240 (JSC::FTL::LowerDFGToLLVM::compileCompareEq): 241 (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq): 242 (JSC::FTL::LowerDFGToLLVM::compare): 243 (JSC::FTL::LowerDFGToLLVM::boolify): 244 (JSC::FTL::LowerDFGToLLVM::lowInt52): 245 (JSC::FTL::LowerDFGToLLVM::lowStrictInt52): 246 (JSC::FTL::LowerDFGToLLVM::lowWhicheverInt52): 247 (JSC::FTL::LowerDFGToLLVM::lowDouble): 248 (JSC::FTL::LowerDFGToLLVM::lowJSValue): 249 (JSC::FTL::LowerDFGToLLVM::strictInt52ToDouble): 250 (JSC::FTL::LowerDFGToLLVM::jsValueToDouble): 251 (JSC::FTL::LowerDFGToLLVM::speculate): 252 (JSC::FTL::LowerDFGToLLVM::speculateNumber): 253 (JSC::FTL::LowerDFGToLLVM::speculateDoubleReal): 254 (JSC::FTL::LowerDFGToLLVM::compileInt52ToValue): Deleted. 255 (JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble): Deleted. 256 (JSC::FTL::LowerDFGToLLVM::setInt52WithStrictValue): Deleted. 257 (JSC::FTL::LowerDFGToLLVM::speculateRealNumber): Deleted. 258 (JSC::FTL::LowerDFGToLLVM::speculateMachineInt): Deleted. 259 * ftl/FTLValueFormat.cpp: 260 (JSC::FTL::reboxAccordingToFormat): 261 * jit/AssemblyHelpers.cpp: 262 (JSC::AssemblyHelpers::sanitizeDouble): 263 * jit/AssemblyHelpers.h: 264 (JSC::AssemblyHelpers::boxDouble): 265 1 266 2014-04-15 Commit Queue <commit-queue@webkit.org> 2 267 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r167313 r167325 611 611 0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 612 612 0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 613 0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };614 613 0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; 615 614 0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 895 894 5540772118DA58AD00EFF7F2 /* JSArrayBufferViewInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */; }; 896 895 5540772218DA58AD00EFF7F2 /* JSArrayIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */; }; 897 5540772518DA58AD00EFF7F2 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };896 5540772518DA58AD00EFF7F2 /* (null) in Headers */ = {isa = PBXBuildFile; }; 898 897 5540772B18DA58AD00EFF7F2 /* JSCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC1167D80E19BCC9008066DD /* JSCell.h */; }; 899 898 5540772C18DA58AD00EFF7F2 /* JSCellInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F97496F1687ADE200A4FF6A /* JSCellInlines.h */; }; … … 1044 1043 5540788D18DA58AD00EFF7F2 /* WriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A7DCB77912E3D90500911940 /* WriteBarrier.h */; }; 1045 1044 5540788F18DA58AD00EFF7F2 /* WriteBarrierInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */; }; 1046 5540789E18DA58AD00EFF7F2 /* Arguments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC257DE50E1F51C50016B6C9 /* Arguments.cpp */; };1047 554078A018DA58AD00EFF7F2 /* ArgumentsIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A76140C9182982CB00750624 /* ArgumentsIteratorPrototype.cpp */; };1048 1045 554078AB18DA58AD00EFF7F2 /* ArrayConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */; }; 1049 554078AD18DA58AD00EFF7F2 /* ArrayIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BDAEC217F4EA1400F6140C /* ArrayIteratorPrototype.cpp */; };1050 1046 554078AF18DA58AD00EFF7F2 /* ArrayPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A84D0255597D01FF60F7 /* ArrayPrototype.cpp */; }; 1051 554078B218DA58AD00EFF7F2 /* BooleanConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952320E15EB5600A898AB /* BooleanConstructor.cpp */; };1052 554078B418DA58AD00EFF7F2 /* BooleanPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC7952340E15EB5600A898AB /* BooleanPrototype.cpp */; };1053 554078D518DA58AD00EFF7F2 /* DateConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD203450E17135E002C7E82 /* DateConstructor.cpp */; };1054 554078D818DA58AD00EFF7F2 /* DatePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD203470E17135E002C7E82 /* DatePrototype.cpp */; };1055 5540794B18DA58AD00EFF7F2 /* ErrorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9040E1839DB000F9297 /* ErrorConstructor.cpp */; };1056 5540794E18DA58AD00EFF7F2 /* ErrorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */; };1057 5540797D18DA58AD00EFF7F2 /* FunctionConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C00E16D4E900A06E92 /* FunctionConstructor.cpp */; };1058 5540797F18DA58AD00EFF7F2 /* FunctionPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */; };1059 554079C218DA58AD00EFF7F2 /* JSArrayBufferConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66B617B6B5AB00A7AE3F /* JSArrayBufferConstructor.cpp */; };1060 554079C318DA58AD00EFF7F2 /* JSArrayBufferPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66B817B6B5AB00A7AE3F /* JSArrayBufferPrototype.cpp */; };1061 554079C518DA58AD00EFF7F2 /* JSArrayIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */; };1062 554079C718DA58AD00EFF7F2 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };1063 554079D318DA58AD00EFF7F2 /* JSDataViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66BF17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp */; };1064 554079D518DA58AD00EFF7F2 /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; };1065 554079DA18DA58AD00EFF7F2 /* JSGlobalObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */; };1066 554079EB18DA58AD00EFF7F2 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; };1067 554079EE18DA58AD00EFF7F2 /* JSPromiseConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C184E2017BEE240007CB63A /* JSPromiseConstructor.cpp */; };1068 554079F018DA58AD00EFF7F2 /* JSPromiseFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C008CD0186F8A9300955C24 /* JSPromiseFunctions.cpp */; };1069 554079F118DA58AD00EFF7F2 /* JSPromisePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C184E1C17BEE22E007CB63A /* JSPromisePrototype.cpp */; };1070 55407A2218DA58AD00EFF7F2 /* ConsolePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A53CE08118BC1A5600BEDF76 /* ConsolePrototype.cpp */; };1071 55407A2518DA58AD00EFF7F2 /* MapConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873717CBE85300C3E643 /* MapConstructor.cpp */; };1072 55407A2818DA58AD00EFF7F2 /* MapIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DEF8D182D991400522C22 /* MapIteratorPrototype.cpp */; };1073 55407A2918DA58AD00EFF7F2 /* MapPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A700873B17CBE8D300C3E643 /* MapPrototype.cpp */; };1074 55407A2E18DA58AD00EFF7F2 /* MathObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A86A0255597D01FF60F7 /* MathObject.cpp */; };1075 55407A3118DA58AD00EFF7F2 /* NameConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2F91560F036008E9222 /* NameConstructor.cpp */; };1076 55407A3318DA58AD00EFF7F2 /* NamePrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EBF2FD1560F036008E9222 /* NamePrototype.cpp */; };1077 1047 55407A3818DA58AD00EFF7F2 /* NumberConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C20E16D4E900A06E92 /* NumberConstructor.cpp */; }; 1078 1048 55407A3A18DA58AD00EFF7F2 /* NumberPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C40E16D4E900A06E92 /* NumberPrototype.cpp */; }; 1079 55407A3C18DA58AD00EFF7F2 /* ObjectConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C60E16D4E900A06E92 /* ObjectConstructor.cpp */; };1080 55407A3D18DA58AD00EFF7F2 /* ObjectPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC2680C80E16D4E900A06E92 /* ObjectPrototype.cpp */; };1081 55407A6318DA58AD00EFF7F2 /* RegExpConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */; };1082 55407A6618DA58AD00EFF7F2 /* RegExpPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */; };1083 55407A7B18DA58AD00EFF7F2 /* SetIteratorPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A790DD67182F499700588807 /* SetIteratorPrototype.cpp */; };1084 55407A7C18DA58AD00EFF7F2 /* SetPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9F17D12848005F5FF9 /* SetPrototype.cpp */; };1085 55407A8818DA58AD00EFF7F2 /* StringConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C00E16EE3300B34460 /* StringConstructor.cpp */; };1086 55407A8A18DA58AD00EFF7F2 /* StringPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC18C3C50E16EE3300B34460 /* StringPrototype.cpp */; };1087 55407AAC18DA58AD00EFF7F2 /* WeakMapConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA3ADD17DA41AE006538AF /* WeakMapConstructor.cpp */; };1088 55407AAE18DA58AD00EFF7F2 /* WeakMapPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7CA3ADF17DA41AE006538AF /* WeakMapPrototype.cpp */; };1089 55F1380B18EF5F5000982015 /* NativeErrorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */; };1090 55F1380C18EF5FB900982015 /* SetConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299DA317D12858005F5FF9 /* SetConstructor.cpp */; };1091 1049 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 1092 1050 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; … … 2186 2144 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayAllocationProfile.h; sourceTree = "<group>"; }; 2187 2145 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBranchDirection.h; path = dfg/DFGBranchDirection.h; sourceTree = "<group>"; }; 2188 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariadicFunction.h; path = dfg/DFGVariadicFunction.h; sourceTree = "<group>"; };2189 2146 0F885E101849A3BE00F1E3FA /* BytecodeUseDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeUseDef.h; sourceTree = "<group>"; }; 2190 2147 0F8F2B93172E049E007DBDA5 /* FTLLink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLink.cpp; path = ftl/FTLLink.cpp; sourceTree = "<group>"; }; … … 4850 4807 0F2BDC421522801700CD8910 /* DFGVariableEventStream.cpp */, 4851 4808 0F2BDC431522801700CD8910 /* DFGVariableEventStream.h */, 4852 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */,4853 4809 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */, 4854 4810 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */, … … 5277 5233 5540771B18DA58AD00EFF7F2 /* JSArgumentsIterator.h in Headers */, 5278 5234 5540772218DA58AD00EFF7F2 /* JSArrayIterator.h in Headers */, 5279 5540772518DA58AD00EFF7F2 /* JSBoundFunction.hin Headers */,5235 5540772518DA58AD00EFF7F2 /* (null) in Headers */, 5280 5236 5540774818DA58AD00EFF7F2 /* JSGlobalObjectDebuggable.h in Headers */, 5281 5237 5540774A18DA58AD00EFF7F2 /* JSGlobalObjectFunctions.h in Headers */, … … 5751 5707 0F2BDC491522809600CD8910 /* DFGVariableEvent.h in Headers */, 5752 5708 0F2BDC4B1522809D00CD8910 /* DFGVariableEventStream.h in Headers */, 5753 0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */,5754 5709 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */, 5755 5710 0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */, -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86.h
r164764 r167325 158 158 159 159 // Possibly clobbers src. 160 // FIXME: Don't do that. 161 // https://bugs.webkit.org/show_bug.cgi?id=131690 160 162 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) 161 163 { -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r167094 r167325 38 38 #include "DFGDriver.h" 39 39 #include "DFGJITCode.h" 40 #include "DFGNode.h"41 40 #include "DFGWorklist.h" 42 41 #include "Debugger.h" -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r166678 r167325 46 46 #include "DFGCommonData.h" 47 47 #include "DFGExitProfile.h" 48 #include "DFGMinifiedGraph.h"49 #include "DFGOSREntry.h"50 #include "DFGOSRExit.h"51 #include "DFGVariableEventStream.h"52 48 #include "DeferredCompilationCallback.h" 53 49 #include "EvalCodeCache.h" -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r164424 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 158 158 BooleanResult booleanResult(Node*, AbstractValue&); 159 159 160 void setBuiltInConstant(Node* node, JSValue value) 161 { 162 AbstractValue& abstractValue = forNode(node); 163 abstractValue.set(m_graph, value); 164 abstractValue.fixTypeForRepresentation(node); 165 } 166 160 167 void setConstant(Node* node, JSValue value) 161 168 { 162 forNode(node).set(m_graph, value);169 setBuiltInConstant(node, value); 163 170 m_state.setFoundConstants(true); 164 171 } -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r167189 r167325 127 127 switch (node->op()) { 128 128 case JSConstant: 129 case DoubleConstant: 130 case Int52Constant: 129 131 case WeakJSConstant: 130 132 case PhantomArguments: { 131 forNode(node).set(m_graph, m_graph.valueOfJSConstant(node));133 setBuiltInConstant(node, m_graph.valueOfJSConstant(node)); 132 134 break; 133 135 } … … 308 310 } 309 311 310 case Int32ToDouble: {312 case DoubleRep: { 311 313 JSValue child = forNode(node->child1()).value(); 312 314 if (child && child.isNumber()) { 313 setConstant(node, JSValue(JSValue::EncodeAsDouble,child.asNumber()));314 break; 315 } 316 if (isInt32Speculation(forNode(node->child1()).m_type))317 forNode(node).setType(SpecDoubleReal);318 else319 forNode(node).setType(SpecDouble);320 break;321 }322 323 case Int52ToDouble: {315 setConstant(node, jsDoubleNumber(child.asNumber())); 316 break; 317 } 318 forNode(node).setType(forNode(node->child1()).m_type); 319 forNode(node).fixTypeForRepresentation(node); 320 break; 321 } 322 323 case Int52Rep: { 324 RELEASE_ASSERT(node->child1().useKind() == Int32Use); 325 324 326 JSValue child = forNode(node->child1()).value(); 325 if (child && child.is Number()) {327 if (child && child.isInt32()) { 326 328 setConstant(node, child); 327 329 break; 328 330 } 329 forNode(node).setType(SpecDouble);330 break;331 }332 333 case Int52ToValue: {334 JSValue child = forNode(node->child1()).value();335 if (child && child.isNumber()) {336 setConstant(node, child);337 break;338 }339 SpeculatedType type = forNode(node->child1()).m_type;340 if (type & SpecInt52)341 type = (type | SpecInt32 | SpecInt52AsDouble) & ~SpecInt52;342 forNode(node). setType(type);331 332 forNode(node).setType(SpecInt32); 333 break; 334 } 335 336 case ValueRep: { 337 JSValue value = forNode(node->child1()).value(); 338 if (value) { 339 setConstant(node, value); 340 break; 341 } 342 343 forNode(node).setType(forNode(node->child1()).m_type); 344 forNode(node).fixTypeForRepresentation(node); 343 345 break; 344 346 } … … 371 373 node->setCanExit(true); 372 374 break; 373 case MachineIntUse:375 case Int52RepUse: 374 376 if (left && right && left.isMachineInt() && right.isMachineInt()) { 375 377 JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt()); … … 384 386 node->setCanExit(true); 385 387 break; 386 case NumberUse:388 case DoubleRepUse: 387 389 if (left && right && left.isNumber() && right.isNumber()) { 388 setConstant(node, js Number(left.asNumber() + right.asNumber()));390 setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber())); 389 391 break; 390 392 } … … 427 429 node->setCanExit(true); 428 430 break; 429 case MachineIntUse:431 case Int52RepUse: 430 432 if (left && right && left.isMachineInt() && right.isMachineInt()) { 431 433 JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt()); … … 440 442 node->setCanExit(true); 441 443 break; 442 case NumberUse:444 case DoubleRepUse: 443 445 if (left && right && left.isNumber() && right.isNumber()) { 444 setConstant(node, js Number(left.asNumber() - right.asNumber()));446 setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber())); 445 447 break; 446 448 } … … 478 480 node->setCanExit(true); 479 481 break; 480 case MachineIntUse:482 case Int52RepUse: 481 483 if (child && child.isMachineInt()) { 482 484 double doubleResult; … … 497 499 node->setCanExit(true); 498 500 break; 499 case NumberUse:501 case DoubleRepUse: 500 502 if (child && child.isNumber()) { 501 setConstant(node, js Number(-child.asNumber()));503 setConstant(node, jsDoubleNumber(-child.asNumber())); 502 504 break; 503 505 } … … 534 536 node->setCanExit(true); 535 537 break; 536 case MachineIntUse:538 case Int52RepUse: 537 539 if (left && right && left.isMachineInt() && right.isMachineInt()) { 538 540 double doubleResult = left.asNumber() * right.asNumber(); … … 548 550 node->setCanExit(true); 549 551 break; 550 case NumberUse:552 case DoubleRepUse: 551 553 if (left && right && left.isNumber() && right.isNumber()) { 552 setConstant(node, js Number(left.asNumber() * right.asNumber()));554 setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber())); 553 555 break; 554 556 } … … 586 588 node->setCanExit(true); 587 589 break; 588 case NumberUse:590 case DoubleRepUse: 589 591 if (left && right && left.isNumber() && right.isNumber()) { 590 setConstant(node, js Number(left.asNumber() / right.asNumber()));592 setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber())); 591 593 break; 592 594 } … … 620 622 node->setCanExit(true); 621 623 break; 622 case NumberUse:624 case DoubleRepUse: 623 625 if (left && right && left.isNumber() && right.isNumber()) { 624 setConstant(node, js Number(fmod(left.asNumber(), right.asNumber())));626 setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber()))); 625 627 break; 626 628 } … … 646 648 node->setCanExit(true); 647 649 break; 648 case NumberUse:650 case DoubleRepUse: 649 651 if (left && right && left.isNumber() && right.isNumber()) { 650 652 double a = left.asNumber(); 651 653 double b = right.asNumber(); 652 setConstant(node, js Number(a < b ? a : (b <= a ? b : a + b)));654 setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b))); 653 655 break; 654 656 } … … 674 676 node->setCanExit(true); 675 677 break; 676 case NumberUse:678 case DoubleRepUse: 677 679 if (left && right && left.isNumber() && right.isNumber()) { 678 680 double a = left.asNumber(); 679 681 double b = right.asNumber(); 680 setConstant(node, js Number(a > b ? a : (b >= a ? b : a + b)));682 setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b))); 681 683 break; 682 684 } … … 704 706 node->setCanExit(true); 705 707 break; 706 case NumberUse:708 case DoubleRepUse: 707 709 if (child && child.isNumber()) { 708 setConstant(node, js Number(child.asNumber()));710 setConstant(node, jsDoubleNumber(child.asNumber())); 709 711 break; 710 712 } … … 721 723 JSValue child = forNode(node->child1()).value(); 722 724 if (child && child.isNumber()) { 723 setConstant(node, js Number(sqrt(child.asNumber())));725 setConstant(node, jsDoubleNumber(sqrt(child.asNumber()))); 724 726 break; 725 727 } … … 731 733 JSValue child = forNode(node->child1()).value(); 732 734 if (child && child.isNumber()) { 733 setConstant(node, js Number(static_cast<float>(child.asNumber())));735 setConstant(node, jsDoubleNumber(static_cast<float>(child.asNumber()))); 734 736 break; 735 737 } … … 741 743 JSValue child = forNode(node->child1()).value(); 742 744 if (child && child.isNumber()) { 743 setConstant(node, js Number(sin(child.asNumber())));745 setConstant(node, jsDoubleNumber(sin(child.asNumber()))); 744 746 break; 745 747 } … … 751 753 JSValue child = forNode(node->child1()).value(); 752 754 if (child && child.isNumber()) { 753 setConstant(node, js Number(cos(child.asNumber())));755 setConstant(node, jsDoubleNumber(cos(child.asNumber()))); 754 756 break; 755 757 } … … 770 772 case BooleanUse: 771 773 case Int32Use: 772 case NumberUse:774 case DoubleRepUse: 773 775 case UntypedUse: 774 776 case StringUse: -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r164229 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 68 68 69 69 m_type = speculationFromValue(value); 70 if (m_type == SpecInt52AsDouble)71 m_type = SpecInt52;72 70 m_value = value; 73 71 … … 84 82 85 83 checkConsistency(); 84 } 85 86 void AbstractValue::fixTypeForRepresentation(NodeFlags representation) 87 { 88 if (representation == NodeResultDouble) { 89 if (m_value) { 90 ASSERT(m_value.isNumber()); 91 if (m_value.isInt32()) 92 m_value = jsDoubleNumber(m_value.asNumber()); 93 } 94 if (m_type & SpecMachineInt) { 95 m_type &= ~SpecMachineInt; 96 m_type |= SpecInt52AsDouble; 97 } 98 RELEASE_ASSERT(!(m_type & ~SpecDouble)); 99 } else if (representation == NodeResultInt52) { 100 if (m_type & SpecInt52AsDouble) { 101 m_type &= ~SpecInt52AsDouble; 102 m_type |= SpecInt52; 103 } 104 RELEASE_ASSERT(!(m_type & ~SpecMachineInt)); 105 } else { 106 if (m_type & SpecInt52) { 107 m_type &= ~SpecInt52; 108 m_type |= SpecInt52AsDouble; 109 } 110 RELEASE_ASSERT(!(m_type & ~SpecBytecodeTop)); 111 } 112 113 checkConsistency(); 114 } 115 116 void AbstractValue::fixTypeForRepresentation(Node* node) 117 { 118 fixTypeForRepresentation(node->result()); 86 119 } 87 120 … … 245 278 if (!!m_value) { 246 279 SpeculatedType type = m_type; 280 // This relaxes the assertion below a bit, since we don't know the representation of the 281 // node. 247 282 if (type & SpecInt52) 248 283 type |= SpecInt52AsDouble; -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r164424 r167325 1 1 /* 2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 31 31 #include "ArrayProfile.h" 32 32 #include "DFGFiltrationResult.h" 33 #include "DFGNodeFlags.h" 33 34 #include "DFGStructureAbstractValue.h" 34 35 #include "JSCell.h" … … 40 41 41 42 class Graph; 43 struct Node; 42 44 43 45 struct AbstractValue { … … 129 131 checkConsistency(); 130 132 } 133 134 void fixTypeForRepresentation(NodeFlags representation); 135 void fixTypeForRepresentation(Node*); 131 136 132 137 bool operator==(const AbstractValue& other) const -
trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
r164229 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 211 211 } 212 212 213 case Identity:214 213 case UInt32ToNumber: { 215 214 node->child1()->mergeFlags(flags); … … 379 378 break; 380 379 } 380 381 case Identity: 382 // This would be trivial to handle but we just assert that we cannot see these yet. 383 RELEASE_ASSERT_NOT_REACHED(); 384 break; 381 385 382 386 // Note: ArithSqrt, ArithSin, and ArithCos and other math intrinsics don't have special -
trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h
r165869 r167325 34 34 #include "DFGFlushedAt.h" 35 35 #include "DFGNode.h" 36 #include "DFGVariadicFunction.h"37 36 #include "Operands.h" 38 37 #include <wtf/HashMap.h> … … 99 98 void replacePredecessor(BasicBlock* from, BasicBlock* to); 100 99 101 #define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 102 templatePre typeParams templatePost Node* appendNode(Graph&, SpeculatedType valueParamsComma valueParams); 103 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) 104 #undef DFG_DEFINE_APPEND_NODE 100 template<typename... Params> 101 Node* appendNode(Graph&, SpeculatedType, Params...); 105 102 106 #define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 107 templatePre typeParams templatePost Node* appendNonTerminal(Graph&, SpeculatedType valueParamsComma valueParams); 108 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) 109 #undef DFG_DEFINE_APPEND_NODE 103 template<typename... Params> 104 Node* appendNonTerminal(Graph&, SpeculatedType, Params...); 110 105 111 106 void dump(PrintStream& out) const; -
trunk/Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h
r163802 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 34 34 namespace JSC { namespace DFG { 35 35 36 #define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 37 templatePre typeParams templatePost inline Node* BasicBlock::appendNode(Graph& graph, SpeculatedType type valueParamsComma valueParams) \ 38 { \ 39 Node* result = graph.addNode(type valueParamsComma valueArgs); \ 40 append(result); \ 41 return result; \ 42 } 43 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) 44 #undef DFG_DEFINE_APPEND_NODE 36 template<typename... Params> 37 Node* BasicBlock::appendNode(Graph& graph, SpeculatedType type, Params... params) 38 { 39 Node* result = graph.addNode(type, params...); 40 append(result); 41 return result; 42 } 45 43 46 #define DFG_DEFINE_APPEND_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 47 templatePre typeParams templatePost inline Node* BasicBlock::appendNonTerminal(Graph& graph, SpeculatedType type valueParamsComma valueParams) \ 48 { \ 49 Node* result = graph.addNode(type valueParamsComma valueArgs); \ 50 insertBeforeLast(result); \ 51 return result; \ 52 } 53 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_APPEND_NODE) 54 #undef DFG_DEFINE_APPEND_NODE 44 template<typename... Params> 45 Node* BasicBlock::appendNonTerminal(Graph& graph, SpeculatedType type, Params... params) 46 { 47 Node* result = graph.addNode(type, params...); 48 insertBeforeLast(result); 49 return result; 50 } 55 51 56 52 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r167189 r167325 3264 3264 3265 3265 case op_to_number: { 3266 set(VirtualRegister(currentInstruction[1].u.operand), 3267 addToGraph(Identity, Edge(get(VirtualRegister(currentInstruction[2].u.operand)), NumberUse))); 3266 Node* node = get(VirtualRegister(currentInstruction[2].u.operand)); 3267 addToGraph(Phantom, Edge(node, NumberUse)); 3268 set(VirtualRegister(currentInstruction[1].u.operand), node); 3268 3269 NEXT_OPCODE(op_to_number); 3269 3270 } -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r167189 r167325 1 1 /* 2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 162 162 } 163 163 164 Node* int32ToDoubleCSE(Node* node)165 {166 for (unsigned i = m_indexInBlock; i--;) {167 Node* otherNode = m_currentBlock->at(i);168 if (otherNode == node->child1())169 return 0;170 switch (otherNode->op()) {171 case Int32ToDouble:172 if (otherNode->child1().sanitized() == node->child1().sanitized())173 return otherNode;174 break;175 default:176 break;177 }178 }179 return 0;180 }181 182 164 Node* constantCSE(Node* node) 183 165 { 184 166 for (unsigned i = endIndexForPureCSE(); i--;) { 185 167 Node* otherNode = m_currentBlock->at(i); 186 if (otherNode->op() != JSConstant)168 if (otherNode->op() != node->op()) 187 169 continue; 188 170 … … 1149 1131 case ValueToInt32: 1150 1132 case MakeRope: 1151 case Int52ToDouble: 1152 case Int52ToValue: 1133 case DoubleRep: 1134 case ValueRep: 1135 case Int52Rep: 1153 1136 if (cseMode == StoreElimination) 1154 1137 break; … … 1177 1160 break; 1178 1161 } 1179 1180 case Int32ToDouble:1181 if (cseMode == StoreElimination)1182 break;1183 setReplacement(int32ToDoubleCSE(node));1184 break;1185 1162 1186 1163 case GetCallee: … … 1262 1239 Node* dataNode = replacement->child1().node(); 1263 1240 ASSERT(dataNode->hasResult()); 1264 node->child1() = Edge(dataNode);1241 node->child1() = dataNode->defaultEdge(); 1265 1242 m_graph.dethread(); 1266 1243 m_changed = true; … … 1269 1246 1270 1247 case JSConstant: 1248 case DoubleConstant: 1249 case Int52Constant: 1271 1250 if (cseMode == StoreElimination) 1272 1251 break; -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r164734 r167325 1 1 /* 2 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #include "CodeBlock.h" 30 30 #include "DFGCommon.h" 31 #include "DFGNode.h"32 31 #include "Executable.h" 33 32 #include "Interpreter.h" -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r167189 r167325 84 84 switch (node->op()) { 85 85 case JSConstant: 86 case DoubleConstant: 87 case Int52Constant: 86 88 case WeakJSConstant: 87 89 case Identity: … … 124 126 case IsString: 125 127 case LogicalNot: 126 case Int32ToDouble:127 128 case ExtractOSREntryLocal: 128 case Int52ToDouble:129 case Int52ToValue:130 129 case CheckInBounds: 131 130 case ConstantStoragePointer: … … 133 132 case DoubleAsInt32: 134 133 case Check: 134 case DoubleRep: 135 case ValueRep: 136 case Int52Rep: 135 137 return; 136 138 -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r165407 r167325 300 300 AbstractValue constantValue; 301 301 constantValue.set(m_graph, value); 302 constantValue.fixTypeForRepresentation(node); 302 303 if (oldValue.merge(constantValue)) 303 304 continue; -
trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
r165522 r167325 195 195 switch (node->op()) { 196 196 case MovHint: { 197 ASSERT(node->child1().useKind() == UntypedUse);197 ASSERT(node->child1().useKind() == node->child1()->defaultUseKind()); 198 198 if (!node->child1()->shouldGenerate()) { 199 199 node->setOpAndDefaultFlags(ZombieHint); … … 201 201 break; 202 202 } 203 node->setOpAndDefaultFlags(MovHint);204 203 break; 205 204 } -
trunk/Source/JavaScriptCore/dfg/DFGEdge.h
r164424 r167325 1 1 /* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 123 123 bool willNotHaveCheck() const 124 124 { 125 return isProved() || useKind() == UntypedUse;125 return isProved() || shouldNotHaveTypeCheck(useKind()); 126 126 } 127 127 bool willHaveCheck() const -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r167189 r167325 62 62 63 63 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) 64 fixup SetLocalsInBlock(m_graph.block(blockIndex));64 fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex)); 65 65 } 66 66 … … 124 124 else if (nodeCanSpeculateInt32(node->arithNodeFlags())) 125 125 node->setArithMode(Arith::CheckOverflow); 126 else 126 else { 127 127 node->setArithMode(Arith::DoOverflow); 128 node->setResult(NodeResultDouble); 129 } 128 130 break; 129 131 } … … 136 138 } 137 139 if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) { 138 fixEdge< NumberUse>(node->child1());139 fixEdge< NumberUse>(node->child2());140 fixEdge<DoubleRepUse>(node->child1()); 141 fixEdge<DoubleRepUse>(node->child2()); 140 142 node->setOp(ArithAdd); 141 143 node->clearFlags(NodeMustGenerate | NodeClobbersWorld); 144 node->setResult(NodeResultDouble); 142 145 break; 143 146 } … … 178 181 if (attemptToMakeIntegerAdd(node)) 179 182 break; 180 fixEdge<NumberUse>(node->child1()); 181 fixEdge<NumberUse>(node->child2()); 183 fixEdge<DoubleRepUse>(node->child1()); 184 fixEdge<DoubleRepUse>(node->child2()); 185 node->setResult(NodeResultDouble); 182 186 break; 183 187 } … … 195 199 } 196 200 if (m_graph.negateShouldSpeculateMachineInt(node)) { 197 fixEdge< MachineIntUse>(node->child1());201 fixEdge<Int52RepUse>(node->child1()); 198 202 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 199 203 node->setArithMode(Arith::CheckOverflow); 200 204 else 201 205 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 202 break; 203 } 204 fixEdge<NumberUse>(node->child1()); 206 node->setResult(NodeResultInt52); 207 break; 208 } 209 fixEdge<DoubleRepUse>(node->child1()); 210 node->setResult(NodeResultDouble); 205 211 break; 206 212 } … … 219 225 } 220 226 if (m_graph.mulShouldSpeculateMachineInt(node)) { 221 fixEdge< MachineIntUse>(node->child1());222 fixEdge< MachineIntUse>(node->child2());227 fixEdge<Int52RepUse>(node->child1()); 228 fixEdge<Int52RepUse>(node->child2()); 223 229 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 224 230 node->setArithMode(Arith::CheckOverflow); 225 231 else 226 232 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 227 break; 228 } 229 fixEdge<NumberUse>(node->child1()); 230 fixEdge<NumberUse>(node->child2()); 233 node->setResult(NodeResultInt52); 234 break; 235 } 236 fixEdge<DoubleRepUse>(node->child1()); 237 fixEdge<DoubleRepUse>(node->child2()); 238 node->setResult(NodeResultDouble); 231 239 break; 232 240 } … … 247 255 break; 248 256 } 249 fixEdge<NumberUse>(node->child1()); 250 fixEdge<NumberUse>(node->child2()); 257 258 // This will cause conversion nodes to be inserted later. 259 fixEdge<DoubleRepUse>(node->child1()); 260 fixEdge<DoubleRepUse>(node->child2()); 261 262 // But we have to make sure that everything is phantom'd until after the 263 // DoubleAsInt32 node, which occurs after the Div/Mod node that the conversions 264 // will be insered on. 265 addRequiredPhantom(node->child1().node()); 266 addRequiredPhantom(node->child2().node()); 251 267 252 268 // We don't need to do ref'ing on the children because we're stealing them from … … 254 270 Node* newDivision = m_insertionSet.insertNode( 255 271 m_indexInBlock, SpecDouble, *node); 272 newDivision->setResult(NodeResultDouble); 256 273 257 274 node->setOp(DoubleAsInt32); 258 node->children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());275 node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge()); 259 276 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 260 277 node->setArithMode(Arith::CheckOverflow); … … 263 280 break; 264 281 } 265 fixEdge<NumberUse>(node->child1()); 266 fixEdge<NumberUse>(node->child2()); 282 fixEdge<DoubleRepUse>(node->child1()); 283 fixEdge<DoubleRepUse>(node->child2()); 284 node->setResult(NodeResultDouble); 267 285 break; 268 286 } … … 276 294 break; 277 295 } 278 fixEdge<NumberUse>(node->child1()); 279 fixEdge<NumberUse>(node->child2()); 296 fixEdge<DoubleRepUse>(node->child1()); 297 fixEdge<DoubleRepUse>(node->child2()); 298 node->setResult(NodeResultDouble); 280 299 break; 281 300 } … … 287 306 break; 288 307 } 289 fixEdge<NumberUse>(node->child1()); 308 fixEdge<DoubleRepUse>(node->child1()); 309 node->setResult(NodeResultDouble); 290 310 break; 291 311 } … … 295 315 case ArithSin: 296 316 case ArithCos: { 297 fixEdge<NumberUse>(node->child1()); 317 fixEdge<DoubleRepUse>(node->child1()); 318 node->setResult(NodeResultDouble); 298 319 break; 299 320 } … … 307 328 fixEdge<Int32Use>(node->child1()); 308 329 else if (node->child1()->shouldSpeculateNumber()) 309 fixEdge< NumberUse>(node->child1());330 fixEdge<DoubleRepUse>(node->child1()); 310 331 else if (node->child1()->shouldSpeculateString()) 311 332 fixEdge<StringUse>(node->child1()); … … 338 359 if (enableInt52() 339 360 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) { 340 fixEdge< MachineIntUse>(node->child1());341 fixEdge< MachineIntUse>(node->child2());361 fixEdge<Int52RepUse>(node->child1()); 362 fixEdge<Int52RepUse>(node->child2()); 342 363 node->clearFlags(NodeMustGenerate | NodeClobbersWorld); 343 364 break; 344 365 } 345 366 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) { 346 fixEdge< NumberUse>(node->child1());347 fixEdge< NumberUse>(node->child2());367 fixEdge<DoubleRepUse>(node->child1()); 368 fixEdge<DoubleRepUse>(node->child2()); 348 369 node->clearFlags(NodeMustGenerate | NodeClobbersWorld); 349 370 break; … … 403 424 if (enableInt52() 404 425 && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) { 405 fixEdge< MachineIntUse>(node->child1());406 fixEdge< MachineIntUse>(node->child2());426 fixEdge<Int52RepUse>(node->child1()); 427 fixEdge<Int52RepUse>(node->child2()); 407 428 break; 408 429 } 409 430 if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) { 410 fixEdge< NumberUse>(node->child1());411 fixEdge< NumberUse>(node->child2());431 fixEdge<DoubleRepUse>(node->child1()); 432 fixEdge<DoubleRepUse>(node->child2()); 412 433 break; 413 434 } … … 502 523 } 503 524 504 switch (node->arrayMode().type()) { 525 arrayMode = node->arrayMode(); 526 switch (arrayMode.type()) { 505 527 case Array::SelectUsingPredictions: 506 528 case Array::Unprofiled: … … 518 540 fixEdge<KnownCellUse>(node->child1()); 519 541 fixEdge<Int32Use>(node->child2()); 542 break; 543 } 544 545 switch (arrayMode.type()) { 546 case Array::Double: 547 if (!arrayMode.isOutOfBounds()) 548 node->setResult(NodeResultDouble); 549 break; 550 551 case Array::Float32Array: 552 case Array::Float64Array: 553 node->setResult(NodeResultDouble); 554 break; 555 556 case Array::Uint32Array: 557 if (node->shouldSpeculateInt32()) 558 break; 559 if (node->shouldSpeculateMachineInt() && enableInt52()) 560 node->setResult(NodeResultInt52); 561 else 562 node->setResult(NodeResultDouble); 563 break; 564 565 default: 520 566 break; 521 567 } … … 560 606 fixEdge<Int32Use>(child3); 561 607 if (child3->prediction() & SpecInt52) 562 fixEdge< MachineIntUse>(child3);608 fixEdge<Int52RepUse>(child3); 563 609 else 564 610 fixEdge<Int32Use>(child3); … … 567 613 fixEdge<KnownCellUse>(child1); 568 614 fixEdge<Int32Use>(child2); 569 fixEdge< RealNumberUse>(child3);615 fixEdge<DoubleRepRealUse>(child3); 570 616 break; 571 617 case Array::Int8Array: … … 581 627 fixEdge<Int32Use>(child3); 582 628 else if (child3->shouldSpeculateMachineInt()) 583 fixEdge< MachineIntUse>(child3);629 fixEdge<Int52RepUse>(child3); 584 630 else 585 fixEdge< NumberUse>(child3);631 fixEdge<DoubleRepUse>(child3); 586 632 break; 587 633 case Array::Float32Array: … … 589 635 fixEdge<KnownCellUse>(child1); 590 636 fixEdge<Int32Use>(child2); 591 fixEdge< NumberUse>(child3);637 fixEdge<DoubleRepUse>(child3); 592 638 break; 593 639 case Array::Contiguous: … … 631 677 break; 632 678 case Array::Double: 633 fixEdge< RealNumberUse>(node->child2());679 fixEdge<DoubleRepRealUse>(node->child2()); 634 680 break; 635 681 case Array::Contiguous: … … 664 710 fixEdge<Int32Use>(node->child1()); 665 711 else if (node->child1()->shouldSpeculateNumber()) 666 fixEdge< NumberUse>(node->child1());712 fixEdge<DoubleRepUse>(node->child1()); 667 713 668 714 Node* logicalNot = node->child1().node(); … … 761 807 case ALL_DOUBLE_INDEXING_TYPES: 762 808 for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex) 763 fixEdge< RealNumberUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);809 fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]); 764 810 break; 765 811 case ALL_CONTIGUOUS_INDEXING_TYPES: … … 937 983 938 984 case Phantom: 939 case Identity:940 985 case Check: { 941 986 switch (node->child1().useKind()) { … … 962 1007 case CheckTierUpAtReturn: 963 1008 case CheckTierUpAndOSREnter: 964 case Int52ToDouble:965 case Int52ToValue:966 1009 case InvalidationPoint: 967 1010 case CheckArray: … … 969 1012 case ConstantStoragePointer: 970 1013 case DoubleAsInt32: 971 case Int32ToDouble:972 1014 case ValueToInt32: 973 1015 case HardPhantom: // HardPhantom would be trivial to handle but anyway we assert that we won't see it here yet. 1016 case DoubleRep: 1017 case Int52Rep: 1018 case ValueRep: 1019 case DoubleConstant: 1020 case Int52Constant: 1021 case Identity: // This should have been cleaned up. 974 1022 // These are just nodes that we don't currently expect to see during fixup. 975 1023 // If we ever wanted to insert them prior to fixup, then we just have to create … … 1313 1361 } 1314 1362 1315 void fixup SetLocalsInBlock(BasicBlock* block)1363 void fixupGetAndSetLocalsInBlock(BasicBlock* block) 1316 1364 { 1317 1365 if (!block) … … 1321 1369 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { 1322 1370 Node* node = m_currentNode = block->at(m_indexInBlock); 1323 if (node->op() != SetLocal )1371 if (node->op() != SetLocal && node->op() != GetLocal) 1324 1372 continue; 1325 1373 1326 1374 VariableAccessData* variable = node->variableAccessData(); 1327 switch (variable->flushFormat()) { 1328 case FlushedJSValue: 1329 break; 1330 case FlushedDouble: 1331 fixEdge<NumberUse>(node->child1()); 1332 break; 1333 case FlushedInt32: 1334 fixEdge<Int32Use>(node->child1()); 1335 break; 1336 case FlushedInt52: 1337 fixEdge<MachineIntUse>(node->child1()); 1338 break; 1339 case FlushedCell: 1340 fixEdge<CellUse>(node->child1()); 1341 break; 1342 case FlushedBoolean: 1343 fixEdge<BooleanUse>(node->child1()); 1344 break; 1375 switch (node->op()) { 1376 case GetLocal: 1377 switch (variable->flushFormat()) { 1378 case FlushedDouble: 1379 node->setResult(NodeResultDouble); 1380 break; 1381 case FlushedInt52: 1382 node->setResult(NodeResultInt52); 1383 break; 1384 default: 1385 break; 1386 } 1387 break; 1388 1389 case SetLocal: 1390 switch (variable->flushFormat()) { 1391 case FlushedJSValue: 1392 break; 1393 case FlushedDouble: 1394 fixEdge<DoubleRepUse>(node->child1()); 1395 break; 1396 case FlushedInt32: 1397 fixEdge<Int32Use>(node->child1()); 1398 break; 1399 case FlushedInt52: 1400 fixEdge<Int52RepUse>(node->child1()); 1401 break; 1402 case FlushedCell: 1403 fixEdge<CellUse>(node->child1()); 1404 break; 1405 case FlushedBoolean: 1406 fixEdge<BooleanUse>(node->child1()); 1407 break; 1408 default: 1409 RELEASE_ASSERT_NOT_REACHED(); 1410 break; 1411 } 1412 break; 1413 1345 1414 default: 1346 1415 RELEASE_ASSERT_NOT_REACHED(); … … 1468 1537 break; 1469 1538 case NumberUse: 1470 case RealNumberUse: 1539 case DoubleRepUse: 1540 case DoubleRepRealUse: 1471 1541 if (variable->doubleFormatState() == UsingDoubleFormat) 1472 1542 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); … … 1477 1547 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); 1478 1548 break; 1479 case MachineIntUse:1549 case Int52RepUse: 1480 1550 if (isMachineIntSpeculation(variable->prediction())) 1481 1551 m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true); … … 1520 1590 UseKind useKind; 1521 1591 if (node->shouldSpeculateMachineInt()) 1522 useKind = MachineIntUse;1592 useKind = Int52RepUse; 1523 1593 else if (node->shouldSpeculateNumber()) 1524 useKind = NumberUse;1594 useKind = DoubleRepUse; 1525 1595 else if (node->shouldSpeculateBoolean()) 1526 1596 useKind = BooleanUse; … … 1590 1660 1591 1661 if (m_graph.addShouldSpeculateMachineInt(node)) { 1592 fixEdge< MachineIntUse>(node->child1());1593 fixEdge< MachineIntUse>(node->child2());1662 fixEdge<Int52RepUse>(node->child1()); 1663 fixEdge<Int52RepUse>(node->child2()); 1594 1664 node->setArithMode(Arith::CheckOverflow); 1665 node->setResult(NodeResultInt52); 1595 1666 return true; 1596 1667 } … … 1725 1796 m_currentNode = block->at(m_indexInBlock); 1726 1797 addPhantomsIfNecessary(); 1727 if (m_currentNode->containsMovHint()) 1728 continue; 1798 tryToRelaxRepresentation(m_currentNode); 1729 1799 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, injectTypeConversionsForEdge); 1730 1800 } … … 1733 1803 } 1734 1804 1805 void tryToRelaxRepresentation(Node* node) 1806 { 1807 // Some operations may be able to operate more efficiently over looser representations. 1808 // Identify those here. This avoids inserting a redundant representation conversion. 1809 // Also, for some operations, like MovHint, this is a necessary optimization: inserting 1810 // an otherwise-dead conversion just for a MovHint would break OSR's understanding of 1811 // the IR. 1812 1813 switch (node->op()) { 1814 case MovHint: 1815 case Phantom: 1816 case Check: 1817 case HardPhantom: 1818 DFG_NODE_DO_TO_CHILDREN(m_graph, m_currentNode, fixEdgeRepresentation); 1819 break; 1820 1821 case ValueToInt32: 1822 if (node->child1().useKind() == DoubleRepUse 1823 && !node->child1()->hasDoubleResult()) { 1824 node->child1().setUseKind(NumberUse); 1825 break; 1826 } 1827 break; 1828 1829 default: 1830 break; 1831 } 1832 } 1833 1834 void fixEdgeRepresentation(Node*, Edge& edge) 1835 { 1836 switch (edge.useKind()) { 1837 case DoubleRepUse: 1838 case DoubleRepRealUse: 1839 if (edge->hasDoubleResult()) 1840 break; 1841 1842 if (edge->hasInt52Result()) 1843 edge.setUseKind(Int52RepUse); 1844 else if (edge.useKind() == DoubleRepUse) 1845 edge.setUseKind(NumberUse); 1846 break; 1847 1848 case Int52RepUse: 1849 // Nothing we can really do. 1850 break; 1851 1852 case UntypedUse: 1853 case NumberUse: 1854 if (edge->hasDoubleResult()) 1855 edge.setUseKind(DoubleRepUse); 1856 else if (edge->hasInt52Result()) 1857 edge.setUseKind(Int52RepUse); 1858 break; 1859 1860 default: 1861 break; 1862 } 1863 } 1864 1735 1865 void injectTypeConversionsForEdge(Node* node, Edge& edge) 1736 1866 { 1737 1867 ASSERT(node == m_currentNode); 1738 1868 1739 if (isDouble(edge.useKind())) { 1740 if (edge->shouldSpeculateInt32ForArithmetic()) { 1741 addRequiredPhantom(edge.node()); 1742 1743 Node* result = m_insertionSet.insertNode( 1744 m_indexInBlock, SpecInt52AsDouble, Int32ToDouble, 1745 node->origin, Edge(edge.node(), NumberUse)); 1746 1747 edge.setNode(result); 1748 return; 1749 } 1750 1751 if (enableInt52() && edge->shouldSpeculateMachineInt()) { 1752 // Make all double uses of int52 values have an intermediate Int52ToDouble. 1753 // This is for the same reason as Int52ToValue (see below) except that 1754 // Int8ToDouble will convert int52's that fit in an int32 into a double 1755 // rather than trying to create a boxed int32 like Int52ToValue does. 1756 1757 addRequiredPhantom(edge.node()); 1758 Node* result = m_insertionSet.insertNode( 1759 m_indexInBlock, SpecInt52AsDouble, Int52ToDouble, 1760 node->origin, Edge(edge.node(), NumberUse)); 1761 edge.setNode(result); 1762 return; 1763 } 1764 } 1765 1766 if (enableInt52() && edge.useKind() != MachineIntUse 1767 && edge->shouldSpeculateMachineInt() && !edge->shouldSpeculateInt32()) { 1768 // We make all non-int52 uses of int52 values have an intermediate Int52ToValue 1769 // node to ensure that we handle this properly: 1770 // 1771 // a: SomeInt52 1772 // b: ArithAdd(@a, ...) 1773 // c: Call(..., @a) 1774 // d: ArithAdd(@a, ...) 1775 // 1776 // Without an intermediate node and just labeling the uses, we will get: 1777 // 1778 // a: SomeInt52 1779 // b: ArithAdd(Int52:@a, ...) 1780 // c: Call(..., Untyped:@a) 1781 // d: ArithAdd(Int52:@a, ...) 1782 // 1783 // And now the c->Untyped:@a edge will box the value of @a into a double. This 1784 // is bad, because now the d->Int52:@a edge will either have to do double-to-int 1785 // conversions, or will have to OSR exit unconditionally. Alternatively we could 1786 // have the c->Untyped:@a edge box the value by copying rather than in-place. 1787 // But these boxings are also costly so this wouldn't be great. 1788 // 1789 // The solution we use is to always have non-Int52 uses of predicted Int52's use 1790 // an intervening Int52ToValue node: 1791 // 1792 // a: SomeInt52 1793 // b: ArithAdd(Int52:@a, ...) 1794 // x: Int52ToValue(Int52:@a) 1795 // c: Call(..., Untyped:@x) 1796 // d: ArithAdd(Int52:@a, ...) 1797 // 1798 // Note that even if we had multiple non-int52 uses of @a, the multiple 1799 // Int52ToValue's would get CSE'd together. So the boxing would only happen once. 1800 // At the same time, @a would continue to be represented as a native int52. 1801 // 1802 // An alternative would have been to insert ToNativeInt52 nodes on int52 uses of 1803 // int52's. This would have handled the above example but would fall over for: 1804 // 1805 // a: SomeInt52 1806 // b: Call(..., @a) 1807 // c: ArithAdd(@a, ...) 1808 // 1809 // But the solution we use handles the above gracefully. 1869 switch (edge.useKind()) { 1870 case DoubleRepUse: 1871 case DoubleRepRealUse: { 1872 if (edge->hasDoubleResult()) 1873 break; 1810 1874 1811 1875 addRequiredPhantom(edge.node()); 1812 Node* result = m_insertionSet.insertNode( 1813 m_indexInBlock, SpecInt52, Int52ToValue, 1814 node->origin, Edge(edge.node(), UntypedUse)); 1876 1877 Node* result; 1878 if (edge->hasInt52Result()) { 1879 result = m_insertionSet.insertNode( 1880 m_indexInBlock, SpecInt52AsDouble, DoubleRep, node->origin, 1881 Edge(edge.node(), Int52RepUse)); 1882 } else { 1883 result = m_insertionSet.insertNode( 1884 m_indexInBlock, SpecDouble, DoubleRep, node->origin, 1885 Edge(edge.node(), NumberUse)); 1886 } 1887 1815 1888 edge.setNode(result); 1816 return; 1817 } 1889 break; 1890 } 1891 1892 case Int52RepUse: { 1893 if (edge->hasInt52Result()) 1894 break; 1895 1896 addRequiredPhantom(edge.node()); 1897 1898 Node* result; 1899 if (edge->hasDoubleResult()) { 1900 // This will never happen. 1901 RELEASE_ASSERT_NOT_REACHED(); 1902 } else if (edge->shouldSpeculateInt32ForArithmetic()) { 1903 result = m_insertionSet.insertNode( 1904 m_indexInBlock, SpecInt32, Int52Rep, node->origin, 1905 Edge(edge.node(), Int32Use)); 1906 } else { 1907 // This is only here for dealing with constants. 1908 RELEASE_ASSERT(edge->op() == JSConstant); 1909 result = m_insertionSet.insertNode( 1910 m_indexInBlock, SpecMachineInt, Int52Constant, node->origin, 1911 OpInfo(edge->constantNumber())); 1912 } 1913 1914 edge.setNode(result); 1915 break; 1916 } 1917 1918 default: { 1919 if (!edge->hasDoubleResult() && !edge->hasInt52Result()) 1920 break; 1921 1922 addRequiredPhantom(edge.node()); 1923 1924 Node* result; 1925 if (edge->hasDoubleResult()) { 1926 result = m_insertionSet.insertNode( 1927 m_indexInBlock, SpecDouble, ValueRep, node->origin, 1928 Edge(edge.node(), DoubleRepUse)); 1929 } else { 1930 result = m_insertionSet.insertNode( 1931 m_indexInBlock, SpecInt32 | SpecInt52AsDouble, ValueRep, node->origin, 1932 Edge(edge.node(), Int52RepUse)); 1933 } 1934 1935 edge.setNode(result); 1936 break; 1937 } } 1818 1938 } 1819 1939 1820 1940 void addRequiredPhantom(Node* node) 1821 1941 { 1822 if (!m_codeOriginOfPhantoms) {1823 ASSERT(m_requiredPhantoms.isEmpty());1824 m_codeOriginOfPhantoms = m_currentNode->origin.forExit;1825 } else {1826 ASSERT(!m_requiredPhantoms.isEmpty());1827 ASSERT(m_codeOriginOfPhantoms == m_currentNode->origin.forExit);1828 }1829 1830 1942 m_requiredPhantoms.append(node); 1831 1943 } … … 1836 1948 return; 1837 1949 1838 RELEASE_ASSERT(!!m_codeOriginOfPhantoms);1839 1840 if (m_currentNode->origin.forExit == m_codeOriginOfPhantoms)1841 return;1842 1843 1950 for (unsigned i = m_requiredPhantoms.size(); i--;) { 1951 Node* node = m_requiredPhantoms[i]; 1844 1952 m_insertionSet.insertNode( 1845 m_indexInBlock, SpecNone, Phantom, NodeOrigin(m_codeOriginOfPhantoms),1846 Edge(m_requiredPhantoms[i], UntypedUse));1953 m_indexInBlock, SpecNone, Phantom, m_currentNode->origin, 1954 node->defaultEdge()); 1847 1955 } 1848 1956 1849 1957 m_requiredPhantoms.resize(0); 1850 m_codeOriginOfPhantoms = CodeOrigin();1851 1958 } 1852 1959 … … 1864 1971 1865 1972 m_requiredPhantoms.resize(0); 1866 m_codeOriginOfPhantoms = CodeOrigin();1867 1973 } 1868 1974 … … 1872 1978 InsertionSet m_insertionSet; 1873 1979 bool m_profitabilityChanged; 1874 CodeOrigin m_codeOriginOfPhantoms;1875 1980 Vector<Node*, 3> m_requiredPhantoms; 1876 1981 }; -
trunk/Source/JavaScriptCore/dfg/DFGFlushFormat.h
r164424 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 63 63 return NodeResultInt52; 64 64 case FlushedDouble: 65 return NodeResult Number;65 return NodeResultDouble; 66 66 case FlushedBoolean: 67 67 return NodeResultBoolean; … … 84 84 return Int32Use; 85 85 case FlushedInt52: 86 return MachineIntUse;86 return Int52RepUse; 87 87 case FlushedDouble: 88 return NumberUse;88 return DoubleRepUse; 89 89 case FlushedBoolean: 90 90 return BooleanUse; -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r165995 r167325 315 315 if (node->hasStoragePointer()) 316 316 out.print(comma, RawPointer(node->storagePointer())); 317 if ( op == JSConstant) {317 if (node->isConstant()) { 318 318 out.print(comma, "$", node->constantNumber()); 319 319 JSValue value = valueOfJSConstant(node); -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r166440 r167325 40 40 #include "DFGPlan.h" 41 41 #include "DFGScannable.h" 42 #include "DFGVariadicFunction.h"43 42 #include "InlineCallFrameSet.h" 44 43 #include "JSStack.h" … … 137 136 } 138 137 139 #define DFG_DEFINE_ADD_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 140 templatePre typeParams templatePost Node* addNode(SpeculatedType type valueParamsComma valueParams) \ 141 { \ 142 Node* node = new (m_allocator) Node(valueArgs); \ 143 node->predict(type); \ 144 return node; \ 145 } 146 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_ADD_NODE) 147 #undef DFG_DEFINE_ADD_NODE 138 template<typename... Params> 139 Node* addNode(SpeculatedType type, Params... params) 140 { 141 Node* node = new (m_allocator) Node(params...); 142 node->predict(type); 143 return node; 144 } 148 145 149 146 void dethread(); -
trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
r165522 r167325 156 156 block->valuesAtTail.local(i).clear(); 157 157 } 158 if (m_graph.m_form == SSA) 159 continue; 158 160 if (!block->isOSRTarget) 159 161 continue; … … 161 163 continue; 162 164 for (size_t i = 0; i < m_graph.m_mustHandleAbstractValues.size(); ++i) { 165 int operand = m_graph.m_mustHandleAbstractValues.operandForIndex(i); 166 Node* node = block->variablesAtHead.operand(operand); 167 if (!node) 168 continue; 163 169 AbstractValue value = m_graph.m_mustHandleAbstractValues[i]; 164 int operand = m_graph.m_mustHandleAbstractValues.operandForIndex(i); 165 block->valuesAtHead.operand(operand).merge(value); 170 AbstractValue& abstractValue = block->valuesAtHead.operand(operand); 171 VariableAccessData* variable = node->variableAccessData(); 172 FlushFormat format = variable->flushFormat(); 173 abstractValue.merge(value); 174 abstractValue.fixTypeForRepresentation(resultFor(format)); 166 175 } 167 176 block->cfaShouldRevisit = true; -
trunk/Source/JavaScriptCore/dfg/DFGInsertionSet.h
r164424 r167325 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 55 55 return insert(Insertion(index, element)); 56 56 } 57 58 template<typename... Params> 59 Node* insertNode(size_t index, SpeculatedType type, Params... params) 60 { 61 return insert(index, m_graph.addNode(type, params...)); 62 } 57 63 58 #define DFG_DEFINE_INSERT_NODE(templatePre, templatePost, typeParams, valueParamsComma, valueParams, valueArgs) \ 59 templatePre typeParams templatePost Node* insertNode(size_t index, SpeculatedType type valueParamsComma valueParams) \ 60 { \ 61 return insert(index, m_graph.addNode(type valueParamsComma valueArgs)); \ 62 } 63 DFG_VARIADIC_TEMPLATE_FUNCTION(DFG_DEFINE_INSERT_NODE) 64 #undef DFG_DEFINE_INSERT_NODE 65 66 Node* insertConstant(size_t index, NodeOrigin origin, JSValue value) 64 Node* insertConstant( 65 size_t index, NodeOrigin origin, JSValue value, 66 NodeType op = JSConstant) 67 67 { 68 68 unsigned constantReg = 69 69 m_graph.constantRegisterForConstant(value); 70 70 return insertNode( 71 index, speculationFromValue(value), JSConstant, origin, 72 OpInfo(constantReg)); 71 index, speculationFromValue(value), op, origin, OpInfo(constantReg)); 73 72 } 74 73 75 Node* insertConstant(size_t index, CodeOrigin origin, JSValue value) 74 Node* insertConstant( 75 size_t index, CodeOrigin origin, JSValue value, NodeType op = JSConstant) 76 76 { 77 return insertConstant(index, NodeOrigin(origin), value); 77 return insertConstant(index, NodeOrigin(origin), value, op); 78 } 79 80 Edge insertConstantForUse( 81 size_t index, NodeOrigin origin, JSValue value, UseKind useKind) 82 { 83 NodeType op; 84 if (isDouble(useKind)) 85 op = DoubleConstant; 86 else if (useKind == Int52RepUse) 87 op = Int52Constant; 88 else 89 op = JSConstant; 90 return Edge(insertConstant(index, origin, value, op), useKind); 91 } 92 93 Edge insertConstantForUse( 94 size_t index, CodeOrigin origin, JSValue value, UseKind useKind) 95 { 96 return insertConstantForUse(index, NodeOrigin(origin), value, useKind); 78 97 } 79 98 -
trunk/Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp
r164229 r167325 371 371 return source.node(); 372 372 return m_insertionSet.insertNode( 373 nodeIndex, source->prediction(), ArithAdd, origin, OpInfo(arithMode),374 source, Edge(375 m_insertionSet.insertConstant(nodeIndex, origin, jsNumber(addend)),376 source.useKind()));373 nodeIndex, source->prediction(), source->result(), 374 ArithAdd, origin, OpInfo(arithMode), source, 375 m_insertionSet.insertConstantForUse( 376 nodeIndex, origin, jsNumber(addend), source.useKind())); 377 377 } 378 378 … … 382 382 Node* result = insertAdd(nodeIndex, origin, source, addend); 383 383 m_insertionSet.insertNode( 384 nodeIndex, SpecNone, HardPhantom, origin, Edge(result, UntypedUse));384 nodeIndex, SpecNone, HardPhantom, origin, result->defaultEdge()); 385 385 return result; 386 386 } -
trunk/Source/JavaScriptCore/dfg/DFGNode.cpp
r164620 r167325 92 92 } 93 93 94 void Node::convertToIdentity() 95 { 96 RELEASE_ASSERT(child1()); 97 RELEASE_ASSERT(!child2()); 98 NodeFlags result = canonicalResultRepresentation(this->result()); 99 setOpAndDefaultFlags(Identity); 100 setResult(result); 101 } 102 94 103 } } // namespace JSC::DFG 95 104 … … 122 131 } 123 132 out.print("@", node->index()); 124 out.print(AbbreviatedSpeculationDump(node->prediction())); 133 if (node->hasDoubleResult()) 134 out.print("<Double>"); 135 else if (node->hasInt52Result()) 136 out.print("<Int52>"); 125 137 } 126 138 -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r166095 r167325 39 39 #include "DFGNodeOrigin.h" 40 40 #include "DFGNodeType.h" 41 #include "DFGUseKind.h" 41 42 #include "DFGVariableAccessData.h" 42 43 #include "GetByIdVariant.h" … … 240 241 } 241 242 243 // Construct a node with up to 3 children, no immediate value. 244 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 245 : origin(nodeOrigin) 246 , children(AdjacencyList::Fixed, child1, child2, child3) 247 , m_virtualRegister(VirtualRegister()) 248 , m_refCount(1) 249 , m_prediction(SpecNone) 250 , m_opInfo(0) 251 , m_opInfo2(0) 252 { 253 misc.replacement = 0; 254 setOpAndDefaultFlags(op); 255 setResult(result); 256 ASSERT(!(m_flags & NodeHasVarArgs)); 257 } 258 242 259 // Construct a node with up to 3 children and an immediate value. 243 260 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) … … 255 272 } 256 273 274 // Construct a node with up to 3 children and an immediate value. 275 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) 276 : origin(nodeOrigin) 277 , children(AdjacencyList::Fixed, child1, child2, child3) 278 , m_virtualRegister(VirtualRegister()) 279 , m_refCount(1) 280 , m_prediction(SpecNone) 281 , m_opInfo(imm.m_value) 282 , m_opInfo2(0) 283 { 284 misc.replacement = 0; 285 setOpAndDefaultFlags(op); 286 setResult(result); 287 ASSERT(!(m_flags & NodeHasVarArgs)); 288 } 289 257 290 // Construct a node with up to 3 children and two immediate values. 258 291 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge()) … … 326 359 } 327 360 361 void setResult(NodeFlags result) 362 { 363 ASSERT(!(result & ~NodeResultMask)); 364 clearFlags(NodeResultMask); 365 mergeFlags(result); 366 } 367 368 NodeFlags result() const 369 { 370 return flags() & NodeResultMask; 371 } 372 328 373 void setOpAndDefaultFlags(NodeType op) 329 374 { … … 342 387 } 343 388 344 void convertToIdentity() 345 { 346 RELEASE_ASSERT(child1()); 347 RELEASE_ASSERT(!child2()); 348 setOpAndDefaultFlags(Identity); 349 } 389 void convertToIdentity(); 350 390 351 391 bool mustGenerate() … … 369 409 bool isConstant() 370 410 { 371 return op() == JSConstant; 411 switch (op()) { 412 case JSConstant: 413 case DoubleConstant: 414 case Int52Constant: 415 return true; 416 default: 417 return false; 418 } 372 419 } 373 420 … … 386 433 switch (op()) { 387 434 case JSConstant: 435 case DoubleConstant: 436 case Int52Constant: 388 437 case WeakJSConstant: 389 438 case PhantomArguments: … … 402 451 void convertToConstant(unsigned constantNumber) 403 452 { 404 m_op = JSConstant; 453 if (hasDoubleResult()) 454 m_op = DoubleConstant; 455 else if (hasInt52Result()) 456 m_op = Int52Constant; 457 else 458 m_op = JSConstant; 405 459 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld); 406 460 m_opInfo = constantNumber; … … 503 557 return JSValue(weakConstant()); 504 558 case JSConstant: 559 case DoubleConstant: 560 case Int52Constant: 505 561 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get(); 506 562 case PhantomArguments: … … 798 854 bool hasResult() 799 855 { 800 return m_flags & NodeResultMask;856 return !!result(); 801 857 } 802 858 803 859 bool hasInt32Result() 804 860 { 805 return (m_flags & NodeResultMask) == NodeResultInt32; 861 return result() == NodeResultInt32; 862 } 863 864 bool hasInt52Result() 865 { 866 return result() == NodeResultInt52; 806 867 } 807 868 808 869 bool hasNumberResult() 809 870 { 810 return (m_flags & NodeResultMask) == NodeResultNumber; 871 return result() == NodeResultNumber; 872 } 873 874 bool hasDoubleResult() 875 { 876 return result() == NodeResultDouble; 811 877 } 812 878 813 879 bool hasJSResult() 814 880 { 815 return (m_flags & NodeResultMask) == NodeResultJS;881 return result() == NodeResultJS; 816 882 } 817 883 818 884 bool hasBooleanResult() 819 885 { 820 return (m_flags & NodeResultMask) == NodeResultBoolean;886 return result() == NodeResultBoolean; 821 887 } 822 888 823 889 bool hasStorageResult() 824 890 { 825 return (m_flags & NodeResultMask) == NodeResultStorage; 891 return result() == NodeResultStorage; 892 } 893 894 UseKind defaultUseKind() 895 { 896 return useKindForResult(result()); 897 } 898 899 Edge defaultEdge() 900 { 901 return Edge(this, defaultUseKind()); 826 902 } 827 903 -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
r165995 r167325 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 47 47 case NodeResultNumber: 48 48 out.print(comma, "Number"); 49 break; 50 case NodeResultDouble: 51 out.print(comma, "Double"); 49 52 break; 50 53 case NodeResultInt32: -
trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h
r166095 r167325 1 1 /* 2 * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 39 39 #define NodeResultJS 0x0001 40 40 #define NodeResultNumber 0x0002 41 #define NodeResultInt32 0x0003 42 #define NodeResultInt52 0x0004 43 #define NodeResultBoolean 0x0005 44 #define NodeResultStorage 0x0006 41 #define NodeResultDouble 0x0003 42 #define NodeResultInt32 0x0004 43 #define NodeResultInt52 0x0005 44 #define NodeResultBoolean 0x0006 45 #define NodeResultStorage 0x0007 45 46 46 47 #define NodeMustGenerate 0x0008 // set on nodes that have side effects, and may not trivially be removed by DCE. … … 115 116 } 116 117 118 // FIXME: Get rid of this. 119 // https://bugs.webkit.org/show_bug.cgi?id=131689 120 static inline NodeFlags canonicalResultRepresentation(NodeFlags flags) 121 { 122 switch (flags) { 123 case NodeResultDouble: 124 case NodeResultInt52: 125 case NodeResultStorage: 126 return flags; 127 default: 128 return NodeResultJS; 129 } 130 } 131 117 132 void dumpNodeFlags(PrintStream&, NodeFlags); 118 133 MAKE_PRINT_ADAPTOR(NodeFlagsDump, NodeFlags, dumpNodeFlags); -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r167189 r167325 38 38 macro(JSConstant, NodeResultJS | NodeDoesNotExit) \ 39 39 \ 40 /* Constants with specific representations. */\ 41 macro(DoubleConstant, NodeResultDouble | NodeDoesNotExit) \ 42 macro(Int52Constant, NodeResultInt52 | NodeDoesNotExit) \ 43 \ 40 44 /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\ 41 45 /* code block. */\ … … 107 111 macro(UInt32ToNumber, NodeResultNumber) \ 108 112 \ 109 /* Used to cast known integers to doubles, so as to separate the double form */\ 110 /* of the value from the integer form. */\ 111 macro(Int32ToDouble, NodeResultNumber) \ 112 /* Used to speculate that a double value is actually an integer. */\ 113 /* Attempt to truncate a double to int32; this will exit if it can't do it. */\ 113 114 macro(DoubleAsInt32, NodeResultInt32) \ 114 /* Used to separate representation and register allocation of Int52's represented */\ 115 /* as values. */\ 116 macro(Int52ToValue, NodeResultJS) \ 117 macro(Int52ToDouble, NodeResultNumber) \ 115 \ 116 /* Change the representation of a value. */\ 117 macro(DoubleRep, NodeResultDouble) \ 118 macro(Int52Rep, NodeResultInt52) \ 119 macro(ValueRep, NodeResultJS) \ 118 120 \ 119 121 /* Nodes for arithmetic operations. */\ -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp
r166662 r167325 270 270 switch (recovery.technique()) { 271 271 case InPair: 272 case InFPR:273 272 case DisplacedInJSStack: 274 case DoubleDisplacedInJSStack:275 273 m_jit.load32( 276 274 &bitwise_cast<EncodedValueDescriptor*>(scratch + index)->asBits.tag, … … 287 285 break; 288 286 287 case InFPR: 288 case DoubleDisplacedInJSStack: 289 m_jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0); 290 m_jit.loadDouble(GPRInfo::regT0, FPRInfo::fpRegT0); 291 m_jit.sanitizeDouble(FPRInfo::fpRegT0); 292 m_jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor(operand)); 293 break; 294 289 295 case UnboxedInt32InGPR: 290 296 case Int32DisplacedInJSStack: -
trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp
r166662 r167325 298 298 m_jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0); 299 299 m_jit.loadDouble(GPRInfo::regT0, FPRInfo::fpRegT0); 300 m_jit.sanitizeDouble(FPRInfo::fpRegT0); 300 301 m_jit.boxDouble(FPRInfo::fpRegT0, GPRInfo::regT0); 301 302 m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand)); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r167189 r167325 491 491 case GetArrayLength: 492 492 case GetTypedArrayByteOffset: 493 case Int32ToDouble:494 493 case DoubleAsInt32: 495 494 case GetLocalUnlinked: … … 505 504 case CheckTierUpAndOSREnter: 506 505 case InvalidationPoint: 507 case Int52ToValue:508 case Int52ToDouble:509 506 case CheckInBounds: 510 507 case ValueToInt32: 511 case HardPhantom: { 508 case HardPhantom: 509 case DoubleRep: 510 case Int52Rep: 511 case ValueRep: 512 case DoubleConstant: 513 case Int52Constant: 514 case Identity: { 512 515 // This node should never be visible at this stage of compilation. It is 513 516 // inserted by fixup(), which follows this phase. … … 534 537 case In: 535 538 changed |= setPrediction(SpecBoolean); 536 break;537 538 case Identity:539 changed |= mergePrediction(node->child1()->prediction());540 539 break; 541 540 -
trunk/Source/JavaScriptCore/dfg/DFGResurrectionForValidationPhase.cpp
r164229 r167325 58 58 continue; 59 59 insertionSet.insertNode( 60 nodeIndex + 1, SpecNone, Phantom, node->origin, Edge(node));60 nodeIndex + 1, SpecNone, Phantom, node->origin, node->defaultEdge()); 61 61 } 62 62 -
trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp
r165995 r167325 193 193 m_insertionSet.insertNode( 194 194 0, SpecNone, MovHint, NodeOrigin(), 195 OpInfo(variable->local().offset()), Edge(node));195 OpInfo(variable->local().offset()), node->defaultEdge()); 196 196 } 197 197 } … … 351 351 if (variable->isCaptured()) 352 352 break; 353 node->child1().setNode(block->variablesAtHead.operand(variable->local())); 353 ASSERT(node->child1().useKind() == UntypedUse); 354 node->child1() = 355 block->variablesAtHead.operand(variable->local())->defaultEdge(); 354 356 node->convertToPhantom(); 355 357 // This is only for Upsilons. An Upsilon will only refer to a … … 364 366 break; 365 367 node->setOpAndDefaultFlags(GetArgument); 366 node-> mergeFlags(resultFor(node->variableAccessData()->flushFormat()));368 node->setResult(resultFor(node->variableAccessData()->flushFormat())); 367 369 break; 368 370 } -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r167189 r167325 47 47 case UntypedUse: 48 48 case Int32Use: 49 case RealNumberUse: 49 case DoubleRepUse: 50 case DoubleRepRealUse: 51 case Int52RepUse: 50 52 case NumberUse: 51 53 case BooleanUse: … … 62 64 case OtherUse: 63 65 case MiscUse: 64 case MachineIntUse:65 66 return; 66 67 67 68 case KnownInt32Use: 68 69 if (m_state.forNode(edge).m_type & ~SpecInt32) 69 m_result = false;70 return;71 72 case KnownNumberUse:73 if (m_state.forNode(edge).m_type & ~SpecFullNumber)74 70 m_result = false; 75 71 return; … … 112 108 switch (node->op()) { 113 109 case JSConstant: 110 case DoubleConstant: 111 case Int52Constant: 114 112 case WeakJSConstant: 115 113 case Identity: … … 138 136 case ValueToInt32: 139 137 case UInt32ToNumber: 140 case Int32ToDouble:141 138 case DoubleAsInt32: 142 139 case ArithAdd: … … 243 240 case CheckTierUpAndOSREnter: 244 241 case LoopHint: 245 case Int52ToDouble:246 case Int52ToValue:247 242 case StoreBarrier: 248 243 case StoreBarrierWithNullCheck: … … 256 251 case MultiGetByOffset: 257 252 case MultiPutByOffset: 253 case ValueRep: 254 case DoubleRep: 255 case Int52Rep: 258 256 return true; 259 257 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r167112 r167325 333 333 if (node->hasConstant()) 334 334 fillAction = SetInt52Constant; 335 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)336 fillAction = Load32PayloadConvertToInt52;337 335 else if (info.spillFormat() == DataFormatInt52) 338 336 fillAction = Load64; … … 342 340 fillAction = Load64; 343 341 else { 344 // Should never happen. Anything that qualifies as an int32 will never345 // be turned into a cell (immediate spec fail) or a double (to-double346 // conversions involve a separate node).347 342 RELEASE_ASSERT_NOT_REACHED(); 348 343 fillAction = Load64; // Make GCC happy. … … 351 346 if (node->hasConstant()) 352 347 fillAction = SetStrictInt52Constant; 353 else if (isJSInt32(info.spillFormat()) || info.spillFormat() == DataFormatJS)354 fillAction = Load32PayloadSignExtend;355 348 else if (info.spillFormat() == DataFormatInt52) 356 349 fillAction = Load64ShiftInt52Right; … … 360 353 fillAction = Load64; 361 354 else { 362 // Should never happen. Anything that qualifies as an int32 will never363 // be turned into a cell (immediate spec fail) or a double (to-double364 // conversions involve a separate node).365 355 RELEASE_ASSERT_NOT_REACHED(); 366 356 fillAction = Load64; // Make GCC happy. … … 377 367 ASSERT(registerFormat == DataFormatJSInt32); 378 368 fillAction = Load32PayloadBoxInt; 379 } else if (info.spillFormat() == DataFormatDouble) {380 ASSERT(registerFormat == DataFormatJSDouble);381 fillAction = LoadDoubleBoxDouble;382 369 } else 383 370 fillAction = Load64; … … 435 422 ASSERT(isNumberConstant(node)); 436 423 fillAction = SetDoubleConstant; 437 } else if (info.spillFormat() != DataFormatNone && info.spillFormat() != DataFormatDouble) { 438 // it was already spilled previously and not as a double, which means we need unboxing. 439 ASSERT(info.spillFormat() & DataFormatJS); 440 fillAction = LoadJSUnboxDouble; 441 } else 424 } else { 425 ASSERT(info.spillFormat() == DataFormatNone || info.spillFormat() == DataFormatDouble); 442 426 fillAction = LoadDouble; 427 } 443 428 #elif USE(JSVALUE32_64) 444 ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);429 ASSERT(info.registerFormat() == DataFormatDouble); 445 430 if (node->hasConstant()) { 446 431 ASSERT(isNumberConstant(node)); … … 528 513 m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr()); 529 514 m_jit.signExtend32ToPtr(plan.gpr(), plan.gpr()); 530 break;531 case LoadDoubleBoxDouble:532 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());533 m_jit.sub64(GPRInfo::tagTypeNumberRegister, plan.gpr());534 break;535 case LoadJSUnboxDouble:536 m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), canTrample);537 unboxDouble(canTrample, plan.fpr());538 515 break; 539 516 #else … … 1040 1017 #endif // USE(JSVALUE32_64) 1041 1018 1019 JSValueRegsTemporary::JSValueRegsTemporary() { } 1020 1021 JSValueRegsTemporary::JSValueRegsTemporary(SpeculativeJIT* jit) 1022 #if USE(JSVALUE64) 1023 : m_gpr(jit) 1024 #else 1025 : m_payloadGPR(jit) 1026 , m_tagGPR(jit) 1027 #endif 1028 { 1029 } 1030 1031 JSValueRegsTemporary::~JSValueRegsTemporary() { } 1032 1033 JSValueRegs JSValueRegsTemporary::regs() 1034 { 1035 #if USE(JSVALUE64) 1036 return JSValueRegs(m_gpr.gpr()); 1037 #else 1038 return JSValueRegs(m_tagGPR.gpr(), m_payloadGPR.gpr()); 1039 #endif 1040 } 1041 1042 1042 void GPRTemporary::adopt(GPRTemporary& other) 1043 1043 { … … 1259 1259 compilePeepHoleInt32Branch(node, branchNode, condition); 1260 1260 #if USE(JSVALUE64) 1261 else if (node->isBinaryUseKind( MachineIntUse))1261 else if (node->isBinaryUseKind(Int52RepUse)) 1262 1262 compilePeepHoleInt52Branch(node, branchNode, condition); 1263 1263 #endif // USE(JSVALUE64) 1264 else if (node->isBinaryUseKind( NumberUse))1264 else if (node->isBinaryUseKind(DoubleRepUse)) 1265 1265 compilePeepHoleDoubleBranch(node, branchNode, doubleCondition); 1266 1266 else if (node->op() == CompareEq) { … … 1818 1818 case DataFormatJS: 1819 1819 case DataFormatJSBoolean: 1820 case DataFormatJSDouble: 1820 1821 return GeneratedOperandJSValue; 1821 1822 … … 1824 1825 return GeneratedOperandInteger; 1825 1826 1826 case DataFormatJSDouble:1827 case DataFormatDouble:1828 return GeneratedOperandDouble;1829 1830 1827 default: 1831 1828 RELEASE_ASSERT_NOT_REACHED(); … … 1846 1843 1847 1844 #if USE(JSVALUE64) 1848 case MachineIntUse: {1845 case Int52RepUse: { 1849 1846 SpeculateStrictInt52Operand op1(this, node->child1()); 1850 1847 GPRTemporary result(this, Reuse, op1); … … 1856 1853 } 1857 1854 #endif // USE(JSVALUE64) 1855 1856 case DoubleRepUse: { 1857 GPRTemporary result(this); 1858 SpeculateDoubleOperand op1(this, node->child1()); 1859 FPRReg fpr = op1.fpr(); 1860 GPRReg gpr = result.gpr(); 1861 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed); 1862 1863 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr)); 1864 1865 int32Result(gpr, node); 1866 return; 1867 } 1858 1868 1859 1869 case NumberUse: … … 1865 1875 m_jit.move(op1.gpr(), result.gpr()); 1866 1876 int32Result(result.gpr(), node, op1.format()); 1867 return;1868 }1869 case GeneratedOperandDouble: {1870 GPRTemporary result(this);1871 SpeculateDoubleOperand op1(this, node->child1(), ManualOperandSpeculation);1872 FPRReg fpr = op1.fpr();1873 GPRReg gpr = result.gpr();1874 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);1875 1876 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));1877 1878 int32Result(gpr, node);1879 1877 return; 1880 1878 } … … 2067 2065 } 2068 2066 2069 void SpeculativeJIT::compileInt32ToDouble(Node* node) 2070 { 2071 ASSERT(!isInt32Constant(node->child1().node())); // This should have been constant folded. 2072 2073 if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) { 2074 SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation); 2067 void SpeculativeJIT::compileDoubleRep(Node* node) 2068 { 2069 switch (node->child1().useKind()) { 2070 case NumberUse: { 2071 ASSERT(!isNumberConstant(node->child1().node())); // This should have been constant folded. 2072 2073 if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) { 2074 SpeculateInt32Operand op1(this, node->child1(), ManualOperandSpeculation); 2075 FPRTemporary result(this); 2076 m_jit.convertInt32ToDouble(op1.gpr(), result.fpr()); 2077 doubleResult(result.fpr(), node); 2078 return; 2079 } 2080 2081 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 2075 2082 FPRTemporary result(this); 2076 m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());2077 doubleResult(result.fpr(), node);2078 return;2079 }2080 2081 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);2082 FPRTemporary result(this);2083 2083 2084 2084 #if USE(JSVALUE64) 2085 GPRTemporary temp(this); 2086 2087 GPRReg op1GPR = op1.gpr(); 2088 GPRReg tempGPR = temp.gpr(); 2089 FPRReg resultFPR = result.fpr(); 2090 2091 JITCompiler::Jump isInteger = m_jit.branch64( 2092 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2093 2094 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2095 typeCheck( 2096 JSValueRegs(op1GPR), node->child1(), SpecFullNumber, 2097 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2098 } 2099 2100 m_jit.move(op1GPR, tempGPR); 2101 unboxDouble(tempGPR, resultFPR); 2102 JITCompiler::Jump done = m_jit.jump(); 2103 2104 isInteger.link(&m_jit); 2105 m_jit.convertInt32ToDouble(op1GPR, resultFPR); 2106 done.link(&m_jit); 2107 #else 2108 FPRTemporary temp(this); 2109 2110 GPRReg op1TagGPR = op1.tagGPR(); 2111 GPRReg op1PayloadGPR = op1.payloadGPR(); 2112 FPRReg tempFPR = temp.fpr(); 2113 FPRReg resultFPR = result.fpr(); 2114 2115 JITCompiler::Jump isInteger = m_jit.branch32( 2116 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2117 2118 if (needsTypeCheck(node->child1(), SpecFullNumber)) { 2119 typeCheck( 2120 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecFullNumber, 2121 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2122 } 2123 2124 unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR); 2125 JITCompiler::Jump done = m_jit.jump(); 2126 2127 isInteger.link(&m_jit); 2128 m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR); 2129 done.link(&m_jit); 2085 GPRTemporary temp(this); 2086 2087 GPRReg op1GPR = op1.gpr(); 2088 GPRReg tempGPR = temp.gpr(); 2089 FPRReg resultFPR = result.fpr(); 2090 2091 JITCompiler::Jump isInteger = m_jit.branch64( 2092 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 2093 2094 if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) { 2095 typeCheck( 2096 JSValueRegs(op1GPR), node->child1(), SpecBytecodeNumber, 2097 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 2098 } 2099 2100 m_jit.move(op1GPR, tempGPR); 2101 unboxDouble(tempGPR, resultFPR); 2102 JITCompiler::Jump done = m_jit.jump(); 2103 2104 isInteger.link(&m_jit); 2105 m_jit.convertInt32ToDouble(op1GPR, resultFPR); 2106 done.link(&m_jit); 2107 #else // USE(JSVALUE64) -> this is the 32_64 case 2108 FPRTemporary temp(this); 2109 2110 GPRReg op1TagGPR = op1.tagGPR(); 2111 GPRReg op1PayloadGPR = op1.payloadGPR(); 2112 FPRReg tempFPR = temp.fpr(); 2113 FPRReg resultFPR = result.fpr(); 2114 2115 JITCompiler::Jump isInteger = m_jit.branch32( 2116 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 2117 2118 if (needsTypeCheck(node->child1(), SpecBytecodeNumber)) { 2119 typeCheck( 2120 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecBytecodeNumber, 2121 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 2122 } 2123 2124 unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR); 2125 JITCompiler::Jump done = m_jit.jump(); 2126 2127 isInteger.link(&m_jit); 2128 m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR); 2129 done.link(&m_jit); 2130 #endif // USE(JSVALUE64) 2131 2132 doubleResult(resultFPR, node); 2133 return; 2134 } 2135 2136 #if USE(JSVALUE64) 2137 case Int52RepUse: { 2138 SpeculateStrictInt52Operand value(this, node->child1()); 2139 FPRTemporary result(this); 2140 2141 GPRReg valueGPR = value.gpr(); 2142 FPRReg resultFPR = result.fpr(); 2143 2144 m_jit.convertInt64ToDouble(valueGPR, resultFPR); 2145 2146 doubleResult(resultFPR, node); 2147 return; 2148 } 2149 #endif // USE(JSVALUE64) 2150 2151 default: 2152 RELEASE_ASSERT_NOT_REACHED(); 2153 return; 2154 } 2155 } 2156 2157 void SpeculativeJIT::compileValueRep(Node* node) 2158 { 2159 switch (node->child1().useKind()) { 2160 case DoubleRepUse: { 2161 SpeculateDoubleOperand value(this, node->child1()); 2162 JSValueRegsTemporary result(this); 2163 2164 FPRReg valueFPR = value.fpr(); 2165 JSValueRegs resultRegs = result.regs(); 2166 2167 #if CPU(X86) 2168 // boxDouble() on X86 clobbers the source, so we need to copy. 2169 // FIXME: Don't do that! https://bugs.webkit.org/show_bug.cgi?id=131690 2170 FPRTemporary temp(this); 2171 m_jit.moveDouble(valueFPR, temp.fpr()); 2172 valueFPR = temp.fpr(); 2130 2173 #endif 2131 2132 doubleResult(resultFPR, node); 2174 2175 boxDouble(valueFPR, resultRegs); 2176 2177 jsValueResult(resultRegs, node); 2178 return; 2179 } 2180 2181 #if USE(JSVALUE64) 2182 case Int52RepUse: { 2183 SpeculateStrictInt52Operand value(this, node->child1()); 2184 GPRTemporary result(this); 2185 2186 GPRReg valueGPR = value.gpr(); 2187 GPRReg resultGPR = result.gpr(); 2188 2189 boxInt52(valueGPR, resultGPR, DataFormatStrictInt52); 2190 2191 jsValueResult(resultGPR, node); 2192 return; 2193 } 2194 #endif // USE(JSVALUE64) 2195 2196 default: 2197 RELEASE_ASSERT_NOT_REACHED(); 2198 return; 2199 } 2133 2200 } 2134 2201 … … 2321 2388 2322 2389 #if USE(JSVALUE64) 2323 case MachineIntUse: {2390 case Int52RepUse: { 2324 2391 SpeculateStrictInt52Operand valueOp(this, valueUse); 2325 2392 GPRTemporary scratch(this); … … 2345 2412 #endif // USE(JSVALUE64) 2346 2413 2347 case NumberUse: {2414 case DoubleRepUse: { 2348 2415 if (isClamped(type)) { 2349 2416 ASSERT(elementSize(type) == 1); … … 2441 2508 } 2442 2509 2443 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg); 2444 static const double NaN = QNaN; 2445 m_jit.loadDouble(&NaN, resultReg); 2446 notNaN.link(&m_jit); 2510 m_jit.sanitizeDouble(resultReg); 2447 2511 2448 2512 doubleResult(resultReg, node); … … 2642 2706 2643 2707 #if USE(JSVALUE64) 2644 case MachineIntUse: {2708 case Int52RepUse: { 2645 2709 ASSERT(shouldCheckOverflow(node->arithMode())); 2646 2710 ASSERT(!shouldCheckNegativeZero(node->arithMode())); … … 2671 2735 #endif // USE(JSVALUE64) 2672 2736 2673 case NumberUse: {2737 case DoubleRepUse: { 2674 2738 SpeculateDoubleOperand op1(this, node->child1()); 2675 2739 SpeculateDoubleOperand op2(this, node->child2()); … … 2808 2872 2809 2873 #if USE(JSVALUE64) 2810 case MachineIntUse: {2874 case Int52RepUse: { 2811 2875 ASSERT(shouldCheckOverflow(node->arithMode())); 2812 2876 ASSERT(!shouldCheckNegativeZero(node->arithMode())); … … 2837 2901 #endif // USE(JSVALUE64) 2838 2902 2839 case NumberUse: {2903 case DoubleRepUse: { 2840 2904 SpeculateDoubleOperand op1(this, node->child1()); 2841 2905 SpeculateDoubleOperand op2(this, node->child2()); … … 2882 2946 2883 2947 #if USE(JSVALUE64) 2884 case MachineIntUse: {2948 case Int52RepUse: { 2885 2949 ASSERT(shouldCheckOverflow(node->arithMode())); 2886 2950 … … 2919 2983 #endif // USE(JSVALUE64) 2920 2984 2921 case NumberUse: {2985 case DoubleRepUse: { 2922 2986 SpeculateDoubleOperand op1(this, node->child1()); 2923 2987 FPRTemporary result(this); … … 2970 3034 2971 3035 #if USE(JSVALUE64) 2972 case MachineIntUse: {3036 case Int52RepUse: { 2973 3037 ASSERT(shouldCheckOverflow(node->arithMode())); 2974 3038 … … 3027 3091 #endif // USE(JSVALUE64) 3028 3092 3029 case NumberUse: {3093 case DoubleRepUse: { 3030 3094 SpeculateDoubleOperand op1(this, node->child1()); 3031 3095 SpeculateDoubleOperand op2(this, node->child2()); … … 3191 3255 } 3192 3256 3193 case NumberUse: {3257 case DoubleRepUse: { 3194 3258 SpeculateDoubleOperand op1(this, node->child1()); 3195 3259 SpeculateDoubleOperand op2(this, node->child2()); … … 3496 3560 } 3497 3561 3498 case NumberUse: {3562 case DoubleRepUse: { 3499 3563 SpeculateDoubleOperand op1(this, node->child1()); 3500 3564 SpeculateDoubleOperand op2(this, node->child2()); … … 3531 3595 3532 3596 #if USE(JSVALUE64) 3533 if (node->isBinaryUseKind( MachineIntUse)) {3597 if (node->isBinaryUseKind(Int52RepUse)) { 3534 3598 compileInt52Compare(node, condition); 3535 3599 return false; … … 3537 3601 #endif // USE(JSVALUE64) 3538 3602 3539 if (node->isBinaryUseKind( NumberUse)) {3603 if (node->isBinaryUseKind(DoubleRepUse)) { 3540 3604 compileDoubleCompare(node, doubleCondition); 3541 3605 return false; … … 3611 3675 3612 3676 #if USE(JSVALUE64) 3613 if (node->isBinaryUseKind( MachineIntUse)) {3677 if (node->isBinaryUseKind(Int52RepUse)) { 3614 3678 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3615 3679 if (branchIndexInBlock != UINT_MAX) { … … 3627 3691 #endif // USE(JSVALUE64) 3628 3692 3629 if (node->isBinaryUseKind( NumberUse)) {3693 if (node->isBinaryUseKind(DoubleRepUse)) { 3630 3694 unsigned branchIndexInBlock = detectPeepHoleBranch(); 3631 3695 if (branchIndexInBlock != UINT_MAX) { … … 4488 4552 } 4489 4553 4490 void SpeculativeJIT::speculateMachineInt(Edge edge) 4491 { 4554 void SpeculativeJIT::speculateNumber(Edge edge) 4555 { 4556 if (!needsTypeCheck(edge, SpecBytecodeNumber)) 4557 return; 4558 4559 JSValueOperand value(this, edge, ManualOperandSpeculation); 4492 4560 #if USE(JSVALUE64) 4493 if (!needsTypeCheck(edge, SpecMachineInt)) 4494 return; 4495 4496 (SpeculateWhicheverInt52Operand(this, edge)).gpr(); 4497 #else // USE(JSVALUE64) 4498 UNUSED_PARAM(edge); 4499 UNREACHABLE_FOR_PLATFORM(); 4500 #endif // USE(JSVALUE64) 4501 } 4502 4503 void SpeculativeJIT::speculateNumber(Edge edge) 4504 { 4505 if (!needsTypeCheck(edge, SpecFullNumber)) 4506 return; 4507 4508 (SpeculateDoubleOperand(this, edge)).fpr(); 4509 } 4510 4511 void SpeculativeJIT::speculateRealNumber(Edge edge) 4512 { 4513 if (!needsTypeCheck(edge, SpecFullRealNumber)) 4561 GPRReg gpr = value.gpr(); 4562 typeCheck( 4563 JSValueRegs(gpr), edge, SpecBytecodeNumber, 4564 m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); 4565 #else 4566 GPRReg tagGPR = value.tagGPR(); 4567 DFG_TYPE_CHECK( 4568 value.jsValueRegs(), edge, ~SpecInt32, 4569 m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag))); 4570 DFG_TYPE_CHECK( 4571 value.jsValueRegs(), edge, SpecBytecodeNumber, 4572 m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 4573 #endif 4574 } 4575 4576 void SpeculativeJIT::speculateDoubleReal(Edge edge) 4577 { 4578 if (!needsTypeCheck(edge, SpecDoubleReal)) 4514 4579 return; 4515 4580 4516 4581 SpeculateDoubleOperand operand(this, edge); 4517 4582 FPRReg fpr = operand.fpr(); 4518 DFG_TYPE_CHECK(4519 JSValueRegs(), edge, Spec FullRealNumber,4583 typeCheck( 4584 JSValueRegs(), edge, SpecDoubleReal, 4520 4585 m_jit.branchDouble( 4521 4586 MacroAssembler::DoubleNotEqualOrUnordered, fpr, fpr)); … … 4769 4834 ASSERT(!needsTypeCheck(edge, SpecInt32)); 4770 4835 break; 4771 case KnownNumberUse: 4772 ASSERT(!needsTypeCheck(edge, SpecFullNumber)); 4836 case DoubleRepUse: 4837 ASSERT(!needsTypeCheck(edge, SpecDouble)); 4838 break; 4839 case Int52RepUse: 4840 ASSERT(!needsTypeCheck(edge, SpecMachineInt)); 4773 4841 break; 4774 4842 case KnownCellUse: … … 4781 4849 speculateInt32(edge); 4782 4850 break; 4783 case MachineIntUse:4784 speculateMachineInt(edge);4785 break;4786 case RealNumberUse:4787 speculateRealNumber(edge);4788 break;4789 4851 case NumberUse: 4790 4852 speculateNumber(edge); 4853 break; 4854 case DoubleRepRealUse: 4855 speculateDoubleReal(edge); 4791 4856 break; 4792 4857 case BooleanUse: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r166135 r167325 55 55 class SpeculateBooleanOperand; 56 56 57 enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperand Double, GeneratedOperandJSValue};57 enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandJSValue}; 58 58 59 59 inline GPRReg extractResult(GPRReg result) { return result; } … … 191 191 #if USE(JSVALUE32_64) 192 192 GenerationInfo& info = generationInfoFromVirtualRegister(spillMe); 193 RELEASE_ASSERT(info.registerFormat() != DataFormatJSDouble);194 193 if ((info.registerFormat() & DataFormatJS)) 195 194 m_gprs.release(info.tagGPR() == gpr ? info.payloadGPR() : info.tagGPR()); … … 266 265 m_gprs.release(info.gpr()); 267 266 #elif USE(JSVALUE32_64) 268 if (registerFormat == DataFormatDouble || registerFormat == DataFormatJSDouble)267 if (registerFormat == DataFormatDouble) 269 268 m_fprs.release(info.fpr()); 270 269 else if (registerFormat & DataFormatJS) { … … 460 459 } 461 460 #endif 461 void boxDouble(FPRReg fpr, JSValueRegs regs) 462 { 463 m_jit.boxDouble(fpr, regs); 464 } 462 465 463 466 // Spill a VirtualRegister to the JSStack. … … 529 532 } 530 533 531 case DataFormatDouble: 532 case DataFormatJSDouble: { 534 case DataFormatDouble: { 533 535 // On JSVALUE32_64 boxing a double is a no-op. 534 536 m_jit.storeDouble(info.fpr(), JITCompiler::addressFor(spillMe)); 535 info.spill(*m_stream, spillMe, DataFormat JSDouble);537 info.spill(*m_stream, spillMe, DataFormatDouble); 536 538 return; 537 539 } … … 926 928 } 927 929 #endif 930 void jsValueResult(JSValueRegs regs, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren) 931 { 932 #if USE(JSVALUE64) 933 jsValueResult(regs.gpr(), node, format, mode); 934 #else 935 jsValueResult(regs.tagGPR(), regs.payloadGPR(), node, format, mode); 936 #endif 937 } 928 938 void storageResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren) 929 939 { … … 2081 2091 void compileGetArrayLength(Node*); 2082 2092 2093 void compileValueRep(Node*); 2094 void compileDoubleRep(Node*); 2095 2083 2096 void compileValueToInt32(Node*); 2084 2097 void compileUInt32ToNumber(Node*); 2085 2098 void compileDoubleAsInt32(Node*); 2086 void compileInt32ToDouble(Node*);2087 2099 void compileAdd(Node*); 2088 2100 void compileMakeRope(Node*); … … 2186 2198 void emitAllocateJSArray(GPRReg resultGPR, Structure*, GPRReg storageGPR, unsigned numElements); 2187 2199 2188 #if USE(JSVALUE64)2189 JITCompiler::Jump convertToDouble(GPRReg value, FPRReg result, GPRReg tmp);2190 #elif USE(JSVALUE32_64)2191 JITCompiler::Jump convertToDouble(JSValueOperand&, FPRReg result);2192 #endif2193 2194 2200 // Add a speculation check. 2195 2201 void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail); … … 2218 2224 void speculateMachineInt(Edge); 2219 2225 void speculateNumber(Edge); 2220 void speculate RealNumber(Edge);2226 void speculateDoubleReal(Edge); 2221 2227 void speculateBoolean(Edge); 2222 2228 void speculateCell(Edge); … … 2566 2572 }; 2567 2573 2574 class JSValueRegsTemporary { 2575 public: 2576 JSValueRegsTemporary(); 2577 JSValueRegsTemporary(SpeculativeJIT*); 2578 ~JSValueRegsTemporary(); 2579 2580 JSValueRegs regs(); 2581 2582 private: 2583 #if USE(JSVALUE64) 2584 GPRTemporary m_gpr; 2585 #else 2586 GPRTemporary m_payloadGPR; 2587 GPRTemporary m_tagGPR; 2588 #endif 2589 }; 2590 2568 2591 class FPRTemporary { 2569 2592 public: … … 2755 2778 class SpeculateInt52Operand { 2756 2779 public: 2757 explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)2780 explicit SpeculateInt52Operand(SpeculativeJIT* jit, Edge edge) 2758 2781 : m_jit(jit) 2759 2782 , m_edge(edge) 2760 2783 , m_gprOrInvalid(InvalidGPRReg) 2761 2784 { 2762 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);2785 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 2763 2786 if (jit->isFilled(node())) 2764 2787 gpr(); … … 2802 2825 class SpeculateStrictInt52Operand { 2803 2826 public: 2804 explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)2827 explicit SpeculateStrictInt52Operand(SpeculativeJIT* jit, Edge edge) 2805 2828 : m_jit(jit) 2806 2829 , m_edge(edge) 2807 2830 , m_gprOrInvalid(InvalidGPRReg) 2808 2831 { 2809 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);2832 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 2810 2833 if (jit->isFilled(node())) 2811 2834 gpr(); … … 2850 2873 class SpeculateWhicheverInt52Operand { 2851 2874 public: 2852 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)2875 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge) 2853 2876 : m_jit(jit) 2854 2877 , m_edge(edge) … … 2856 2879 , m_strict(jit->betterUseStrictInt52(edge)) 2857 2880 { 2858 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);2881 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 2859 2882 if (jit->isFilled(node())) 2860 2883 gpr(); 2861 2884 } 2862 2885 2863 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other , OperandSpeculationMode mode = AutomaticOperandSpeculation)2886 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, const SpeculateWhicheverInt52Operand& other) 2864 2887 : m_jit(jit) 2865 2888 , m_edge(edge) … … 2867 2890 , m_strict(other.m_strict) 2868 2891 { 2869 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);2892 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 2870 2893 if (jit->isFilled(node())) 2871 2894 gpr(); 2872 2895 } 2873 2896 2874 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other , OperandSpeculationMode mode = AutomaticOperandSpeculation)2897 explicit SpeculateWhicheverInt52Operand(SpeculativeJIT* jit, Edge edge, OppositeShiftTag, const SpeculateWhicheverInt52Operand& other) 2875 2898 : m_jit(jit) 2876 2899 , m_edge(edge) … … 2878 2901 , m_strict(!other.m_strict) 2879 2902 { 2880 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse);2903 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 2881 2904 if (jit->isFilled(node())) 2882 2905 gpr(); … … 2927 2950 class SpeculateDoubleOperand { 2928 2951 public: 2929 explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)2952 explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge edge) 2930 2953 : m_jit(jit) 2931 2954 , m_edge(edge) … … 2933 2956 { 2934 2957 ASSERT(m_jit); 2935 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation ||isDouble(edge.useKind()));2958 RELEASE_ASSERT(isDouble(edge.useKind())); 2936 2959 if (jit->isFilled(node())) 2937 2960 fpr(); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r167189 r167325 135 135 136 136 case DataFormatJSDouble: 137 case DataFormatDouble: {138 FPRReg oldFPR = info.fpr();139 m_fprs.lock(oldFPR);140 tagGPR = allocate();141 payloadGPR = allocate();142 boxDouble(oldFPR, tagGPR, payloadGPR);143 m_fprs.unlock(oldFPR);144 m_fprs.release(oldFPR);145 m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);146 m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);147 info.fillJSValue(*m_stream, tagGPR, payloadGPR, DataFormatJS);148 return true;149 }150 151 137 case DataFormatJS: 152 138 case DataFormatJSInt32: … … 161 147 162 148 case DataFormatStorage: 149 case DataFormatDouble: 163 150 // this type currently never occurs 164 151 RELEASE_ASSERT_NOT_REACHED(); … … 757 744 switch (info.registerFormat()) { 758 745 case DataFormatNone: { 759 if (info.spillFormat() == DataFormatDouble) {760 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);761 returnFormat = DataFormatInt32;762 return allocate();763 }764 765 746 if (edge->hasConstant()) { 766 747 ASSERT(isInt32Constant(edge.node())); … … 814 795 } 815 796 816 case DataFormatDouble:817 797 case DataFormatCell: 818 798 case DataFormatBoolean: … … 824 804 return allocate(); 825 805 806 case DataFormatDouble: 826 807 case DataFormatStorage: 827 808 default: … … 846 827 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge) 847 828 { 848 AbstractValue& value = m_state.forNode(edge); 849 SpeculatedType type = value.m_type; 850 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber)); 851 m_interpreter.filter(value, SpecFullNumber); 829 ASSERT(isDouble(edge.useKind())); 830 ASSERT(edge->hasDoubleResult()); 852 831 VirtualRegister virtualRegister = edge->virtualRegister(); 853 832 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); … … 856 835 857 836 if (edge->hasConstant()) { 858 if (isInt32Constant(edge.node())) { 859 GPRReg gpr = allocate(); 860 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 861 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant); 862 info.fillInt32(*m_stream, gpr); 863 unlock(gpr); 864 } else if (isNumberConstant(edge.node())) { 865 FPRReg fpr = fprAllocate(); 866 m_jit.loadDouble(addressOfDoubleConstant(edge.node()), fpr); 867 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant); 868 info.fillDouble(*m_stream, fpr); 869 return fpr; 870 } else { 871 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 872 return fprAllocate(); 873 } 874 } else { 875 DataFormat spillFormat = info.spillFormat(); 876 ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32); 877 if (spillFormat == DataFormatJSDouble || spillFormat == DataFormatDouble) { 878 FPRReg fpr = fprAllocate(); 879 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 880 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled); 881 info.fillDouble(*m_stream, fpr); 882 return fpr; 883 } 884 837 RELEASE_ASSERT(isNumberConstant(edge.node())); 885 838 FPRReg fpr = fprAllocate(); 886 JITCompiler::Jump hasUnboxedDouble; 887 888 if (spillFormat != DataFormatJSInt32 && spillFormat != DataFormatInt32) { 889 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)); 890 if (type & ~SpecFullNumber) 891 speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::LowestTag))); 892 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 893 hasUnboxedDouble = m_jit.jump(); 894 895 isInteger.link(&m_jit); 896 } 897 898 m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr); 899 900 if (hasUnboxedDouble.isSet()) 901 hasUnboxedDouble.link(&m_jit); 902 903 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled); 839 m_jit.loadDouble(addressOfDoubleConstant(edge.node()), fpr); 840 m_fprs.retain(fpr, virtualRegister, SpillOrderConstant); 904 841 info.fillDouble(*m_stream, fpr); 905 info.killSpilled();906 842 return fpr; 907 843 } 908 } 909 910 switch (info.registerFormat()) { 911 case DataFormatJS: 912 case DataFormatJSInt32: { 913 GPRReg tagGPR = info.tagGPR(); 914 GPRReg payloadGPR = info.payloadGPR(); 844 845 RELEASE_ASSERT(info.spillFormat() == DataFormatDouble); 915 846 FPRReg fpr = fprAllocate(); 916 917 m_gprs.lock(tagGPR); 918 m_gprs.lock(payloadGPR); 919 920 JITCompiler::Jump hasUnboxedDouble; 921 922 if (info.registerFormat() != DataFormatJSInt32) { 923 FPRTemporary scratch(this); 924 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 925 if (type & ~SpecFullNumber) 926 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 927 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 928 hasUnboxedDouble = m_jit.jump(); 929 isInteger.link(&m_jit); 930 } 931 932 m_jit.convertInt32ToDouble(payloadGPR, fpr); 933 934 if (hasUnboxedDouble.isSet()) 935 hasUnboxedDouble.link(&m_jit); 936 937 m_gprs.release(tagGPR); 938 m_gprs.release(payloadGPR); 939 m_gprs.unlock(tagGPR); 940 m_gprs.unlock(payloadGPR); 941 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 847 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 848 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled); 942 849 info.fillDouble(*m_stream, fpr); 943 info.killSpilled();944 850 return fpr; 945 851 } 946 852 947 case DataFormatInt32: { 948 FPRReg fpr = fprAllocate(); 949 GPRReg gpr = info.gpr(); 950 m_gprs.lock(gpr); 951 m_jit.convertInt32ToDouble(gpr, fpr); 952 m_gprs.unlock(gpr); 953 return fpr; 954 } 955 956 case DataFormatJSDouble: 957 case DataFormatDouble: { 958 FPRReg fpr = info.fpr(); 959 m_fprs.lock(fpr); 960 return fpr; 961 } 962 963 case DataFormatNone: 964 case DataFormatStorage: 965 RELEASE_ASSERT_NOT_REACHED(); 966 967 case DataFormatCell: 968 case DataFormatJSCell: 969 case DataFormatBoolean: 970 case DataFormatJSBoolean: 971 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 972 return fprAllocate(); 973 974 default: 975 RELEASE_ASSERT_NOT_REACHED(); 976 return InvalidFPRReg; 977 } 853 RELEASE_ASSERT(info.registerFormat() == DataFormatDouble); 854 FPRReg fpr = info.fpr(); 855 m_fprs.lock(fpr); 856 return fpr; 978 857 } 979 858 … … 989 868 switch (info.registerFormat()) { 990 869 case DataFormatNone: { 991 if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {870 if (info.spillFormat() == DataFormatInt32) { 992 871 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 993 872 return allocate(); … … 1053 932 case DataFormatInt32: 1054 933 case DataFormatJSDouble: 1055 case DataFormatDouble:1056 934 case DataFormatJSBoolean: 1057 935 case DataFormatBoolean: … … 1059 937 return allocate(); 1060 938 939 case DataFormatDouble: 1061 940 case DataFormatStorage: 1062 941 RELEASE_ASSERT_NOT_REACHED(); … … 1078 957 switch (info.registerFormat()) { 1079 958 case DataFormatNone: { 1080 if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {959 if (info.spillFormat() == DataFormatInt32) { 1081 960 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1082 961 return allocate(); … … 1134 1013 case DataFormatInt32: 1135 1014 case DataFormatJSDouble: 1136 case DataFormatDouble:1137 1015 case DataFormatJSCell: 1138 1016 case DataFormatCell: … … 1140 1018 return allocate(); 1141 1019 1020 case DataFormatDouble: 1142 1021 case DataFormatStorage: 1143 1022 RELEASE_ASSERT_NOT_REACHED(); … … 1147 1026 return InvalidGPRReg; 1148 1027 } 1149 }1150 1151 JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg result)1152 {1153 FPRTemporary scratch(this);1154 1155 GPRReg opPayloadGPR = op.payloadGPR();1156 GPRReg opTagGPR = op.tagGPR();1157 FPRReg scratchFPR = scratch.fpr();1158 1159 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, opTagGPR, TrustedImm32(JSValue::Int32Tag));1160 JITCompiler::Jump notNumber = m_jit.branch32(MacroAssembler::AboveOrEqual, opPayloadGPR, TrustedImm32(JSValue::LowestTag));1161 1162 unboxDouble(opTagGPR, opPayloadGPR, result, scratchFPR);1163 JITCompiler::Jump done = m_jit.jump();1164 1165 isInteger.link(&m_jit);1166 m_jit.convertInt32ToDouble(opPayloadGPR, result);1167 1168 done.link(&m_jit);1169 1170 return notNumber;1171 1028 } 1172 1029 … … 1548 1405 } 1549 1406 1550 case NumberUse: {1407 case DoubleRepUse: { 1551 1408 SpeculateDoubleOperand value(this, node->child1()); 1552 1409 FPRTemporary scratch(this); … … 1677 1534 } 1678 1535 1679 case NumberUse:1536 case DoubleRepUse: 1680 1537 case Int32Use: { 1681 1538 if (node->child1().useKind() == Int32Use) { … … 1818 1675 switch (op) { 1819 1676 case JSConstant: 1677 case DoubleConstant: 1820 1678 initConstantInfo(node); 1821 1679 break; … … 1979 1837 case FlushedJSValue: 1980 1838 case FlushedArguments: { 1981 if (generationInfoFromVirtualRegister(node->child1()->virtualRegister()).registerFormat() == DataFormatDouble) {1982 SpeculateDoubleOperand value(this, node->child1(), ManualOperandSpeculation);1983 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));1984 noResult(node);1985 recordSetLocal(DataFormatDouble);1986 break;1987 }1988 1989 1839 JSValueOperand value(this, node->child1()); 1990 1840 m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal())); … … 2078 1928 } 2079 1929 2080 case Int32ToDouble: { 2081 compileInt32ToDouble(node); 1930 case DoubleRep: { 1931 compileDoubleRep(node); 1932 break; 1933 } 1934 1935 case ValueRep: { 1936 compileValueRep(node); 2082 1937 break; 2083 1938 } … … 2152 2007 2153 2008 2154 case NumberUse: {2009 case DoubleRepUse: { 2155 2010 SpeculateDoubleOperand op1(this, node->child1()); 2156 2011 FPRTemporary result(this); … … 2194 2049 } 2195 2050 2196 case NumberUse: {2051 case DoubleRepUse: { 2197 2052 SpeculateDoubleOperand op1(this, node->child1()); 2198 2053 SpeculateDoubleOperand op2(this, node->child2()); … … 4746 4601 case CheckTierUpAtReturn: 4747 4602 case CheckTierUpAndOSREnter: 4748 case Int52 ToDouble:4749 case Int52 ToValue:4603 case Int52Rep: 4604 case Int52Constant: 4750 4605 case CheckInBounds: 4751 4606 case ArithIMul: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r167189 r167325 107 107 } 108 108 109 case DataFormatInt52:110 case DataFormatStrictInt52: {111 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);112 boxInt52(gpr, gpr, spillFormat);113 return gpr;114 }115 116 109 default: 117 110 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 118 if (spillFormat == DataFormatDouble) { 119 // Need to box the double, since we want a JSValue. 120 m_jit.sub64(GPRInfo::tagTypeNumberRegister, gpr); 121 spillFormat = DataFormatJSDouble; 122 } else 123 RELEASE_ASSERT(spillFormat & DataFormatJS); 111 RELEASE_ASSERT(spillFormat & DataFormatJS); 124 112 break; 125 113 } … … 142 130 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32); 143 131 return gpr; 144 }145 146 case DataFormatDouble: {147 FPRReg fpr = info.fpr();148 GPRReg gpr = boxDouble(fpr);149 150 // Update all info151 info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);152 m_fprs.release(fpr);153 m_gprs.retain(gpr, virtualRegister, SpillOrderJS);154 155 return gpr;156 }157 158 case DataFormatInt52:159 case DataFormatStrictInt52: {160 GPRReg gpr = info.gpr();161 lock(gpr);162 GPRReg resultGPR = allocate();163 boxInt52(gpr, resultGPR, info.registerFormat());164 unlock(gpr);165 return resultGPR;166 132 } 167 133 … … 180 146 case DataFormatBoolean: 181 147 case DataFormatStorage: 148 case DataFormatDouble: 149 case DataFormatInt52: 182 150 // this type currently never occurs 183 151 RELEASE_ASSERT_NOT_REACHED(); … … 770 738 switch (info.registerFormat()) { 771 739 case DataFormatNone: { 772 if (info.spillFormat() == DataFormatDouble) {773 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);774 returnFormat = DataFormatInt32;775 return allocate();776 }777 778 740 GPRReg gpr = allocate(); 779 741 … … 789 751 DataFormat spillFormat = info.spillFormat(); 790 752 791 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);753 RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32); 792 754 793 755 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); … … 808 770 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32); 809 771 returnFormat = DataFormatJSInt32; 810 return gpr;811 }812 if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {813 // Generally, this can only happen if we've already proved that the814 // value is an int32. That's because if a value originated as a JSValue815 // then we would speculate that it's an int32 before representing it as816 // an int52. Otherwise, if we knowingly produced an int52, then we would817 // be boxing it into a value using Int52ToValue. This assertion is valid818 // only because Int52 is something that we introduce at prediction time.819 // However: we may have an int32-producing node replaced by an820 // int52-producing node due to CSE. So we must do a check.821 RELEASE_ASSERT(!(type & ~SpecMachineInt));822 if (type & SpecInt52) {823 GPRReg temp = allocate();824 m_jit.signExtend32ToPtr(gpr, temp);825 // Currently, we can't supply value profiling information here. :-/826 speculationCheck(827 BadType, JSValueRegs(), 0,828 m_jit.branch64(MacroAssembler::NotEqual, gpr, temp));829 unlock(temp);830 }831 if (spillFormat == DataFormatStrictInt52)832 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);833 else {834 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);835 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);836 m_jit.zeroExtend32ToPtr(gpr, gpr);837 }838 info.fillInt32(*m_stream, gpr);839 returnFormat = DataFormatInt32;840 772 return gpr; 841 773 } … … 898 830 } 899 831 900 case DataFormatStrictInt52: 901 case DataFormatInt52: { 902 GPRReg gpr = info.gpr(); 903 GPRReg result; 904 DataFormat oldFormat = info.registerFormat(); 905 if (m_gprs.isLocked(gpr)) { 906 result = allocate(); 907 m_jit.move(gpr, result); 908 } else { 909 lock(gpr); 910 info.fillInt32(*m_stream, gpr); 911 result = gpr; 912 } 913 RELEASE_ASSERT(!(type & ~SpecMachineInt)); 914 if (oldFormat == DataFormatInt52) 915 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 916 if (type & SpecInt52) { 917 GPRReg temp = allocate(); 918 m_jit.signExtend32ToPtr(result, temp); 919 // Currently, we can't supply value profiling information here. :-/ 920 speculationCheck( 921 BadType, JSValueRegs(), 0, 922 m_jit.branch64(MacroAssembler::NotEqual, result, temp)); 923 unlock(temp); 924 } 925 m_jit.zeroExtend32ToPtr(result, result); 926 returnFormat = DataFormatInt32; 927 return gpr; 928 } 929 930 case DataFormatDouble: 931 case DataFormatJSDouble: { 932 if (edge->hasConstant() && isInt32Constant(edge.node())) { 933 GPRReg gpr = allocate(); 934 ASSERT(isInt32Constant(edge.node())); 935 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr); 936 returnFormat = DataFormatInt32; 937 return gpr; 938 } 939 FALLTHROUGH; 940 } 832 case DataFormatJSDouble: 941 833 case DataFormatCell: 942 834 case DataFormatBoolean: … … 948 840 } 949 841 842 case DataFormatDouble: 950 843 case DataFormatStorage: 844 case DataFormatInt52: 845 case DataFormatStrictInt52: 951 846 RELEASE_ASSERT_NOT_REACHED(); 952 847 … … 977 872 ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52); 978 873 AbstractValue& value = m_state.forNode(edge); 979 SpeculatedType type = value.m_type;980 874 m_interpreter.filter(value, SpecMachineInt); 981 875 VirtualRegister virtualRegister = edge->virtualRegister(); … … 984 878 switch (info.registerFormat()) { 985 879 case DataFormatNone: { 986 if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) {880 if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt())) { 987 881 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 988 882 return allocate(); … … 1005 899 DataFormat spillFormat = info.spillFormat(); 1006 900 1007 RELEASE_ASSERT( (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 ||spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);901 RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52); 1008 902 1009 903 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1010 904 1011 if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {1012 // If we know this was spilled as an integer we can fill without checking.1013 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);1014 m_jit.signExtend32ToPtr(gpr, gpr);1015 i f (desiredFormat == DataFormatStrictInt52) {1016 info.fillStrictInt52(*m_stream, gpr);1017 return gpr;1018 }905 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 906 if (desiredFormat == DataFormatStrictInt52) { 907 if (spillFormat == DataFormatInt52) 908 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 909 info.fillStrictInt52(*m_stream, gpr); 910 return gpr; 911 } 912 if (spillFormat == DataFormatStrictInt52) 1019 913 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1020 info.fillInt52(*m_stream, gpr); 1021 return gpr; 1022 } 1023 if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) { 1024 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1025 if (desiredFormat == DataFormatStrictInt52) { 1026 if (spillFormat == DataFormatInt52) 1027 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1028 info.fillStrictInt52(*m_stream, gpr); 1029 return gpr; 1030 } 1031 if (spillFormat == DataFormatStrictInt52) 1032 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr); 1033 info.fillInt52(*m_stream, gpr); 1034 return gpr; 1035 } 1036 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1037 1038 // Fill as JSValue, and fall through. 1039 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32); 1040 m_gprs.unlock(gpr); 1041 FALLTHROUGH; 1042 } 1043 1044 case DataFormatJS: { 1045 // Check the value is an integer. Note that we would *like* to unbox an Int52 1046 // at this point but this is too costly. We only *prove* that this is an Int52 1047 // even though we check if it's an int32. 1048 GPRReg gpr = info.gpr(); 1049 GPRReg result; 1050 if (m_gprs.isLocked(gpr)) { 1051 result = allocate(); 1052 m_jit.move(gpr, result); 1053 } else { 1054 m_gprs.lock(gpr); 1055 result = gpr; 1056 } 1057 if (type & ~SpecInt32) 1058 speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister)); 1059 if (result == gpr) // The not-already-locked, so fill in-place, case. 1060 info.fillInt52(*m_stream, gpr, desiredFormat); 1061 m_jit.signExtend32ToPtr(result, result); 1062 if (desiredFormat == DataFormatInt52) 1063 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 1064 return result; 1065 } 1066 1067 case DataFormatInt32: 1068 case DataFormatJSInt32: { 1069 GPRReg gpr = info.gpr(); 1070 GPRReg result; 1071 if (m_gprs.isLocked(gpr)) { 1072 result = allocate(); 1073 m_jit.move(gpr, result); 1074 } else { 1075 m_gprs.lock(gpr); 1076 info.fillInt52(*m_stream, gpr, desiredFormat); 1077 result = gpr; 1078 } 1079 m_jit.signExtend32ToPtr(result, result); 1080 if (desiredFormat == DataFormatInt52) 1081 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result); 1082 return result; 914 info.fillInt52(*m_stream, gpr); 915 return gpr; 1083 916 } 1084 917 … … 1117 950 } 1118 951 1119 case DataFormatDouble:1120 case DataFormatJSDouble:1121 if (edge->hasConstant()) {1122 JSValue jsValue = valueOfJSConstant(edge.node());1123 if (jsValue.isMachineInt()) {1124 int64_t value = jsValue.asMachineInt();1125 if (desiredFormat == DataFormatInt52)1126 value = value << JSValue::int52ShiftAmount;1127 GPRReg gpr = allocate();1128 m_jit.move(MacroAssembler::Imm64(value), gpr);1129 return gpr;1130 }1131 }1132 FALLTHROUGH;1133 case DataFormatCell:1134 case DataFormatBoolean:1135 case DataFormatJSCell:1136 case DataFormatJSBoolean: {1137 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);1138 return allocate();1139 }1140 1141 case DataFormatStorage:1142 RELEASE_ASSERT_NOT_REACHED();1143 1144 952 default: 1145 953 RELEASE_ASSERT_NOT_REACHED(); … … 1150 958 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge) 1151 959 { 1152 AbstractValue& value = m_state.forNode(edge); 1153 SpeculatedType type = value.m_type; 1154 ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber)); 1155 m_interpreter.filter(value, SpecFullNumber); 960 ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse); 961 ASSERT(edge->hasDoubleResult()); 1156 962 VirtualRegister virtualRegister = edge->virtualRegister(); 1157 963 GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister); … … 1161 967 GPRReg gpr = allocate(); 1162 968 1163 if (isInt32Constant(edge.node())) {1164 FPRReg fpr = fprAllocate();1165 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant(edge.node())))), gpr);1166 m_jit.move64ToDouble(gpr, fpr);1167 unlock(gpr);1168 1169 // Don't fill double here since that will lead to confusion: the1170 // register allocator will now think that this is a double while1171 // everyone else thinks it's an integer.1172 return fpr;1173 }1174 969 if (isNumberConstant(edge.node())) { 1175 970 FPRReg fpr = fprAllocate(); … … 1187 982 1188 983 DataFormat spillFormat = info.spillFormat(); 1189 switch (spillFormat) { 1190 case DataFormatDouble: { 1191 FPRReg fpr = fprAllocate(); 1192 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 1193 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 1194 info.fillDouble(*m_stream, fpr); 1195 return fpr; 1196 } 1197 1198 case DataFormatInt32: { 1199 GPRReg gpr = allocate(); 1200 1201 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1202 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr); 1203 info.fillInt32(*m_stream, gpr); 1204 unlock(gpr); 1205 break; 1206 } 1207 1208 case DataFormatInt52: { 1209 GPRReg gpr = allocate(); 1210 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1211 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1212 info.fillInt52(*m_stream, gpr); 1213 unlock(gpr); 1214 break; 1215 } 1216 1217 case DataFormatStrictInt52: { 1218 GPRReg gpr = allocate(); 1219 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1220 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1221 info.fillStrictInt52(*m_stream, gpr); 1222 unlock(gpr); 1223 break; 1224 } 1225 1226 default: 1227 GPRReg gpr = allocate(); 1228 1229 RELEASE_ASSERT(spillFormat & DataFormatJS); 1230 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); 1231 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr); 1232 info.fillJSValue(*m_stream, gpr, spillFormat); 1233 unlock(gpr); 1234 break; 1235 } 1236 } 1237 1238 switch (info.registerFormat()) { 1239 case DataFormatNone: // Should have filled, above. 1240 case DataFormatBoolean: // This type never occurs. 1241 case DataFormatStorage: 1242 RELEASE_ASSERT_NOT_REACHED(); 1243 1244 case DataFormatCell: 1245 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1246 return fprAllocate(); 1247 1248 case DataFormatJSCell: 1249 case DataFormatJS: 1250 case DataFormatJSBoolean: { 1251 GPRReg jsValueGpr = info.gpr(); 1252 m_gprs.lock(jsValueGpr); 984 RELEASE_ASSERT(spillFormat == DataFormatDouble); 1253 985 FPRReg fpr = fprAllocate(); 1254 GPRReg tempGpr = allocate(); 1255 1256 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); 1257 1258 if (type & ~SpecFullNumber) 1259 speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister)); 1260 1261 // First, if we get here we have a double encoded as a JSValue 1262 m_jit.move(jsValueGpr, tempGpr); 1263 unboxDouble(tempGpr, fpr); 1264 JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); 1265 1266 // Finally, handle integers. 1267 isInteger.link(&m_jit); 1268 m_jit.convertInt32ToDouble(jsValueGpr, fpr); 1269 hasUnboxedDouble.link(&m_jit); 1270 1271 m_gprs.release(jsValueGpr); 1272 m_gprs.unlock(jsValueGpr); 1273 m_gprs.unlock(tempGpr); 986 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr); 1274 987 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 1275 988 info.fillDouble(*m_stream, fpr); 1276 info.killSpilled();1277 989 return fpr; 1278 990 } 1279 991 1280 case DataFormatJSInt32: 1281 case DataFormatInt32: { 1282 FPRReg fpr = fprAllocate(); 1283 GPRReg gpr = info.gpr(); 1284 m_gprs.lock(gpr); 1285 m_jit.convertInt32ToDouble(gpr, fpr); 1286 m_gprs.unlock(gpr); 1287 return fpr; 1288 } 1289 1290 case DataFormatInt52: { 1291 FPRReg fpr = fprAllocate(); 1292 GPRReg gpr = info.gpr(); 1293 m_gprs.lock(gpr); 1294 GPRReg temp = allocate(); 1295 m_jit.move(gpr, temp); 1296 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp); 1297 m_jit.convertInt64ToDouble(temp, fpr); 1298 unlock(temp); 1299 m_gprs.unlock(gpr); 1300 return fpr; 1301 } 1302 1303 case DataFormatStrictInt52: { 1304 FPRReg fpr = fprAllocate(); 1305 GPRReg gpr = info.gpr(); 1306 m_gprs.lock(gpr); 1307 m_jit.convertInt64ToDouble(gpr, fpr); 1308 m_gprs.unlock(gpr); 1309 return fpr; 1310 } 1311 1312 // Unbox the double 1313 case DataFormatJSDouble: { 1314 GPRReg gpr = info.gpr(); 1315 FPRReg fpr = fprAllocate(); 1316 if (m_gprs.isLocked(gpr)) { 1317 // Make sure we don't trample gpr if it is in use. 1318 GPRReg temp = allocate(); 1319 m_jit.move(gpr, temp); 1320 unboxDouble(temp, fpr); 1321 unlock(temp); 1322 } else 1323 unboxDouble(gpr, fpr); 1324 1325 m_gprs.release(gpr); 1326 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble); 1327 1328 info.fillDouble(*m_stream, fpr); 1329 return fpr; 1330 } 1331 1332 case DataFormatDouble: { 1333 FPRReg fpr = info.fpr(); 1334 m_fprs.lock(fpr); 1335 return fpr; 1336 } 1337 1338 default: 1339 RELEASE_ASSERT_NOT_REACHED(); 1340 return InvalidFPRReg; 1341 } 992 RELEASE_ASSERT(info.registerFormat() == DataFormatDouble); 993 FPRReg fpr = info.fpr(); 994 m_fprs.lock(fpr); 995 return fpr; 1342 996 } 1343 997 … … 1353 1007 switch (info.registerFormat()) { 1354 1008 case DataFormatNone: { 1355 if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {1356 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);1357 return allocate();1358 }1359 1360 1009 GPRReg gpr = allocate(); 1361 1010 … … 1406 1055 case DataFormatInt32: 1407 1056 case DataFormatJSDouble: 1408 case DataFormatDouble:1409 1057 case DataFormatJSBoolean: 1410 case DataFormatBoolean: 1411 case DataFormatInt52: 1412 case DataFormatStrictInt52: { 1058 case DataFormatBoolean: { 1413 1059 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1414 1060 return allocate(); 1415 1061 } 1416 1062 1063 case DataFormatDouble: 1417 1064 case DataFormatStorage: 1065 case DataFormatInt52: 1066 case DataFormatStrictInt52: 1418 1067 RELEASE_ASSERT_NOT_REACHED(); 1419 1068 … … 1434 1083 switch (info.registerFormat()) { 1435 1084 case DataFormatNone: { 1436 if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {1085 if (info.spillFormat() == DataFormatInt32) { 1437 1086 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1438 1087 return allocate(); … … 1488 1137 case DataFormatInt32: 1489 1138 case DataFormatJSDouble: 1490 case DataFormatDouble:1491 1139 case DataFormatJSCell: 1492 1140 case DataFormatCell: 1493 case DataFormatInt52:1494 case DataFormatStrictInt52: {1495 1141 terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0); 1496 1142 return allocate(); 1497 }1498 1143 1144 case DataFormatDouble: 1499 1145 case DataFormatStorage: 1146 case DataFormatInt52: 1147 case DataFormatStrictInt52: 1500 1148 RELEASE_ASSERT_NOT_REACHED(); 1501 1149 … … 1504 1152 return InvalidGPRReg; 1505 1153 } 1506 }1507 1508 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)1509 {1510 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);1511 1512 JITCompiler::Jump notNumber = m_jit.branchTest64(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);1513 1514 m_jit.move(value, tmp);1515 unboxDouble(tmp, result);1516 1517 JITCompiler::Jump done = m_jit.jump();1518 1519 isInteger.link(&m_jit);1520 1521 m_jit.convertInt32ToDouble(value, result);1522 1523 done.link(&m_jit);1524 1525 return notNumber;1526 1154 } 1527 1155 … … 1922 1550 } 1923 1551 1924 case NumberUse: {1552 case DoubleRepUse: { 1925 1553 SpeculateDoubleOperand value(this, node->child1()); 1926 1554 FPRTemporary scratch(this); … … 2061 1689 2062 1690 case Int32Use: 2063 case NumberUse: {1691 case DoubleRepUse: { 2064 1692 if (node->child1().useKind() == Int32Use) { 2065 1693 bool invert = false; … … 2154 1782 switch (op) { 2155 1783 case JSConstant: 1784 case DoubleConstant: 1785 case Int52Constant: 2156 1786 initConstantInfo(node); 2157 1787 break; … … 2401 2031 } 2402 2032 2403 case Int32ToDouble: { 2404 compileInt32ToDouble(node); 2405 break; 2406 } 2407 2408 case Int52ToValue: { 2409 JSValueOperand operand(this, node->child1()); 2033 case DoubleRep: { 2034 compileDoubleRep(node); 2035 break; 2036 } 2037 2038 case ValueRep: { 2039 compileValueRep(node); 2040 break; 2041 } 2042 2043 case Int52Rep: { 2044 SpeculateInt32Operand operand(this, node->child1()); 2410 2045 GPRTemporary result(this, Reuse, operand); 2411 m_jit.move(operand.gpr(), result.gpr()); 2412 jsValueResult(result.gpr(), node); 2413 break; 2414 } 2415 2416 case Int52ToDouble: { 2417 SpeculateDoubleOperand operand(this, node->child1()); 2418 FPRTemporary result(this, operand); 2419 m_jit.moveDouble(operand.fpr(), result.fpr()); 2420 doubleResult(result.fpr(), node); 2046 2047 m_jit.signExtend32ToPtr(operand.gpr(), result.gpr()); 2048 2049 strictInt52Result(result.gpr(), node); 2421 2050 break; 2422 2051 } … … 2487 2116 } 2488 2117 2489 case NumberUse: {2118 case DoubleRepUse: { 2490 2119 SpeculateDoubleOperand op1(this, node->child1()); 2491 2120 FPRTemporary result(this); … … 2525 2154 } 2526 2155 2527 case NumberUse: {2156 case DoubleRepUse: { 2528 2157 SpeculateDoubleOperand op1(this, node->child1()); 2529 2158 SpeculateDoubleOperand op2(this, node->child2()); -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r164229 r167325 171 171 break; 172 172 173 case ValueRep: 174 case Int52Rep: 175 case DoubleRep: { 176 // This short-circuits circuitous conversions, like ValueRep(DoubleRep(value)) or 177 // even more complicated things. Like, it can handle a beast like 178 // ValueRep(DoubleRep(Int52Rep(value))). 179 180 // The only speculation that we would do beyond validating that we have a type that 181 // can be represented a certain way is an Int32 check that would appear on Int52Rep 182 // nodes. For now, if we see this and the final type we want is an Int52, we use it 183 // as an excuse not to fold. The only thing we would need is a Int52RepInt32Use kind. 184 bool hadInt32Check = false; 185 if (m_node->op() == Int52Rep) { 186 ASSERT(m_node->child1().useKind() == Int32Use); 187 hadInt32Check = true; 188 } 189 for (Node* node = m_node->child1().node(); ; node = node->child1().node()) { 190 if (canonicalResultRepresentation(node->result()) == 191 canonicalResultRepresentation(m_node->result())) { 192 m_insertionSet.insertNode( 193 m_nodeIndex, SpecNone, Phantom, m_node->origin, m_node->child1()); 194 if (hadInt32Check) { 195 // FIXME: Consider adding Int52RepInt32Use or even DoubleRepInt32Use, 196 // which would be super weird. The latter would only arise in some 197 // seriously circuitous conversions. 198 if (canonicalResultRepresentation(node->result()) != NodeResultJS) 199 break; 200 201 m_insertionSet.insertNode( 202 m_nodeIndex, SpecNone, Phantom, m_node->origin, 203 Edge(node, Int32Use)); 204 } 205 m_node->child1() = node->defaultEdge(); 206 m_node->convertToIdentity(); 207 m_changed = true; 208 break; 209 } 210 211 switch (node->op()) { 212 case Int52Rep: 213 ASSERT(node->child1().useKind() == Int32Use); 214 hadInt32Check = true; 215 continue; 216 217 case DoubleRep: 218 case ValueRep: 219 continue; 220 221 default: 222 break; 223 } 224 break; 225 } 226 break; 227 } 228 173 229 default: 174 230 break; -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp
r165842 r167325 47 47 out.print("KnownInt32"); 48 48 break; 49 case MachineIntUse: 50 out.print("MachineInt"); 51 break; 52 case RealNumberUse: 53 out.print("RealNumber"); 49 case Int52RepUse: 50 out.print("Int52Rep"); 54 51 break; 55 52 case NumberUse: 56 53 out.print("Number"); 57 54 break; 58 case KnownNumberUse: 59 out.print("KnownNumber"); 55 case DoubleRepUse: 56 out.print("DoubleRep"); 57 break; 58 case DoubleRepRealUse: 59 out.print("DoubleRepReal"); 60 60 break; 61 61 case BooleanUse: -
trunk/Source/JavaScriptCore/dfg/DFGUseKind.h
r165842 r167325 29 29 #if ENABLE(DFG_JIT) 30 30 31 #include "DFGNodeFlags.h" 31 32 #include "SpeculatedType.h" 32 33 #include <wtf/PrintStream.h> … … 38 39 Int32Use, 39 40 KnownInt32Use, 40 MachineIntUse, 41 RealNumberUse, 41 Int52RepUse, 42 42 NumberUse, 43 KnownNumberUse, 43 DoubleRepUse, 44 DoubleRepRealUse, 44 45 BooleanUse, 45 46 CellUse, … … 60 61 }; 61 62 62 ALWAYS_INLINESpeculatedType typeFilterFor(UseKind useKind)63 inline SpeculatedType typeFilterFor(UseKind useKind) 63 64 { 64 65 switch (useKind) { … … 68 69 case KnownInt32Use: 69 70 return SpecInt32; 70 case MachineIntUse:71 case Int52RepUse: 71 72 return SpecMachineInt; 72 case RealNumberUse:73 return SpecFullRealNumber;74 73 case NumberUse: 75 case KnownNumberUse: 76 return SpecFullNumber; 74 return SpecBytecodeNumber; 75 case DoubleRepUse: 76 return SpecDouble; 77 case DoubleRepRealUse: 78 return SpecDoubleReal; 77 79 case BooleanUse: 78 80 return SpecBoolean; … … 109 111 } 110 112 111 ALWAYS_INLINEbool shouldNotHaveTypeCheck(UseKind kind)113 inline bool shouldNotHaveTypeCheck(UseKind kind) 112 114 { 113 115 switch (kind) { 114 116 case UntypedUse: 115 117 case KnownInt32Use: 116 case KnownNumberUse:117 118 case KnownCellUse: 118 119 case KnownStringUse: 119 return true; 120 default: 121 return false; 122 } 123 } 124 125 ALWAYS_INLINE bool mayHaveTypeCheck(UseKind kind) 120 case Int52RepUse: 121 case DoubleRepUse: 122 return true; 123 default: 124 return false; 125 } 126 } 127 128 inline bool mayHaveTypeCheck(UseKind kind) 126 129 { 127 130 return !shouldNotHaveTypeCheck(kind); 128 131 } 129 132 130 ALWAYS_INLINEbool isNumerical(UseKind kind)133 inline bool isNumerical(UseKind kind) 131 134 { 132 135 switch (kind) { 133 136 case Int32Use: 134 137 case KnownInt32Use: 135 case MachineIntUse:136 case RealNumberUse:137 138 case NumberUse: 138 case KnownNumberUse: 139 return true; 140 default: 141 return false; 142 } 143 } 144 145 ALWAYS_INLINE bool isDouble(UseKind kind) 146 { 147 switch (kind) { 148 case RealNumberUse: 149 case NumberUse: 150 case KnownNumberUse: 151 return true; 152 default: 153 return false; 154 } 155 } 156 157 ALWAYS_INLINE bool isCell(UseKind kind) 139 case Int52RepUse: 140 case DoubleRepUse: 141 case DoubleRepRealUse: 142 return true; 143 default: 144 return false; 145 } 146 } 147 148 inline bool isDouble(UseKind kind) 149 { 150 switch (kind) { 151 case DoubleRepUse: 152 case DoubleRepRealUse: 153 return true; 154 default: 155 return false; 156 } 157 } 158 159 inline bool isCell(UseKind kind) 158 160 { 159 161 switch (kind) { … … 175 177 // Returns true if it uses structure in a way that could be clobbered by 176 178 // things that change the structure. 177 ALWAYS_INLINEbool usesStructure(UseKind kind)179 inline bool usesStructure(UseKind kind) 178 180 { 179 181 switch (kind) { … … 186 188 } 187 189 190 inline UseKind useKindForResult(NodeFlags result) 191 { 192 ASSERT(!(result & ~NodeResultMask)); 193 switch (result) { 194 case NodeResultInt52: 195 return Int52RepUse; 196 case NodeResultDouble: 197 return DoubleRepUse; 198 default: 199 return UntypedUse; 200 } 201 } 202 188 203 } } // namespace JSC::DFG 189 204 -
trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp
r164229 r167325 1 1 /* 2 * Copyright (C) 2012 , 2013Apple Inc. All rights reserved.2 * Copyright (C) 2012-2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 116 116 m_myRefCounts.find(edge.node())->value++; 117 117 118 VALIDATE((node, edge), edge->hasDoubleResult() == (edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse)); 119 VALIDATE((node, edge), edge->hasInt52Result() == (edge.useKind() == Int52RepUse)); 120 118 121 if (m_graph.m_form == SSA) { 119 122 // In SSA, all edges must hasResult(). -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r167189 r167325 91 91 case ArithNegate: 92 92 case UInt32ToNumber: 93 case Int32ToDouble:94 93 case CompareEqConstant: 95 94 case Jump: … … 104 103 case GetClosureVar: 105 104 case PutClosureVar: 106 case Int52ToValue:107 105 case InvalidationPoint: 108 106 case StringCharAt: … … 153 151 case CheckHasInstance: 154 152 case InstanceOf: 153 case DoubleRep: 154 case ValueRep: 155 case Int52Rep: 156 case DoubleConstant: 157 case Int52Constant: 155 158 // These are OK. 159 break; 160 case Identity: 161 // No backend handles this because it will be optimized out. But we may check 162 // for capabilities before optimization. It would be a deep error to remove this 163 // case because it would prevent us from catching bugs where the FTL backend 164 // pipeline failed to optimize out an Identity. 156 165 break; 157 166 case PutByIdDirect: … … 236 245 if (node->isBinaryUseKind(Int32Use)) 237 246 break; 238 if (node->isBinaryUseKind( MachineIntUse))239 break; 240 if (node->isBinaryUseKind( NumberUse))247 if (node->isBinaryUseKind(Int52RepUse)) 248 break; 249 if (node->isBinaryUseKind(DoubleRepUse)) 241 250 break; 242 251 if (node->isBinaryUseKind(StringIdentUse)) … … 256 265 if (node->isBinaryUseKind(Int32Use)) 257 266 break; 258 if (node->isBinaryUseKind( MachineIntUse))259 break; 260 if (node->isBinaryUseKind( NumberUse))267 if (node->isBinaryUseKind(Int52RepUse)) 268 break; 269 if (node->isBinaryUseKind(DoubleRepUse)) 261 270 break; 262 271 if (node->isBinaryUseKind(StringIdentUse)) … … 281 290 if (node->isBinaryUseKind(Int32Use)) 282 291 break; 283 if (node->isBinaryUseKind( MachineIntUse))284 break; 285 if (node->isBinaryUseKind( NumberUse))292 if (node->isBinaryUseKind(Int52RepUse)) 293 break; 294 if (node->isBinaryUseKind(DoubleRepUse)) 286 295 break; 287 296 if (node->isBinaryUseKind(UntypedUse)) … … 351 360 case Int32Use: 352 361 case KnownInt32Use: 353 case MachineIntUse:362 case Int52RepUse: 354 363 case NumberUse: 355 case KnownNumberUse:356 case RealNumberUse:364 case DoubleRepUse: 365 case DoubleRepRealUse: 357 366 case BooleanUse: 358 367 case CellUse: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r167189 r167325 187 187 LType type; 188 188 switch (node->flags() & NodeResultMask) { 189 case NodeResult Number:189 case NodeResultDouble: 190 190 type = m_out.doubleType; 191 191 break; … … 283 283 case JSConstant: 284 284 break; 285 case DoubleConstant: 286 compileDoubleConstant(); 287 break; 288 case Int52Constant: 289 compileInt52Constant(); 290 break; 285 291 case WeakJSConstant: 286 292 compileWeakJSConstant(); … … 288 294 case PhantomArguments: 289 295 compilePhantomArguments(); 296 break; 297 case DoubleRep: 298 compileDoubleRep(); 299 break; 300 case ValueRep: 301 compileValueRep(); 302 break; 303 case Int52Rep: 304 compileInt52Rep(); 305 break; 306 case ValueToInt32: 307 compileValueToInt32(); 290 308 break; 291 309 case GetArgument: … … 378 396 case UInt32ToNumber: 379 397 compileUInt32ToNumber(); 380 break;381 case Int32ToDouble:382 compileInt32ToDouble();383 398 break; 384 399 case CheckStructure: … … 569 584 case InvalidationPoint: 570 585 compileInvalidationPoint(); 571 break;572 case ValueToInt32:573 compileValueToInt32();574 break;575 case Int52ToValue:576 compileInt52ToValue();577 586 break; 578 587 case CheckArgumentsNotCreated: … … 634 643 } 635 644 645 void compileUpsilon() 646 { 647 LValue destination = m_phis.get(m_node->phi()); 648 649 switch (m_node->child1().useKind()) { 650 case DoubleRepUse: 651 m_out.set(lowDouble(m_node->child1()), destination); 652 break; 653 case Int32Use: 654 m_out.set(lowInt32(m_node->child1()), destination); 655 break; 656 case Int52RepUse: 657 m_out.set(lowInt52(m_node->child1()), destination); 658 break; 659 case BooleanUse: 660 m_out.set(lowBoolean(m_node->child1()), destination); 661 break; 662 case CellUse: 663 m_out.set(lowCell(m_node->child1()), destination); 664 break; 665 case UntypedUse: 666 m_out.set(lowJSValue(m_node->child1()), destination); 667 break; 668 default: 669 RELEASE_ASSERT_NOT_REACHED(); 670 break; 671 } 672 } 673 674 void compilePhi() 675 { 676 LValue source = m_phis.get(m_node); 677 678 switch (m_node->flags() & NodeResultMask) { 679 case NodeResultDouble: 680 setDouble(m_out.get(source)); 681 break; 682 case NodeResultInt32: 683 setInt32(m_out.get(source)); 684 break; 685 case NodeResultInt52: 686 setInt52(m_out.get(source)); 687 break; 688 case NodeResultBoolean: 689 setBoolean(m_out.get(source)); 690 break; 691 case NodeResultJS: 692 setJSValue(m_out.get(source)); 693 break; 694 default: 695 RELEASE_ASSERT_NOT_REACHED(); 696 break; 697 } 698 } 699 700 void compileDoubleConstant() 701 { 702 setDouble(m_out.constDouble(m_graph.valueOfNumberConstant(m_node))); 703 } 704 705 void compileInt52Constant() 706 { 707 int64_t value = m_graph.valueOfJSConstant(m_node).asMachineInt(); 708 709 setInt52(m_out.constInt64(value << JSValue::int52ShiftAmount)); 710 setStrictInt52(m_out.constInt64(value)); 711 } 712 713 void compileWeakJSConstant() 714 { 715 setJSValue(weakPointer(m_node->weakConstant())); 716 } 717 718 void compilePhantomArguments() 719 { 720 setJSValue(m_out.constInt64(JSValue::encode(JSValue()))); 721 } 722 723 void compileDoubleRep() 724 { 725 switch (m_node->child1().useKind()) { 726 case NumberUse: { 727 LValue value = lowJSValue(m_node->child1(), ManualOperandSpeculation); 728 setDouble(jsValueToDouble(m_node->child1(), value)); 729 return; 730 } 731 732 case Int52RepUse: { 733 setDouble(strictInt52ToDouble(lowStrictInt52(m_node->child1()))); 734 return; 735 } 736 737 default: 738 RELEASE_ASSERT_NOT_REACHED(); 739 } 740 } 741 742 void compileValueRep() 743 { 744 switch (m_node->child1().useKind()) { 745 case DoubleRepUse: { 746 setJSValue(boxDouble(lowDouble(m_node->child1()))); 747 return; 748 } 749 750 case Int52RepUse: { 751 setJSValue(strictInt52ToJSValue(lowStrictInt52(m_node->child1()))); 752 return; 753 } 754 755 default: 756 RELEASE_ASSERT_NOT_REACHED(); 757 } 758 } 759 760 void compileInt52Rep() 761 { 762 setStrictInt52(m_out.signExt(lowInt32(m_node->child1()), m_out.int64)); 763 } 764 636 765 void compileValueToInt32() 637 766 { … … 641 770 break; 642 771 643 case MachineIntUse:772 case Int52RepUse: 644 773 setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1()))); 774 break; 775 776 case DoubleRepUse: 777 setInt32(doubleToInt32(lowDouble(m_node->child1()))); 645 778 break; 646 779 … … 659 792 } 660 793 661 value = m_doubleValues.get(m_node->child1().node());662 if (isValid(value)) {663 setInt32(doubleToInt32(value.value()));664 break;665 }666 667 794 // We'll basically just get here for constants. But it's good to have this 668 795 // catch-all since we often add new representations into the mix. … … 684 811 } 685 812 686 void compileInt52ToValue()687 {688 setJSValue(lowJSValue(m_node->child1()));689 }690 691 void compileUpsilon()692 {693 LValue destination = m_phis.get(m_node->phi());694 695 switch (m_node->child1().useKind()) {696 case NumberUse:697 m_out.set(lowDouble(m_node->child1()), destination);698 break;699 case Int32Use:700 m_out.set(lowInt32(m_node->child1()), destination);701 break;702 case MachineIntUse:703 m_out.set(lowInt52(m_node->child1()), destination);704 break;705 case BooleanUse:706 m_out.set(lowBoolean(m_node->child1()), destination);707 break;708 case CellUse:709 m_out.set(lowCell(m_node->child1()), destination);710 break;711 case UntypedUse:712 m_out.set(lowJSValue(m_node->child1()), destination);713 break;714 default:715 RELEASE_ASSERT_NOT_REACHED();716 break;717 }718 }719 720 void compilePhi()721 {722 LValue source = m_phis.get(m_node);723 724 switch (m_node->flags() & NodeResultMask) {725 case NodeResultNumber:726 setDouble(m_out.get(source));727 break;728 case NodeResultInt32:729 setInt32(m_out.get(source));730 break;731 case NodeResultInt52:732 setInt52(m_out.get(source));733 break;734 case NodeResultBoolean:735 setBoolean(m_out.get(source));736 break;737 case NodeResultJS:738 setJSValue(m_out.get(source));739 break;740 default:741 RELEASE_ASSERT_NOT_REACHED();742 break;743 }744 }745 746 void compilePhantomArguments()747 {748 setJSValue(m_out.constInt64(JSValue::encode(JSValue())));749 }750 751 void compileWeakJSConstant()752 {753 setJSValue(weakPointer(m_node->weakConstant()));754 }755 756 813 void compileGetArgument() 757 814 { … … 967 1024 } 968 1025 969 case MachineIntUse: {1026 case Int52RepUse: { 970 1027 if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52) 971 1028 && !m_state.forNode(m_node->child2()).couldBeType(SpecInt52)) { … … 1017 1074 } 1018 1075 1019 case NumberUse: {1076 case DoubleRepUse: { 1020 1077 LValue C1 = lowDouble(m_node->child1()); 1021 1078 LValue C2 = lowDouble(m_node->child2()); … … 1066 1123 } 1067 1124 1068 case MachineIntUse: {1125 case Int52RepUse: { 1069 1126 Int52Kind kind; 1070 1127 LValue left = lowWhicheverInt52(m_node->child1(), kind); … … 1093 1150 } 1094 1151 1095 case NumberUse: {1152 case DoubleRepUse: { 1096 1153 setDouble( 1097 1154 m_out.doubleMul(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); … … 1196 1253 } 1197 1254 1198 case NumberUse: {1255 case DoubleRepUse: { 1199 1256 setDouble(m_out.doubleDiv( 1200 1257 lowDouble(m_node->child1()), lowDouble(m_node->child2()))); … … 1294 1351 } 1295 1352 1296 case NumberUse: {1353 case DoubleRepUse: { 1297 1354 setDouble( 1298 1355 m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); … … 1322 1379 } 1323 1380 1324 case NumberUse: {1381 case DoubleRepUse: { 1325 1382 LValue left = lowDouble(m_node->child1()); 1326 1383 LValue right = lowDouble(m_node->child2()); … … 1372 1429 } 1373 1430 1374 case NumberUse: {1431 case DoubleRepUse: { 1375 1432 setDouble(m_out.doubleAbs(lowDouble(m_node->child1()))); 1376 1433 break; … … 1419 1476 } 1420 1477 1421 case MachineIntUse: {1478 case Int52RepUse: { 1422 1479 if (!m_state.forNode(m_node->child1()).couldBeType(SpecInt52)) { 1423 1480 Int52Kind kind; … … 1439 1496 } 1440 1497 1441 case NumberUse: {1498 case DoubleRepUse: { 1442 1499 setDouble(m_out.doubleNeg(lowDouble(m_node->child1()))); 1443 1500 break; … … 1497 1554 speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero)); 1498 1555 setInt32(value); 1499 }1500 1501 void compileInt32ToDouble()1502 {1503 setDouble(lowDouble(m_node->child1()));1504 1556 } 1505 1557 … … 2214 2266 LValue intValue; 2215 2267 switch (child3.useKind()) { 2216 case MachineIntUse:2268 case Int52RepUse: 2217 2269 case Int32Use: { 2218 2270 if (child3.useKind() == Int32Use) … … 2247 2299 } 2248 2300 2249 case NumberUse: {2301 case DoubleRepUse: { 2250 2302 LValue doubleValue = lowDouble(child3); 2251 2303 … … 3329 3381 { 3330 3382 if (m_node->isBinaryUseKind(Int32Use) 3331 || m_node->isBinaryUseKind( MachineIntUse)3332 || m_node->isBinaryUseKind( NumberUse)3383 || m_node->isBinaryUseKind(Int52RepUse) 3384 || m_node->isBinaryUseKind(DoubleRepUse) 3333 3385 || m_node->isBinaryUseKind(ObjectUse) 3334 3386 || m_node->isBinaryUseKind(BooleanUse) … … 3372 3424 } 3373 3425 3374 if (m_node->isBinaryUseKind( MachineIntUse)) {3426 if (m_node->isBinaryUseKind(Int52RepUse)) { 3375 3427 Int52Kind kind; 3376 3428 LValue left = lowWhicheverInt52(m_node->child1(), kind); … … 3380 3432 } 3381 3433 3382 if (m_node->isBinaryUseKind( NumberUse)) {3434 if (m_node->isBinaryUseKind(DoubleRepUse)) { 3383 3435 setBoolean( 3384 3436 m_out.doubleEqual(lowDouble(m_node->child1()), lowDouble(m_node->child2()))); … … 4124 4176 } 4125 4177 4126 if (m_node->isBinaryUseKind( MachineIntUse)) {4178 if (m_node->isBinaryUseKind(Int52RepUse)) { 4127 4179 Int52Kind kind; 4128 4180 LValue left = lowWhicheverInt52(m_node->child1(), kind); … … 4132 4184 } 4133 4185 4134 if (m_node->isBinaryUseKind( NumberUse)) {4186 if (m_node->isBinaryUseKind(DoubleRepUse)) { 4135 4187 LValue left = lowDouble(m_node->child1()); 4136 4188 LValue right = lowDouble(m_node->child2()); … … 4389 4441 case Int32Use: 4390 4442 return m_out.notZero32(lowInt32(m_node->child1())); 4391 case NumberUse:4443 case DoubleRepUse: 4392 4444 return m_out.doubleNotEqual(lowDouble(edge), m_out.doubleZero); 4393 4445 case ObjectOrOtherUse: … … 4735 4787 4736 4788 enum Int52Kind { StrictInt52, Int52 }; 4737 LValue lowInt52(Edge edge, Int52Kind kind, OperandSpeculationMode mode = AutomaticOperandSpeculation) 4738 { 4739 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == MachineIntUse); 4740 4741 if (edge->hasConstant()) { 4742 JSValue value = m_graph.valueOfJSConstant(edge.node()); 4743 if (!value.isMachineInt()) { 4744 terminate(Uncountable); 4745 return m_out.int64Zero; 4746 } 4747 int64_t result = value.asMachineInt(); 4748 if (kind == Int52) 4749 result <<= JSValue::int52ShiftAmount; 4750 return m_out.constInt64(result); 4751 } 4789 LValue lowInt52(Edge edge, Int52Kind kind) 4790 { 4791 RELEASE_ASSERT(edge.useKind() == Int52RepUse); 4752 4792 4753 4793 LoweredNodeValue value; … … 4774 4814 break; 4775 4815 } 4776 4777 value = m_int32Values.get(edge.node()); 4778 if (isValid(value)) { 4779 return setInt52WithStrictValue( 4780 edge.node(), m_out.signExt(value.value(), m_out.int64), kind); 4781 } 4782 4783 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecInt52)); 4784 4785 value = m_jsValueValues.get(edge.node()); 4786 if (isValid(value)) { 4787 LValue boxedResult = value.value(); 4788 FTL_TYPE_CHECK( 4789 jsValueValue(boxedResult), edge, SpecMachineInt, isNotInt32(boxedResult)); 4790 return setInt52WithStrictValue( 4791 edge.node(), m_out.signExt(unboxInt32(boxedResult), m_out.int64), kind); 4792 } 4793 4794 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecMachineInt)); 4816 4817 RELEASE_ASSERT(!m_state.forNode(edge).m_type); 4795 4818 terminate(Uncountable); 4796 4819 return m_out.int64Zero; 4797 4820 } 4798 4821 4799 LValue lowInt52(Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)4800 { 4801 return lowInt52(edge, Int52 , mode);4802 } 4803 4804 LValue lowStrictInt52(Edge edge , OperandSpeculationMode mode = AutomaticOperandSpeculation)4805 { 4806 return lowInt52(edge, StrictInt52 , mode);4822 LValue lowInt52(Edge edge) 4823 { 4824 return lowInt52(edge, Int52); 4825 } 4826 4827 LValue lowStrictInt52(Edge edge) 4828 { 4829 return lowInt52(edge, StrictInt52); 4807 4830 } 4808 4831 … … 4831 4854 } 4832 4855 4833 LValue lowWhicheverInt52(Edge edge, Int52Kind& kind , OperandSpeculationMode mode = AutomaticOperandSpeculation)4856 LValue lowWhicheverInt52(Edge edge, Int52Kind& kind) 4834 4857 { 4835 4858 kind = bestInt52Kind(edge); 4836 return lowInt52(edge, kind , mode);4859 return lowInt52(edge, kind); 4837 4860 } 4838 4861 … … 4932 4955 } 4933 4956 4934 LValue lowDouble(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation) 4935 { 4936 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || isDouble(edge.useKind())); 4937 4938 if (edge->hasConstant()) { 4939 JSValue value = m_graph.valueOfJSConstant(edge.node()); 4940 if (!value.isNumber()) { 4941 terminate(Uncountable); 4942 return m_out.doubleZero; 4943 } 4944 return m_out.constDouble(value.asNumber()); 4945 } 4957 LValue lowDouble(Edge edge) 4958 { 4959 RELEASE_ASSERT(isDouble(edge.useKind())); 4946 4960 4947 4961 LoweredNodeValue value = m_doubleValues.get(edge.node()); … … 4949 4963 return value.value(); 4950 4964 4951 value = m_int32Values.get(edge.node()); 4952 if (isValid(value)) { 4953 LValue result = m_out.intToDouble(value.value()); 4954 setDouble(edge.node(), result); 4955 return result; 4956 } 4957 4958 value = m_strictInt52Values.get(edge.node()); 4959 if (isValid(value)) 4960 return strictInt52ToDouble(edge, value.value()); 4961 4962 value = m_int52Values.get(edge.node()); 4963 if (isValid(value)) 4964 return strictInt52ToDouble(edge, int52ToStrictInt52(value.value())); 4965 4966 value = m_jsValueValues.get(edge.node()); 4967 if (isValid(value)) { 4968 LValue boxedResult = value.value(); 4969 4970 LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("Double unboxing int case")); 4971 LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("Double unboxing double case")); 4972 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("Double unboxing continuation")); 4973 4974 m_out.branch(isNotInt32(boxedResult), unsure(doubleCase), unsure(intCase)); 4975 4976 LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase); 4977 4978 ValueFromBlock intToDouble = m_out.anchor( 4979 m_out.intToDouble(unboxInt32(boxedResult))); 4980 m_out.jump(continuation); 4981 4982 m_out.appendTo(doubleCase, continuation); 4983 4984 FTL_TYPE_CHECK( 4985 jsValueValue(boxedResult), edge, SpecFullNumber, isCellOrMisc(boxedResult)); 4986 4987 ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedResult)); 4988 m_out.jump(continuation); 4989 4990 m_out.appendTo(continuation, lastNext); 4991 4992 LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble); 4993 4994 setDouble(edge.node(), result); 4995 return result; 4996 } 4997 4998 RELEASE_ASSERT(!(m_state.forNode(edge).m_type & SpecFullNumber)); 4965 RELEASE_ASSERT(!m_state.forNode(edge).m_type); 4999 4966 terminate(Uncountable); 5000 4967 return m_out.doubleZero; … … 5004 4971 { 5005 4972 ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse); 4973 RELEASE_ASSERT(!isDouble(edge.useKind())); 4974 RELEASE_ASSERT(edge.useKind() != Int52RepUse); 5006 4975 5007 4976 if (edge->hasConstant()) … … 5019 4988 } 5020 4989 5021 value = m_strictInt52Values.get(edge.node());5022 if (isValid(value))5023 return strictInt52ToJSValue(value.value());5024 5025 value = m_int52Values.get(edge.node());5026 if (isValid(value))5027 return strictInt52ToJSValue(int52ToStrictInt52(value.value()));5028 5029 4990 value = m_booleanValues.get(edge.node()); 5030 4991 if (isValid(value)) { 5031 4992 LValue result = boxBoolean(value.value()); 5032 setJSValue(edge.node(), result);5033 return result;5034 }5035 5036 value = m_doubleValues.get(edge.node());5037 if (isValid(value)) {5038 LValue result = boxDouble(value.value());5039 4993 setJSValue(edge.node(), result); 5040 4994 return result; … … 5066 5020 } 5067 5021 5068 LValue strictInt52ToDouble(Edge edge, LValue value) 5069 { 5070 LValue result = m_out.intToDouble(value); 5071 setDouble(edge.node(), result); 5072 return result; 5022 LValue strictInt52ToDouble(LValue value) 5023 { 5024 return m_out.intToDouble(value); 5073 5025 } 5074 5026 … … 5100 5052 } 5101 5053 5102 LValue setInt52WithStrictValue(Node* node, LValue value, Int52Kind kind)5103 {5104 switch (kind) {5105 case StrictInt52:5106 setStrictInt52(node, value);5107 return value;5108 5109 case Int52:5110 value = strictInt52ToInt52(value);5111 setInt52(node, value);5112 return value;5113 }5114 5115 RELEASE_ASSERT_NOT_REACHED();5116 return 0;5117 }5118 5119 5054 LValue strictInt52ToInt52(LValue value) 5120 5055 { … … 5148 5083 return m_out.testNonZero64(jsValue, m_tagTypeNumber); 5149 5084 } 5085 5150 5086 LValue unboxDouble(LValue jsValue) 5151 5087 { … … 5155 5091 { 5156 5092 return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber); 5093 } 5094 LValue jsValueToDouble(Edge edge, LValue boxedValue) 5095 { 5096 LBasicBlock intCase = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing int case")); 5097 LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing double case")); 5098 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("DoubleRep unboxing continuation")); 5099 5100 LValue isNotInt32; 5101 if (!m_interpreter.needsTypeCheck(edge, SpecInt32)) 5102 isNotInt32 = m_out.booleanFalse; 5103 else if (!m_interpreter.needsTypeCheck(edge, ~SpecInt32)) 5104 isNotInt32 = m_out.booleanTrue; 5105 else 5106 isNotInt32 = this->isNotInt32(boxedValue); 5107 m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase)); 5108 5109 LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase); 5110 5111 ValueFromBlock intToDouble = m_out.anchor( 5112 m_out.intToDouble(unboxInt32(boxedValue))); 5113 m_out.jump(continuation); 5114 5115 m_out.appendTo(doubleCase, continuation); 5116 5117 FTL_TYPE_CHECK( 5118 jsValueValue(boxedValue), edge, SpecBytecodeNumber, isCellOrMisc(boxedValue)); 5119 5120 ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue)); 5121 m_out.jump(continuation); 5122 5123 m_out.appendTo(continuation, lastNext); 5124 5125 return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble); 5157 5126 } 5158 5127 … … 5227 5196 break; 5228 5197 case KnownInt32Use: 5229 case KnownNumberUse:5230 5198 case KnownStringUse: 5199 case DoubleRepUse: 5200 case Int52RepUse: 5231 5201 ASSERT(!m_interpreter.needsTypeCheck(edge)); 5232 5202 break; … … 5261 5231 speculateStringOrStringObject(edge); 5262 5232 break; 5263 case RealNumberUse:5264 speculateRealNumber(edge);5265 break;5266 5233 case NumberUse: 5267 5234 speculateNumber(edge); 5268 5235 break; 5269 case MachineIntUse:5270 speculate MachineInt(edge);5236 case DoubleRepRealUse: 5237 speculateDoubleReal(edge); 5271 5238 break; 5272 5239 case BooleanUse: … … 5530 5497 void speculateNumber(Edge edge) 5531 5498 { 5499 LValue value = lowJSValue(edge, ManualOperandSpeculation); 5500 FTL_TYPE_CHECK(jsValueValue(value), edge, SpecBytecodeNumber, isNotNumber(value)); 5501 } 5502 5503 void speculateDoubleReal(Edge edge) 5504 { 5532 5505 // Do an early return here because lowDouble() can create a lot of control flow. 5533 5506 if (!m_interpreter.needsTypeCheck(edge)) 5534 5507 return; 5535 5508 5536 lowDouble(edge);5537 }5538 5539 void speculateRealNumber(Edge edge)5540 {5541 // Do an early return here because lowDouble() can create a lot of control flow.5542 if (!m_interpreter.needsTypeCheck(edge))5543 return;5544 5545 5509 LValue value = lowDouble(edge); 5546 5510 FTL_TYPE_CHECK( 5547 doubleValue(value), edge, Spec FullRealNumber,5511 doubleValue(value), edge, SpecDoubleReal, 5548 5512 m_out.doubleNotEqualOrUnordered(value, value)); 5549 }5550 5551 void speculateMachineInt(Edge edge)5552 {5553 if (!m_interpreter.needsTypeCheck(edge))5554 return;5555 5556 Int52Kind kind;5557 lowWhicheverInt52(edge, kind);5558 5513 } 5559 5514 -
trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp
r160587 r167325 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 72 72 jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch1); 73 73 jit.move64ToDouble(value, FPRInfo::fpRegT0); 74 jit.sanitizeDouble(FPRInfo::fpRegT0); 74 75 jit.boxDouble(FPRInfo::fpRegT0, value); 75 76 jit.move64ToDouble(scratch1, FPRInfo::fpRegT0); -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp
r163844 r167325 1 1 /* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 55 55 } 56 56 57 void AssemblyHelpers::sanitizeDouble(FPRReg fpr) 58 { 59 MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr); 60 static const double NaN = QNaN; 61 loadDouble(&NaN, fpr); 62 notNaN.link(this); 63 } 64 57 65 #if ENABLE(SAMPLING_FLAGS) 58 66 void AssemblyHelpers::setSamplingFlag(int32_t flag) -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r166908 r167325 1 1 /* 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 418 418 void jitAssertArgumentCountSane() { } 419 419 #endif 420 421 void sanitizeDouble(FPRReg); 420 422 421 423 // These methods convert between doubles, and doubles boxed and JSValues. … … 434 436 move64ToDouble(gpr, fpr); 435 437 return fpr; 438 } 439 440 void boxDouble(FPRReg fpr, JSValueRegs regs) 441 { 442 boxDouble(fpr, regs.gpr()); 436 443 } 437 444 … … 468 475 moveIntsToDouble(payloadGPR, tagGPR, fpr, scratchFPR); 469 476 } 477 478 void boxDouble(FPRReg fpr, JSValueRegs regs) 479 { 480 boxDouble(fpr, regs.tagGPR(), regs.payloadGPR()); 481 } 470 482 #endif 471 483
Note: See TracChangeset
for help on using the changeset viewer.