WebKit Bugzilla
Attachment 357224 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-20181213102649.patch (text/plain), 25.94 KB, created by
Caio Lima
on 2018-12-13 04:26:51 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-12-13 04:26:51 PST
Size:
25.94 KB
patch
obsolete
>Subversion Revision: 239130 >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 31522434d77a3ffa3b1ef47ca56d57c52db43d66..ee48c2640f85f2e2258a57e41aa93ed1d99f23ad 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-11 Yusuke Suzuki <yusukesuzuki@slowstart.org> > > [BigInt] Simplify boolean context evaluation by leveraging JSString::offsetOfLength() == JSBigInt::offsetOfLength() >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index c8f66dde246ac8dcc5736cc65466ba812932b963..463551ac72f4d895c7e0576f955bd7b314ee358b 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -375,13 +375,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 aa23167327c6de6814614a2a314b5b7a2f03d0b8..21beee0d3b84d12d04bd86a480e426faa33ddbf3 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -4898,7 +4898,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 95404f3f920dd99d6311875feb82a9ba393b2b64..1293b08c94b37ddc53af5ed59494eba0f2eeeea9 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 64e2f5efecad64b3013d4189e2849cb153498f69..383061bad4748498951cb622a862693d62620516 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 5b0de12fa5067183c6b886f11fc0cb04980cb91c..00e8249b1fb68568bcd01ddf20f4d5046b2e720a 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -173,14 +173,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 40f62645769f191f17bf6bfe1b831b1cabf77b19..45281ee6494de965a3339ba44cbeb535af880671 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 be992af6f638f396687b22f84d6aa30f09fbd818..62bf662b25725ecfcbb859c30b477e80fbe969a8 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.cpp >+++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp >@@ -341,10 +341,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) >@@ -1322,6 +1328,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 e455609a1f599eceea0186b3f6dbeb1a618bef41..c3f58279380b300baa8d6e460deeb2952dfbeff9 100644 >--- a/Source/JavaScriptCore/dfg/DFGOperations.h >+++ b/Source/JavaScriptCore/dfg/DFGOperations.h >@@ -167,6 +167,7 @@ size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCel > 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 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 e8299eb873c5061abb4a45f0dc1b17d239025a30..fce97b7265e852eac61c6ec3c842c30803952034 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: { >@@ -1105,6 +1111,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 07cf01f38eb6ef13a3a2c4d06f85e5d73aa804a0..7b29708b450421c6d4e46ecd2a6c003a4d626ceb 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -230,6 +230,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 465bf3fb0fd87c4a08e5f5d96fa98f3338a4ab62..9e28f61e3cbed124a973a25fcdce435c4e7137e2 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 a20e39a83afe8cbb2929271d3ce25afe33e7ea87..7a4d65df07d38484df78fa473fc41370e6a0cfba 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -1329,6 +1329,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 bcf7c72488e87650af6bcf42ab57fcc17325893b..f442ecbb5eaa6841093e755fa85ded58d9a69ccd 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 066274490093fec2b0f2f886372adc041d058782..cbc26dea18ab442ce47dd6a45f9cafa177ad8252 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 0a3569fe8876545768bc6c6e688ad1bc448a6af5..f81c7ad6d4ea7920982d7870252312bd1e6bb647 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -90,6 +90,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 72eb9363edbbe575dbbedc6cc8d5a31f053e748b..5edcd9f2982b7db503bbea3a8ce03230f14977db 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -656,6 +656,9 @@ private: > case ArithUnary: > compileArithUnary(); > break; >+ case ValueBitNot: >+ compileValueBitNot(); >+ break; > case ArithBitNot: > compileArithBitNot(); > break; >@@ -2863,15 +2866,23 @@ private: > } > } > >- void compileArithBitNot() >+ void compileValueBitNot() > { >- if (m_node->child1().useKind() == UntypedUse) { >- LValue operand = lowJSValue(m_node->child1()); >- LValue result = vmCall(pointerType(), 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 c6b86c9c26d5b33f88bf9cc998a05ced901d2265..b53f76e2500db82523e2c3d84e9b63735a4a3e86 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-10 Mark Lam <mark.lam@apple.com> > > PropertyAttribute needs a CustomValue bit. >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 3b3186bc1e2d07cd66ba1c38936f16ec80a62e55..9dacb9daeb9eda0eb00d25a803966a38b2348ab6 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-10 Caio Lima <ticaiolima@gmail.com> > > [BigInt] Add ValueMul 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