WebKit Bugzilla
Attachment 341440 Details for
Bug 182214
: [ESNext][BigInt] Implement "+" and "-" unary operation
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
big-int-negate.diff (text/plain), 45.29 KB, created by
Caio Lima
on 2018-05-27 18:46:27 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2018-05-27 18:46:27 PDT
Size:
45.29 KB
patch
obsolete
>diff --git a/JSTests/ChangeLog b/JSTests/ChangeLog >index 6801af6..d975758 100644 >--- a/JSTests/ChangeLog >+++ b/JSTests/ChangeLog >@@ -1,3 +1,14 @@ >+2018-05-27 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement "+" and "-" unary operation >+ https://bugs.webkit.org/show_bug.cgi?id=182214 >+ >+ Reviewed by Yusuke Suzuki. >+ >+ * stress/big-int-negate-basic.js: Added. >+ * stress/big-int-negate-jit.js: Added. >+ * stress/big-int-unary-plus.js: Added. >+ > 2018-05-26 Yusuke Suzuki <utatane.tea@gmail.com> > > [JSC] Rename Array#flatten to flat >diff --git a/JSTests/stress/big-int-negate-basic.js b/JSTests/stress/big-int-negate-basic.js >new file mode 100644 >index 0000000..59ba3c4 >--- /dev/null >+++ b/JSTests/stress/big-int-negate-basic.js >@@ -0,0 +1,71 @@ >+//@ runBigIntEnabled >+// Original tests from https://github.com/tc39/test262/blob/master/test/language/expressions/unary-minus/bigint.js >+ >+function assert(a, b, message) { >+ if (a !== b) >+ throw new Error(message); >+} >+ >+function assertNotEqual(a, b, message) { >+ if (a === b) >+ throw new Error(message); >+} >+ >+assert(-0n, 0n, "-0n === 0n"); >+assert(-(0n), 0n, "-(0n) === 0n"); >+assertNotEqual(-1n, 1n, "-1n !== 1n"); >+assert(-(1n), -1n, "-(1n) === -1n"); >+assertNotEqual(-(1n), 1n, "-(1n) !== 1n"); >+assert(-(-1n), 1n, "-(-1n) === 1n"); >+assertNotEqual(-(-1n), -1n, "-(-1n) !== -1n"); >+assert(- - 1n, 1n, "- - 1n === 1n"); >+assertNotEqual(- - 1n, -1n, "- - 1n !== -1n"); >+assert(-(0x1fffffffffffff01n), -0x1fffffffffffff01n, "-(0x1fffffffffffff01n) === -0x1fffffffffffff01n"); >+assertNotEqual(-(0x1fffffffffffff01n), 0x1fffffffffffff01n, "-(0x1fffffffffffff01n) !== 0x1fffffffffffff01n"); >+assertNotEqual(-(0x1fffffffffffff01n), -0x1fffffffffffff00n, "-(0x1fffffffffffff01n) !== -0x1fffffffffffff00n"); >+ >+// Non-primitive cases >+ >+assert(-Object(1n), -1n, "-Object(1n) === -1n"); >+assertNotEqual(-Object(1n), 1n, "-Object(1n) !== 1n"); >+assertNotEqual(-Object(1n), Object(-1n), "-Object(1n) !== Object(-1n)"); >+assert(-Object(-1n), 1n, "-Object(-1n) === 1n"); >+assertNotEqual(-Object(-1n), -1n, "-Object(-1n) !== -1n"); >+assertNotEqual(-Object(-1n), Object(1n), "-Object(-1n) !== Object(1n)"); >+ >+let obj = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ }, >+ valueOf: function() { >+ throw new Error("Should never be called"); >+ }, >+ toString: function() { >+ throw new Error("Should never be called"); >+ } >+}; >+assert(-obj, -1n, "@@toPrimitive not called properly"); >+ >+obj = { >+ valueOf: function() { >+ return 1n; >+ }, >+ toString: function() { >+ throw new Error("Should never be called"); >+ } >+} >+assert(-obj, -1n, "valueOf not called properly"); >+ >+obj = { >+ toString: function() { >+ return 1n; >+ } >+}; >+ >+assert(-obj, -1n, "-{toString: function() { return 1n; }} === -1n"); >+ >+let x = 1n; >+let y = -x; >+let z = -y; >+assert(x, z, "-(-x) !== z"); >+ >diff --git a/JSTests/stress/big-int-negate-jit.js b/JSTests/stress/big-int-negate-jit.js >new file mode 100644 >index 0000000..ab49783 >--- /dev/null >+++ b/JSTests/stress/big-int-negate-jit.js >@@ -0,0 +1,48 @@ >+//@ skip if not $jitTests >+//@ runBigIntEnabled >+ >+function assert(a, b) { >+ if (a !== b) >+ throw new Error("Bad!"); >+} >+ >+function negateBigInt(n) { >+ return -n; >+} >+noInline(negateBigInt); >+ >+for (let i = 0; i < 100000; i++) { >+ assert(negateBigInt(100n), -100n); >+ assert(negateBigInt(-0x1fffffffffffff01n), 0x1fffffffffffff01n); >+} >+ >+if (numberOfDFGCompiles(negateBigInt) > 1) >+ throw "Failed negateBigInt(). We should have compiled a single negate for the BigInt type."; >+ >+function negateBigIntSpecializedToInt(n) { >+ return -n; >+} >+noInline(negateBigIntSpecializedToInt); >+ >+for (let i = 0; i < 100000; i++) { >+ negateBigIntSpecializedToInt(100); >+} >+ >+assert(negateBigIntSpecializedToInt(100n), -100n); >+ >+// Testing case mixing int and BigInt speculations >+function mixedSpeculationNegateBigInt(n, arr) { >+ return -(-(-n)); >+} >+noInline(mixedSpeculationNegateBigInt); >+ >+for (let i = 0; i < 100000; i++) { >+ if (i % 2) >+ assert(mixedSpeculationNegateBigInt(100), -100); >+ else >+ assert(mixedSpeculationNegateBigInt(-0x1fffffffffffff01n), 0x1fffffffffffff01n); >+} >+ >+if (numberOfDFGCompiles(mixedSpeculationNegateBigInt) > 1) >+ throw "Failed negateBigInt(). We should have compiled a single negate for the BigInt type."; >+ >diff --git a/JSTests/stress/big-int-unary-plus.js b/JSTests/stress/big-int-unary-plus.js >new file mode 100644 >index 0000000..4d4ac37 >--- /dev/null >+++ b/JSTests/stress/big-int-unary-plus.js >@@ -0,0 +1,51 @@ >+//@ runBigIntEnabled >+ >+function assert(a) { >+ if (!a) >+ throw new Error("Bad!") >+} >+ >+function assertTypeError(input) { >+ try { >+ let a = +input; >+ assert(false); >+ } catch(e) { >+ assert(e instanceof TypeError); >+ } >+} >+ >+assertTypeError(10n); >+assertTypeError(-10n); >+assertTypeError(Object(10n)); >+assertTypeError(Object(-10n)); >+ >+let obj = { >+ [Symbol.toPrimitive]: function() { >+ return 1n; >+ }, >+ valueOf: function() { >+ throw new Error("Should never be called"); >+ }, >+ toString: function() { >+ throw new Error("Should never be called"); >+ } >+}; >+assertTypeError(obj); >+ >+obj = { >+ valueOf: function() { >+ return 1n; >+ }, >+ toString: function() { >+ throw new Error("Should never be called"); >+ } >+}; >+assertTypeError(obj); >+ >+obj = { >+ toString: function() { >+ return 1n; >+ } >+}; >+assertTypeError(obj); >+ >diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index af3750d..bcdce45 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,86 @@ >+2018-05-27 Caio Lima <ticaiolima@gmail.com> >+ >+ [ESNext][BigInt] Implement "+" and "-" unary operation >+ https://bugs.webkit.org/show_bug.cgi?id=182214 >+ >+ Reviewed by Yusuke Suzuki. >+ >+ This Patch is implementing support to "-" unary operation on BigInt. >+ It is also changing the logic of ASTBuilder::makeNegateNode to >+ calculate BigInt literals with properly sign, avoiding >+ unecessary operation. It required a refactoring into >+ JSBigInt::parseInt to consider the sign as parameter. >+ >+ We are also introducing a new DFG Node called ValueNegate to handle BigInt negate >+ operations. With the introduction of BigInt, it is not true >+ that every negate operation returns a Number. As ArithNegate is a >+ node that considers its result is always a Number, like all other >+ Arith<Operation>, we decided to keep this consistency and use ValueNegate when >+ speculation indicates that the operand is a BigInt. >+ This design is following the same distinction between ArithAdd and >+ ValueAdd. Also, this new node will make simpler the introduction of >+ optimizations when we create speculation paths for BigInt in future >+ patches. >+ >+ In the case of "+" unary operation on BigInt, the current semantic we already have >+ is correctly, since it needs to throw TypeError because of ToNumber call[1]. >+ In such case, we are adding tests to verify other edge cases. >+ >+ [1] - https://tc39.github.io/proposal-bigint/#sec-unary-plus-operator >+ >+ * bytecompiler/BytecodeGenerator.cpp: >+ (JSC::BytecodeGenerator::addBigIntConstant): >+ * bytecompiler/BytecodeGenerator.h: >+ * bytecompiler/NodesCodegen.cpp: >+ (JSC::BigIntNode::jsValue const): >+ * dfg/DFGAbstractInterpreterInlines.h: >+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): >+ * 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::fixupNode): >+ * dfg/DFGNode.h: >+ (JSC::DFG::Node::arithNodeFlags): >+ * dfg/DFGNodeType.h: >+ * dfg/DFGPredictionPropagationPhase.cpp: >+ * dfg/DFGSafeToExecute.h: >+ (JSC::DFG::safeToExecute): >+ * dfg/DFGSpeculativeJIT.cpp: >+ (JSC::DFG::SpeculativeJIT::compileValueNegate): >+ (JSC::DFG::SpeculativeJIT::compileArithNegate): >+ * 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::compileValueNegate): >+ (JSC::FTL::DFG::LowerDFGToB3::compileArithNegate): >+ * jit/JITOperations.cpp: >+ * parser/ASTBuilder.h: >+ (JSC::ASTBuilder::createBigIntWithSign): >+ (JSC::ASTBuilder::createBigIntFromUnaryOperation): >+ (JSC::ASTBuilder::makeNegateNode): >+ * parser/NodeConstructors.h: >+ (JSC::BigIntNode::BigIntNode): >+ * parser/Nodes.h: >+ * runtime/CommonSlowPaths.cpp: >+ (JSC::updateArithProfileForUnaryArithOp): >+ (JSC::SLOW_PATH_DECL): >+ * runtime/JSBigInt.cpp: >+ (JSC::JSBigInt::parseInt): >+ * runtime/JSBigInt.h: >+ * runtime/JSCJSValueInlines.h: >+ (JSC::JSValue::strictEqualSlowCaseInline): >+ > 2018-05-26 Yusuke Suzuki <utatane.tea@gmail.com> > > [JSC] Rename Array#flatten to flat >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 96ee938..651759f 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -3161,11 +3161,12 @@ RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst) > return dst; > } > >-JSValue BytecodeGenerator::addBigIntConstant(const Identifier& identifier, uint8_t radix) >+JSValue BytecodeGenerator::addBigIntConstant(const Identifier& identifier, uint8_t radix, bool sign) > { >- return m_bigIntMap.ensure(BigIntMapEntry(identifier.impl(), radix), [&] { >+ return m_bigIntMap.ensure(BigIntMapEntry(identifier.impl(), radix, sign), [&] { > auto scope = DECLARE_CATCH_SCOPE(*vm()); >- JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, *vm(), identifier.string(), radix); >+ auto parseIntSign = sign ? JSBigInt::ParseIntSign::Signed : JSBigInt::ParseIntSign::Unsigned; >+ JSBigInt* bigIntInMap = JSBigInt::parseInt(nullptr, *vm(), identifier.string(), radix, JSBigInt::ErrorParseMode::ThrowExceptions, parseIntSign); > // FIXME: [ESNext] Enables a way to throw an error on ByteCodeGenerator step > // https://bugs.webkit.org/show_bug.cgi?id=180139 > scope.assertNoException(); >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index f0176b2..a9bcb45 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -1026,7 +1026,7 @@ namespace JSC { > void allocateCalleeSaveSpace(); > void allocateAndEmitScope(); > >- using BigIntMapEntry = std::pair<UniquedStringImpl*, uint8_t>; >+ using BigIntMapEntry = std::tuple<UniquedStringImpl*, uint8_t, bool>; > > using NumberMap = HashMap<double, JSValue>; > using IdentifierStringMap = HashMap<UniquedStringImpl*, JSString*, IdentifierRepHash>; >@@ -1122,7 +1122,7 @@ namespace JSC { > > public: > JSString* addStringConstant(const Identifier&); >- JSValue addBigIntConstant(const Identifier&, uint8_t radix); >+ JSValue addBigIntConstant(const Identifier&, uint8_t radix, bool sign); > RegisterID* addTemplateObjectConstant(Ref<TemplateObjectDescriptor>&&); > > Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; } >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index eb08254..84e2548 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -125,7 +125,7 @@ JSValue StringNode::jsValue(BytecodeGenerator& generator) const > > JSValue BigIntNode::jsValue(BytecodeGenerator& generator) const > { >- return generator.addBigIntConstant(m_value, m_radix); >+ return generator.addBigIntConstant(m_value, m_radix, m_sign); > } > > // ------------------------------ NumberNode ---------------------------------- >diff --git a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >index ea3ebe4..a1a8349 100644 >--- a/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >+++ b/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h >@@ -761,6 +761,12 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > break; > } > >+ case ValueNegate: { >+ clobberWorld(); >+ setTypeForNode(node, SpecBytecodeNumber | SpecBigInt); >+ break; >+ } >+ > case ArithNegate: { > JSValue child = forNode(node->child1()).value(); > switch (node->child1().useKind()) { >@@ -808,9 +814,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi > forNode(node->child1()).m_type)); > break; > default: >- DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind()); >- clobberWorld(); >- setNonCellTypeForNode(node, SpecBytecodeNumber); >+ RELEASE_ASSERT_NOT_REACHED(); > break; > } > break; >diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >index fad17fe..7442b81 100644 >--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp >@@ -937,17 +937,19 @@ private: > node->mergeFlags(NodeMayHaveNonNumberResult); > break; > } >+ case ValueNegate: > case ArithNegate: { >- // We'd like to assert here that the arith profile for the result of negate never >- // sees a non-number, but we can't. It's true that negate never produces a non-number. >- // But sometimes we'll end up grabbing the wrong ArithProfile during OSR exit, and >- // profiling the wrong value, leading the ArithProfile to think it observed a non-number result. > if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble()) > node->mergeFlags(NodeMayHaveDoubleResult); > if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) > node->mergeFlags(NodeMayNegZeroInBaseline); > if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) > node->mergeFlags(NodeMayOverflowInt32InBaseline); >+ if (arithProfile->didObserveNonNumber()) { >+ // FIXME: We should add support to BigInt into speculation >+ // https://bugs.webkit.org/show_bug.cgi?id=182470 >+ node->mergeFlags(NodeMayHaveNonNumberResult); >+ } > break; > } > >@@ -4714,7 +4716,10 @@ void ByteCodeParser::parseBlock(unsigned limit) > > case op_negate: { > Node* op1 = get(VirtualRegister(currentInstruction[2].u.operand)); >- set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithNegate, op1))); >+ if (op1->hasNumberResult()) >+ set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ArithNegate, op1))); >+ else >+ set(VirtualRegister(currentInstruction[1].u.operand), makeSafe(addToGraph(ValueNegate, op1))); > NEXT_OPCODE(op_negate); > } > >diff --git a/Source/JavaScriptCore/dfg/DFGClobberize.h b/Source/JavaScriptCore/dfg/DFGClobberize.h >index 515c677..f781b15 100644 >--- a/Source/JavaScriptCore/dfg/DFGClobberize.h >+++ b/Source/JavaScriptCore/dfg/DFGClobberize.h >@@ -627,6 +627,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu > case InByVal: > case InById: > case HasOwnProperty: >+ case ValueNegate: > case ValueAdd: > case SetFunctionName: > case GetDynamicVar: >diff --git a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >index fdf2e77..e08d21a 100644 >--- a/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >+++ b/Source/JavaScriptCore/dfg/DFGDoesGC.cpp >@@ -97,6 +97,7 @@ bool doesGC(Graph& graph, Node* node) > case ArithFRound: > case ArithUnary: > case ValueAdd: >+ case ValueNegate: > case TryGetById: > case GetById: > case GetByIdFlush: >diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >index ae76a94..5dc8596 100644 >--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp >@@ -146,7 +146,45 @@ private: > } > break; > } >+ >+ case ValueNegate: { >+ if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) { >+ node->setOp(ArithNegate); >+ fixIntOrBooleanEdge(node->child1()); >+ if (bytecodeCanTruncateInteger(node->arithNodeFlags())) >+ node->setArithMode(Arith::Unchecked); >+ else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) >+ node->setArithMode(Arith::CheckOverflow); >+ else >+ node->setArithMode(Arith::CheckOverflowAndNegativeZero); >+ node->setResult(NodeResultInt32); >+ node->clearFlags(NodeMustGenerate); >+ break; >+ } > >+ if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) { >+ node->setOp(ArithNegate); >+ fixEdge<Int52RepUse>(node->child1()); >+ if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) >+ node->setArithMode(Arith::CheckOverflow); >+ else >+ node->setArithMode(Arith::CheckOverflowAndNegativeZero); >+ node->setResult(NodeResultInt52); >+ node->clearFlags(NodeMustGenerate); >+ break; >+ } >+ if (node->child1()->shouldSpeculateNotCell()) { >+ node->setOp(ArithNegate); >+ fixDoubleOrBooleanEdge(node->child1()); >+ node->setResult(NodeResultDouble); >+ node->clearFlags(NodeMustGenerate); >+ } else { >+ fixEdge<UntypedUse>(node->child1()); >+ node->setResult(NodeResultJS); >+ } >+ break; >+ } >+ > case ValueAdd: { > if (attemptToMakeIntegerAdd(node)) { > node->setOp(ArithAdd); >@@ -257,12 +295,10 @@ private: > node->clearFlags(NodeMustGenerate); > break; > } >- if (node->child1()->shouldSpeculateNotCell()) { >- fixDoubleOrBooleanEdge(node->child1()); >- node->setResult(NodeResultDouble); >- node->clearFlags(NodeMustGenerate); >- } else >- fixEdge<UntypedUse>(node->child1()); >+ >+ fixDoubleOrBooleanEdge(node->child1()); >+ node->setResult(NodeResultDouble); >+ node->clearFlags(NodeMustGenerate); > break; > } > >diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h >index 005f836..10b51fe 100644 >--- a/Source/JavaScriptCore/dfg/DFGNode.h >+++ b/Source/JavaScriptCore/dfg/DFGNode.h >@@ -1107,7 +1107,7 @@ public: > 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) >+ if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32 || op() == ValueNegate) > return result; > return result & ~NodeBytecodeNeedsNegZero; > } >diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h >index 531711b..52b7bb9 100644 >--- a/Source/JavaScriptCore/dfg/DFGNodeType.h >+++ b/Source/JavaScriptCore/dfg/DFGNodeType.h >@@ -162,6 +162,9 @@ namespace JSC { namespace DFG { > macro(ArithSqrt, NodeResultDouble | NodeMustGenerate) \ > macro(ArithUnary, NodeResultDouble | NodeMustGenerate) \ > \ >+ /* BigInt is a valid operand for negate operations */\ >+ macro(ValueNegate, NodeResultJS | NodeMustGenerate) \ >+ \ > /* Add of values may either be arithmetic, or result in string concatenation. */\ > macro(ValueAdd, NodeResultJS | NodeMustGenerate) \ > \ >diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >index 9c661f9..5a6addb 100644 >--- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >+++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp >@@ -245,6 +245,7 @@ private: > break; > } > >+ case ValueNegate: > case ArithNegate: { > SpeculatedType prediction = node->child1()->prediction(); > if (prediction) { >@@ -256,6 +257,11 @@ private: > changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); > else { > changed |= mergePrediction(SpecInt32Only); >+ if (node->op() == ValueNegate && node->mayHaveNonNumberResult()) { >+ // FIXME: We should add support to BigInt into speculatio >+ // https://bugs.webkit.org/show_bug.cgi?id=182470 >+ changed |= mergePrediction(SpecBigInt); >+ } > if (node->mayHaveDoubleResult()) > changed |= mergePrediction(SpecBytecodeDouble); > } >@@ -1038,6 +1044,7 @@ private: > case GetLocal: > case SetLocal: > case UInt32ToNumber: >+ case ValueNegate: > case ValueAdd: > case ArithAdd: > case ArithSub: >diff --git a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >index d6d026c..b35078f 100644 >--- a/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >+++ b/Source/JavaScriptCore/dfg/DFGSafeToExecute.h >@@ -219,6 +219,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno > case ArithCeil: > case ArithTrunc: > case ArithUnary: >+ case ValueNegate: > case ValueAdd: > case TryGetById: > case DeleteById: >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >index 3d5ebfe..42f0546 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp >@@ -4478,6 +4478,18 @@ void SpeculativeJIT::compileArithSub(Node* node) > } > } > >+void SpeculativeJIT::compileValueNegate(Node* node) >+{ >+ CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic); >+ ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); >+ Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex]; >+ JITNegIC* negIC = m_jit.codeBlock()->addJITNegIC(arithProfile, instruction); >+ auto repatchingFunction = operationArithNegateOptimize; >+ auto nonRepatchingFunction = operationArithNegate; >+ bool needsScratchGPRReg = true; >+ compileMathIC(node, negIC, needsScratchGPRReg, repatchingFunction, nonRepatchingFunction); >+} >+ > void SpeculativeJIT::compileArithNegate(Node* node) > { > switch (node->child1().useKind()) { >@@ -4552,15 +4564,7 @@ void SpeculativeJIT::compileArithNegate(Node* node) > } > > default: { >- CodeBlock* baselineCodeBlock = m_jit.graph().baselineCodeBlockFor(node->origin.semantic); >- ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(node->origin.semantic.bytecodeIndex); >- Instruction* instruction = &baselineCodeBlock->instructions()[node->origin.semantic.bytecodeIndex]; >- JITNegIC* negIC = m_jit.codeBlock()->addJITNegIC(arithProfile, instruction); >- auto repatchingFunction = operationArithNegateOptimize; >- auto nonRepatchingFunction = operationArithNegate; >- bool needsScratchGPRReg = true; >- compileMathIC(node, negIC, needsScratchGPRReg, repatchingFunction, nonRepatchingFunction); >- return; >+ RELEASE_ASSERT_NOT_REACHED(); > } > } > } >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >index 05a08ea..8b04194 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h >@@ -1348,6 +1348,7 @@ public: > void compileArithAbs(Node*); > void compileArithClz32(Node*); > void compileArithSub(Node*); >+ void compileValueNegate(Node*); > void compileArithNegate(Node*); > void compileArithMul(Node*); > void compileArithDiv(Node*); >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >index b97ccbd..ac73b7b 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp >@@ -2015,6 +2015,10 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >+ case ValueNegate: >+ compileValueNegate(node); >+ break; >+ > case ValueAdd: > compileValueAdd(node); > break; >diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >index 513862d..db19347 100644 >--- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >+++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp >@@ -2165,6 +2165,10 @@ void SpeculativeJIT::compile(Node* node) > break; > } > >+ case ValueNegate: >+ compileValueNegate(node); >+ break; >+ > case ValueAdd: > compileValueAdd(node); > break; >diff --git a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >index f1513bb99..7b44b66 100644 >--- a/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >+++ b/Source/JavaScriptCore/ftl/FTLCapabilities.cpp >@@ -86,6 +86,7 @@ inline CapabilityLevel canCompile(Node* node) > case GetGlobalVar: > case GetGlobalLexicalVariable: > case PutGlobalVariable: >+ case ValueNegate: > case ValueAdd: > case StrCat: > case ArithAdd: >diff --git a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >index 563de2b..cca064a 100644 >--- a/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >+++ b/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp >@@ -584,6 +584,9 @@ private: > case ToThis: > compileToThis(); > break; >+ case ValueNegate: >+ compileValueNegate(); >+ break; > case ValueAdd: > compileValueAdd(); > break; >@@ -2709,7 +2712,18 @@ private: > LValue result = vmCall(Double, m_out.operation(operationArithFRound), m_callFrame, argument); > setDouble(result); > } >- >+ >+ void compileValueNegate() >+ { >+ DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse); >+ CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic); >+ ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex); >+ Instruction* instruction = &baselineCodeBlock->instructions()[m_node->origin.semantic.bytecodeIndex]; >+ auto repatchingFunction = operationArithNegateOptimize; >+ auto nonRepatchingFunction = operationArithNegate; >+ compileUnaryMathIC<JITNegGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction); >+ } >+ > void compileArithNegate() > { > switch (m_node->child1().useKind()) { >@@ -2758,13 +2772,7 @@ private: > } > > default: >- DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == UntypedUse, m_node->child1().useKind()); >- CodeBlock* baselineCodeBlock = m_ftlState.graph.baselineCodeBlockFor(m_node->origin.semantic); >- ArithProfile* arithProfile = baselineCodeBlock->arithProfileForBytecodeOffset(m_node->origin.semantic.bytecodeIndex); >- Instruction* instruction = &baselineCodeBlock->instructions()[m_node->origin.semantic.bytecodeIndex]; >- auto repatchingFunction = operationArithNegateOptimize; >- auto nonRepatchingFunction = operationArithNegate; >- compileUnaryMathIC<JITNegGenerator>(arithProfile, instruction, repatchingFunction, nonRepatchingFunction); >+ DFG_CRASH(m_graph, m_node, "Bad use kind"); > break; > } > } >diff --git a/Source/JavaScriptCore/jit/JITOperations.cpp b/Source/JavaScriptCore/jit/JITOperations.cpp >index d3a2a8e..6ec866f 100644 >--- a/Source/JavaScriptCore/jit/JITOperations.cpp >+++ b/Source/JavaScriptCore/jit/JITOperations.cpp >@@ -2705,7 +2705,14 @@ ALWAYS_INLINE static EncodedJSValue unprofiledNegate(ExecState* exec, EncodedJSV > NativeCallFrameTracer tracer(&vm, exec); > > JSValue operand = JSValue::decode(encodedOperand); >- double number = operand.toNumber(exec); >+ >+ JSValue primValue = operand.toPrimitive(exec, PreferNumber); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ >+ if (primValue.isBigInt()) >+ return JSValue::encode(JSBigInt::unaryMinus(vm, asBigInt(primValue))); >+ >+ double number = primValue.toNumber(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > return JSValue::encode(jsNumber(-number)); > } >@@ -2718,9 +2725,19 @@ ALWAYS_INLINE static EncodedJSValue profiledNegate(ExecState* exec, EncodedJSVal > > JSValue operand = JSValue::decode(encodedOperand); > arithProfile.observeLHS(operand); >- double number = operand.toNumber(exec); >+ >+ JSValue primValue = operand.toPrimitive(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ >+ if (primValue.isBigInt()) { >+ JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue)); >+ arithProfile.observeResult(result); >+ >+ return JSValue::encode(result); >+ } > >+ double number = primValue.toNumber(exec); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); > JSValue result = jsNumber(-number); > arithProfile.observeResult(result); > return JSValue::encode(result); >@@ -2754,7 +2771,16 @@ EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(ExecState* exe > exec->codeBlock()->dumpMathICStats(); > #endif > >- double number = operand.toNumber(exec); >+ JSValue primValue = operand.toPrimitive(exec); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ >+ if (primValue.isBigInt()) { >+ JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue)); >+ arithProfile->observeResult(result); >+ return JSValue::encode(result); >+ } >+ >+ double number = primValue.toNumber(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > JSValue result = jsNumber(-number); > arithProfile->observeResult(result); >@@ -2777,7 +2803,15 @@ EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, Encod > exec->codeBlock()->dumpMathICStats(); > #endif > >- double number = operand.toNumber(exec); >+ JSValue primValue = operand.toPrimitive(exec); >+ RETURN_IF_EXCEPTION(scope, encodedJSValue()); >+ >+ if (primValue.isBigInt()) { >+ JSBigInt* result = JSBigInt::unaryMinus(vm, asBigInt(primValue)); >+ return JSValue::encode(result); >+ } >+ >+ double number = primValue.toNumber(exec); > RETURN_IF_EXCEPTION(scope, encodedJSValue()); > return JSValue::encode(jsNumber(-number)); > } >diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h >index 5c6dd33..65ad107 100644 >--- a/Source/JavaScriptCore/parser/ASTBuilder.h >+++ b/Source/JavaScriptCore/parser/ASTBuilder.h >@@ -1072,6 +1072,10 @@ private: > { > return new (m_parserArena) DoubleNode(location, d); > } >+ ExpressionNode* createBigIntWithSign(const JSTokenLocation& location, const Identifier& bigInt, uint8_t radix, bool sign) >+ { >+ return new (m_parserArena) BigIntNode(location, bigInt, radix, sign); >+ } > ExpressionNode* createNumberFromBinaryOperation(const JSTokenLocation& location, double value, const NumberNode& originalNodeA, const NumberNode& originalNodeB) > { > if (originalNodeA.isIntegerNode() && originalNodeB.isIntegerNode()) >@@ -1084,6 +1088,10 @@ private: > return createIntegerLikeNumber(location, value); > return createDoubleLikeNumber(location, value); > } >+ ExpressionNode* createBigIntFromUnaryOperation(const JSTokenLocation& location, bool sign, const BigIntNode& originalNode) >+ { >+ return createBigIntWithSign(location, originalNode.identifier(), originalNode.radix(), sign); >+ } > > void tryInferNameInPattern(DestructuringPattern pattern, ExpressionNode* defaultValue) > { >@@ -1156,6 +1164,11 @@ ExpressionNode* ASTBuilder::makeNegateNode(const JSTokenLocation& location, Expr > return createNumberFromUnaryOperation(location, -numberNode.value(), numberNode); > } > >+ if (n->isBigInt()) { >+ const BigIntNode& bigIntNode = static_cast<const BigIntNode&>(*n); >+ return createBigIntFromUnaryOperation(location, !bigIntNode.sign(), bigIntNode); >+ } >+ > return new (m_parserArena) NegateNode(location, n); > } > >diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h >index 5d77db1..5e113f3 100644 >--- a/Source/JavaScriptCore/parser/NodeConstructors.h >+++ b/Source/JavaScriptCore/parser/NodeConstructors.h >@@ -97,6 +97,15 @@ namespace JSC { > : ConstantNode(location, ResultType::bigIntType()) > , m_value(value) > , m_radix(radix) >+ , m_sign(false) >+ { >+ } >+ >+ inline BigIntNode::BigIntNode(const JSTokenLocation& location, const Identifier& value, uint8_t radix, bool sign) >+ : ConstantNode(location, ResultType::bigIntType()) >+ , m_value(value) >+ , m_radix(radix) >+ , m_sign(sign) > { > } > >diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h >index 6c0f2db..4365637 100644 >--- a/Source/JavaScriptCore/parser/Nodes.h >+++ b/Source/JavaScriptCore/parser/Nodes.h >@@ -345,14 +345,20 @@ namespace JSC { > class BigIntNode final : public ConstantNode { > public: > BigIntNode(const JSTokenLocation&, const Identifier&, uint8_t radix); >+ BigIntNode(const JSTokenLocation&, const Identifier&, uint8_t radix, bool sign); > const Identifier& value() { return m_value; } > >+ const Identifier& identifier() const { return m_value; } >+ uint8_t radix() const { return m_radix; } >+ bool sign() const { return m_sign; } >+ > private: > bool isBigInt() const final { return true; } > JSValue jsValue(BytecodeGenerator&) const final; > > const Identifier& m_value; > const uint8_t m_radix; >+ const bool m_sign; > }; > > class ThrowableExpressionData { >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index 5e842fb..cba4f5f 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -369,26 +369,29 @@ static void updateArithProfileForUnaryArithOp(Instruction* pc, JSValue result, J > { > ArithProfile& profile = *bitwise_cast<ArithProfile*>(&pc[3].u.operand); > profile.observeLHS(operand); >- ASSERT(result.isNumber()); >- if (!result.isInt32()) { >- if (operand.isInt32()) >- profile.setObservedInt32Overflow(); >- >- double doubleVal = result.asNumber(); >- if (!doubleVal && std::signbit(doubleVal)) >- profile.setObservedNegZeroDouble(); >- else { >- profile.setObservedNonNegZeroDouble(); >- >- // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. >- // Therefore, we will get a false positive if the result is that value. This is intentionally >- // done to simplify the checking algorithm. >- static const int64_t int52OverflowPoint = (1ll << 51); >- int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal)); >- if (int64Val >= int52OverflowPoint) >- profile.setObservedInt52Overflow(); >+ ASSERT(result.isNumber() || result.isBigInt()); >+ if (result.isNumber()) { >+ if (!result.isInt32()) { >+ if (operand.isInt32()) >+ profile.setObservedInt32Overflow(); >+ >+ double doubleVal = result.asNumber(); >+ if (!doubleVal && std::signbit(doubleVal)) >+ profile.setObservedNegZeroDouble(); >+ else { >+ profile.setObservedNonNegZeroDouble(); >+ >+ // The Int52 overflow check here intentionally omits 1ll << 51 as a valid negative Int52 value. >+ // Therefore, we will get a false positive if the result is that value. This is intentionally >+ // done to simplify the checking algorithm. >+ static const int64_t int52OverflowPoint = (1ll << 51); >+ int64_t int64Val = static_cast<int64_t>(std::abs(doubleVal)); >+ if (int64Val >= int52OverflowPoint) >+ profile.setObservedInt52Overflow(); >+ } > } >- } >+ } else >+ profile.setObservedNonNumber(); > } > #else > static void updateArithProfileForUnaryArithOp(Instruction*, JSValue, JSValue) { } >@@ -398,7 +401,18 @@ SLOW_PATH_DECL(slow_path_negate) > { > BEGIN(); > JSValue operand = OP_C(2).jsValue(); >- JSValue result = jsNumber(-operand.toNumber(exec)); >+ JSValue primValue = operand.toPrimitive(exec, PreferNumber); >+ CHECK_EXCEPTION(); >+ >+ if (primValue.isBigInt()) { >+ JSBigInt* result = JSBigInt::unaryMinus(exec->vm(), asBigInt(primValue)); >+ RETURN_WITH_PROFILING(result, { >+ updateArithProfileForUnaryArithOp(pc, result, operand); >+ }); >+ } >+ >+ JSValue result = jsNumber(-primValue.toNumber(exec)); >+ CHECK_EXCEPTION(); > RETURN_WITH_PROFILING(result, { > updateArithProfileForUnaryArithOp(pc, result, operand); > }); >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.cpp b/Source/JavaScriptCore/runtime/JSBigInt.cpp >index 0e021f1..cfee119 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.cpp >+++ b/Source/JavaScriptCore/runtime/JSBigInt.cpp >@@ -215,11 +215,11 @@ JSBigInt* JSBigInt::parseInt(ExecState* state, StringView s, ErrorParseMode pars > return parseInt(state, s.characters16(), s.length(), parserMode); > } > >-JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, StringView s, uint8_t radix, ErrorParseMode parserMode) >+JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, StringView s, uint8_t radix, ErrorParseMode parserMode, ParseIntSign sign) > { > if (s.is8Bit()) >- return parseInt(state, vm, s.characters8(), s.length(), 0, radix, parserMode, false); >- return parseInt(state, vm, s.characters16(), s.length(), 0, radix, parserMode, false); >+ return parseInt(state, vm, s.characters8(), s.length(), 0, radix, parserMode, sign, ParseIntMode::DisallowEmptyString); >+ return parseInt(state, vm, s.characters16(), s.length(), 0, radix, parserMode, sign, ParseIntMode::DisallowEmptyString); > } > > JSBigInt* JSBigInt::stringToBigInt(ExecState* state, StringView s) >@@ -1054,42 +1054,42 @@ JSBigInt* JSBigInt::parseInt(ExecState* state, CharType* data, unsigned length, > // Check Radix from frist characters > if (static_cast<unsigned>(p) + 1 < static_cast<unsigned>(length) && data[p] == '0') { > if (isASCIIAlphaCaselessEqual(data[p + 1], 'b')) >- return parseInt(state, vm, data, length, p + 2, 2, errorParseMode, false); >+ return parseInt(state, vm, data, length, p + 2, 2, errorParseMode, ParseIntSign::Unsigned, ParseIntMode::DisallowEmptyString); > > if (isASCIIAlphaCaselessEqual(data[p + 1], 'x')) >- return parseInt(state, vm, data, length, p + 2, 16, errorParseMode, false); >+ return parseInt(state, vm, data, length, p + 2, 16, errorParseMode, ParseIntSign::Unsigned, ParseIntMode::DisallowEmptyString); > > if (isASCIIAlphaCaselessEqual(data[p + 1], 'o')) >- return parseInt(state, vm, data, length, p + 2, 8, errorParseMode, false); >+ return parseInt(state, vm, data, length, p + 2, 8, errorParseMode, ParseIntSign::Unsigned, ParseIntMode::DisallowEmptyString); > } > >- bool sign = false; >+ ParseIntSign sign = ParseIntSign::Unsigned; > if (p < length) { > if (data[p] == '+') > ++p; > else if (data[p] == '-') { >- sign = true; >+ sign = ParseIntSign::Signed; > ++p; > } > } > >- JSBigInt* result = parseInt(state, vm, data, length, p, 10, errorParseMode); >+ JSBigInt* result = parseInt(state, vm, data, length, p, 10, errorParseMode, sign); > > if (result && !result->isZero()) >- result->setSign(sign); >+ result->setSign(sign == ParseIntSign::Signed); > > return result; > } > > template <typename CharType> >-JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode errorParseMode, bool allowEmptyString) >+JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode errorParseMode, ParseIntSign sign, ParseIntMode parseMode) > { > ASSERT(length >= 0); > unsigned p = startIndex; > > auto scope = DECLARE_THROW_SCOPE(vm); > >- if (!allowEmptyString && startIndex == length) { >+ if (parseMode != ParseIntMode::AllowEmptyString && startIndex == length) { > ASSERT(state); > if (errorParseMode == ErrorParseMode::ThrowExceptions) > throwVMError(state, scope, createSyntaxError(state, "Failed to parse String to BigInt")); >@@ -1133,6 +1133,7 @@ JSBigInt* JSBigInt::parseInt(ExecState* state, VM& vm, CharType* data, unsigned > result->inplaceMultiplyAdd(static_cast<Digit>(radix), static_cast<Digit>(digit)); > } > >+ result->setSign(sign == ParseIntSign::Signed ? true : false); > if (p == length) > return result->rightTrim(vm); > >diff --git a/Source/JavaScriptCore/runtime/JSBigInt.h b/Source/JavaScriptCore/runtime/JSBigInt.h >index 67650fc..533ff4a 100644 >--- a/Source/JavaScriptCore/runtime/JSBigInt.h >+++ b/Source/JavaScriptCore/runtime/JSBigInt.h >@@ -72,13 +72,16 @@ public: > void setLength(unsigned length) { m_length = length; } > unsigned length() const { return m_length; } > >- enum ErrorParseMode { >+ enum class ErrorParseMode { > ThrowExceptions, > IgnoreExceptions > }; > >- static JSBigInt* parseInt(ExecState*, VM&, StringView, uint8_t radix, ErrorParseMode = ThrowExceptions); >- static JSBigInt* parseInt(ExecState*, StringView, ErrorParseMode = ThrowExceptions); >+ enum class ParseIntMode { DisallowEmptyString, AllowEmptyString }; >+ enum class ParseIntSign { Unsigned, Signed }; >+ >+ static JSBigInt* parseInt(ExecState*, VM&, StringView, uint8_t radix, ErrorParseMode = ErrorParseMode::ThrowExceptions, ParseIntSign = ParseIntSign::Unsigned); >+ static JSBigInt* parseInt(ExecState*, StringView, ErrorParseMode = ErrorParseMode::ThrowExceptions); > static JSBigInt* stringToBigInt(ExecState*, StringView); > > std::optional<uint8_t> singleDigitValueForString(); >@@ -156,7 +159,7 @@ private: > static JSBigInt* parseInt(ExecState*, CharType* data, unsigned length, ErrorParseMode); > > template <typename CharType> >- static JSBigInt* parseInt(ExecState*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode, bool allowEmptyString = true); >+ static JSBigInt* parseInt(ExecState*, VM&, CharType* data, unsigned length, unsigned startIndex, unsigned radix, ErrorParseMode, ParseIntSign = ParseIntSign::Signed, ParseIntMode = ParseIntMode::AllowEmptyString); > > static JSBigInt* allocateFor(ExecState*, VM&, unsigned radix, unsigned charcount); > >diff --git a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >index 55b1218..2d46b8d 100644 >--- a/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >+++ b/Source/JavaScriptCore/runtime/JSCJSValueInlines.h >@@ -1100,7 +1100,7 @@ ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v > if (v1.asCell()->isString() && v2.asCell()->isString()) > return asString(v1)->equal(exec, asString(v2)); > if (v1.isBigInt() && v2.isBigInt()) >- return JSBigInt::equals(asBigInt(v1.asCell()), asBigInt(v2.asCell())); >+ return JSBigInt::equals(asBigInt(v1), asBigInt(v2)); > return v1 == v2; > } >
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 182214
:
332473
|
332485
|
332486
|
333018
|
333056
|
335475
|
337703
|
337718
|
338072
|
338075
|
338579
|
338956
|
339233
|
339241
|
339254
|
339646
|
340157
|
340263
|
340265
|
340270
|
340808
|
340812
|
341279
| 341440