Changeset 112040 in webkit
- Timestamp:
- Mar 25, 2012, 4:50:24 PM (15 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 14 edited
-
ChangeLog (modified) (1 diff)
-
JavaScriptCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
bytecode/PredictedType.h (modified) (2 diffs)
-
dfg/DFGAbstractState.cpp (modified) (1 diff)
-
dfg/DFGCSEPhase.cpp (modified) (1 diff)
-
dfg/DFGCommon.h (modified) (1 diff)
-
dfg/DFGFixupPhase.cpp (modified) (5 diffs)
-
dfg/DFGGraph.cpp (modified) (1 diff)
-
dfg/DFGInsertionSet.h (added)
-
dfg/DFGNodeType.h (modified) (1 diff)
-
dfg/DFGPredictionPropagationPhase.cpp (modified) (1 diff)
-
dfg/DFGSpeculativeJIT.cpp (modified) (6 diffs)
-
dfg/DFGSpeculativeJIT.h (modified) (10 diffs)
-
dfg/DFGSpeculativeJIT32_64.cpp (modified) (1 diff)
-
dfg/DFGSpeculativeJIT64.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r112039 r112040 1 2012-03-25 Filip Pizlo <fpizlo@apple.com> 2 3 DFG int-to-double conversion should be revealed to CSE 4 https://bugs.webkit.org/show_bug.cgi?id=82135 5 6 Reviewed by Oliver Hunt. 7 8 This introduces the notion of an Int32ToDouble node, which is injected 9 into the graph anytime we know that we have a double use of a node that 10 was predicted integer. The Int32ToDouble simplifies double speculation 11 on integers by skipping the path that would unbox doubles, if we know 12 that the value is already proven to be an integer. It allows integer to 13 double conversions to be subjected to common subexpression elimination 14 (CSE) by allowing the CSE phase to see where these conversions are 15 occurring. Finally, it allows us to see when a constant is being used 16 as both a double and an integer. This is a bit odd, since it means that 17 sometimes a double use of a constant will not refer directly to the 18 constant. This should not cause problems, for now, but it may require 19 some canonizalization in the future if we want to support strength 20 reductions of double operations based on constants. 21 22 To allow injection of nodes into the graph, this change introduces the 23 DFG::InsertionSet, which is a way of lazily inserting elements into a 24 list. This allows the FixupPhase to remain O(N) despite performing 25 multiple injections in a single basic block. Without the InsertionSet, 26 each injection would require performing an insertion into a vector, 27 which is O(N), leading to O(N^2) performance overall. With the 28 InsertionSet, each injection simply records what insertion would have 29 been performed, and all insertions are performed at once (via 30 InsertionSet::execute) after processing of a basic block is completed. 31 32 * JavaScriptCore.xcodeproj/project.pbxproj: 33 * bytecode/PredictedType.h: 34 (JSC::isActionableIntMutableArrayPrediction): 35 (JSC): 36 (JSC::isActionableFloatMutableArrayPrediction): 37 (JSC::isActionableTypedMutableArrayPrediction): 38 (JSC::isActionableMutableArrayPrediction): 39 * dfg/DFGAbstractState.cpp: 40 (JSC::DFG::AbstractState::execute): 41 * dfg/DFGCSEPhase.cpp: 42 (JSC::DFG::CSEPhase::performNodeCSE): 43 * dfg/DFGCommon.h: 44 (JSC::DFG::useKindToString): 45 (DFG): 46 * dfg/DFGFixupPhase.cpp: 47 (JSC::DFG::FixupPhase::run): 48 (JSC::DFG::FixupPhase::fixupBlock): 49 (FixupPhase): 50 (JSC::DFG::FixupPhase::fixupNode): 51 (JSC::DFG::FixupPhase::fixDoubleEdge): 52 * dfg/DFGGraph.cpp: 53 (JSC::DFG::Graph::dump): 54 * dfg/DFGInsertionSet.h: Added. 55 (DFG): 56 (Insertion): 57 (JSC::DFG::Insertion::Insertion): 58 (JSC::DFG::Insertion::index): 59 (JSC::DFG::Insertion::element): 60 (InsertionSet): 61 (JSC::DFG::InsertionSet::InsertionSet): 62 (JSC::DFG::InsertionSet::append): 63 (JSC::DFG::InsertionSet::execute): 64 * dfg/DFGNodeType.h: 65 (DFG): 66 * dfg/DFGPredictionPropagationPhase.cpp: 67 (JSC::DFG::PredictionPropagationPhase::propagate): 68 * dfg/DFGSpeculativeJIT.cpp: 69 (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): 70 (JSC::DFG::SpeculativeJIT::compileValueToInt32): 71 (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): 72 (DFG): 73 * dfg/DFGSpeculativeJIT.h: 74 (SpeculativeJIT): 75 (JSC::DFG::IntegerOperand::IntegerOperand): 76 (JSC::DFG::DoubleOperand::DoubleOperand): 77 (JSC::DFG::JSValueOperand::JSValueOperand): 78 (JSC::DFG::StorageOperand::StorageOperand): 79 (JSC::DFG::SpeculateIntegerOperand::SpeculateIntegerOperand): 80 (JSC::DFG::SpeculateStrictInt32Operand::SpeculateStrictInt32Operand): 81 (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand): 82 (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): 83 (JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand): 84 * dfg/DFGSpeculativeJIT32_64.cpp: 85 (JSC::DFG::SpeculativeJIT::compile): 86 * dfg/DFGSpeculativeJIT64.cpp: 87 (JSC::DFG::SpeculativeJIT::compile): 88 1 89 2012-03-25 Filip Pizlo <fpizlo@apple.com> 2 90 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r112039 r112040 75 75 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */; }; 76 76 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 77 0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 77 78 0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC2B151FDE8B00CD8910 /* Operands.h */; settings = {ATTRIBUTES = (Private, ); }; }; 78 79 0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 725 726 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFixupPhase.cpp; path = dfg/DFGFixupPhase.cpp; sourceTree = "<group>"; }; 726 727 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFixupPhase.h; path = dfg/DFGFixupPhase.h; sourceTree = "<group>"; }; 728 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInsertionSet.h; path = dfg/DFGInsertionSet.h; sourceTree = "<group>"; }; 727 729 0F2BDC2B151FDE8B00CD8910 /* Operands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Operands.h; sourceTree = "<group>"; }; 728 730 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; }; … … 1995 1997 86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */, 1996 1998 86EC9DB81328DF82002B2AD7 /* DFGGraph.h */, 1999 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */, 1997 2000 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */, 1998 2001 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */, … … 2501 2504 0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */, 2502 2505 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */, 2506 0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */, 2503 2507 0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */, 2504 2508 ); -
trunk/Source/JavaScriptCore/bytecode/PredictedType.h
r110631 r112040 160 160 } 161 161 162 inline bool isActionableMutableArrayPrediction(PredictedType value) 163 { 164 return isArrayPrediction(value) 165 || isByteArrayPrediction(value) 162 inline bool isActionableIntMutableArrayPrediction(PredictedType value) 163 { 164 return isByteArrayPrediction(value) 166 165 #if CPU(X86) || CPU(X86_64) 167 166 || isInt8ArrayPrediction(value) … … 172 171 || isUint8ClampedArrayPrediction(value) 173 172 || isUint16ArrayPrediction(value) 174 || isUint32ArrayPrediction(value) 173 || isUint32ArrayPrediction(value); 174 } 175 176 inline bool isActionableFloatMutableArrayPrediction(PredictedType value) 177 { 178 return false 175 179 #if CPU(X86) || CPU(X86_64) 176 180 || isFloat32ArrayPrediction(value) 177 181 #endif 178 182 || isFloat64ArrayPrediction(value); 183 } 184 185 inline bool isActionableTypedMutableArrayPrediction(PredictedType value) 186 { 187 return isActionableIntMutableArrayPrediction(value) 188 || isActionableFloatMutableArrayPrediction(value); 189 } 190 191 inline bool isActionableMutableArrayPrediction(PredictedType value) 192 { 193 return isArrayPrediction(value) 194 || isActionableTypedMutableArrayPrediction(value); 179 195 } 180 196 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r112013 r112040 301 301 forNode(nodeIndex).set(PredictInt32); 302 302 break; 303 304 case Int32ToDouble: 305 forNode(node.child1()).filter(PredictNumber); 306 forNode(nodeIndex).set(PredictDouble); 307 break; 303 308 304 309 case ValueAdd: -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r111254 r112040 588 588 case StringCharAt: 589 589 case StringCharCodeAt: 590 case Int32ToDouble: 590 591 setReplacement(pureCSE(node)); 591 592 break; -
trunk/Source/JavaScriptCore/dfg/DFGCommon.h
r111974 r112040 98 98 enum UseKind { 99 99 UntypedUse, 100 DoubleUse, 100 101 LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements. 101 102 }; 103 104 inline const char* useKindToString(UseKind useKind) 105 { 106 switch (useKind) { 107 case UntypedUse: 108 return ""; 109 case DoubleUse: 110 return "d"; 111 default: 112 ASSERT_NOT_REACHED(); 113 return 0; 114 } 115 } 102 116 103 117 } } // namespace JSC::DFG -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r111974 r112040 30 30 31 31 #include "DFGGraph.h" 32 #include "DFGInsertionSet.h" 32 33 #include "DFGPhase.h" 33 34 … … 43 44 void run() 44 45 { 45 for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) 46 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) 47 fixupBlock(m_graph.m_blocks[blockIndex].get()); 48 } 49 50 private: 51 void fixupBlock(BasicBlock* block) 52 { 53 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { 54 m_compileIndex = block->at(m_indexInBlock); 46 55 fixupNode(m_graph[m_compileIndex]); 47 } 48 49 private: 56 } 57 m_insertionSet.execute(*block); 58 } 59 50 60 void fixupNode(Node& node) 51 61 { … … 153 163 } 154 164 165 case CompareEq: 166 case CompareLess: 167 case CompareLessEq: 168 case CompareGreater: 169 case CompareGreaterEq: 170 case CompareStrictEq: { 171 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])) 172 break; 173 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) 174 break; 175 fixDoubleEdge(0); 176 fixDoubleEdge(1); 177 break; 178 } 179 180 case LogicalNot: { 181 if (m_graph[node.child1()].shouldSpeculateInteger()) 182 break; 183 if (!m_graph[node.child1()].shouldSpeculateNumber()) 184 break; 185 fixDoubleEdge(0); 186 break; 187 } 188 189 case Branch: { 190 if (m_graph[node.child1()].shouldSpeculateInteger()) 191 break; 192 if (!m_graph[node.child1()].shouldSpeculateNumber()) 193 break; 194 fixDoubleEdge(0); 195 break; 196 } 197 198 case SetLocal: { 199 if (m_graph.isCaptured(node.local())) 200 break; 201 if (!node.variableAccessData()->shouldUseDoubleFormat()) 202 break; 203 fixDoubleEdge(0); 204 break; 205 } 206 207 case ArithAdd: 208 case ValueAdd: { 209 if (m_graph.addShouldSpeculateInteger(node)) 210 break; 211 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) 212 break; 213 fixDoubleEdge(0); 214 fixDoubleEdge(1); 215 break; 216 } 217 218 case ArithSub: { 219 if (m_graph.addShouldSpeculateInteger(node) 220 && node.canSpeculateInteger()) 221 break; 222 fixDoubleEdge(0); 223 fixDoubleEdge(1); 224 break; 225 } 226 227 case ArithNegate: { 228 if (m_graph.negateShouldSpeculateInteger(node)) 229 break; 230 fixDoubleEdge(0); 231 break; 232 } 233 234 case ArithMin: 235 case ArithMax: 236 case ArithMul: 237 case ArithDiv: 238 case ArithMod: { 239 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) 240 && node.canSpeculateInteger()) 241 break; 242 fixDoubleEdge(0); 243 fixDoubleEdge(1); 244 break; 245 } 246 247 case ArithAbs: { 248 if (m_graph[node.child1()].shouldSpeculateInteger() 249 && node.canSpeculateInteger()) 250 break; 251 fixDoubleEdge(0); 252 break; 253 } 254 255 case ArithSqrt: { 256 fixDoubleEdge(0); 257 break; 258 } 259 260 case PutByVal: { 261 if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) 262 break; 263 if (!m_graph[node.child2()].shouldSpeculateInteger()) 264 break; 265 if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) { 266 if (m_graph[node.child3()].isConstant()) 267 break; 268 if (m_graph[node.child3()].shouldSpeculateInteger()) 269 break; 270 fixDoubleEdge(2); 271 break; 272 } 273 if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) { 274 fixDoubleEdge(2); 275 break; 276 } 277 break; 278 } 279 155 280 default: 156 281 break; … … 158 283 159 284 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 285 if (!(node.flags() & NodeHasVarArgs)) { 286 dataLog("new children: "); 287 node.dumpChildren(WTF::dataFile()); 288 } 160 289 dataLog("\n"); 161 290 #endif … … 180 309 } 181 310 311 void fixDoubleEdge(unsigned childIndex) 312 { 313 Node& source = m_graph[m_compileIndex]; 314 Edge& edge = source.children.child(childIndex); 315 316 if (!m_graph[edge].shouldSpeculateInteger()) { 317 edge.setUseKind(DoubleUse); 318 return; 319 } 320 321 NodeIndex resultIndex = (NodeIndex)m_graph.size(); 322 323 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 324 dataLog("(replacing @%u->@%u with @%u->@%u) ", 325 m_compileIndex, edge.index(), m_compileIndex, resultIndex); 326 #endif 327 328 // Fix the edge up here because it's a reference that will be clobbered by 329 // the append() below. 330 NodeIndex oldIndex = edge.index(); 331 edge = Edge(resultIndex, DoubleUse); 332 333 m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex)); 334 m_insertionSet.append(m_indexInBlock, resultIndex); 335 336 Node& int32ToDouble = m_graph[resultIndex]; 337 int32ToDouble.predict(PredictDouble); 338 int32ToDouble.ref(); 339 } 340 341 unsigned m_indexInBlock; 182 342 NodeIndex m_compileIndex; 343 InsertionSet<NodeIndex> m_insertionSet; 183 344 }; 184 345 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp
r112015 r112040 164 164 else 165 165 hasPrinted = true; 166 dataLog("@%u%s", m_varArgChildren[childIdx].index(), predictionToAbbreviatedString(at(childIdx).prediction())); 166 dataLog("%s@%u%s", 167 useKindToString(m_varArgChildren[childIdx].useKind()), 168 m_varArgChildren[childIdx].index(), 169 predictionToAbbreviatedString(at(childIdx).prediction())); 167 170 } 168 171 } else { 169 if (!!node.child1()) 170 dataLog("@%u%s", node.child1().index(), predictionToAbbreviatedString(at(node.child1()).prediction())); 171 if (!!node.child2()) 172 dataLog(", @%u%s", node.child2().index(), predictionToAbbreviatedString(at(node.child2()).prediction())); 173 if (!!node.child3()) 174 dataLog(", @%u%s", node.child3().index(), predictionToAbbreviatedString(at(node.child3()).prediction())); 172 if (!!node.child1()) { 173 dataLog("%s@%u%s", 174 useKindToString(node.child1().useKind()), 175 node.child1().index(), 176 predictionToAbbreviatedString(at(node.child1()).prediction())); 177 } 178 if (!!node.child2()) { 179 dataLog(", %s@%u%s", 180 useKindToString(node.child2().useKind()), 181 node.child2().index(), 182 predictionToAbbreviatedString(at(node.child2()).prediction())); 183 } 184 if (!!node.child3()) { 185 dataLog(", %s@%u%s", 186 useKindToString(node.child3().useKind()), 187 node.child3().index(), 188 predictionToAbbreviatedString(at(node.child3()).prediction())); 189 } 175 190 hasPrinted = !!node.child1(); 176 191 } -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r111129 r112040 76 76 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ 77 77 macro(UInt32ToNumber, NodeResultNumber) \ 78 /* Used to cast known integers to doubles, so as to separate the double form */\ 79 /* of the value from the integer form. */\ 80 macro(Int32ToDouble, NodeResultNumber) \ 78 81 \ 79 82 /* Nodes for arithmetic operations. */\ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r112015 r112040 570 570 case GetFloat32ArrayLength: 571 571 case GetFloat64ArrayLength: 572 case GetStringLength: { 572 case GetStringLength: 573 case Int32ToDouble: { 573 574 // This node should never be visible at this stage of compilation. It is 574 575 // inserted by fixup(), which follows this phase. -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r112013 r112040 1285 1285 // There are four possibilities: 1286 1286 // 1287 // Int32ToDouble: We can use this in place of the original node, but 1288 // we'd rather not; so we use it only if it is the only remaining 1289 // live version. 1290 // 1287 1291 // ValueToInt32: If the only remaining live version of the value is 1288 1292 // ValueToInt32, then we can use it. … … 1307 1311 1308 1312 if (!found) { 1313 NodeIndex int32ToDoubleIndex = NoNode; 1309 1314 NodeIndex valueToInt32Index = NoNode; 1310 1315 NodeIndex uint32ToNumberIndex = NoNode; … … 1320 1325 continue; 1321 1326 switch (node.op()) { 1327 case Int32ToDouble: 1328 int32ToDoubleIndex = info.nodeIndex(); 1329 break; 1322 1330 case ValueToInt32: 1323 1331 valueToInt32Index = info.nodeIndex(); … … 1332 1340 1333 1341 NodeIndex nodeIndexToUse; 1334 if (valueToInt32Index != NoNode) 1342 if (int32ToDoubleIndex != NoNode) 1343 nodeIndexToUse = int32ToDoubleIndex; 1344 else if (valueToInt32Index != NoNode) 1335 1345 nodeIndexToUse = valueToInt32Index; 1336 1346 else if (uint32ToNumberIndex != NoNode) … … 1538 1548 case GeneratedOperandDouble: { 1539 1549 GPRTemporary result(this); 1540 SpeculateDoubleOperand op1(this, node.child1());1550 DoubleOperand op1(this, node.child1()); 1541 1551 FPRReg fpr = op1.fpr(); 1542 1552 GPRReg gpr = result.gpr(); … … 1673 1683 m_jit.move(op1.gpr(), result.gpr()); 1674 1684 integerResult(result.gpr(), m_compileIndex, op1.format()); 1685 } 1686 1687 void SpeculativeJIT::compileInt32ToDouble(Node& node) 1688 { 1689 #if USE(JSVALUE64) 1690 // On JSVALUE64 we have a way of loading double constants in a more direct manner 1691 // than a int->double conversion. On 32_64, unfortunately, we currently don't have 1692 // any such mechanism - though we could have it, if we just provisioned some memory 1693 // in CodeBlock for the double form of integer constants. 1694 if (at(node.child1()).hasConstant()) { 1695 ASSERT(isInt32Constant(node.child1().index())); 1696 FPRTemporary result(this); 1697 GPRTemporary temp(this); 1698 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(node.child1().index())))), temp.gpr()); 1699 m_jit.movePtrToDouble(temp.gpr(), result.fpr()); 1700 doubleResult(result.fpr(), m_compileIndex); 1701 return; 1702 } 1703 #endif 1704 1705 if (isInt32Prediction(m_state.forNode(node.child1()).m_type)) { 1706 SpeculateIntegerOperand op1(this, node.child1()); 1707 FPRTemporary result(this); 1708 m_jit.convertInt32ToDouble(op1.gpr(), result.fpr()); 1709 doubleResult(result.fpr(), m_compileIndex); 1710 return; 1711 } 1712 1713 JSValueOperand op1(this, node.child1()); 1714 FPRTemporary result(this); 1715 1716 #if USE(JSVALUE64) 1717 GPRTemporary temp(this); 1718 1719 GPRReg op1GPR = op1.gpr(); 1720 GPRReg tempGPR = temp.gpr(); 1721 FPRReg resultFPR = result.fpr(); 1722 1723 JITCompiler::Jump isInteger = m_jit.branchPtr( 1724 MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); 1725 1726 speculationCheck( 1727 BadType, JSValueRegs(op1GPR), node.child1(), 1728 m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); 1729 1730 m_jit.move(op1GPR, tempGPR); 1731 unboxDouble(tempGPR, resultFPR); 1732 JITCompiler::Jump done = m_jit.jump(); 1733 1734 isInteger.link(&m_jit); 1735 m_jit.convertInt32ToDouble(op1GPR, resultFPR); 1736 done.link(&m_jit); 1737 #else 1738 FPRTemporary temp(this); 1739 1740 GPRReg op1TagGPR = op1.tagGPR(); 1741 GPRReg op1PayloadGPR = op1.payloadGPR(); 1742 FPRReg tempFPR = temp.fpr(); 1743 FPRReg resultFPR = result.fpr(); 1744 1745 JITCompiler::Jump isInteger = m_jit.branch32( 1746 MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); 1747 1748 speculationCheck( 1749 BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(), 1750 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); 1751 1752 unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR); 1753 JITCompiler::Jump done = m_jit.jump(); 1754 1755 isInteger.link(&m_jit); 1756 m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR); 1757 done.link(&m_jit); 1758 #endif 1759 1760 doubleResult(resultFPR, m_compileIndex); 1675 1761 } 1676 1762 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r111906 r112040 1733 1733 void compileValueToInt32(Node&); 1734 1734 void compileUInt32ToNumber(Node&); 1735 void compileInt32ToDouble(Node&); 1735 1736 void compileGetByValOnByteArray(Node&); 1736 1737 void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&); … … 1985 1986 { 1986 1987 ASSERT(m_jit); 1988 ASSERT(use.useKind() != DoubleUse); 1987 1989 if (jit->isFilled(m_index)) 1988 1990 gpr(); … … 2034 2036 { 2035 2037 ASSERT(m_jit); 2038 2039 // This is counter-intuitive but correct. DoubleOperand is intended to 2040 // be used only when you're a node that is happy to accept an untyped 2041 // value, but will special-case for doubles (using DoubleOperand) if the 2042 // value happened to already be represented as a double. The implication 2043 // is that you will not try to force the value to become a double if it 2044 // is not one already. 2045 ASSERT(use.useKind() != DoubleUse); 2046 2036 2047 if (jit->isFilledDouble(m_index)) 2037 2048 fpr(); … … 2079 2090 { 2080 2091 ASSERT(m_jit); 2092 ASSERT(use.useKind() != DoubleUse); 2081 2093 #if USE(JSVALUE64) 2082 2094 if (jit->isFilled(m_index)) … … 2189 2201 { 2190 2202 ASSERT(m_jit); 2203 ASSERT(use.useKind() != DoubleUse); 2191 2204 if (jit->isFilled(m_index)) 2192 2205 gpr(); … … 2361 2374 { 2362 2375 ASSERT(m_jit); 2376 ASSERT(use.useKind() != DoubleUse); 2363 2377 if (jit->isFilled(m_index)) 2364 2378 gpr(); … … 2405 2419 { 2406 2420 ASSERT(m_jit); 2421 ASSERT(use.useKind() != DoubleUse); 2407 2422 if (jit->isFilled(m_index)) 2408 2423 gpr(); … … 2446 2461 { 2447 2462 ASSERT(m_jit); 2463 ASSERT(use.useKind() == DoubleUse); 2448 2464 if (jit->isFilled(m_index)) 2449 2465 fpr(); … … 2482 2498 { 2483 2499 ASSERT(m_jit); 2500 ASSERT(use.useKind() != DoubleUse); 2484 2501 if (jit->isFilled(m_index)) 2485 2502 gpr(); … … 2523 2540 { 2524 2541 ASSERT(m_jit); 2542 ASSERT(use.useKind() != DoubleUse); 2525 2543 if (jit->isFilled(m_index)) 2526 2544 gpr(); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r111649 r112040 1879 1879 break; 1880 1880 } 1881 1882 case Int32ToDouble: { 1883 compileInt32ToDouble(node); 1884 break; 1885 } 1881 1886 1882 1887 case ValueAdd: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r112018 r112040 1966 1966 break; 1967 1967 } 1968 1969 case Int32ToDouble: { 1970 compileInt32ToDouble(node); 1971 break; 1972 } 1968 1973 1969 1974 case ValueAdd:
Note:
See TracChangeset
for help on using the changeset viewer.