WebKit Bugzilla
Attachment 357227 Details for
Bug 182216
: [ESNext][BigInt] Implement "~" unary operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-182216-20181213121009.patch (text/plain), 25.83 KB, created by
Caio Lima
on 2018-12-13 06:10:11 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-12-13 06:10:11 PST
Size:
25.83 KB
patch
obsolete
>Subversion Revision: 239159 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 75aa37446fb7bbe4281f1aaf02984bc1c2b13a7a..caa20f91e871963cfb77c5590ffa2fc180fcf267 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,52 @@ >+2018-12-13 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement "~" unary operation >+ https://bugs.webkit.org/show_bug.cgi?id=182216 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This Patch is adding support of BigInt into op_bitnot operations. In >+ addition, we are changing ArithBitNot to handle only Number operands, >+ while introducing a new node named ValueBitNot to handle Untyped and >+ BigInt. This node follows the same approach we are doing into other >+ arithimetic operations into DFG. >+ >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * dfg/DFGByteCodeParser.cpp: >+ (JSC::DFG::ByteCodeParser::parseBlock): >+ * dfg/DFGClobberize.h: >+ (JSC::DFG::clobberize): >+ * dfg/DFGDoesGC.cpp: >+ (JSC::DFG::doesGC): >+ * dfg/DFGFixupPhase.cpp: >+ (JSC::DFG::FixupPhase::fixupNode): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGOperations.cpp: >+ * dfg/DFGOperations.h: >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileValueBitNot): >+ (JSC::DFG::SpeculativeJIT::compileBitwiseNot): >+ * dfg/DFGSpeculativeJIT.h: >+ * dfg/DFGSpeculativeJIT32_64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * dfg/DFGSpeculativeJIT64.cpp: >+ (JSC::DFG::SpeculativeJIT::compile): >+ * ftl/FTLCapabilities.cpp: >+ (JSC::FTL::canCompile): >+ * ftl/FTLLowerDFGToB3.cpp: >+ (JSC::FTL::DFG::LowerDFGToB3::compileNode): >+ (JSC::FTL::DFG::LowerDFGToB3::compileValueBitNot): >+ (JSC::FTL::DFG::LowerDFGToB3::compileArithBitNot): >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::SLOW_PATH_DECL): >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::bitwiseNot): >+ * runtime/JSBigInt.h: >+ > 2018-12-13 Caio Lima <ticaiolima@gmail.com> > > [BigInt] Add ValueDiv into DFG >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index 3bff948719c448ead2840023588a5a64321233f2..777502dc85842be39faeee868d894f6cbb947978 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -376,13 +376,24 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > break; > } > >- case ArithBitNot: { >- if (node->child1().useKind() == UntypedUse) { >- clobberWorld(); >- setNonCellTypeForNode(node, SpecInt32Only); >+ case ValueBitNot: { >+ JSValue operand = forNode(node->child1()).value(); >+ if (operand && operand.isInt32()) { >+ int32_t a = operand.asInt32(); >+ setConstant(node, JSValue(~a)); > break; > } > >+ clobberWorld(); >+ if (node->child1().useKind() == BigIntUse) >+ setTypeForNode(node, SpecBigInt); >+ else >+ setTypeForNode(node, SpecBoolInt32 | SpecBigInt); >+ >+ break; >+ } >+ >+ case ArithBitNot: { > JSValue operand = forNode(node->child1()).value(); > if (operand && operand.isInt32()) { > int32_t a = operand.asInt32(); >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index d6e3843a8d8349490154e08777274f08655f650b..cc191d8ad963c0e81505c609d861c18ad0bf40f8 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -4926,7 +4926,10 @@ void ByteCodeParser::parseBlock(unsigned limit) > case op_bitnot: { > auto bytecode = currentInstruction->as<OpBitnot>(); > Node* op1 = get(bytecode.operand); >- set(bytecode.dst, addToGraph(ArithBitNot, op1)); >+ if (isInt32Speculation(getPrediction())) >+ set(bytecode.dst, addToGraph(ArithBitNot, op1)); >+ else >+ set(bytecode.dst, addToGraph(ValueBitNot, op1)); > NEXT_OPCODE(op_bitnot); > } > >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index 250ec00443d12c063aa43eeebdc48c70294125a5..9342683be3bf03d0b1692a5f30aa2754c50586a9 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -647,6 +647,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu > case ValueBitAnd: > case ValueBitXor: > case ValueBitOr: >+ case ValueBitNot: > case ValueNegate: > case ValueAdd: > case ValueSub: >diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >index df74930bdbb3864ad944bc4720712fe0f3947bd5..be597084f9d718749abbcf059c21027d9629df98 100644 >--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >@@ -100,6 +100,7 @@ bool doesGC(Graph& graph, Node* node) > case ValueBitAnd: > case ValueBitOr: > case ValueBitXor: >+ case ValueBitNot: > case ValueAdd: > case ValueSub: > case ValueMul: >diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >index a2eefa5ab0bc10fc50d439612eb21cc18f7e0c22..3a4402ca85a9e553f8e0ed40dd4e1b09486685ef 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -211,14 +211,26 @@ private: > break; > } > >+ case ValueBitNot: { >+ Edge& operandEdge = node->child1(); >+ >+ if (operandEdge.node()->shouldSpeculateBigInt()) >+ fixEdge<BigIntUse>(operandEdge); >+ else >+ fixEdge<UntypedUse>(operandEdge); >+ break; >+ } >+ > case ArithBitNot: { >- if (node->child1().node()->shouldSpeculateUntypedForBitOps()) { >- fixEdge<UntypedUse>(node->child1()); >+ Edge& operandEdge = node->child1(); >+ >+ if (operandEdge.node()->shouldSpeculateUntypedForBitOps()) { >+ fixEdge<UntypedUse>(operandEdge); >+ node->setOpAndDefaultFlags(ValueBitNot); > break; > } > >- fixIntConvertingEdge(node->child1()); >- node->clearFlags(NodeMustGenerate); >+ fixIntConvertingEdge(operandEdge); > break; > } > >diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h >index dc2f3e16b832aac0af7f0ad63c4c8e281dcba34e..a503f9190a07569358faba3b0f3a3925fcf98397 100644 >--- a/Source/JavaScriptCore/dfg/DFGNodeType.h >+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h >@@ -111,7 +111,8 @@ namespace JSC { namespace DFG { > macro(InvalidationPoint, NodeMustGenerate) \ > \ > /* Nodes for bitwise operations. */\ >- macro(ArithBitNot, NodeResultInt32 | NodeMustGenerate) \ >+ macro(ValueBitNot, NodeResultJS | NodeMustGenerate) \ >+ macro(ArithBitNot, NodeResultInt32) \ > macro(ValueBitAnd, NodeResultJS | NodeMustGenerate) \ > macro(ArithBitAnd, NodeResultInt32) \ > macro(ValueBitOr, NodeResultJS | NodeMustGenerate) \ >diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp >index 0b26c2d162c7f24cfacebc3a79516c49d732144c..cb408b01897d37d151edc248a1df231d570a0b0f 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -360,10 +360,16 @@ EncodedJSValue JIT_OPERATION operationValueBitNot(ExecState* exec, EncodedJSValu > > JSValue op1 = JSValue::decode(encodedOp1); > >- int32_t operandValue = op1.toInt32(exec); >+ auto operandNumeric = op1.toBigIntOrInt32(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > >- return JSValue::encode(jsNumber(~operandValue)); >+ if (WTF::holds_alternative<JSBigInt*>(operandNumeric)) { >+ JSBigInt* result = JSBigInt::bitwiseNot(exec, WTF::get<JSBigInt*>(operandNumeric)); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ return JSValue::encode(result); >+ } >+ >+ return JSValue::encode(jsNumber(~WTF::get<int32_t>(operandNumeric))); > } > > EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) >@@ -1341,6 +1347,16 @@ JSCell* JIT_OPERATION operationSubBigInt(ExecState* exec, JSCell* op1, JSCell* o > return JSBigInt::sub(exec, leftOperand, rightOperand); > } > >+JSCell* JIT_OPERATION operationBitNotBigInt(ExecState* exec, JSCell* op1) >+{ >+ VM* vm = &exec->vm(); >+ NativeCallFrameTracer tracer(vm, exec); >+ >+ JSBigInt* operand = jsCast<JSBigInt*>(op1); >+ >+ return JSBigInt::bitwiseNot(exec, operand); >+} >+ > JSCell* JIT_OPERATION operationMulBigInt(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 38c116a54f91a615b81c15112148f25f94adb1ef..97bf29123459c9d61ffc9ea431f0b9d10774ac75 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.h >+++ b/Source/JavaScriptCore/dfg/DFGOperations.h >@@ -170,6 +170,7 @@ JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) W > JSCell* JIT_OPERATION operationMulBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationDivBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; >+JSCell* JIT_OPERATION operationBitNotBigInt(ExecState*, JSCell* op1) WTF_INTERNAL; > JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationAddBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; > JSCell* JIT_OPERATION operationBitXorBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL; >diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >index b3c69bcf124727bfcc676b2afadab5a88c22f93a..c2f18e1265c336010db8dbdf4d06f5f6b308850c 100644 >--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >@@ -277,6 +277,12 @@ private: > break; > } > >+ case ValueBitNot: { >+ if (node->child1()->shouldSpeculateBigInt()) >+ changed |= mergePrediction(SpecBigInt); >+ break; >+ } >+ > case ValueBitXor: > case ValueBitOr: > case ValueBitAnd: { >@@ -1119,6 +1125,7 @@ private: > case ValueBitOr: > case ValueBitAnd: > case ValueBitXor: >+ case ValueBitNot: > case ValueNegate: > case ValueAdd: > case ValueSub: >diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >index f106982ae39ff3bcc36cfb5aee0d716c07e94316..053de19f95d079e769b0631621152e5166323aca 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -231,6 +231,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno > case ValueBitAnd: > case ValueBitXor: > case ValueBitOr: >+ case ValueBitNot: > case ValueNegate: > case ValueAdd: > case ValueSub: >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index e1c69aa293f4795d34778f51bddd79e66c4874ea..0d16836e3aa12a6c9ecb3527ec1ffa1b9b7a2842 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -3510,24 +3510,43 @@ void SpeculativeJIT::compileInstanceOf(Node* node) > return; > } > >-void SpeculativeJIT::compileBitwiseNot(Node* node) >+void SpeculativeJIT::compileValueBitNot(Node* node) > { > Edge& child1 = node->child1(); > >- if (child1.useKind() == UntypedUse) { >- JSValueOperand operand(this, child1); >- JSValueRegs operandRegs = operand.jsValueRegs(); >+ if (child1.useKind() == BigIntUse) { >+ SpeculateCellOperand operand(this, child1); >+ GPRReg operandGPR = operand.gpr(); >+ >+ speculateBigInt(child1, operandGPR); > > flushRegisters(); >- JSValueRegsFlushedCallResult result(this); >- JSValueRegs resultRegs = result.regs(); >- callOperation(operationValueBitNot, resultRegs, operandRegs); >+ GPRFlushedCallResult result(this); >+ GPRReg resultGPR = result.gpr(); >+ >+ callOperation(operationBitNotBigInt, resultGPR, operandGPR); > m_jit.exceptionCheck(); >+ cellResult(resultGPR, node); > >- jsValueResult(resultRegs, node); > return; > } > >+ JSValueOperand operand(this, child1); >+ JSValueRegs operandRegs = operand.jsValueRegs(); >+ >+ flushRegisters(); >+ JSValueRegsFlushedCallResult result(this); >+ JSValueRegs resultRegs = result.regs(); >+ callOperation(operationValueBitNot, resultRegs, operandRegs); >+ m_jit.exceptionCheck(); >+ >+ jsValueResult(resultRegs, node); >+} >+ >+void SpeculativeJIT::compileBitwiseNot(Node* node) >+{ >+ Edge& child1 = node->child1(); >+ > SpeculateInt32Operand operand(this, child1); > GPRTemporary result(this); > GPRReg resultGPR = result.gpr(); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >index 4934fd5d3c96ee72342154268eb4301f2ab13abf..b667a51f5d64febf13423aa320e7af0526e6241d 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -1330,6 +1330,7 @@ public: > void compileUInt32ToNumber(Node*); > void compileDoubleAsInt32(Node*); > >+ void compileValueBitNot(Node*); > void compileBitwiseNot(Node*); > > template<typename SnippetGenerator, J_JITOperation_EJJ slowPathFunction> >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >index df632106690176498a78be0a4fbb416ef2cc675c..001c7802044949901b6c5c65cd4570598ca8b091 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >@@ -1991,6 +1991,10 @@ void SpeculativeJIT::compile(Node* node) > compileBitwiseOp(node); > break; > >+ case ValueBitNot: >+ compileValueBitNot(node); >+ break; >+ > case ArithBitNot: > compileBitwiseNot(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >index 5da1657c91d8d171eedae9998f1a3987d5251123..efad53c4867c61c9fefd2e0dc999383499b75d90 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >@@ -2074,6 +2074,10 @@ void SpeculativeJIT::compile(Node* node) > recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat())); > break; > >+ case ValueBitNot: >+ compileValueBitNot(node); >+ break; >+ > case ArithBitNot: > compileBitwiseNot(node); > break; >diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >index 23c9396f4d69e04f6f0cb5f491ba04e6ccfad10a..367b907cf6fcc00fdb109770f2966abcfd23fda8 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -91,6 +91,7 @@ inline CapabilityLevel canCompile(Node* node) > case ValueBitAnd: > case ValueBitXor: > case ValueBitOr: >+ case ValueBitNot: > case ValueNegate: > case ValueAdd: > case ValueSub: >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index 6323b45b09ff0d38fb09150b9118513192e85a56..9959f34a284902189cef956a6258d23c723009ae 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -659,6 +659,9 @@ private: > case ArithUnary: > compileArithUnary(); > break; >+ case ValueBitNot: >+ compileValueBitNot(); >+ break; > case ArithBitNot: > compileArithBitNot(); > break; >@@ -2881,15 +2884,23 @@ private: > } > } > >- void compileArithBitNot() >+ void compileValueBitNot() > { >- if (m_node->child1().useKind() == UntypedUse) { >- LValue operand = lowJSValue(m_node->child1()); >- LValue result = vmCall(Int64, m_out.operation(operationValueBitNot), m_callFrame, operand); >+ if (m_node->child1().useKind() == BigIntUse) { >+ LValue operand = lowBigInt(m_node->child1()); >+ >+ LValue result = vmCall(pointerType(), m_out.operation(operationBitNotBigInt), m_callFrame, operand); > setJSValue(result); > return; > } > >+ LValue operand = lowJSValue(m_node->child1()); >+ LValue result = vmCall(Int64, m_out.operation(operationValueBitNot), m_callFrame, operand); >+ setJSValue(result); >+ } >+ >+ void compileArithBitNot() >+ { > setInt32(m_out.bitNot(lowInt32(m_node->child1()))); > } > >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index 2dfeaa5e6007e028605a18bf682dc79a9d5db4b6..dfaf1b3e73831d46f8e6f6b94382a3492f36f957 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -720,9 +720,16 @@ SLOW_PATH_DECL(slow_path_bitnot) > { > BEGIN(); > auto bytecode = pc->as<OpBitnot>(); >- int32_t operand = GET_C(bytecode.operand).jsValue().toInt32(exec); >+ auto operandNumeric = GET_C(bytecode.operand).jsValue().toBigIntOrInt32(exec); > CHECK_EXCEPTION(); >- RETURN_PROFILED(jsNumber(~operand)); >+ >+ if (WTF::holds_alternative<JSBigInt*>(operandNumeric)) { >+ JSBigInt* result = JSBigInt::bitwiseNot(exec, WTF::get<JSBigInt*>(operandNumeric)); >+ CHECK_EXCEPTION(); >+ RETURN_PROFILED(result); >+ } >+ >+ RETURN_PROFILED(jsNumber(~WTF::get<int32_t>(operandNumeric))); > } > > SLOW_PATH_DECL(slow_path_bitand) >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp >index afe3cfde0036c9e6b2551abdea0564228500df14..190cc9e0a524ba47973900a4b89dc919e018c6b9 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp >+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp >@@ -525,6 +525,21 @@ JSBigInt* JSBigInt::signedRightShift(ExecState* exec, JSBigInt* x, JSBigInt* y) > return rightShiftByAbsolute(exec, x, y); > } > >+JSBigInt* JSBigInt::bitwiseNot(ExecState* exec, JSBigInt* x) >+{ >+ VM& vm = exec->vm(); >+ JSBigInt* result = nullptr; >+ if (x->sign()) { >+ // ~(-x) == ~(~(x-1)) == x-1 >+ result = absoluteSubOne(exec, x, x->length()); >+ } else { >+ // ~x == -x-1 == -(x+1) >+ result = absoluteAddOne(exec, x, SignOption::Signed); >+ } >+ >+ return result->rightTrim(vm); >+} >+ > #if USE(JSVALUE32_64) > #define HAVE_TWO_DIGIT 1 > typedef uint64_t TwoDigit; >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index 8e14ca51230c554e2d4c1e829bd4d6c0a3a5365c..5ab94a452174305404519c854a1bce69c66343ea 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -123,6 +123,7 @@ public: > static JSBigInt* bitwiseAnd(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* bitwiseOr(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* bitwiseXor(ExecState*, JSBigInt* x, JSBigInt* y); >+ static JSBigInt* bitwiseNot(ExecState*, JSBigInt* x); > > static JSBigInt* leftShift(ExecState*, JSBigInt* x, JSBigInt* y); > static JSBigInt* signedRightShift(ExecState*, JSBigInt* x, JSBigInt* y); >diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index e33fa4051c8d1c583f852da242f01500f9d1f027..3d469aa5ae4c248ce0d3ecd9b011a47f1fa0ec21 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,15 @@ >+2018-12-13 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement "~" unary operation >+ https://bugs.webkit.org/show_bug.cgi?id=182216 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * stress/big-int-bit-not-general.js: Added. >+ * stress/big-int-bitwise-not-jit.js: Added. >+ * stress/big-int-bitwise-not-wrapped-value.js: Added. >+ * stress/bitwise-not-fixup-rules.js: Added. >+ > 2018-12-13 Caio Lima <ticaiolima@gmail.com> > > [BigInt] Add ValueDiv into DFG >diff --git a/JSTests/stress/big-int-bit-not-general.js b/JSTests/stress/big-int-bit-not-general.js >new file mode 100644 >index 0000000000000000000000000000000000000000..07eb056479a8588ce8fdb0497ba31d9273c37609 >--- /dev/null >+++ b/JSTests/stress/big-int-bit-not-general.js >@@ -0,0 +1,39 @@ >+//@ runBigIntEnabled >+ >+// Copyright (C) 2017 Josh Wolfe. All rights reserved. >+// This code is governed by the BSD license found in the LICENSE file. >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad assertion"); >+} >+ >+assert.sameValue = function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+} >+ >+assert.sameValue(~0n, -1n, "~0n === -1n"); >+assert.sameValue(~(0n), -1n, "~(0n) === -1n"); >+assert.sameValue(~1n, -2n, "~1n === -2n"); >+assert.sameValue(~-1n, 0n, "~-1n === 0n"); >+assert.sameValue(~(-1n), 0n, "~(-1n) === 0n"); >+assert.sameValue(~~1n, 1n, "~~1n === 1n"); >+assert.sameValue(~0x5an, -0x5bn, "~0x5an === -0x5bn"); >+assert.sameValue(~-0x5an, 0x59n, "~-0x5an === 0x59n"); >+assert.sameValue(~0xffn, -0x100n, "~0xffn === -0x100n"); >+assert.sameValue(~-0xffn, 0xfen, "~-0xffn === 0xfen"); >+assert.sameValue(~0xffffn, -0x10000n, "~0xffffn === -0x10000n"); >+assert.sameValue(~-0xffffn, 0xfffen, "~-0xffffn === 0xfffen"); >+assert.sameValue(~0xffffffffn, -0x100000000n, "~0xffffffffn === -0x100000000n"); >+assert.sameValue(~-0xffffffffn, 0xfffffffen, "~-0xffffffffn === 0xfffffffen"); >+assert.sameValue( >+ ~0xffffffffffffffffn, -0x10000000000000000n, >+ "~0xffffffffffffffffn === -0x10000000000000000n"); >+assert.sameValue( >+ ~-0xffffffffffffffffn, 0xfffffffffffffffen, >+ "~-0xffffffffffffffffn === 0xfffffffffffffffen"); >+assert.sameValue( >+ ~0x123456789abcdef0fedcba9876543210n, -0x123456789abcdef0fedcba9876543211n, >+ "~0x123456789abcdef0fedcba9876543210n === -0x123456789abcdef0fedcba9876543211n"); >+ >diff --git a/JSTests/stress/big-int-bitwise-not-jit.js b/JSTests/stress/big-int-bitwise-not-jit.js >new file mode 100644 >index 0000000000000000000000000000000000000000..d761e1f75976a54cacdc0de2d205c19b7183b5f3 >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-not-jit.js >@@ -0,0 +1,19 @@ >+//@ runBigIntEnabled >+ >+let assert = { >+ sameValue: function(i, e, m) { >+ if (i !== e) >+ throw new Error(m); >+ } >+} >+ >+function bigIntBitNot(a) { >+ return ~(~a); >+} >+noInline(bigIntBitNot); >+ >+for (let i = 0; i < 10000; i++) { >+ let r = bigIntBitNot(3n); >+ assert.sameValue(r, 3n, "~~" + 3n + " = " + r); >+} >+ >diff --git a/JSTests/stress/big-int-bitwise-not-wrapped-value.js b/JSTests/stress/big-int-bitwise-not-wrapped-value.js >new file mode 100644 >index 0000000000000000000000000000000000000000..1bc571bd029a6040a0278f5b1b9aa6a2fd5f30e3 >--- /dev/null >+++ b/JSTests/stress/big-int-bitwise-not-wrapped-value.js >@@ -0,0 +1,36 @@ >+//@ runBigIntEnabled >+ >+assert = { >+ sameValue: function (input, expected, message) { >+ if (input !== expected) >+ throw new Error(message); >+ } >+}; >+ >+function testBitNot(x, z, message) { >+ assert.sameValue(~x, z, message); >+} >+ >+testBitNot(Object(1n), -2n, "ToPrimitive: unbox object with internal slot"); >+ >+let o = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ } >+}; >+testBitNot(o, -2n, "ToPrimitive: @@toPrimitive"); >+ >+o = { >+ valueOf: function() { >+ return 1n; >+ } >+}; >+testBitNot(o, -2n, "ToPrimitive: valueOf"); >+ >+o = { >+ toString: function() { >+ return 1n; >+ } >+} >+testBitNot(o, -2n, "ToPrimitive: toString"); >+ >diff --git a/JSTests/stress/bitwise-not-fixup-rules.js b/JSTests/stress/bitwise-not-fixup-rules.js >new file mode 100644 >index 0000000000000000000000000000000000000000..62be62a4ea70397a72b0def6241cf201ee9c277e >--- /dev/null >+++ b/JSTests/stress/bitwise-not-fixup-rules.js >@@ -0,0 +1,27 @@ >+//@ runBigIntEnabled >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Expected to be: " + e + " but got: " + a); >+} >+ >+function foo(a) { >+ return ~a; >+} >+noInline(foo); >+ >+let c = 0; >+let o = { >+ valueOf: () => { >+ c++; >+ return 3; >+ } >+}; >+ >+for (let i = 0; i < 10000; i++) >+ foo(o); >+ >+assert(c, 10000); >+if (numberOfDFGCompiles(foo) > 1) >+ throw new Error("Function 'foo' should be compiled just once"); >+ >diff --git a/PerformanceTests/BigIntBench/big-int-simple-bit-not.js b/PerformanceTests/BigIntBench/big-int-simple-bit-not.js >new file mode 100644 >index 0000000000000000000000000000000000000000..488a70d4f74038a1eaad5aab0d744cb431137f19 >--- /dev/null >+++ b/PerformanceTests/BigIntBench/big-int-simple-bit-not.js >@@ -0,0 +1,15 @@ >+function bigInt(a, b) { >+ let c = ~a; >+ return ~a + ~c; >+} >+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/ChangeLog b/PerformanceTests/ChangeLog >index c59f3f60d28bb7d0b85229d339934ffa3a8b4763..6708c0cc07e14aad859af03911e640fd8fc1b5a2 100644 >--- a/PerformanceTests/ChangeLog >+++ b/PerformanceTests/ChangeLog >@@ -1,3 +1,12 @@ >+2018-12-13 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement "~" unary operation >+ https://bugs.webkit.org/show_bug.cgi?id=182216 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * BigIntBench/big-int-simple-bit-not.js: Added. >+ > 2018-12-13 Caio Lima <ticaiolima@gmail.com> > > [BigInt] Add ValueDiv into DFG
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 182216
:
356382
|
356489
|
356498
|
357224
|
357227
|
358064
|
359198
|
359235
|
359236
|
359885
|
359890
|
359898
|
360006
|
360007
|
360931
|
362250
|
363089
|
363878
|
364004