Changeset 143241 in webkit
- Timestamp:
- Feb 18, 2013 10:40:09 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r143240 r143241 1 2013-02-17 Filip Pizlo <fpizlo@apple.com> 2 3 Get rid of DFG::DoubleOperand and simplify ValueToInt32 4 https://bugs.webkit.org/show_bug.cgi?id=110072 5 6 Reviewed by Geoffrey Garen. 7 8 * fast/js/dfg-value-to-int32-with-side-effect-expected.txt: Added. 9 * fast/js/dfg-value-to-int32-with-side-effect.html: Added. 10 * fast/js/jsc-test-list: 11 * fast/js/script-tests/dfg-value-to-int32-with-side-effect.js: Added. 12 (foo): 13 (.result.foo): 14 1 15 2013-02-18 Joseph Pecoraro <pecoraro@apple.com> 2 16 -
trunk/LayoutTests/fast/js/jsc-test-list
r142779 r143241 188 188 fast/js/dfg-uint8array 189 189 fast/js/dfg-uint8clampedarray 190 fast/js/dfg-value-to-int32-with-side-effects 190 191 fast/js/dfg-weak-js-constant-silent-fill 191 192 fast/js/dictionary-no-cache -
trunk/Source/JavaScriptCore/ChangeLog
r143235 r143241 1 2013-02-17 Filip Pizlo <fpizlo@apple.com> 2 3 Get rid of DFG::DoubleOperand and simplify ValueToInt32 4 https://bugs.webkit.org/show_bug.cgi?id=110072 5 6 Reviewed by Geoffrey Garen. 7 8 ValueToInt32 had a side-effecting path, which was not OSR-friendly: an OSR after 9 the side-effect would lead to the side-effect re-executing. I got rid of that path 10 and replaced it with an optimization for the case where the input is speculated 11 number-or-other. This makes idioms like null|0 and true|0 work as expected, and 12 get optimized appropriately. 13 14 Also got rid of DoubleOperand. Replaced all remaining uses of it with 15 SpeculateDoubleOperand. Because the latter asserts that the Edge is a DoubleUse 16 edge and the remaining uses of DoubleOperand are all for untyped uses, I worked 17 around the assertion by setting the UseKind to DoubleUse by force. This is sound, 18 since all existing assertions for DoubleUse are actually asserting that we're not 19 converting a value to double unexpectedly. But all of these calls to 20 SpeculateDoubleOperand are when the operand is already known to be represented as 21 double, so there is no conversion. 22 23 This is neutral on benchmarks, except stanford-crypto-ccm, which speeds up a 24 little. Mostly, this is intended to delete a bunch of code. DoubleOperand was 25 equivalent to the replace-edge-with-DoubleUse trick that I'm using now, except it 26 involved a _lot_ more code. 27 28 * dfg/DFGAbstractState.cpp: 29 (JSC::DFG::AbstractState::execute): 30 * dfg/DFGCSEPhase.cpp: 31 (JSC::DFG::CSEPhase::performNodeCSE): 32 * dfg/DFGFixupPhase.cpp: 33 (JSC::DFG::FixupPhase::fixupNode): 34 * dfg/DFGNodeType.h: 35 (DFG): 36 * dfg/DFGSpeculativeJIT.cpp: 37 (DFG): 38 (JSC::DFG::SpeculativeJIT::compileValueToInt32): 39 * dfg/DFGSpeculativeJIT.h: 40 (SpeculativeJIT): 41 (DFG): 42 (FPRTemporary): 43 * dfg/DFGSpeculativeJIT32_64.cpp: 44 (DFG): 45 (JSC::DFG::SpeculativeJIT::compile): 46 * dfg/DFGSpeculativeJIT64.cpp: 47 (DFG): 48 1 49 2013-02-18 Ádám Kallai <kadam@inf.u-szeged.hu> 2 50 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r143024 r143241 426 426 if (node->child1()->shouldSpeculateInteger()) 427 427 speculateInt32Unary(node); 428 else if (node->child1()->shouldSpeculateBoolean()) 429 speculateBooleanUnary(node); 428 430 else if (node->child1()->shouldSpeculateNumber()) 429 431 speculateNumberUnary(node); 430 else if (node->child1()->shouldSpeculateBoolean())431 speculateBooleanUnary(node);432 else433 node->setCanExit(false);432 else { 433 node->setCanExit(forNode(node->child1()).m_type & SpecCell); 434 forNode(node->child1()).filter(~SpecCell); 435 } 434 436 435 437 forNode(node).set(SpecInt32); -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r142544 r143241 1133 1133 case TypeOf: 1134 1134 case CompareEqConstant: 1135 case ValueToInt32: 1135 1136 setReplacement(pureCSE(node)); 1136 1137 break; -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r142779 r143241 178 178 case ArrayPop: { 179 179 blessArrayOperation(node->child1(), Edge(), 1); 180 break;181 }182 183 case ValueToInt32: {184 if (node->child1()->shouldSpeculateNumber()185 && node->mustGenerate()) {186 node->clearFlags(NodeMustGenerate);187 m_graph.deref(node);188 }189 180 break; 190 181 } -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r142544 r143241 87 87 macro(BitURShift, NodeResultInt32) \ 88 88 /* Bitwise operators call ToInt32 on their operands. */\ 89 macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \89 macro(ValueToInt32, NodeResultInt32) \ 90 90 /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ 91 91 macro(UInt32ToNumber, NodeResultNumber) \ -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r143168 r143241 1389 1389 } 1390 1390 1391 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1)1392 : m_jit(jit)1393 , m_fpr(InvalidFPRReg)1394 {1395 if (m_jit->canReuse(op1.node()))1396 m_fpr = m_jit->reuse(op1.fpr());1397 else1398 m_fpr = m_jit->fprAllocate();1399 }1400 1401 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1, DoubleOperand& op2)1402 : m_jit(jit)1403 , m_fpr(InvalidFPRReg)1404 {1405 if (m_jit->canReuse(op1.node()))1406 m_fpr = m_jit->reuse(op1.fpr());1407 else if (m_jit->canReuse(op2.node()))1408 m_fpr = m_jit->reuse(op2.fpr());1409 else1410 m_fpr = m_jit->fprAllocate();1411 }1412 1413 1391 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1) 1414 1392 : m_jit(jit) … … 2180 2158 } 2181 2159 2182 if (node->child1()->shouldSpeculateNumber()) { 2183 switch (checkGeneratedTypeForToInt32(node->child1().node())) { 2184 case GeneratedOperandInteger: { 2185 SpeculateIntegerOperand op1(this, node->child1()); 2186 GPRTemporary result(this, op1); 2187 m_jit.move(op1.gpr(), result.gpr()); 2188 integerResult(result.gpr(), node, op1.format()); 2189 return; 2190 } 2191 case GeneratedOperandDouble: { 2192 GPRTemporary result(this); 2193 DoubleOperand op1(this, node->child1()); 2194 FPRReg fpr = op1.fpr(); 2195 GPRReg gpr = result.gpr(); 2196 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed); 2160 if (node->child1()->shouldSpeculateBoolean()) { 2161 SpeculateBooleanOperand op1(this, node->child1()); 2162 GPRTemporary result(this, op1); 2163 2164 m_jit.move(op1.gpr(), result.gpr()); 2165 m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr()); 2166 2167 integerResult(result.gpr(), node); 2168 return; 2169 } 2170 2171 switch (checkGeneratedTypeForToInt32(node->child1().node())) { 2172 case GeneratedOperandInteger: { 2173 SpeculateIntegerOperand op1(this, node->child1()); 2174 GPRTemporary result(this, op1); 2175 m_jit.move(op1.gpr(), result.gpr()); 2176 integerResult(result.gpr(), node, op1.format()); 2177 return; 2178 } 2179 case GeneratedOperandDouble: { 2180 GPRTemporary result(this); 2181 SpeculateDoubleOperand op1(this, Edge(node->child1().node(), DoubleUse)); // SpeculateDoubleOperand will assert that this is a double use. We force it to think that it was a double use, since we are inferring that we ought to emit a double use quite late. 2182 FPRReg fpr = op1.fpr(); 2183 GPRReg gpr = result.gpr(); 2184 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed); 2197 2185 2198 2199 2200 2201 2202 2203 2204 2186 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr)); 2187 2188 integerResult(gpr, node); 2189 return; 2190 } 2191 case GeneratedOperandJSValue: { 2192 GPRTemporary result(this); 2205 2193 #if USE(JSVALUE64) 2206 JSValueOperand op1(this, node->child1()); 2207 2208 GPRReg gpr = op1.gpr(); 2209 GPRReg resultGpr = result.gpr(); 2194 JSValueOperand op1(this, node->child1()); 2195 2196 GPRReg gpr = op1.gpr(); 2197 GPRReg resultGpr = result.gpr(); 2198 FPRTemporary tempFpr(this); 2199 FPRReg fpr = tempFpr.fpr(); 2200 2201 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); 2202 JITCompiler::JumpList converted; 2203 2204 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) { 2205 if (node->child1()->shouldSpeculateNumber()) 2206 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); 2207 else { 2208 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister); 2209 2210 if (m_state.forNode(node->child1()).m_type & SpecCell) 2211 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister)); 2212 2213 // It's not a cell: so true turns into 1 and all else turns into 0. 2214 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr); 2215 converted.append(m_jit.jump()); 2216 2217 isNumber.link(&m_jit); 2218 } 2219 } 2220 2221 // First, if we get here we have a double encoded as a JSValue 2222 m_jit.move(gpr, resultGpr); 2223 unboxDouble(resultGpr, fpr); 2224 2225 silentSpillAllRegisters(resultGpr); 2226 callOperation(toInt32, resultGpr, fpr); 2227 silentFillAllRegisters(resultGpr); 2228 2229 converted.append(m_jit.jump()); 2230 2231 isInteger.link(&m_jit); 2232 m_jit.zeroExtend32ToPtr(gpr, resultGpr); 2233 2234 converted.link(&m_jit); 2235 #else 2236 Node* childNode = node->child1().node(); 2237 VirtualRegister virtualRegister = childNode->virtualRegister(); 2238 GenerationInfo& info = m_generationInfo[virtualRegister]; 2239 2240 JSValueOperand op1(this, node->child1()); 2241 2242 GPRReg payloadGPR = op1.payloadGPR(); 2243 GPRReg resultGpr = result.gpr(); 2244 2245 JITCompiler::JumpList converted; 2246 2247 if (info.registerFormat() == DataFormatJSInteger) 2248 m_jit.move(payloadGPR, resultGpr); 2249 else { 2250 GPRReg tagGPR = op1.tagGPR(); 2210 2251 FPRTemporary tempFpr(this); 2211 2252 FPRReg fpr = tempFpr.fpr(); 2212 2213 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); 2214 2215 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) 2216 speculationCheck(BadType, JSValueRegs(gpr), node->child1(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); 2217 2218 // First, if we get here we have a double encoded as a JSValue 2219 m_jit.move(gpr, resultGpr); 2220 unboxDouble(resultGpr, fpr); 2253 FPRTemporary scratch(this); 2254 2255 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 2256 2257 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) { 2258 if (node->child1()->shouldSpeculateNumber()) 2259 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 2260 else { 2261 JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag)); 2262 2263 if (m_state.forNode(node->child1()).m_type & SpecCell) 2264 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag))); 2265 2266 // It's not a cell: so true turns into 1 and all else turns into 0. 2267 JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag)); 2268 m_jit.move(TrustedImm32(0), resultGpr); 2269 converted.append(m_jit.jump()); 2270 2271 isBoolean.link(&m_jit); 2272 m_jit.move(payloadGPR, resultGpr); 2273 converted.append(m_jit.jump()); 2274 2275 isNumber.link(&m_jit); 2276 } 2277 } 2278 2279 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 2221 2280 2222 2281 silentSpillAllRegisters(resultGpr); … … 2224 2283 silentFillAllRegisters(resultGpr); 2225 2284 2226 JITCompiler::Jump converted = m_jit.jump();2285 converted.append(m_jit.jump()); 2227 2286 2228 2287 isInteger.link(&m_jit); 2229 m_jit. zeroExtend32ToPtr(gpr, resultGpr);2288 m_jit.move(payloadGPR, resultGpr); 2230 2289 2231 2290 converted.link(&m_jit); 2232 #else 2233 Node* childNode = node->child1().node(); 2234 VirtualRegister virtualRegister = childNode->virtualRegister(); 2235 GenerationInfo& info = m_generationInfo[virtualRegister]; 2236 2237 JSValueOperand op1(this, node->child1()); 2238 2239 GPRReg payloadGPR = op1.payloadGPR(); 2240 GPRReg resultGpr = result.gpr(); 2241 2242 if (info.registerFormat() == DataFormatJSInteger) 2243 m_jit.move(payloadGPR, resultGpr); 2244 else { 2245 GPRReg tagGPR = op1.tagGPR(); 2246 FPRTemporary tempFpr(this); 2247 FPRReg fpr = tempFpr.fpr(); 2248 FPRTemporary scratch(this); 2249 2250 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); 2251 2252 if (!isNumberSpeculation(m_state.forNode(node->child1()).m_type)) 2253 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node->child1(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); 2254 2255 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); 2256 2257 silentSpillAllRegisters(resultGpr); 2258 callOperation(toInt32, resultGpr, fpr); 2259 silentFillAllRegisters(resultGpr); 2260 2261 JITCompiler::Jump converted = m_jit.jump(); 2262 2263 isInteger.link(&m_jit); 2264 m_jit.move(payloadGPR, resultGpr); 2265 2266 converted.link(&m_jit); 2267 } 2268 #endif 2269 integerResult(resultGpr, node); 2270 return; 2271 } 2272 case GeneratedOperandTypeUnknown: 2273 RELEASE_ASSERT_NOT_REACHED(); 2274 break; 2275 } 2276 } 2277 2278 if (node->child1()->shouldSpeculateBoolean()) { 2279 SpeculateBooleanOperand op1(this, node->child1()); 2280 GPRTemporary result(this, op1); 2281 2282 m_jit.move(op1.gpr(), result.gpr()); 2283 m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr()); 2284 2285 integerResult(result.gpr(), node); 2286 return; 2287 } 2288 2289 // Do it the safe way. 2290 nonSpeculativeValueToInt32(node); 2291 return; 2291 } 2292 #endif 2293 integerResult(resultGpr, node); 2294 return; 2295 } 2296 case GeneratedOperandTypeUnknown: 2297 RELEASE_ASSERT_NOT_REACHED(); 2298 break; 2299 } 2292 2300 } 2293 2301 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r143168 r143241 123 123 124 124 GPRReg fillInteger(Node*, DataFormat& returnFormat); 125 FPRReg fillDouble(Node*);126 125 #if USE(JSVALUE64) 127 126 GPRReg fillJSValue(Node*); … … 691 690 } 692 691 693 void nonSpeculativeValueToInt32(Node*);694 692 void nonSpeculativeUInt32ToNumber(Node*); 695 693 … … 2298 2296 // === Operand types === 2299 2297 // 2300 // IntegerOperand , DoubleOperandand JSValueOperand.2298 // IntegerOperand and JSValueOperand. 2301 2299 // 2302 2300 // These classes are used to lock the operands to a node into machine … … 2358 2356 GPRReg m_gprOrInvalid; 2359 2357 DataFormat m_format; 2360 };2361 2362 class DoubleOperand {2363 public:2364 explicit DoubleOperand(SpeculativeJIT* jit, Edge use)2365 : m_jit(jit)2366 , m_node(use.node())2367 , m_fprOrInvalid(InvalidFPRReg)2368 {2369 ASSERT(m_jit);2370 2371 // This is counter-intuitive but correct. DoubleOperand is intended to2372 // be used only when you're a node that is happy to accept an untyped2373 // value, but will special-case for doubles (using DoubleOperand) if the2374 // value happened to already be represented as a double. The implication2375 // is that you will not try to force the value to become a double if it2376 // is not one already.2377 ASSERT(use.useKind() != DoubleUse);2378 2379 if (jit->isFilledDouble(m_node))2380 fpr();2381 }2382 2383 ~DoubleOperand()2384 {2385 ASSERT(m_fprOrInvalid != InvalidFPRReg);2386 m_jit->unlock(m_fprOrInvalid);2387 }2388 2389 Node* node() const2390 {2391 return m_node;2392 }2393 2394 FPRReg fpr()2395 {2396 if (m_fprOrInvalid == InvalidFPRReg)2397 m_fprOrInvalid = m_jit->fillDouble(node());2398 return m_fprOrInvalid;2399 }2400 2401 void use()2402 {2403 m_jit->use(m_node);2404 }2405 2406 private:2407 SpeculativeJIT* m_jit;2408 Node* m_node;2409 FPRReg m_fprOrInvalid;2410 2358 }; 2411 2359 … … 2615 2563 public: 2616 2564 FPRTemporary(SpeculativeJIT*); 2617 FPRTemporary(SpeculativeJIT*, DoubleOperand&);2618 FPRTemporary(SpeculativeJIT*, DoubleOperand&, DoubleOperand&);2619 2565 FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&); 2620 2566 FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&, SpeculateDoubleOperand&); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r143165 r143241 111 111 RELEASE_ASSERT_NOT_REACHED(); 112 112 return InvalidGPRReg; 113 }114 }115 116 FPRReg SpeculativeJIT::fillDouble(Node* node)117 {118 VirtualRegister virtualRegister = node->virtualRegister();119 GenerationInfo& info = m_generationInfo[virtualRegister];120 121 if (info.registerFormat() == DataFormatNone) {122 123 if (node->hasConstant()) {124 if (isInt32Constant(node)) {125 // FIXME: should not be reachable?126 GPRReg gpr = allocate();127 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(node)), gpr);128 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);129 info.fillInteger(*m_stream, gpr);130 unlock(gpr);131 } else if (isNumberConstant(node)) {132 FPRReg fpr = fprAllocate();133 m_jit.loadDouble(addressOfDoubleConstant(node), fpr);134 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);135 info.fillDouble(*m_stream, fpr);136 return fpr;137 } else {138 // FIXME: should not be reachable?139 RELEASE_ASSERT_NOT_REACHED();140 }141 } else {142 DataFormat spillFormat = info.spillFormat();143 ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);144 if (spillFormat == DataFormatJSDouble) {145 FPRReg fpr = fprAllocate();146 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);147 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);148 info.fillDouble(*m_stream, fpr);149 return fpr;150 }151 152 FPRReg fpr = fprAllocate();153 JITCompiler::Jump hasUnboxedDouble;154 155 if (spillFormat != DataFormatJSInteger && spillFormat != DataFormatInteger) {156 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag));157 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);158 hasUnboxedDouble = m_jit.jump();159 isInteger.link(&m_jit);160 }161 162 m_jit.convertInt32ToDouble(JITCompiler::payloadFor(virtualRegister), fpr);163 164 if (hasUnboxedDouble.isSet())165 hasUnboxedDouble.link(&m_jit);166 167 m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);168 info.fillDouble(*m_stream, fpr);169 return fpr;170 }171 }172 173 switch (info.registerFormat()) {174 case DataFormatNone:175 // Should have filled, above.176 case DataFormatCell:177 case DataFormatJSCell:178 case DataFormatBoolean:179 case DataFormatJSBoolean:180 case DataFormatStorage:181 // Should only be calling this function if we know this operand to be numeric.182 RELEASE_ASSERT_NOT_REACHED();183 184 case DataFormatJSInteger:185 case DataFormatJS: {186 GPRReg tagGPR = info.tagGPR();187 GPRReg payloadGPR = info.payloadGPR();188 FPRReg fpr = fprAllocate();189 m_gprs.lock(tagGPR);190 m_gprs.lock(payloadGPR);191 192 JITCompiler::Jump hasUnboxedDouble;193 194 if (info.registerFormat() != DataFormatJSInteger) {195 FPRTemporary scratch(this);196 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));197 m_jit.jitAssertIsJSDouble(tagGPR);198 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());199 hasUnboxedDouble = m_jit.jump();200 isInteger.link(&m_jit);201 }202 203 m_jit.convertInt32ToDouble(payloadGPR, fpr);204 205 if (hasUnboxedDouble.isSet())206 hasUnboxedDouble.link(&m_jit);207 208 m_gprs.release(tagGPR);209 m_gprs.release(payloadGPR);210 m_gprs.unlock(tagGPR);211 m_gprs.unlock(payloadGPR);212 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);213 info.fillDouble(*m_stream, fpr);214 info.killSpilled();215 return fpr;216 }217 218 case DataFormatInteger: {219 FPRReg fpr = fprAllocate();220 GPRReg gpr = info.gpr();221 m_gprs.lock(gpr);222 m_jit.convertInt32ToDouble(gpr, fpr);223 m_gprs.unlock(gpr);224 return fpr;225 }226 227 case DataFormatJSDouble:228 case DataFormatDouble: {229 FPRReg fpr = info.fpr();230 m_fprs.lock(fpr);231 return fpr;232 }233 234 default:235 RELEASE_ASSERT_NOT_REACHED();236 return InvalidFPRReg;237 113 } 238 114 } … … 364 240 } 365 241 366 void SpeculativeJIT::nonSpeculativeValueToInt32(Node* node)367 {368 ASSERT(!isInt32Constant(node->child1().node()));369 370 if (isKnownInteger(node->child1().node())) {371 IntegerOperand op1(this, node->child1());372 GPRTemporary result(this, op1);373 m_jit.move(op1.gpr(), result.gpr());374 integerResult(result.gpr(), node);375 return;376 }377 378 GenerationInfo& childInfo = m_generationInfo[node->child1()->virtualRegister()];379 if (childInfo.isJSDouble()) {380 DoubleOperand op1(this, node->child1());381 GPRTemporary result(this);382 FPRReg fpr = op1.fpr();383 GPRReg gpr = result.gpr();384 op1.use();385 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);386 387 addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));388 389 integerResult(gpr, node, UseChildrenCalledExplicitly);390 return;391 }392 393 JSValueOperand op1(this, node->child1());394 GPRTemporary result(this);395 GPRReg tagGPR = op1.tagGPR();396 GPRReg payloadGPR = op1.payloadGPR();397 GPRReg resultGPR = result.gpr();398 op1.use();399 400 JITCompiler::Jump isNotInteger = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::Int32Tag));401 402 m_jit.move(payloadGPR, resultGPR);403 404 addSlowPathGenerator(slowPathCall(isNotInteger, this, dfgConvertJSValueToInt32, resultGPR, tagGPR, payloadGPR));405 406 integerResult(resultGPR, node, UseChildrenCalledExplicitly);407 }408 409 242 void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node) 410 243 { … … 2216 2049 SpeculatedType predictedType = node->variableAccessData()->argumentAwarePrediction(); 2217 2050 if (m_generationInfo[node->child1()->virtualRegister()].registerFormat() == DataFormatDouble) { 2218 DoubleOperand value(this, node->child1());2051 SpeculateDoubleOperand value(this, Edge(node->child1().node(), DoubleUse)); 2219 2052 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local())); 2220 2053 noResult(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r143165 r143241 118 118 } 119 119 120 FPRReg SpeculativeJIT::fillDouble(Node* node)121 {122 VirtualRegister virtualRegister = node->virtualRegister();123 GenerationInfo& info = m_generationInfo[virtualRegister];124 125 if (info.registerFormat() == DataFormatNone) {126 if (node->hasConstant()) {127 GPRReg gpr = allocate();128 129 if (isInt32Constant(node)) {130 // FIXME: should not be reachable?131 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(node)), gpr);132 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);133 info.fillInteger(*m_stream, gpr);134 unlock(gpr);135 } else if (isNumberConstant(node)) {136 FPRReg fpr = fprAllocate();137 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(node))), gpr);138 m_jit.move64ToDouble(gpr, fpr);139 unlock(gpr);140 141 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);142 info.fillDouble(*m_stream, fpr);143 return fpr;144 } else {145 // FIXME: should not be reachable?146 ASSERT(isJSConstant(node));147 JSValue jsValue = valueOfJSConstant(node);148 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);149 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);150 info.fillJSValue(*m_stream, gpr, DataFormatJS);151 unlock(gpr);152 }153 } else {154 DataFormat spillFormat = info.spillFormat();155 switch (spillFormat) {156 case DataFormatDouble: {157 FPRReg fpr = fprAllocate();158 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);159 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);160 info.fillDouble(*m_stream, fpr);161 return fpr;162 }163 164 case DataFormatInteger: {165 GPRReg gpr = allocate();166 167 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);168 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);169 info.fillInteger(*m_stream, gpr);170 unlock(gpr);171 break;172 }173 174 default:175 GPRReg gpr = allocate();176 177 RELEASE_ASSERT(spillFormat & DataFormatJS);178 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);179 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);180 info.fillJSValue(*m_stream, gpr, spillFormat);181 unlock(gpr);182 break;183 }184 }185 }186 187 switch (info.registerFormat()) {188 case DataFormatNone:189 // Should have filled, above.190 case DataFormatCell:191 case DataFormatJSCell:192 case DataFormatBoolean:193 case DataFormatJSBoolean:194 case DataFormatStorage:195 // Should only be calling this function if we know this operand to be numeric.196 RELEASE_ASSERT_NOT_REACHED();197 198 case DataFormatJS: {199 GPRReg jsValueGpr = info.gpr();200 m_gprs.lock(jsValueGpr);201 FPRReg fpr = fprAllocate();202 GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?203 204 JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);205 206 m_jit.jitAssertIsJSDouble(jsValueGpr);207 208 // First, if we get here we have a double encoded as a JSValue209 m_jit.move(jsValueGpr, tempGpr);210 unboxDouble(tempGpr, fpr);211 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();212 213 // Finally, handle integers.214 isInteger.link(&m_jit);215 m_jit.convertInt32ToDouble(jsValueGpr, fpr);216 hasUnboxedDouble.link(&m_jit);217 218 m_gprs.release(jsValueGpr);219 m_gprs.unlock(jsValueGpr);220 m_gprs.unlock(tempGpr);221 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);222 info.fillDouble(*m_stream, fpr);223 info.killSpilled();224 return fpr;225 }226 227 case DataFormatJSInteger:228 case DataFormatInteger: {229 FPRReg fpr = fprAllocate();230 GPRReg gpr = info.gpr();231 m_gprs.lock(gpr);232 m_jit.convertInt32ToDouble(gpr, fpr);233 m_gprs.unlock(gpr);234 return fpr;235 }236 237 // Unbox the double238 case DataFormatJSDouble: {239 GPRReg gpr = info.gpr();240 FPRReg fpr = fprAllocate();241 if (m_gprs.isLocked(gpr)) {242 // Make sure we don't trample gpr if it is in use.243 GPRReg temp = allocate();244 m_jit.move(gpr, temp);245 unboxDouble(temp, fpr);246 unlock(temp);247 } else248 unboxDouble(gpr, fpr);249 250 m_gprs.release(gpr);251 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);252 253 info.fillDouble(*m_stream, fpr);254 return fpr;255 }256 257 case DataFormatDouble: {258 FPRReg fpr = info.fpr();259 m_fprs.lock(fpr);260 return fpr;261 }262 263 default:264 RELEASE_ASSERT_NOT_REACHED();265 return InvalidFPRReg;266 }267 }268 269 120 GPRReg SpeculativeJIT::fillJSValue(Node* node) 270 121 { … … 362 213 return InvalidGPRReg; 363 214 } 364 }365 366 void SpeculativeJIT::nonSpeculativeValueToInt32(Node* node)367 {368 ASSERT(!isInt32Constant(node->child1().node()));369 370 if (isKnownInteger(node->child1().node())) {371 IntegerOperand op1(this, node->child1());372 GPRTemporary result(this, op1);373 m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());374 integerResult(result.gpr(), m_currentNode);375 return;376 }377 378 GenerationInfo& childInfo = m_generationInfo[node->child1()->virtualRegister()];379 if (childInfo.isJSDouble()) {380 DoubleOperand op1(this, node->child1());381 GPRTemporary result(this);382 FPRReg fpr = op1.fpr();383 GPRReg gpr = result.gpr();384 op1.use();385 JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);386 387 addSlowPathGenerator(388 slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));389 390 integerResult(gpr, m_currentNode, UseChildrenCalledExplicitly);391 return;392 }393 394 JSValueOperand op1(this, node->child1());395 GPRTemporary result(this, op1);396 GPRReg jsValueGpr = op1.gpr();397 GPRReg resultGPR = result.gpr();398 op1.use();399 400 JITCompiler::Jump isNotInteger = m_jit.branch64(MacroAssembler::Below, jsValueGpr, GPRInfo::tagTypeNumberRegister);401 402 m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);403 404 addSlowPathGenerator(405 slowPathCall(isNotInteger, this, dfgConvertJSValueToInt32, resultGPR, jsValueGpr));406 407 integerResult(resultGPR, m_currentNode, UseChildrenCalledExplicitly);408 215 } 409 216
Note: See TracChangeset
for help on using the changeset viewer.