Changeset 193781 in webkit
- Timestamp:
- Dec 8, 2015, 1:44:12 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/LayoutTests/ChangeLog ¶
r193773 r193781 1 2015-12-08 Mark Lam <mark.lam@apple.com> 2 3 Polymorphic operand types for DFG and FTL div. 4 https://bugs.webkit.org/show_bug.cgi?id=151747 5 6 Reviewed by Geoffrey Garen. 7 8 * js/regress/ftl-object-div-expected.txt: Added. 9 * js/regress/ftl-object-div.html: Added. 10 * js/regress/script-tests/ftl-object-div.js: Added. 11 (o1.valueOf): 12 (foo): 13 1 14 2015-12-08 Zalan Bujtas <zalan@apple.com> 2 15 -
TabularUnified trunk/Source/JavaScriptCore/ChangeLog ¶
r193766 r193781 1 2015-12-08 Mark Lam <mark.lam@apple.com> 2 3 Polymorphic operand types for DFG and FTL div. 4 https://bugs.webkit.org/show_bug.cgi?id=151747 5 6 Reviewed by Geoffrey Garen. 7 8 Perf on benchmarks is neutral. The new JSRegress ftl-object-div test shows 9 a speed up not from the div operator itself, but from the fact that the 10 polymorphic operand types support now allow the test function to run without OSR 11 exiting, thereby realizing the DFG and FTL's speed up on other work that the test 12 function does. 13 14 This patch has passed the layout tests on x86_64 with a debug build. 15 It passed the JSC tests with x86 and x86_64 debug builds. 16 17 * dfg/DFGAbstractInterpreterInlines.h: 18 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 19 * dfg/DFGClobberize.h: 20 (JSC::DFG::clobberize): 21 * dfg/DFGFixupPhase.cpp: 22 (JSC::DFG::FixupPhase::fixupNode): 23 * dfg/DFGOperations.cpp: 24 * dfg/DFGOperations.h: 25 * dfg/DFGPredictionPropagationPhase.cpp: 26 (JSC::DFG::PredictionPropagationPhase::propagate): 27 28 * dfg/DFGSpeculativeJIT.cpp: 29 (JSC::DFG::SpeculativeJIT::compileArithDiv): 30 31 * ftl/FTLCompileBinaryOp.cpp: 32 (JSC::FTL::generateBinaryArithOpFastPath): 33 (JSC::FTL::generateBinaryOpFastPath): 34 35 * ftl/FTLInlineCacheDescriptor.h: 36 * ftl/FTLInlineCacheDescriptorInlines.h: 37 (JSC::FTL::ArithDivDescriptor::ArithDivDescriptor): 38 (JSC::FTL::ArithDivDescriptor::icSize): 39 40 * ftl/FTLInlineCacheSize.cpp: 41 (JSC::FTL::sizeOfArithDiv): 42 * ftl/FTLInlineCacheSize.h: 43 44 * ftl/FTLLowerDFGToLLVM.cpp: 45 (JSC::FTL::DFG::LowerDFGToLLVM::lower): 46 (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul): 47 - Fixed a cut-paste bug where the op_mul IC was using the op_sub IC size. 48 This bug is benign because the op_sub IC size turns out to be larger 49 than op_mul needs. 50 (JSC::FTL::DFG::LowerDFGToLLVM::compileArithDiv): 51 52 * jit/JITArithmetic.cpp: 53 (JSC::JIT::emit_op_div): 54 - Fixed a bug where the scratchFPR was not allocated for the 64bit port. 55 This bug is benign because the scratchFPR is only needed if we are 56 using scratchGPR register (used for branchConvertDoubleToInt32()) is 57 >= X86Registers::r8. Since we're always using regT2 for the scratchT2, 58 the scratchFPR is never needed. However, we should fix this anyway to 59 be correct. 60 61 * tests/stress/op_div.js: 62 - Fixed some test values. 63 1 64 2015-12-05 Aleksandr Skachkov <gskachkov@gmail.com> 2 65 -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h ¶
r193766 r193781 673 673 typeOfDoubleQuotient( 674 674 forNode(node->child1()).m_type, forNode(node->child2()).m_type)); 675 break; 676 case UntypedUse: 677 clobberWorld(node->origin.semantic, clobberLimit); 678 forNode(node).setType(m_graph, SpecBytecodeNumber); 675 679 break; 676 680 default: -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGClobberize.h ¶
r193766 r193781 248 248 case ArithAdd: 249 249 case ArithNegate: 250 case ArithDiv:251 250 case ArithMod: 252 251 case DoubleAsInt32: … … 255 254 return; 256 255 256 case ArithDiv: 257 case ArithMul: 257 258 case ArithSub: 258 case ArithMul:259 259 switch (node->binaryUseKind()) { 260 260 case Int32Use: -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp ¶
r193766 r193781 266 266 case ArithDiv: 267 267 case ArithMod: { 268 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 268 Edge& leftChild = node->child1(); 269 Edge& rightChild = node->child2(); 270 if (op == ArithDiv 271 && (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node()) 272 || m_graph.hasExitSite(node->origin.semantic, BadType))) { 273 fixEdge<UntypedUse>(leftChild); 274 fixEdge<UntypedUse>(rightChild); 275 node->setResult(NodeResultJS); 276 break; 277 } 278 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(leftChild.node(), rightChild.node()) 269 279 && node->canSpeculateInt32(FixupPass)) { 270 280 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) { 271 fixIntOrBooleanEdge( node->child1());272 fixIntOrBooleanEdge( node->child2());281 fixIntOrBooleanEdge(leftChild); 282 fixIntOrBooleanEdge(rightChild); 273 283 if (bytecodeCanTruncateInteger(node->arithNodeFlags())) 274 284 node->setArithMode(Arith::Unchecked); … … 281 291 282 292 // This will cause conversion nodes to be inserted later. 283 fixDoubleOrBooleanEdge( node->child1());284 fixDoubleOrBooleanEdge( node->child2());293 fixDoubleOrBooleanEdge(leftChild); 294 fixDoubleOrBooleanEdge(rightChild); 285 295 286 296 // We don't need to do ref'ing on the children because we're stealing them from … … 298 308 break; 299 309 } 300 fixDoubleOrBooleanEdge( node->child1());301 fixDoubleOrBooleanEdge( node->child2());310 fixDoubleOrBooleanEdge(leftChild); 311 fixDoubleOrBooleanEdge(rightChild); 302 312 node->setResult(NodeResultDouble); 303 313 break; -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp ¶
r192993 r193781 201 201 } 202 202 203 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 204 { 205 VM* vm = &exec->vm(); 206 NativeCallFrameTracer tracer(vm, exec); 207 208 JSValue op1 = JSValue::decode(encodedOp1); 209 JSValue op2 = JSValue::decode(encodedOp2); 210 211 double a = op1.toNumber(exec); 212 double b = op2.toNumber(exec); 213 return JSValue::encode(jsNumber(a / b)); 214 } 215 203 216 EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) 204 217 { -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGOperations.h ¶
r192993 r193781 46 46 EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 47 47 EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 48 EncodedJSValue JIT_OPERATION operationValueDiv(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 48 49 EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; 49 50 EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL; -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp ¶
r193766 r193781 355 355 356 356 if (left && right) { 357 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 358 && node->canSpeculateInt32(m_pass)) 359 changed |= mergePrediction(SpecInt32); 360 else 361 changed |= mergePrediction(SpecBytecodeDouble); 357 if (isFullNumberOrBooleanSpeculationExpectingDefined(left) 358 && isFullNumberOrBooleanSpeculationExpectingDefined(right)) { 359 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) 360 && node->canSpeculateInt32(m_pass)) 361 changed |= mergePrediction(SpecInt32); 362 else 363 changed |= mergePrediction(SpecBytecodeDouble); 364 } else 365 changed |= mergePrediction(SpecInt32 | SpecBytecodeDouble); 362 366 } 363 367 break; -
TabularUnified trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp ¶
r193766 r193781 40 40 #include "DirectArguments.h" 41 41 #include "JITAddGenerator.h" 42 #include "JITDivGenerator.h" 42 43 #include "JITMulGenerator.h" 43 44 #include "JITSubGenerator.h" … … 3687 3688 break; 3688 3689 } 3689 3690 3691 case UntypedUse: { 3692 Edge& leftChild = node->child1(); 3693 Edge& rightChild = node->child2(); 3694 3695 if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) { 3696 JSValueOperand left(this, leftChild); 3697 JSValueOperand right(this, rightChild); 3698 JSValueRegs leftRegs = left.jsValueRegs(); 3699 JSValueRegs rightRegs = right.jsValueRegs(); 3700 #if USE(JSVALUE64) 3701 GPRTemporary result(this); 3702 JSValueRegs resultRegs = JSValueRegs(result.gpr()); 3703 #else 3704 GPRTemporary resultTag(this); 3705 GPRTemporary resultPayload(this); 3706 JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr()); 3707 #endif 3708 flushRegisters(); 3709 callOperation(operationValueDiv, resultRegs, leftRegs, rightRegs); 3710 m_jit.exceptionCheck(); 3711 3712 jsValueResult(resultRegs, node); 3713 return; 3714 } 3715 3716 Optional<JSValueOperand> left; 3717 Optional<JSValueOperand> right; 3718 3719 JSValueRegs leftRegs; 3720 JSValueRegs rightRegs; 3721 3722 FPRTemporary leftNumber(this); 3723 FPRTemporary rightNumber(this); 3724 FPRReg leftFPR = leftNumber.fpr(); 3725 FPRReg rightFPR = rightNumber.fpr(); 3726 FPRTemporary fprScratch(this); 3727 FPRReg scratchFPR = fprScratch.fpr(); 3728 3729 #if USE(JSVALUE64) 3730 GPRTemporary result(this); 3731 JSValueRegs resultRegs = JSValueRegs(result.gpr()); 3732 GPRTemporary scratch(this); 3733 GPRReg scratchGPR = scratch.gpr(); 3734 #else 3735 GPRTemporary resultTag(this); 3736 GPRTemporary resultPayload(this); 3737 JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr()); 3738 GPRReg scratchGPR = resultTag.gpr(); 3739 #endif 3740 3741 SnippetOperand leftOperand(m_state.forNode(leftChild).resultType()); 3742 SnippetOperand rightOperand(m_state.forNode(rightChild).resultType()); 3743 3744 if (leftChild->isInt32Constant()) 3745 leftOperand.setConstInt32(leftChild->asInt32()); 3746 #if USE(JSVALUE64) 3747 else if (leftChild->isDoubleConstant()) 3748 leftOperand.setConstDouble(leftChild->asNumber()); 3749 #endif 3750 3751 if (leftOperand.isConst()) { 3752 // The snippet generator only supports 1 argument as a constant. 3753 // Ignore the rightChild's const-ness. 3754 } else if (rightChild->isInt32Constant()) 3755 rightOperand.setConstInt32(rightChild->asInt32()); 3756 #if USE(JSVALUE64) 3757 else if (rightChild->isDoubleConstant()) 3758 rightOperand.setConstDouble(rightChild->asNumber()); 3759 #endif 3760 3761 RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); 3762 3763 if (!leftOperand.isConst()) { 3764 left = JSValueOperand(this, leftChild); 3765 leftRegs = left->jsValueRegs(); 3766 } 3767 if (!rightOperand.isConst()) { 3768 right = JSValueOperand(this, rightChild); 3769 rightRegs = right->jsValueRegs(); 3770 } 3771 3772 JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, 3773 leftFPR, rightFPR, scratchGPR, scratchFPR); 3774 gen.generateFastPath(m_jit); 3775 3776 ASSERT(gen.didEmitFastPath()); 3777 gen.endJumpList().append(m_jit.jump()); 3778 3779 gen.slowPathJumpList().link(&m_jit); 3780 silentSpillAllRegisters(resultRegs); 3781 3782 if (leftOperand.isConst()) { 3783 leftRegs = resultRegs; 3784 m_jit.moveValue(leftChild->asJSValue(), leftRegs); 3785 } 3786 if (rightOperand.isConst()) { 3787 rightRegs = resultRegs; 3788 m_jit.moveValue(rightChild->asJSValue(), rightRegs); 3789 } 3790 3791 callOperation(operationValueDiv, resultRegs, leftRegs, rightRegs); 3792 3793 silentFillAllRegisters(resultRegs); 3794 m_jit.exceptionCheck(); 3795 3796 gen.endJumpList().link(&m_jit); 3797 jsValueResult(resultRegs, node); 3798 return; 3799 } 3800 3690 3801 default: 3691 3802 RELEASE_ASSERT_NOT_REACHED(); -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp ¶
r192993 r193781 33 33 #include "GPRInfo.h" 34 34 #include "JITAddGenerator.h" 35 #include "JITDivGenerator.h" 35 36 #include "JITMulGenerator.h" 36 37 #include "JITSubGenerator.h" … … 154 155 }; 155 156 156 template<typename BinaryArithOpGenerator> 157 enum ScratchFPRUsage { 158 DontNeedScratchFPR, 159 NeedScratchFPR 160 }; 161 162 template<typename BinaryArithOpGenerator, ScratchFPRUsage scratchFPRUsage = DontNeedScratchFPR> 157 163 void generateBinaryArithOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit, 158 164 GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters, … … 167 173 FPRReg rightFPR = allocator.allocateScratchFPR(); 168 174 FPRReg scratchFPR = InvalidFPRReg; 175 if (scratchFPRUsage == NeedScratchFPR) 176 scratchFPR = allocator.allocateScratchFPR(); 169 177 170 178 BinaryArithOpGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result), … … 196 204 { 197 205 switch (ic.nodeType()) { 206 case ArithDiv: 207 generateBinaryArithOpFastPath<JITDivGenerator, NeedScratchFPR>(ic, jit, result, left, right, usedRegisters, done, slowPathStart); 208 break; 198 209 case ArithMul: 199 210 generateBinaryArithOpFastPath<JITMulGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart); -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h ¶
r192993 r193781 166 166 }; 167 167 168 class ArithDivDescriptor : public BinaryOpDescriptor { 169 public: 170 ArithDivDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand); 171 static size_t icSize(); 172 }; 173 168 174 class ArithMulDescriptor : public BinaryOpDescriptor { 169 175 public: -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h ¶
r192993 r193781 35 35 36 36 namespace JSC { namespace FTL { 37 38 ArithDivDescriptor::ArithDivDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, 39 const SnippetOperand& leftOperand, const SnippetOperand& rightOperand) 40 : BinaryOpDescriptor(DFG::ArithDiv, stackmapID, codeOrigin, icSize(), 41 "ArithDiv", "ArithDiv IC fast path", DFG::operationValueDiv, leftOperand, rightOperand) 42 { 43 } 44 45 size_t ArithDivDescriptor::icSize() 46 { 47 return sizeOfArithDiv(); 48 } 37 49 38 50 ArithMulDescriptor::ArithMulDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp ¶
r192993 r193781 126 126 #else 127 127 return 5; 128 #endif 129 } 130 131 size_t sizeOfArithDiv() 132 { 133 #if CPU(ARM64) 134 #ifdef NDEBUG 135 return 180; // ARM64 release. 136 #else 137 return 276; // ARM64 debug. 138 #endif 139 #else // CPU(X86_64) 140 #ifdef NDEBUG 141 return 199; // X86_64 release. 142 #else 143 return 286; // X86_64 debug. 144 #endif 128 145 #endif 129 146 } -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h ¶
r192993 r193781 47 47 size_t sizeOfConstructForwardVarargs(); 48 48 size_t sizeOfIn(); 49 size_t sizeOfArithDiv(); 49 50 size_t sizeOfArithMul(); 50 51 size_t sizeOfArithSub(); -
TabularUnified trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp ¶
r193766 r193781 241 241 break; 242 242 } 243 case ArithDiv: 243 244 case ArithMul: 244 245 case ArithSub: … … 1862 1863 StackmapArgumentList arguments; 1863 1864 arguments.append(m_out.constInt64(stackmapID)); 1864 arguments.append(m_out.constInt32(Arith SubDescriptor::icSize()));1865 arguments.append(m_out.constInt32(ArithMulDescriptor::icSize())); 1865 1866 arguments.append(constNull(m_out.ref8)); 1866 1867 arguments.append(m_out.constInt32(2)); … … 1944 1945 break; 1945 1946 } 1946 1947 1948 case UntypedUse: { 1949 Edge& leftChild = m_node->child1(); 1950 Edge& rightChild = m_node->child2(); 1951 1952 if (!(provenType(leftChild) & SpecFullNumber) || !(provenType(rightChild) & SpecFullNumber)) { 1953 setJSValue(vmCall(m_out.int64, m_out.operation(operationValueDiv), m_callFrame, 1954 lowJSValue(leftChild), lowJSValue(rightChild))); 1955 return; 1956 } 1957 1958 unsigned stackmapID = m_stackmapIDs++; 1959 1960 if (Options::verboseCompilation()) 1961 dataLog(" Emitting ArithDiv patchpoint with stackmap #", stackmapID, "\n"); 1962 1963 #if FTL_USES_B3 1964 CRASH(); 1965 #else 1966 LValue left = lowJSValue(leftChild); 1967 LValue right = lowJSValue(rightChild); 1968 1969 SnippetOperand leftOperand(abstractValue(leftChild).resultType()); 1970 SnippetOperand rightOperand(abstractValue(rightChild).resultType()); 1971 1972 if (leftChild->isInt32Constant()) 1973 leftOperand.setConstInt32(leftChild->asInt32()); 1974 #if USE(JSVALUE64) 1975 else if (leftChild->isDoubleConstant()) 1976 leftOperand.setConstDouble(leftChild->asNumber()); 1977 #endif 1978 1979 if (leftOperand.isConst()) { 1980 // The snippet generator only supports 1 argument as a constant. 1981 // Ignore the rightChild's const-ness. 1982 } else if (rightChild->isInt32Constant()) 1983 rightOperand.setConstInt32(rightChild->asInt32()); 1984 #if USE(JSVALUE64) 1985 else if (rightChild->isDoubleConstant()) 1986 rightOperand.setConstDouble(rightChild->asNumber()); 1987 #endif 1988 1989 RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); 1990 1991 // Arguments: id, bytes, target, numArgs, args... 1992 StackmapArgumentList arguments; 1993 arguments.append(m_out.constInt64(stackmapID)); 1994 arguments.append(m_out.constInt32(ArithDivDescriptor::icSize())); 1995 arguments.append(constNull(m_out.ref8)); 1996 arguments.append(m_out.constInt32(2)); 1997 arguments.append(left); 1998 arguments.append(right); 1999 2000 appendOSRExitArgumentsForPatchpointIfWillCatchException(arguments, 2001 ExceptionType::BinaryOpGenerator, 3); // left, right, and result show up in the stackmap locations. 2002 2003 LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments); 2004 setInstructionCallingConvention(call, LLVMAnyRegCallConv); 2005 2006 m_ftlState.binaryOps.append(ArithDivDescriptor(stackmapID, m_node->origin.semantic, leftOperand, rightOperand)); 2007 2008 setJSValue(call); 2009 #endif // FTL_USES_B3 2010 break; 2011 } 2012 1947 2013 default: 1948 2014 DFG_CRASH(m_graph, m_node, "Bad use kind"); -
TabularUnified trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp ¶
r193633 r193781 800 800 JSValueRegs resultRegs = leftRegs; 801 801 GPRReg scratchGPR = regT2; 802 FPRReg scratchFPR = InvalidFPRReg;803 802 #else 804 803 JSValueRegs leftRegs = JSValueRegs(regT1, regT0); … … 806 805 JSValueRegs resultRegs = leftRegs; 807 806 GPRReg scratchGPR = regT4; 807 #endif 808 808 FPRReg scratchFPR = fpRegT2; 809 #endif810 809 811 810 uint32_t* profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter; -
TabularUnified trunk/Source/JavaScriptCore/tests/stress/op_div.js ¶
r192795 r193781 44 44 '0x10000', 45 45 '-0x10000', 46 '0x7ffffff ',47 '-0x7ffffff ',46 '0x7fffffff', 47 '-0x7fffffff', 48 48 '0x100000000', 49 49 '-0x100000000', … … 60 60 '"0x10000"', 61 61 '"-0x10000"', 62 '"0x7ffffff "',63 '"-0x7ffffff "',62 '"0x7fffffff"', 63 '"-0x7fffffff"', 64 64 '"0x100000000"', 65 65 '"-0x100000000"',
Note:
See TracChangeset
for help on using the changeset viewer.