WebKit Bugzilla
Attachment 356984 Details for
Bug 186175
: [BigInt] Add ValueMul into DFG
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186175-20181210184234.patch (text/plain), 35.48 KB, created by
Caio Lima
on 2018-12-10 12:42:37 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-12-10 12:42:37 PST
Size:
35.48 KB
patch
obsolete
>Subversion Revision: 239035 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 8fef43acb605a59b1112f8305ea99033543ad43b..1c7995865f6dfd00fa230c6d7b18ea523111cbe6 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,58 @@ >+2018-12-10 Caio Lima <ticaiolima@gmail.com> >+ >+ [BigInt] Add ValueMul into DFG >+ https://bugs.webkit.org/show_bug.cgi?id=186175 >+ >+ Reviewed by Yusuke Suzuki. >+ >+ This patch is adding a new DFG node called ValueMul. This node is >+ responsible to handle multiplication operations that can result into >+ non-number values. We emit such node during DFGByteCodeParser when the >+ operands are not numbers. During FixupPhase, we change this >+ operation to ArithMul if we can speculate Number/Boolean operands. >+ >+ The BigInt specialization shows a small progression: >+ >+ noSpec changes >+ >+ big-int-simple-mul 18.8090+-1.0435 ^ 17.4305+-0.2673 ^ definitely 1.0791x faster >+ >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * dfg/DFGBackwardsPropagationPhase.cpp: >+ (JSC::DFG::BackwardsPropagationPhase::propagate): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::makeSafe): >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGDoesGC.cpp: >+ (JSC::DFG::doesGC): >+ * dfg/DFGFixupPhase.cpp: >+ (JSC::DFG::FixupPhase::fixupMultiplication): >+ (JSC::DFG::FixupPhase::fixupNode): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::arithNodeFlags): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGOperations.cpp: >+ * dfg/DFGOperations.h: >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileValueMul): >+ (JSC::DFG::SpeculativeJIT::compileArithMul): >+ * dfg/DFGSpeculativeJIT.h: >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGValidate.cpp: >+ * ftl/FTLCapabilities.cpp: >+ (JSC::FTL::canCompile): >+ * ftl/FTLLowerDFGToB3.cpp: >+ (JSC::FTL::DFG::LowerDFGToB3::compileNode): >+ (JSC::FTL::DFG::LowerDFGToB3::compileValueMul): >+ (JSC::FTL::DFG::LowerDFGToB3::compileArithMul): >+ > 2018-12-08 Mark Lam <mark.lam@apple.com> > > Reduce size of PropertySlot and PutPropertySlot. >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index 25144b5b14240c7db2ce8716b79b9bfac38b547e..c8f66dde246ac8dcc5736cc65466ba812932b963 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -854,6 +854,15 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > break; > } > >+ case ValueMul: { >+ clobberWorld(); >+ if (node->binaryUseKind() == BigIntUse) >+ setTypeForNode(node, SpecBigInt); >+ else >+ setTypeForNode(node, SpecBytecodeNumber | SpecBigInt); >+ break; >+ } >+ > case ArithMul: { > JSValue left = forNode(node->child1()).value(); > JSValue right = forNode(node->child2()).value(); >@@ -897,10 +906,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > typeOfDoubleProduct( > forNode(node->child1()).m_type, forNode(node->child2()).m_type)); > break; >- case UntypedUse: >- clobberWorld(); >- setNonCellTypeForNode(node, SpecBytecodeNumber); >- break; > default: > RELEASE_ASSERT_NOT_REACHED(); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp >index d06906a162de9bc8f747f967cd3b13c8a4e43410..2d8c514d8f834f4b09ba7812f6af04b5d73c9642 100644 >--- a/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp >@@ -269,7 +269,7 @@ private: > case ValueAdd: { > if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node())) > flags &= ~NodeBytecodeNeedsNegZero; >- if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult()) >+ if (node->child1()->hasNumericResult() || node->child2()->hasNumericResult() || node->child1()->hasNumberResult() || node->child2()->hasNumberResult()) > flags &= ~NodeBytecodeUsesAsOther; > if (!isWithinPowerOfTwo<32>(node->child1()) && !isWithinPowerOfTwo<32>(node->child2())) > flags |= NodeBytecodeUsesAsNumber; >@@ -323,6 +323,7 @@ private: > break; > } > >+ case ValueMul: > case ArithMul: { > // As soon as a multiply happens, we can easily end up in the part > // of the double domain where the point at which you do truncation >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index 71fc92b19449ab2f7f7c4120f832ca2e2856ba76..aa23167327c6de6814614a2a314b5b7a2f03d0b8 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -947,6 +947,7 @@ private: > node->mergeFlags(NodeMayHaveBigIntResult); > break; > >+ case ValueMul: > case ArithMul: { > if (arithProfile->didObserveInt52Overflow()) > node->mergeFlags(NodeMayOverflowInt52); >@@ -958,6 +959,8 @@ private: > node->mergeFlags(NodeMayHaveDoubleResult); > if (arithProfile->didObserveNonNumeric()) > node->mergeFlags(NodeMayHaveNonNumericResult); >+ if (arithProfile->didObserveBigInt()) >+ node->mergeFlags(NodeMayHaveBigIntResult); > break; > } > case ValueNegate: >@@ -5017,7 +5020,10 @@ void ByteCodeParser::parseBlock(unsigned limit) > auto bytecode = currentInstruction->as<OpMul>(); > Node* op1 = get(bytecode.lhs); > Node* op2 = get(bytecode.rhs); >- set(bytecode.dst, makeSafe(addToGraph(ArithMul, op1, op2))); >+ if (op1->hasNumberResult() && op2->hasNumberResult()) >+ set(bytecode.dst, makeSafe(addToGraph(ArithMul, op1, op2))); >+ else >+ set(bytecode.dst, makeSafe(addToGraph(ValueMul, op1, op2))); > NEXT_OPCODE(op_mul); > } > >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index 788eecc3c3bad1d915ba857f63a7578256705a0c..95404f3f920dd99d6311875feb82a9ba393b2b64 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -650,6 +650,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu > case ValueNegate: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case SetFunctionName: > case GetDynamicVar: > case PutDynamicVar: >diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >index 6aa263cfa2a40a973ea229d83fa4215b9decabd1..64e2f5efecad64b3013d4189e2849cb153498f69 100644 >--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >@@ -102,6 +102,7 @@ bool doesGC(Graph& graph, Node* node) > case ValueBitXor: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case ValueNegate: > case TryGetById: > case GetById: >diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >index 964e5bc65998d14c5bfdfb9edf0de6dfeb7ce9b8..5b0de12fa5067183c6b886f11fc0cb04980cb91c 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -76,6 +76,35 @@ public: > } > > private: >+ void fixupArithMul(Node* node, Edge& leftChild, Edge& rightChild) >+ { >+ if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) { >+ fixIntOrBooleanEdge(leftChild); >+ fixIntOrBooleanEdge(rightChild); >+ if (bytecodeCanTruncateInteger(node->arithNodeFlags())) >+ node->setArithMode(Arith::Unchecked); >+ else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node()) >+ node->setArithMode(Arith::CheckOverflow); >+ else >+ node->setArithMode(Arith::CheckOverflowAndNegativeZero); >+ return; >+ } >+ if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) { >+ fixEdge<Int52RepUse>(leftChild); >+ fixEdge<Int52RepUse>(rightChild); >+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node()) >+ node->setArithMode(Arith::CheckOverflow); >+ else >+ node->setArithMode(Arith::CheckOverflowAndNegativeZero); >+ node->setResult(NodeResultInt52); >+ return; >+ } >+ >+ fixDoubleOrBooleanEdge(leftChild); >+ fixDoubleOrBooleanEdge(rightChild); >+ node->setResult(NodeResultDouble); >+ } >+ > void fixupBlock(BasicBlock* block) > { > if (!block) >@@ -383,42 +412,45 @@ private: > node->clearFlags(NodeMustGenerate); > break; > } >- >- case ArithMul: { >+ >+ case ValueMul: { > Edge& leftChild = node->child1(); > Edge& rightChild = node->child2(); >+ >+ if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) { >+ fixEdge<BigIntUse>(node->child1()); >+ fixEdge<BigIntUse>(node->child2()); >+ break; >+ } >+ >+ // There are cases where we can have BigInt + Int32 operands reaching ValueMul. >+ // Imagine the scenario where ValueMul was never executed, but we can predict types >+ // reaching the node: >+ // >+ // 63: GetLocal(Check:Untyped:@72, JS|MustGen, NonBoolInt32, ...) predicting NonBoolInt32 >+ // 64: GetLocal(Check:Untyped:@71, JS|MustGen, BigInt, ...) predicting BigInt >+ // 65: ValueMul(Check:Untyped:@63, Check:Untyped:@64, BigInt|BoolInt32|NonBoolInt32, ...) >+ // >+ // In such scenario, we need to emit ValueMul(Untyped, Untyped), so the runtime can throw >+ // an exception whenever it gets excuted. > if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) { > fixEdge<UntypedUse>(leftChild); > fixEdge<UntypedUse>(rightChild); >- node->setResult(NodeResultJS); > break; > } >- if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) { >- fixIntOrBooleanEdge(leftChild); >- fixIntOrBooleanEdge(rightChild); >- if (bytecodeCanTruncateInteger(node->arithNodeFlags())) >- node->setArithMode(Arith::Unchecked); >- else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) >- || leftChild.node() == rightChild.node()) >- node->setArithMode(Arith::CheckOverflow); >- else >- node->setArithMode(Arith::CheckOverflowAndNegativeZero); >- break; >- } >- if (m_graph.binaryArithShouldSpeculateAnyInt(node, FixupPass)) { >- fixEdge<Int52RepUse>(leftChild); >- fixEdge<Int52RepUse>(rightChild); >- if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) >- || leftChild.node() == rightChild.node()) >- node->setArithMode(Arith::CheckOverflow); >- else >- node->setArithMode(Arith::CheckOverflowAndNegativeZero); >- node->setResult(NodeResultInt52); >- break; >- } >- fixDoubleOrBooleanEdge(leftChild); >- fixDoubleOrBooleanEdge(rightChild); >- node->setResult(NodeResultDouble); >+ >+ // At this point, all other possible specializations are only handled by ArithMul. >+ node->setOp(ArithMul); >+ node->setResult(NodeResultNumber); >+ fixupArithMul(node, leftChild, rightChild); >+ break; >+ } >+ >+ case ArithMul: { >+ Edge& leftChild = node->child1(); >+ Edge& rightChild = node->child2(); >+ >+ fixupArithMul(node, leftChild, rightChild); > break; > } > >diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h >index 9952806583e727dd7f583578896a4947b6837b16..5aa83a98404eaea47315aed7013d4739bbe774a7 100644 >--- a/Source/JavaScriptCore/dfg/DFGNode.h >+++ b/Source/JavaScriptCore/dfg/DFGNode.h >@@ -1124,12 +1124,13 @@ public: > PromotedLocationDescriptor promotedLocationDescriptor(); > > // This corrects the arithmetic node flags, so that irrelevant bits are >- // ignored. In particular, anything other than ArithMul does not need >+ // ignored. In particular, anything other than ArithMul or ValueMul does not need > // to know if it can speculate on negative zero. > NodeFlags arithNodeFlags() > { > NodeFlags result = m_flags & NodeArithFlagsMask; >- if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32 || op() == ValueNegate) >+ if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32 || op() == ValueNegate >+ || op() == ValueMul) > return result; > return result & ~NodeBytecodeNeedsNegZero; > } >@@ -1371,6 +1372,21 @@ public: > return result() == NodeResultNumber; > } > >+ bool hasNumericResult() >+ { >+ switch (op()) { >+ case ValueSub: >+ case ValueMul: >+ case ValueBitAnd: >+ case ValueBitOr: >+ case ValueBitXor: >+ case ValueNegate: >+ return true; >+ default: >+ return false; >+ } >+ } >+ > bool hasDoubleResult() > { > return result() == NodeResultDouble; >diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h >index 509fcc9043a695d8f9f907f6490a53aab6c1b36f..40f62645769f191f17bf6bfe1b831b1cabf77b19 100644 >--- a/Source/JavaScriptCore/dfg/DFGNodeType.h >+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h >@@ -174,6 +174,7 @@ namespace JSC { namespace DFG { > macro(ValueAdd, NodeResultJS | NodeMustGenerate) \ > \ > macro(ValueSub, NodeResultJS | NodeMustGenerate) \ >+ macro(ValueMul, NodeResultJS | NodeMustGenerate) \ > \ > /* Add of values that always convers its inputs to strings. May have two or three kids. */\ > macro(StrCat, NodeResultJS | NodeMustGenerate) \ >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index 3f1f494a56a300105024a00d278fdd3cad2e27bf..be992af6f638f396687b22f84d6aa30f09fbd818 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -1322,6 +1322,17 @@ JSCell* JIT_OPERATION operationSubBigInt(ExecState* exec, JSCell* op1, JSCell* o > return JSBigInt::sub(exec, leftOperand, rightOperand); > } > >+JSCell* JIT_OPERATION operationMulBigInt(ExecState* exec, JSCell* op1, JSCell* op2) >+{ >+ VM* vm = &exec->vm(); >+ NativeCallFrameTracer tracer(vm, exec); >+ >+ JSBigInt* leftOperand = jsCast<JSBigInt*>(op1); >+ JSBigInt* rightOperand = jsCast<JSBigInt*>(op2); >+ >+ return JSBigInt::multiply(exec, leftOperand, rightOperand); >+} >+ > JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell* op2) > { > VM* vm = &exec->vm(); >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h >index 512ac11153c8ff522cf62671551b9968df40c44e..e455609a1f599eceea0186b3f6dbeb1a618bef41 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.h >+++ b/Source/JavaScriptCore/dfg/DFGOperations.h >@@ -165,6 +165,7 @@ size_t JIT_OPERATION operationRegExpTest(ExecState*, JSGlobalObject*, RegExpObje > size_t JIT_OPERATION operationRegExpTestGeneric(ExecState*, JSGlobalObject*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL; > size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; >+JSCell* JIT_OPERATION operationMulBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationAddBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; >diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >index f8209fb048c0bcc1ea0cb23c2c1556e6f09a9283..e8299eb873c5061abb4a45f0dc1b17d239025a30 100644 >--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >@@ -320,6 +320,7 @@ private: > break; > } > >+ case ValueMul: > case ArithMul: { > SpeculatedType left = node->child1()->prediction(); > SpeculatedType right = node->child2()->prediction(); >@@ -337,13 +338,18 @@ private: > changed |= mergePrediction(SpecInt52Only); > else > changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); >- } else { >- if (node->mayHaveNonIntResult() >+ } else if (op == ValueMul && isBigIntSpeculation(left) && isBigIntSpeculation(right)) >+ changed |= mergePrediction(SpecBigInt); >+ else { >+ changed |= mergePrediction(SpecInt32Only); >+ if (node->mayHaveDoubleResult() > || (left & SpecBytecodeDouble) > || (right & SpecBytecodeDouble)) >- changed |= mergePrediction(SpecInt32Only | SpecBytecodeDouble); >- else >- changed |= mergePrediction(SpecInt32Only); >+ changed |= mergePrediction(SpecBytecodeDouble); >+ if ((op == ValueMul && node->mayHaveBigIntResult()) >+ || (left & SpecBigInt) >+ || (right & SpecBigInt)) >+ changed |= mergePrediction(SpecBigInt); > } > } > break; >@@ -571,6 +577,7 @@ private: > break; > } > >+ case ValueMul: > case ArithMul: { > SpeculatedType left = node->child1()->prediction(); > SpeculatedType right = node->child2()->prediction(); >@@ -1101,6 +1108,7 @@ private: > case ValueNegate: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case ArithAdd: > case ArithSub: > case ArithNegate: >diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >index b43b7dfda9e779fd222eec3ef505d06fbd992d0e..07cf01f38eb6ef13a3a2c4d06f85e5d73aa804a0 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -233,6 +233,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno > case ValueNegate: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case TryGetById: > case DeleteById: > case DeleteByVal: >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index 2cda06dd6e37771551ddeacc161c9f25e7375893..465bf3fb0fd87c4a08e5f5d96fa98f3338a4ab62 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -4778,6 +4778,63 @@ void SpeculativeJIT::compileMathIC(Node* node, JITUnaryMathIC<Generator>* mathIC > return; > } > >+void SpeculativeJIT::compileValueMul(Node* node) >+{ >+ Edge& leftChild = node->child1(); >+ Edge& rightChild = node->child2(); >+ >+ if (leftChild.useKind() == BigIntUse && rightChild.useKind() == BigIntUse) { >+ SpeculateCellOperand left(this, leftChild); >+ SpeculateCellOperand right(this, rightChild); >+ GPRReg leftGPR = left.gpr(); >+ GPRReg rightGPR = right.gpr(); >+ >+ speculateBigInt(leftChild, leftGPR); >+ speculateBigInt(rightChild, rightGPR); >+ >+ flushRegisters(); >+ GPRFlushedCallResult result(this); >+ GPRReg resultGPR = result.gpr(); >+ >+ callOperation(operationMulBigInt, resultGPR, leftGPR, rightGPR); >+ >+ m_jit.exceptionCheck(); >+ cellResult(resultGPR, node); >+ return; >+ } >+ >+ if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) { >+ JSValueOperand left(this, leftChild); >+ JSValueOperand right(this, rightChild); >+ JSValueRegs leftRegs = left.jsValueRegs(); >+ JSValueRegs rightRegs = right.jsValueRegs(); >+ >+ flushRegisters(); >+ JSValueRegsFlushedCallResult result(this); >+ JSValueRegs resultRegs = result.regs(); >+ callOperation(operationValueMul, resultRegs, leftRegs, rightRegs); >+ m_jit.exceptionCheck(); >+ >+ jsValueResult(resultRegs, node); >+ return; >+ } >+ >+ bool needsScratchGPRReg = true; >+#if USE(JSVALUE64) >+ bool needsScratchFPRReg = false; >+#else >+ bool needsScratchFPRReg = true; >+#endif >+ >+ CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic); >+ ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); >+ const Instruction* instruction = baselineCodeBlock->instructions().at(node->origin.semantic.bytecodeIndex).ptr(); >+ JITMulIC* mulIC = m_jit.codeBlock()->addJITMulIC(arithProfile, instruction); >+ auto repatchingFunction = operationValueMulOptimize; >+ auto nonRepatchingFunction = operationValueMul; >+ >+ compileMathIC(node, mulIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction); >+} > > void SpeculativeJIT::compileArithMul(Node* node) > { >@@ -4917,45 +4974,6 @@ void SpeculativeJIT::compileArithMul(Node* node) > return; > } > >- case UntypedUse: { >- Edge& leftChild = node->child1(); >- Edge& rightChild = node->child2(); >- >- if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) { >- JSValueOperand left(this, leftChild); >- JSValueOperand right(this, rightChild); >- JSValueRegs leftRegs = left.jsValueRegs(); >- JSValueRegs rightRegs = right.jsValueRegs(); >- >- flushRegisters(); >- JSValueRegsFlushedCallResult result(this); >- JSValueRegs resultRegs = result.regs(); >- callOperation(operationValueMul, resultRegs, leftRegs, rightRegs); >- m_jit.exceptionCheck(); >- >- jsValueResult(resultRegs, node); >- return; >- } >- >-#if USE(JSVALUE64) >- bool needsScratchGPRReg = true; >- bool needsScratchFPRReg = false; >-#else >- bool needsScratchGPRReg = true; >- bool needsScratchFPRReg = true; >-#endif >- >- CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic); >- ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); >- const Instruction* instruction = baselineCodeBlock->instructions().at(node->origin.semantic.bytecodeIndex).ptr(); >- JITMulIC* mulIC = m_jit.codeBlock()->addJITMulIC(arithProfile, instruction); >- auto repatchingFunction = operationValueMulOptimize; >- auto nonRepatchingFunction = operationValueMul; >- >- compileMathIC(node, mulIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction); >- return; >- } >- > default: > RELEASE_ASSERT_NOT_REACHED(); > return; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >index adb3ba1c8e17c0a435c772f0fb40c3837074571f..a20e39a83afe8cbb2929271d3ce25afe33e7ea87 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -1354,6 +1354,7 @@ public: > void compileArithSub(Node*); > void compileValueNegate(Node*); > void compileArithNegate(Node*); >+ void compileValueMul(Node*); > void compileArithMul(Node*); > void compileArithDiv(Node*); > void compileArithFRound(Node*); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >index ce3e26635248959b19df566c8ee125838d758d5a..bcf7c72488e87650af6bcf42ab57fcc17325893b 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >@@ -2067,6 +2067,10 @@ void SpeculativeJIT::compile(Node* node) > compileArithMul(node); > break; > >+ case ValueMul: >+ compileValueMul(node); >+ break; >+ > case ArithDiv: { > compileArithDiv(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >index fb161a72b54074f15abadbfc755356d20380558e..066274490093fec2b0f2f886372adc041d058782 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >@@ -2209,6 +2209,10 @@ void SpeculativeJIT::compile(Node* node) > compileArithMul(node); > break; > >+ case ValueMul: >+ compileValueMul(node); >+ break; >+ > case ArithDiv: { > compileArithDiv(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGValidate.cpp b/Source/JavaScriptCore/dfg/DFGValidate.cpp >index 5382f8a2cea70091c185d427b193a02a7d86ec76..6677ee54baf9ec75f660e0fd963eac1bc35c67c7 100644 >--- a/Source/JavaScriptCore/dfg/DFGValidate.cpp >+++ b/Source/JavaScriptCore/dfg/DFGValidate.cpp >@@ -255,6 +255,7 @@ public: > case MakeRope: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case ArithAdd: > case ArithSub: > case ArithMul: >diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >index da113812e17e1d0b044ad28c86ab8f8e74b78b9f..0a3569fe8876545768bc6c6e688ad1bc448a6af5 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -93,6 +93,7 @@ inline CapabilityLevel canCompile(Node* node) > case ValueNegate: > case ValueAdd: > case ValueSub: >+ case ValueMul: > case StrCat: > case ArithAdd: > case ArithClz32: >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index fb0439732c43a4b3d4cb5afa3a5deca3910ea945..0823fc8f78058daf34b59081d73cc7af3173ba9c 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -597,6 +597,9 @@ private: > case ValueSub: > compileValueSub(); > break; >+ case ValueMul: >+ compileValueMul(); >+ break; > case StrCat: > compileStrCat(); > break; >@@ -1904,6 +1907,25 @@ private: > compileBinaryMathIC<JITSubGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction); > } > >+ void compileValueMul() >+ { >+ if (m_node->isBinaryUseKind(BigIntUse)) { >+ LValue left = lowBigInt(m_node->child1()); >+ LValue right = lowBigInt(m_node->child2()); >+ >+ LValue result = vmCall(Int64, m_out.operation(operationMulBigInt), m_callFrame, left, right); >+ setJSValue(result); >+ return; >+ } >+ >+ CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic); >+ ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex); >+ const Instruction* instruction = baselineCodeBlock->instructions().at(m_node->origin.semantic.bytecodeIndex).ptr(); >+ auto repatchingFunction = operationValueMulOptimize; >+ auto nonRepatchingFunction = operationValueMul; >+ compileBinaryMathIC<JITMulGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction); >+ } >+ > template <typename Generator, typename Func1, typename Func2, > typename = std::enable_if_t<std::is_function<typename std::remove_pointer<Func1>::type>::value && std::is_function<typename std::remove_pointer<Func2>::type>::value>> > void compileUnaryMathIC(ArithProfile* arithProfile, const Instruction* instruction, Func1 repatchingFunction, Func2 nonRepatchingFunction) >@@ -2252,16 +2274,6 @@ private: > break; > } > >- case UntypedUse: { >- CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic); >- ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex); >- const Instruction* instruction = baselineCodeBlock->instructions().at(m_node->origin.semantic.bytecodeIndex).ptr(); >- auto repatchingFunction = operationValueMulOptimize; >- auto nonRepatchingFunction = operationValueMul; >- compileBinaryMathIC<JITMulGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction); >- break; >- } >- > default: > DFG_CRASH(m_graph, m_node, "Bad use kind"); > break; >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index fcf0b8e7f3e55b6785368133f1d167f739d458e5..caa0a568b3c4c1044ddd90d5fc1168a932f56482 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-12-10 Caio Lima <ticaiolima@gmail.com> >+ >+ [BigInt] Add ValueMul into DFG >+ https://bugs.webkit.org/show_bug.cgi?id=186175 >+ >+ Reviewed by Yusuke Suzuki. >+ >+ * stress/big-int-mul-jit-osr.js: Added. >+ * stress/big-int-mul-jit-untyped.js: Added. >+ * stress/value-mul-fixup-int32-big-int.js: Added. >+ > 2018-12-06 Keith Miller <keith_miller@apple.com> > > stress/big-wasm-memory tests failing on 32-bit JSC bot >diff --git a/JSTests/stress/big-int-mul-jit-osr.js b/JSTests/stress/big-int-mul-jit-osr.js >new file mode 100644 >index 0000000000000000000000000000000000000000..e7631e54014dd68db3e19a8a498ea6773be89fb3 >--- /dev/null >+++ b/JSTests/stress/big-int-mul-jit-osr.js >@@ -0,0 +1,25 @@ >+//@ runBigIntEnabled >+ >+let assert = { >+ sameValue: function(i, e, m) { >+ if (i !== e) >+ throw new Error(m); >+ } >+} >+ >+function bigIntMul(x, y) { >+ return x * y; >+} >+noInline(bigIntMul); >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntMul(3n, 10n); >+ assert.sameValue(r, 30n, 3n + " * " + 10n + " = " + r); >+} >+ >+let r = bigIntMul(3, 10); >+assert.sameValue(r, 30, 3 + " * " + 10 + " = " + r); >+ >+r = bigIntMul("3", "10"); >+assert.sameValue(r, 30, 3 + " * " + 10 + " = " + r); >+ >diff --git a/JSTests/stress/big-int-mul-jit-untyped.js b/JSTests/stress/big-int-mul-jit-untyped.js >new file mode 100644 >index 0000000000000000000000000000000000000000..5ed64bca39d5c687d6d21c9472da549b7b0f5e18 >--- /dev/null >+++ b/JSTests/stress/big-int-mul-jit-untyped.js >@@ -0,0 +1,36 @@ >+//@ runBigIntEnabled >+ >+let assert = { >+ sameValue: function(i, e, m) { >+ if (i !== e) >+ throw new Error(m); >+ } >+} >+ >+function bigIntMul(x, y) { >+ return x * y; >+} >+noInline(bigIntMul); >+ >+let o = {valueOf: () => 10n}; >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntMul(3n, o); >+ assert.sameValue(r, 30n, 3n + " * {valueOf: () => 10n} = " + r); >+} >+ >+o2 = {valueOf: () => 10000n}; >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntMul(o2, o); >+ assert.sameValue(r, 100000n, "{valueOf: () => 10000n} * {valueOf: () => 10n} = " + r); >+} >+ >+o = Object(10n); >+let r = bigIntMul(3n, o); >+assert.sameValue(r, 30n, 3n + " * Object(10n) = " + r); >+ >+o2 = Object(3241n); >+r = bigIntMul(o2, o); >+assert.sameValue(r, 32410n, "Object(32410n) * Object(10n) = " + r); >+ >diff --git a/JSTests/stress/value-mul-fixup-int32-big-int.js b/JSTests/stress/value-mul-fixup-int32-big-int.js >new file mode 100644 >index 0000000000000000000000000000000000000000..a598833705353e8febbe777b0150a7c2c9bb3d18 >--- /dev/null >+++ b/JSTests/stress/value-mul-fixup-int32-big-int.js >@@ -0,0 +1,29 @@ >+//@ runBigIntEnabled >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Bad!"); >+} >+ >+function foo() { >+ let c; >+ do { >+ >+ let a = 2; >+ let b = 3n; >+ for (let i = 0; i < 10000; i++) { >+ c = i; >+ } >+ >+ c = a * b; >+ } while(true); >+ >+ return c; >+} >+ >+try { >+ foo(); >+} catch(e) { >+ assert(e instanceof TypeError, true); >+} >+ >diff --git a/PerformanceTests/BigIntBench/big-int-simple-mul.js b/PerformanceTests/BigIntBench/big-int-simple-mul.js >new file mode 100644 >index 0000000000000000000000000000000000000000..1380f884ca9184208768dfe18d792994fdcc550c >--- /dev/null >+++ b/PerformanceTests/BigIntBench/big-int-simple-mul.js >@@ -0,0 +1,15 @@ >+function bigInt(a, b) { >+ let c = a * b; >+ return a * c - b; >+} >+noInline(bigInt); >+ >+for (let i = 0; i < 100000; i++) { >+ bigInt(0b1111n, 0b1010n); >+} >+ >+let out; >+for (let i = 0; i < 100000; i++) { >+ out = bigInt(0xffffffffffffffffffn, 0xaaffffffffffffffffffn); >+} >+ >diff --git a/PerformanceTests/BigIntBench/value-mul-type-propagation.js b/PerformanceTests/BigIntBench/value-mul-type-propagation.js >new file mode 100644 >index 0000000000000000000000000000000000000000..9864044031306adf2bf367e45e73d4dcd61d7558 >--- /dev/null >+++ b/PerformanceTests/BigIntBench/value-mul-type-propagation.js >@@ -0,0 +1,39 @@ >+//@ runBigIntEnabled >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Bad!"); >+} >+ >+function foo(o) { >+ let c; >+ do { >+ >+ let a = 2 * o; >+ o.bigInt = true; >+ let b = 1n * o; >+ for (let i = 0; i < 10000; i++) { >+ c = i; >+ } >+ >+ let d = b * o; >+ c = a * d; >+ } while(false); >+} >+noInline(foo); >+ >+let o = { >+ valueOf: function () { >+ return this.bigInt ? 2n : 2; >+ } >+} >+ >+for (let i = 0; i < 1000; i++) { >+ try { >+ o.bigInt = false; >+ foo(o); >+ } catch(e) { >+ assert(e instanceof TypeError, true); >+ } >+} >+ >diff --git a/PerformanceTests/ChangeLog b/PerformanceTests/ChangeLog >index 5d89525740e97c16feb154087968a42952d1a14c..3b3186bc1e2d07cd66ba1c38936f16ec80a62e55 100644 >--- a/PerformanceTests/ChangeLog >+++ b/PerformanceTests/ChangeLog >@@ -1,3 +1,13 @@ >+2018-12-10 Caio Lima <ticaiolima@gmail.com> >+ >+ [BigInt] Add ValueMul into DFG >+ https://bugs.webkit.org/show_bug.cgi?id=186175 >+ >+ Reviewed by Yusuke Suzuki. >+ >+ * BigIntBench/big-int-simple-mul.js: Added. >+ * BigIntBench/value-mul-type-propagation.js: Added. >+ > 2018-11-07 Caio Lima <ticaiolima@gmail.com> > > [BigInt] Add support to BigInt into ValueAdd
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186175
:
355348
|
355948
|
356002
|
356551
|
356590
|
356725
|
356873
|
356979
|
356981
| 356984