Changeset 207369 in webkit
- Timestamp:
- Oct 14, 2016 7:19:16 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r207363 r207369 1 2016-10-14 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] op_negate should with any type 4 https://bugs.webkit.org/show_bug.cgi?id=162587 5 6 Reviewed by Saam Barati. 7 8 * stress/arith-abs-to-arith-negate-range-optimizaton.js: Added. 9 Cover OSR Exits when converting Math.abs() into ArithNegate. 10 11 * stress/arith-negate-on-various-types.js: Added. 12 Cover ArithNegate with all types. 13 1 14 2016-10-14 JF Bastien <jfbastien@apple.com> 2 15 -
trunk/Source/JavaScriptCore/ChangeLog
r207360 r207369 1 2016-10-14 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] op_negate should with any type 4 https://bugs.webkit.org/show_bug.cgi?id=162587 5 6 Reviewed by Saam Barati. 7 8 * dfg/DFGAbstractInterpreterInlines.h: 9 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 10 ArithNegate is quite simple. If the input is double, the output 11 is double. The other cases are set from the LLInt slow case. 12 13 * dfg/DFGByteCodeParser.cpp: 14 (JSC::DFG::ByteCodeParser::makeSafe): 15 * dfg/DFGClobberize.h: 16 (JSC::DFG::clobberize): 17 * dfg/DFGFixupPhase.cpp: 18 (JSC::DFG::FixupPhase::fixupNode): 19 20 * dfg/DFGIntegerRangeOptimizationPhase.cpp: 21 Tweak a bit the IntegerRangeOptimizationPhase when simplifying 22 ArithAbs to ArithNegate. 23 We should not do the conversion if the target nodes OSR Exits 24 on different input than the source node. 25 26 In particular, Checked ArithNegate exits on zero while 27 ArithAbs has not problem with it. 28 Unchecked ArithAbs() do not OSR Exit on INT_MIN, ArithNeg 29 should not either. 30 31 * dfg/DFGPredictionPropagationPhase.cpp: 32 * dfg/DFGSpeculativeJIT.cpp: 33 (JSC::DFG::SpeculativeJIT::compileArithNegate): 34 (JSC::DFG::SpeculativeJIT::compileMathIC): 35 * dfg/DFGSpeculativeJIT.h: 36 (JSC::DFG::SpeculativeJIT::callOperation): 37 * ftl/FTLLowerDFGToB3.cpp: 38 (JSC::FTL::DFG::LowerDFGToB3::compileMathIC): 39 (JSC::FTL::DFG::LowerDFGToB3::compileArithNegate): 40 41 * jit/JITNegGenerator.cpp: 42 (JSC::JITNegGenerator::generateFastPath): 43 * jit/JITOperations.cpp: 44 Add result profiling in baseline to have types we can use 45 in DFG and FTL. 46 1 47 2016-10-14 Keith Miller <keith_miller@apple.com> 2 48 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r206853 r207369 658 658 break; 659 659 default: 660 RELEASE_ASSERT_NOT_REACHED(); 660 DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse); 661 forNode(node).setType(SpecBytecodeNumber); 661 662 break; 662 663 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r207239 r207369 975 975 break; 976 976 } 977 case ArithNegate: { 978 ASSERT_WITH_MESSAGE(!arithProfile->didObserveNonNumber(), "op_negate starts with a toNumber() on the argument, it should only produce numbers."); 979 980 if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble()) 981 node->mergeFlags(NodeMayHaveDoubleResult); 982 if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) 983 node->mergeFlags(NodeMayNegZeroInBaseline); 984 if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) 985 node->mergeFlags(NodeMayOverflowInt32InBaseline); 986 break; 987 } 977 988 978 989 default: … … 990 1001 case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. 991 1002 node->mergeFlags(NodeMayOverflowInt32InBaseline); 992 break;993 994 case ArithNegate:995 // Currently we can't tell the difference between a negation overflowing996 // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow997 // path then we assume that it did both of those things.998 node->mergeFlags(NodeMayOverflowInt32InBaseline);999 node->mergeFlags(NodeMayNegZeroInBaseline);1000 1003 break; 1001 1004 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r206955 r207369 212 212 return; 213 213 214 case ArithNegate: 215 if (node->child1().useKind() == Int32Use 216 || node->child1().useKind() == DoubleRepUse 217 || node->child1().useKind() == Int52RepUse) 218 def(PureValue(node)); 219 else { 220 read(World); 221 write(Heap); 222 } 223 return; 224 214 225 case IsCellWithType: 215 226 def(PureValue(node, node->queriedType())); … … 335 346 336 347 case ArithAdd: 337 case ArithNegate:338 348 case ArithMod: 339 349 case DoubleAsInt32: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r207239 r207369 210 210 211 211 case ArithNegate: { 212 if ( m_graph.unaryArithShouldSpeculateInt32(node,FixupPass)) {212 if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) { 213 213 fixIntOrBooleanEdge(node->child1()); 214 214 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) … … 218 218 else 219 219 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 220 node->setResult(NodeResultInt32); 221 node->clearFlags(NodeMustGenerate); 220 222 break; 221 223 } … … 227 229 node->setArithMode(Arith::CheckOverflowAndNegativeZero); 228 230 node->setResult(NodeResultInt52); 229 break; 230 } 231 fixDoubleOrBooleanEdge(node->child1()); 232 node->setResult(NodeResultDouble); 231 node->clearFlags(NodeMustGenerate); 232 break; 233 } 234 if (node->child1()->shouldSpeculateNotCell()) { 235 fixDoubleOrBooleanEdge(node->child1()); 236 node->setResult(NodeResultDouble); 237 node->clearFlags(NodeMustGenerate); 238 } else 239 fixEdge<UntypedUse>(node->child1()); 233 240 break; 234 241 } -
trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp
r198621 r207369 1253 1253 break; 1254 1254 } 1255 if (maxValue <= 0) { 1255 bool absIsUnchecked = !shouldCheckOverflow(node->arithMode()); 1256 if (maxValue < 0 || (absIsUnchecked && maxValue <= 0)) { 1256 1257 node->convertToArithNegate(); 1257 if ( minValue > std::numeric_limits<int>::min())1258 if (absIsUnchecked || minValue > std::numeric_limits<int>::min()) 1258 1259 node->setArithMode(Arith::Unchecked); 1259 1260 changed = true; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r206853 r207369 246 246 } 247 247 248 case ArithNegate: 249 if (node->child1()->prediction()) { 250 if (m_graph.unaryArithShouldSpeculateInt32(node, m_pass)) 248 case ArithNegate: { 249 SpeculatedType prediction = node->child1()->prediction(); 250 if (prediction) { 251 if (isInt32OrBooleanSpeculation(prediction) && node->canSpeculateInt32(m_pass)) 251 252 changed |= mergePrediction(SpecInt32Only); 252 253 else if (m_graph.unaryArithShouldSpeculateAnyInt(node, m_pass)) 253 254 changed |= mergePrediction(SpecInt52Only); 254 else 255 else if (isBytecodeNumberSpeculation(prediction)) 255 256 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); 256 } 257 break; 258 257 else { 258 changed |= mergePrediction(SpecInt32Only); 259 if (node->mayHaveDoubleResult()) 260 changed |= mergePrediction(SpecBytecodeDouble); 261 } 262 } 263 break; 264 } 259 265 case ArithMin: 260 266 case ArithMax: { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r207239 r207369 4238 4238 } 4239 4239 4240 default: 4241 RELEASE_ASSERT_NOT_REACHED(); 4242 return; 4243 } 4244 } 4240 default: { 4241 ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node->origin.semantic)->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); 4242 JITNegIC* negIC = m_jit.codeBlock()->addJITNegIC(arithProfile); 4243 auto repatchingFunction = operationArithNegateOptimize; 4244 auto nonRepatchingFunction = operationArithNegate; 4245 bool needsScratchGPRReg = true; 4246 compileMathIC(node, negIC, needsScratchGPRReg, repatchingFunction, nonRepatchingFunction); 4247 return; 4248 } 4249 } 4250 } 4251 4252 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction> 4253 void SpeculativeJIT::compileMathIC(Node* node, JITUnaryMathIC<Generator>* mathIC, bool needsScratchGPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction) 4254 { 4255 GPRReg scratchGPR = InvalidGPRReg; 4256 Optional<GPRTemporary> gprScratch; 4257 if (needsScratchGPRReg) { 4258 gprScratch = GPRTemporary(this); 4259 scratchGPR = gprScratch->gpr(); 4260 } 4261 JSValueOperand childOperand(this, node->child1()); 4262 JSValueRegs childRegs = childOperand.jsValueRegs(); 4263 #if USE(JSVALUE64) 4264 GPRTemporary result(this, Reuse, childOperand); 4265 JSValueRegs resultRegs(result.gpr()); 4266 #else 4267 GPRTemporary resultTag(this); 4268 GPRTemporary resultPayload(this); 4269 JSValueRegs resultRegs(resultPayload.gpr(), resultTag.gpr()); 4270 #endif 4271 4272 #if ENABLE(MATH_IC_STATS) 4273 auto inlineStart = m_jit.label(); 4274 #endif 4275 4276 Box<MathICGenerationState> icGenerationState = Box<MathICGenerationState>::create(); 4277 mathIC->m_generator = Generator(resultRegs, childRegs, scratchGPR); 4278 4279 bool shouldEmitProfiling = false; 4280 bool generatedInline = mathIC->generateInline(m_jit, *icGenerationState, shouldEmitProfiling); 4281 4282 if (generatedInline) { 4283 ASSERT(!icGenerationState->slowPathJumps.empty()); 4284 4285 Vector<SilentRegisterSavePlan> savePlans; 4286 silentSpillAllRegistersImpl(false, savePlans, resultRegs); 4287 4288 auto done = m_jit.label(); 4289 4290 addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () { 4291 icGenerationState->slowPathJumps.link(&m_jit); 4292 icGenerationState->slowPathStart = m_jit.label(); 4293 #if ENABLE(MATH_IC_STATS) 4294 auto slowPathStart = m_jit.label(); 4295 #endif 4296 4297 silentSpill(savePlans); 4298 4299 if (icGenerationState->shouldSlowPathRepatch) 4300 icGenerationState->slowPathCall = callOperation(bitwise_cast<J_JITOperation_EJMic>(repatchingFunction), resultRegs, childRegs, TrustedImmPtr(mathIC)); 4301 else 4302 icGenerationState->slowPathCall = callOperation(nonRepatchingFunction, resultRegs, childRegs); 4303 4304 silentFill(savePlans); 4305 m_jit.exceptionCheck(); 4306 m_jit.jump().linkTo(done, &m_jit); 4307 4308 m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 4309 mathIC->finalizeInlineCode(*icGenerationState, linkBuffer); 4310 }); 4311 4312 #if ENABLE(MATH_IC_STATS) 4313 auto slowPathEnd = m_jit.label(); 4314 m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 4315 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress()); 4316 mathIC->m_generatedCodeSize += size; 4317 }); 4318 #endif 4319 4320 }); 4321 } else { 4322 flushRegisters(); 4323 callOperation(nonRepatchingFunction, resultRegs, childRegs); 4324 m_jit.exceptionCheck(); 4325 } 4326 4327 #if ENABLE(MATH_IC_STATS) 4328 auto inlineEnd = m_jit.label(); 4329 m_jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 4330 size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress()); 4331 mathIC->m_generatedCodeSize += size; 4332 }); 4333 #endif 4334 4335 jsValueResult(resultRegs, node); 4336 return; 4337 } 4338 4339 4245 4340 void SpeculativeJIT::compileArithMul(Node* node) 4246 4341 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r207013 r207369 1313 1313 return appendCallSetResult(operation, result); 1314 1314 } 1315 JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC) 1316 { 1317 m_jit.setupArgumentsWithExecState(arg.gpr(), mathIC); 1318 return appendCallSetResult(operation, result.gpr()); 1319 } 1315 1320 JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC) 1316 1321 { … … 1800 1805 return appendCallSetResult(operation, result); 1801 1806 } 1802 1807 JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC) 1808 { 1809 m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg.payloadGPR(), arg.tagGPR(), mathIC); 1810 return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR()); 1811 } 1803 1812 JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC) 1804 1813 { … … 2596 2605 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction> 2597 2606 void compileMathIC(Node*, JITBinaryMathIC<Generator>*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction); 2607 template <typename Generator, typename RepatchingFunction, typename NonRepatchingFunction> 2608 void compileMathIC(Node*, JITUnaryMathIC<Generator>*, bool needsScratchGPRReg, RepatchingFunction, NonRepatchingFunction); 2598 2609 2599 2610 void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue)); -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r207239 r207369 1581 1581 1582 1582 template <typename Generator> 1583 void compileMathIC(JITUnaryMathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction) 1584 { 1585 Node* node = m_node; 1586 1587 LValue operand = lowJSValue(node->child1()); 1588 1589 PatchpointValue* patchpoint = m_out.patchpoint(Int64); 1590 patchpoint->appendSomeRegister(operand); 1591 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); 1592 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); 1593 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint); 1594 patchpoint->numGPScratchRegisters = 1; 1595 patchpoint->clobber(RegisterSet::macroScratchRegisters()); 1596 State* state = &m_ftlState; 1597 patchpoint->setGenerator( 1598 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 1599 AllowMacroScratchRegisterUsage allowScratch(jit); 1600 1601 Box<CCallHelpers::JumpList> exceptions = 1602 exceptionHandle->scheduleExitCreation(params)->jumps(jit); 1603 1604 #if ENABLE(MATH_IC_STATS) 1605 auto inlineStart = jit.label(); 1606 #endif 1607 1608 Box<MathICGenerationState> mathICGenerationState = Box<MathICGenerationState>::create(); 1609 mathIC->m_generator = Generator(JSValueRegs(params[0].gpr()), JSValueRegs(params[1].gpr()), params.gpScratch(0)); 1610 1611 bool shouldEmitProfiling = false; 1612 bool generatedInline = mathIC->generateInline(jit, *mathICGenerationState, shouldEmitProfiling); 1613 1614 if (generatedInline) { 1615 ASSERT(!mathICGenerationState->slowPathJumps.empty()); 1616 auto done = jit.label(); 1617 params.addLatePath([=] (CCallHelpers& jit) { 1618 AllowMacroScratchRegisterUsage allowScratch(jit); 1619 mathICGenerationState->slowPathJumps.link(&jit); 1620 mathICGenerationState->slowPathStart = jit.label(); 1621 #if ENABLE(MATH_IC_STATS) 1622 auto slowPathStart = jit.label(); 1623 #endif 1624 1625 if (mathICGenerationState->shouldSlowPathRepatch) { 1626 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(), 1627 repatchingFunction, params[0].gpr(), params[1].gpr(), CCallHelpers::TrustedImmPtr(mathIC)); 1628 mathICGenerationState->slowPathCall = call.call(); 1629 } else { 1630 SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node->origin.semantic, 1631 exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr()); 1632 mathICGenerationState->slowPathCall = call.call(); 1633 } 1634 jit.jump().linkTo(done, &jit); 1635 1636 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 1637 mathIC->finalizeInlineCode(*mathICGenerationState, linkBuffer); 1638 }); 1639 1640 #if ENABLE(MATH_IC_STATS) 1641 auto slowPathEnd = jit.label(); 1642 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 1643 size_t size = static_cast<char*>(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(slowPathStart).executableAddress()); 1644 mathIC->m_generatedCodeSize += size; 1645 }); 1646 #endif 1647 }); 1648 } else { 1649 callOperation( 1650 *state, params.unavailableRegisters(), jit, node->origin.semantic, exceptions.get(), 1651 nonRepatchingFunction, params[0].gpr(), params[1].gpr()); 1652 } 1653 1654 #if ENABLE(MATH_IC_STATS) 1655 auto inlineEnd = jit.label(); 1656 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 1657 size_t size = static_cast<char*>(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast<char*>(linkBuffer.locationOf(inlineStart).executableAddress()); 1658 mathIC->m_generatedCodeSize += size; 1659 }); 1660 #endif 1661 }); 1662 1663 setJSValue(patchpoint); 1664 } 1665 1666 template <typename Generator> 1583 1667 void compileMathIC(JITBinaryMathIC<Generator>* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction) 1584 1668 { … … 2452 2536 2453 2537 default: 2454 DFG_CRASH(m_graph, m_node, "Bad use kind"); 2538 DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); 2539 ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic)->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex); 2540 JITNegIC* negIC = codeBlock()->addJITNegIC(arithProfile); 2541 auto repatchingFunction = operationArithNegateOptimize; 2542 auto nonRepatchingFunction = operationArithNegate; 2543 compileMathIC(negIC, repatchingFunction, nonRepatchingFunction); 2455 2544 break; 2456 2545 } -
trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp
r206392 r207369 83 83 } 84 84 85 bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* , bool)85 bool JITNegGenerator::generateFastPath(CCallHelpers& jit, CCallHelpers::JumpList& endJumpList, CCallHelpers::JumpList& slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling) 86 86 { 87 87 ASSERT(m_scratchGPR != m_src.payloadGPR()); … … 116 116 jit.xor32(CCallHelpers::TrustedImm32(1 << 31), m_result.tagGPR()); 117 117 #endif 118 // The flags of ArithNegate are basic in DFG. 119 // We only need to know if we ever produced a number. 120 if (shouldEmitProfiling && arithProfile && !arithProfile->lhsObservedType().sawNumber() && !arithProfile->didObserveDouble()) 121 arithProfile->emitSetDouble(jit); 118 122 return true; 119 123 } -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r206853 r207369 2471 2471 if (UNLIKELY(scope.exception())) 2472 2472 return JSValue::encode(JSValue()); 2473 return JSValue::encode(jsNumber(-number)); 2473 2474 JSValue result = jsNumber(-number); 2475 arithProfile.observeResult(result); 2476 return JSValue::encode(result); 2474 2477 } 2475 2478 … … 2505 2508 if (UNLIKELY(scope.exception())) 2506 2509 return JSValue::encode(JSValue()); 2507 return JSValue::encode(jsNumber(-number)); 2510 JSValue result = jsNumber(-number); 2511 arithProfile->observeResult(result); 2512 return JSValue::encode(result); 2508 2513 } 2509 2514
Note: See TracChangeset
for help on using the changeset viewer.