Source/JavaScriptCore/ChangeLog

 12019-02-17 Caio Lima <ticaiolima@gmail.com>
 2
 3 [ESNext][BigInt] Implement support for "**"
 4 https://bugs.webkit.org/show_bug.cgi?id=190799
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 We are introducing support for BigInt into "**" operator. This Patch
 9 also includes changes into DFG, introducing a new node "ValuePow" that
 10 is responsible to handle UntypedUse and BigIntUse.
 11
 12 * dfg/DFGAbstractInterpreterInlines.h:
 13 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
 14 * dfg/DFGByteCodeParser.cpp:
 15 (JSC::DFG::ByteCodeParser::parseBlock):
 16 * dfg/DFGClobberize.h:
 17 (JSC::DFG::clobberize):
 18 * dfg/DFGDoesGC.cpp:
 19 (JSC::DFG::doesGC):
 20 * dfg/DFGFixupPhase.cpp:
 21 (JSC::DFG::FixupPhase::fixupArithPow):
 22 (JSC::DFG::FixupPhase::fixupNode):
 23 * dfg/DFGNodeType.h:
 24 * dfg/DFGOperations.cpp:
 25 * dfg/DFGOperations.h:
 26 * dfg/DFGPredictionPropagationPhase.cpp:
 27 * dfg/DFGSafeToExecute.h:
 28 (JSC::DFG::safeToExecute):
 29 * dfg/DFGSpeculativeJIT.cpp:
 30 (JSC::DFG::SpeculativeJIT::compileValuePow):
 31 * dfg/DFGSpeculativeJIT.h:
 32 * dfg/DFGSpeculativeJIT32_64.cpp:
 33 (JSC::DFG::SpeculativeJIT::compile):
 34 * dfg/DFGSpeculativeJIT64.cpp:
 35 (JSC::DFG::SpeculativeJIT::compile):
 36 * dfg/DFGValidate.cpp:
 37 * ftl/FTLCapabilities.cpp:
 38 (JSC::FTL::canCompile):
 39 * ftl/FTLLowerDFGToB3.cpp:
 40 (JSC::FTL::DFG::LowerDFGToB3::compileNode):
 41 (JSC::FTL::DFG::LowerDFGToB3::compileValuePow):
 42 * runtime/CommonSlowPaths.cpp:
 43 (JSC::SLOW_PATH_DECL):
 44 * runtime/JSBigInt.cpp:
 45 (JSC::JSBigInt::exponentiate):
 46 * runtime/JSBigInt.h:
 47
1482019-02-17 Commit Queue <commit-queue@webkit.org>
249
350 Unreviewed, rolling out r241612.

Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

@@bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
856856 }
857857 break;
858858 }
859 
 859
 860 case ValuePow: {
 861 JSValue childX = forNode(node->child1()).value();
 862 JSValue childY = forNode(node->child2()).value();
 863 if (childX && childY && childX.isNumber() && childY.isNumber()) {
 864 didFoldClobberWorld();
 865 setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
 866 break;
 867 }
 868
 869 if (node->binaryUseKind() == BigIntUse)
 870 setTypeForNode(node, SpecBigInt);
 871 else {
 872 clobberWorld();
 873 setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
 874 }
 875 break;
 876 }
 877
860878 case ValueMul: {
861879 if (node->binaryUseKind() == BigIntUse)
862880 setTypeForNode(node, SpecBigInt);

Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

@@void ByteCodeParser::parseBlock(unsigned limit)
50605060 }
50615061
50625062 case op_pow: {
5063  // FIXME: ArithPow(Untyped, Untyped) should be supported as the same to ArithMul, ArithSub etc.
5064  // https://bugs.webkit.org/show_bug.cgi?id=160012
50655063 auto bytecode = currentInstruction->as<OpPow>();
50665064 Node* op1 = get(bytecode.m_lhs);
50675065 Node* op2 = get(bytecode.m_rhs);
5068  set(bytecode.m_dst, addToGraph(ArithPow, op1, op2));
 5066 if (op1->hasNumberOrAnyIntResult() && op2->hasNumberOrAnyIntResult())
 5067 set(bytecode.m_dst, addToGraph(ArithPow, op1, op2));
 5068 else
 5069 set(bytecode.m_dst, addToGraph(ValuePow, op1, op2));
50695070 NEXT_OPCODE(op_pow);
50705071 }
50715072

Source/JavaScriptCore/dfg/DFGClobberize.h

@@void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
670670 case ValueSub:
671671 case ValueMul:
672672 case ValueDiv:
 673 case ValuePow:
673674 if (node->isBinaryUseKind(BigIntUse)) {
674675 def(PureValue(node));
675676 return;

Source/JavaScriptCore/dfg/DFGDoesGC.cpp

@@bool doesGC(Graph& graph, Node* node)
384384 case ValueSub:
385385 case ValueMul:
386386 case ValueDiv:
 387 case ValuePow:
387388 case ValueNegate:
388389#else
389390 // See comment at the top for why be default for all nodes should be to

Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

@@public:
7575 }
7676
7777private:
 78 void fixupArithPow(Node* node)
 79 {
 80 if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
 81 fixDoubleOrBooleanEdge(node->child1());
 82 fixIntOrBooleanEdge(node->child2());
 83 return;
 84 }
 85
 86 fixDoubleOrBooleanEdge(node->child1());
 87 fixDoubleOrBooleanEdge(node->child2());
 88 }
 89
7890 void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild)
7991 {
8092 if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {

@@private:
561573 break;
562574 }
563575
564  case ArithPow: {
565  if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
566  fixDoubleOrBooleanEdge(node->child1());
567  fixIntOrBooleanEdge(node->child2());
 576 case ValuePow: {
 577 if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
 578 fixEdge<BigIntUse>(node->child1());
 579 fixEdge<BigIntUse>(node->child2());
 580 node->clearFlags(NodeMustGenerate);
568581 break;
569582 }
570583
571  fixDoubleOrBooleanEdge(node->child1());
572  fixDoubleOrBooleanEdge(node->child2());
 584 if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
 585 fixEdge<UntypedUse>(node->child1());
 586 fixEdge<UntypedUse>(node->child2());
 587 break;
 588 }
 589
 590 node->setOp(ArithPow);
 591 node->clearFlags(NodeMustGenerate);
 592 node->setResult(NodeResultDouble);
 593
 594 fixupArithPow(node);
 595 break;
 596 }
 597
 598 case ArithPow: {
 599 fixupArithPow(node);
573600 break;
574601 }
575602

Source/JavaScriptCore/dfg/DFGNodeType.h

@@namespace JSC { namespace DFG {
176176 macro(ValueSub, NodeResultJS | NodeMustGenerate) \
177177 macro(ValueMul, NodeResultJS | NodeMustGenerate) \
178178 macro(ValueDiv, NodeResultJS | NodeMustGenerate) \
 179 macro(ValuePow, NodeResultJS | NodeMustGenerate) \
179180 \
180181 /* Add of values that always convers its inputs to strings. May have two or three kids. */\
181182 macro(StrCat, NodeResultJS | NodeMustGenerate) \

Source/JavaScriptCore/dfg/DFGOperations.cpp

@@EncodedJSValue JIT_OPERATION operationValueDiv(ExecState* exec, EncodedJSValue e
537537 return JSValue::encode(jsNumber(a / b));
538538}
539539
 540EncodedJSValue JIT_OPERATION operationValuePow(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 541{
 542 VM* vm = &exec->vm();
 543 NativeCallFrameTracer tracer(vm, exec);
 544 auto scope = DECLARE_THROW_SCOPE(*vm);
 545
 546 JSValue op1 = JSValue::decode(encodedOp1);
 547 JSValue op2 = JSValue::decode(encodedOp2);
 548
 549 auto leftNumeric = op1.toNumeric(exec);
 550 RETURN_IF_EXCEPTION(scope, encodedJSValue());
 551 auto rightNumeric = op2.toNumeric(exec);
 552 RETURN_IF_EXCEPTION(scope, encodedJSValue());
 553
 554 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
 555 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric))
 556 RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::exponentiate(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric))));
 557
 558 return throwVMTypeError(exec, scope, "Invalid mix of BigInt and other type in exponentiation operation.");
 559 }
 560
 561 scope.release();
 562
 563 double a = WTF::get<double>(leftNumeric);
 564 double b = WTF::get<double>(rightNumeric);
 565 return JSValue::encode(jsNumber(operationMathPow(a, b)));
 566}
 567
540568double JIT_OPERATION operationArithAbs(ExecState* exec, EncodedJSValue encodedOp1)
541569{
542570 VM* vm = &exec->vm();

@@JSCell* JIT_OPERATION operationDivBigInt(ExecState* exec, JSCell* op1, JSCell* o
13551383 return JSBigInt::divide(exec, leftOperand, rightOperand);
13561384}
13571385
 1386JSCell* JIT_OPERATION operationPowBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
 1387{
 1388 VM* vm = &exec->vm();
 1389 NativeCallFrameTracer tracer(vm, exec);
 1390
 1391 JSBigInt* leftOperand = jsCast<JSBigInt*>(op1);
 1392 JSBigInt* rightOperand = jsCast<JSBigInt*>(op2);
 1393
 1394 return JSBigInt::exponentiate(exec, leftOperand, rightOperand);
 1395}
 1396
13581397JSCell* JIT_OPERATION operationBitAndBigInt(ExecState* exec, JSCell* op1, JSCell* op2)
13591398{
13601399 VM* vm = &exec->vm();

Source/JavaScriptCore/dfg/DFGOperations.h

@@EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState*, EncodedJSValue
5959EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
6060EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
6161EncodedJSValue JIT_OPERATION operationValueDiv(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
 62EncodedJSValue JIT_OPERATION operationValuePow(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
6263double JIT_OPERATION operationArithAbs(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
6364uint32_t JIT_OPERATION operationArithClz32(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
6465double JIT_OPERATION operationArithFRound(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;

@@size_t JIT_OPERATION operationCompareStrictEqCell(ExecState*, JSCell* op1, JSCel
169170JSCell* JIT_OPERATION operationSubBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
170171JSCell* JIT_OPERATION operationMulBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
171172JSCell* JIT_OPERATION operationDivBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
 173JSCell* JIT_OPERATION operationPowBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
172174JSCell* JIT_OPERATION operationBitAndBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
173175JSCell* JIT_OPERATION operationBitOrBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;
174176JSCell* JIT_OPERATION operationAddBigInt(ExecState*, JSCell* op1, JSCell* op2) WTF_INTERNAL;

Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

@@private:
277277 break;
278278 }
279279
 280 case ValuePow: {
 281 SpeculatedType left = node->child1()->prediction();
 282 SpeculatedType right = node->child2()->prediction();
 283
 284 if (left && right) {
 285 if (node->child1()->shouldSpeculateBigInt() && node->child2()->shouldSpeculateBigInt())
 286 changed |= mergePrediction(SpecBigInt);
 287 else if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
 288 && isFullNumberOrBooleanSpeculationExpectingDefined(right))
 289 setPrediction(SpecBytecodeDouble);
 290 else
 291 setPrediction(SpecBytecodeDouble | SpecBigInt);
 292 }
 293 break;
 294 }
 295
280296 case ValueNegate:
281297 case ArithNegate: {
282298 SpeculatedType prediction = node->child1()->prediction();

@@private:
11171133 case ValueSub:
11181134 case ValueMul:
11191135 case ValueDiv:
 1136 case ValuePow:
11201137 case ArithAdd:
11211138 case ArithSub:
11221139 case ArithNegate:

Source/JavaScriptCore/dfg/DFGSafeToExecute.h

@@bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
236236 case ValueSub:
237237 case ValueMul:
238238 case ValueDiv:
 239 case ValuePow:
239240 case TryGetById:
240241 case DeleteById:
241242 case DeleteByVal:

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

@@static MacroAssembler::Jump compileArithPowIntegerFastPath(JITCompiler& assemble
57915791 return skipSlowPath;
57925792}
57935793
 5794void SpeculativeJIT::compileValuePow(Node* node)
 5795{
 5796 Edge& leftChild = node->child1();
 5797 Edge& rightChild = node->child2();
 5798
 5799 if (node->binaryUseKind() == BigIntUse) {
 5800 SpeculateCellOperand left(this, leftChild);
 5801 SpeculateCellOperand right(this, rightChild);
 5802 GPRReg leftGPR = left.gpr();
 5803 GPRReg rightGPR = right.gpr();
 5804
 5805 speculateBigInt(leftChild, leftGPR);
 5806 speculateBigInt(rightChild, rightGPR);
 5807
 5808 flushRegisters();
 5809 GPRFlushedCallResult result(this);
 5810 GPRReg resultGPR = result.gpr();
 5811
 5812 callOperation(operationPowBigInt, resultGPR, leftGPR, rightGPR);
 5813
 5814 m_jit.exceptionCheck();
 5815 cellResult(resultGPR, node);
 5816 return;
 5817 }
 5818
 5819 DFG_ASSERT(m_jit.graph(), node, node->binaryUseKind() == UntypedUse, node->binaryUseKind());
 5820
 5821 JSValueOperand left(this, leftChild);
 5822 JSValueOperand right(this, rightChild);
 5823 JSValueRegs leftRegs = left.jsValueRegs();
 5824 JSValueRegs rightRegs = right.jsValueRegs();
 5825
 5826 flushRegisters();
 5827 JSValueRegsFlushedCallResult result(this);
 5828 JSValueRegs resultRegs = result.regs();
 5829 callOperation(operationValuePow, resultRegs, leftRegs, rightRegs);
 5830 m_jit.exceptionCheck();
 5831
 5832 jsValueResult(resultRegs, node);
 5833}
 5834
57945835void SpeculativeJIT::compileArithPow(Node* node)
57955836{
57965837 if (node->child2().useKind() == Int32Use) {

Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

@@public:
13621362 void compileArithFRound(Node*);
13631363 void compileArithMod(Node*);
13641364 void compileArithPow(Node*);
 1365 void compileValuePow(Node*);
13651366 void compileArithRounding(Node*);
13661367 void compileArithRandom(Node*);
13671368 void compileArithUnary(Node*);

Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

@@void SpeculativeJIT::compile(Node* node)
20862086 break;
20872087 }
20882088
 2089 case ValuePow: {
 2090 compileValuePow(node);
 2091 break;
 2092 }
 2093
20892094 case ArithPow: {
20902095 compileArithPow(node);
20912096 break;

Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

@@void SpeculativeJIT::compile(Node* node)
22382238 break;
22392239 }
22402240
 2241 case ValuePow:
 2242 compileValuePow(node);
 2243 break;
 2244
22412245 case ArithPow:
22422246 compileArithPow(node);
22432247 break;

Source/JavaScriptCore/dfg/DFGValidate.cpp

@@public:
257257 case ValueSub:
258258 case ValueMul:
259259 case ValueDiv:
 260 case ValuePow:
260261 case ArithAdd:
261262 case ArithSub:
262263 case ArithMul:

Source/JavaScriptCore/ftl/FTLCapabilities.cpp

@@inline CapabilityLevel canCompile(Node* node)
9696 case ValueSub:
9797 case ValueMul:
9898 case ValueDiv:
 99 case ValuePow:
99100 case StrCat:
100101 case ArithAdd:
101102 case ArithClz32:

Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

@@private:
629629 case ArithAbs:
630630 compileArithAbs();
631631 break;
 632 case ValuePow:
 633 compileValuePow();
 634 break;
632635 case ArithPow:
633636 compileArithPow();
634637 break;

@@private:
25252528 setDouble(result);
25262529 }
25272530
 2531 void compileValuePow()
 2532 {
 2533 if (m_node->isBinaryUseKind(BigIntUse)) {
 2534 LValue base = lowBigInt(m_node->child1());
 2535 LValue exponent = lowBigInt(m_node->child2());
 2536
 2537 LValue result = vmCall(pointerType(), m_out.operation(operationPowBigInt), m_callFrame, base, exponent);
 2538 setJSValue(result);
 2539 return;
 2540 }
 2541
 2542 LValue base = lowJSValue(m_node->child1());
 2543 LValue exponent = lowJSValue(m_node->child2());
 2544 LValue result = vmCall(Int64, m_out.operation(operationValuePow), m_callFrame, base, exponent);
 2545 setJSValue(result);
 2546 }
 2547
25282548 void compileArithPow()
25292549 {
25302550 if (m_node->child2().useKind() == Int32Use)

Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

@@SLOW_PATH_DECL(slow_path_pow)
635635{
636636 BEGIN();
637637 auto bytecode = pc->as<OpPow>();
638  double a = GET_C(bytecode.m_lhs).jsValue().toNumber(exec);
639  if (UNLIKELY(throwScope.exception()))
640  RETURN(JSValue());
641  double b = GET_C(bytecode.m_rhs).jsValue().toNumber(exec);
642  if (UNLIKELY(throwScope.exception()))
643  RETURN(JSValue());
 638 JSValue left = GET_C(bytecode.m_lhs).jsValue();
 639 JSValue right = GET_C(bytecode.m_rhs).jsValue();
 640 auto leftNumeric = left.toNumeric(exec);
 641 CHECK_EXCEPTION();
 642 auto rightNumeric = right.toNumeric(exec);
 643 CHECK_EXCEPTION();
 644
 645 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
 646 if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
 647 JSBigInt* result = JSBigInt::exponentiate(exec, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
 648 CHECK_EXCEPTION();
 649 RETURN(result);
 650 }
 651
 652 THROW(createTypeError(exec, "Invalid mix of BigInt and other type in exponentiation operation."));
 653 }
 654
 655 double a = WTF::get<double>(leftNumeric);
 656 double b = WTF::get<double>(rightNumeric);
 657
644658 RETURN(jsNumber(operationMathPow(a, b)));
645659}
646660

Source/JavaScriptCore/runtime/JSBigInt.cpp

@@void JSBigInt::inplaceMultiplyAdd(Digit factor, Digit summand)
237237 internalMultiplyAdd(this, factor, summand, length(), this);
238238}
239239
 240JSBigInt* JSBigInt::exponentiate(ExecState* exec, JSBigInt* base, JSBigInt* exponent)
 241{
 242 VM& vm = exec->vm();
 243 auto scope = DECLARE_THROW_SCOPE(vm);
 244
 245 if (exponent->sign()) {
 246 throwRangeError(exec, scope, "Negative exponent is not allowed"_s);
 247 return nullptr;
 248 }
 249
 250 // 2. If base is 0n and exponent is 0n, return 1n.
 251 if (exponent->isZero())
 252 return JSBigInt::createFrom(vm, 1);
 253
 254 // 3. Return a BigInt representing the mathematical value of base raised
 255 // to the power exponent.
 256 if (base->isZero())
 257 return base;
 258
 259 if (base->length() == 1 && base->digit(0) == 1) {
 260 // (-1) ** even_number == 1.
 261 if (base->sign() && !(exponent->digit(0) & 1))
 262 return JSBigInt::unaryMinus(vm, base);
 263
 264 // (-1) ** odd_number == -1; 1 ** anything == 1.
 265 return base;
 266 }
 267
 268 // For all bases >= 2, very large exponents would lead to unrepresentable
 269 // results.
 270 static_assert(maxLengthBits < std::numeric_limits<Digit>::max(), "maxLengthBits needs to be less than digit::max()");
 271 if (exponent->length() > 1) {
 272 throwRangeError(exec, scope, "BigInt generated from this operation is too big"_s);
 273 return nullptr;
 274 }
 275
 276 Digit expValue = exponent->digit(0);
 277 if (expValue == 1)
 278 return base;
 279 if (expValue >= maxLengthBits) {
 280 throwRangeError(exec, scope, "BigInt generated from this operation is too big"_s);
 281 return nullptr;
 282 }
 283
 284 static_assert(maxLengthBits <= maxInt, "maxLengthBits needs to be <= maxInt");
 285 int n = static_cast<int>(expValue);
 286 if (base->length() == 1 && base->digit(0) == 2) {
 287 // Fast path for 2^n.
 288 int neededDigits = 1 + (n / digitBits);
 289 JSBigInt* result = JSBigInt::tryCreateWithLength(exec, neededDigits);
 290 if (!result)
 291 return nullptr;
 292
 293 result->initialize(InitializationType::WithZero);
 294 // All bits are zero. Now set the n-th bit.
 295 Digit msd = static_cast<Digit>(1) << (n % digitBits);
 296 result->setDigit(neededDigits - 1, msd);
 297 // Result is negative for odd powers of -2n.
 298 if (base->sign())
 299 result->setSign(static_cast<bool>(n & 1));
 300
 301 return result;
 302 }
 303
 304 JSBigInt* result = nullptr;
 305 JSBigInt* runningSquare = base;
 306
 307 // This implicitly sets the result's sign correctly.
 308 if (n & 1)
 309 result = base;
 310
 311 n >>= 1;
 312 for (; n; n >>= 1) {
 313 JSBigInt* maybeResult = JSBigInt::multiply(exec, runningSquare, runningSquare);
 314 if (!maybeResult)
 315 return nullptr;
 316
 317 runningSquare = maybeResult;
 318 if (n & 1) {
 319 if (!result)
 320 result = runningSquare;
 321 else {
 322 maybeResult = JSBigInt::multiply(exec, result, runningSquare);
 323 if (!maybeResult)
 324 return nullptr;
 325 result = maybeResult;
 326 }
 327 }
 328 }
 329
 330 return result;
 331}
 332
240333JSBigInt* JSBigInt::multiply(ExecState* exec, JSBigInt* x, JSBigInt* y)
241334{
242335 VM& vm = exec->vm();

@@void JSBigInt::absoluteDivWithBigIntDivisor(ExecState* exec, JSBigInt* dividend,
10491142 }
10501143}
10511144
1052 // Returns whether (factor1 * factor2) > (high << kDigitBits) + low.
 1145// Returns whether (factor1 * factor2) > (high << digitBits) + low.
10531146inline bool JSBigInt::productGreaterThan(Digit factor1, Digit factor2, Digit high, Digit low)
10541147{
10551148 Digit resultHigh;

Source/JavaScriptCore/runtime/JSBigInt.h

@@public:
111111 JSObject* toObject(ExecState*, JSGlobalObject*) const;
112112 inline bool toBoolean() const { return !isZero(); }
113113
 114 static JSBigInt* exponentiate(ExecState*, JSBigInt* base, JSBigInt* exponent);
 115
114116 static JSBigInt* multiply(ExecState*, JSBigInt* x, JSBigInt* y);
115117
116118 ComparisonResult static compareToDouble(JSBigInt* x, double y);

JSTests/ChangeLog

 12019-02-17 Caio Lima <ticaiolima@gmail.com>
 2
 3 [ESNext][BigInt] Implement support for "**"
 4 https://bugs.webkit.org/show_bug.cgi?id=190799
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * stress/big-int-exp-basic.js: Added.
 9 * stress/big-int-exp-jit-osr.js: Added.
 10 * stress/big-int-exp-jit-untyped.js: Added.
 11 * stress/big-int-exp-jit.js: Added.
 12 * stress/big-int-exp-negative-exponent.js: Added.
 13 * stress/big-int-exp-to-primitive.js: Added.
 14 * stress/big-int-exp-type-error.js: Added.
 15 * stress/big-int-exp-wrapped-value.js: Added.
 16
1172019-02-15 Michael Saboff <msaboff@apple.com>
218
319 RELEASE_ASSERT at com.apple.JavaScriptCore: JSC::jsSubstringOfResolved

JSTests/stress/big-int-exp-basic.js

 1//@ runBigIntEnabled
 2
 3// Copyright (C) 2017 Robin Templeton. All rights reserved.
 4// This code is governed by the BSD license found in the LICENSE file.
 5
 6var assert = {
 7 sameValue: function (input, expected, message) {
 8 if (input !== expected)
 9 throw new Error(message);
 10 }
 11};
 12
 13assert.sameValue(
 14 0x123n ** 0x123n,
 15 0x37AA7FAA38F2F6026AABEFE979EA730BA9EA4CB99E2E3F645D515D3BBE2D84BCD89F8A034BADF3E3DC0CF417258371B31F4555DC0883DA96760AB157DB7DFFF5E3E97A3EAAB8328B2B178060B5A5E4C4DD8BC8D66B7F4D9F0E0B1AC3A566FDE0A15EBF8DBDBD0565C5FBDB7C123CF250E271DF5C38BC6746A1327F09C7FB4B96E0EDA45C429799CA80B1DB039692C70DFFE4E66F1D9CAB4270863B09A7918F774D686F685F560FEDC6B7B85CB45DE5EEEF6A5FE2FC8B5037FB421204641909347C91F2DC252F49B8F310E867E56D1CA2E81EE9A3AA568682C7B8B41D709A2E7F8D9A8D8C56D6BE78B6CA8365E362B81A64974C315FB8FA50CED4F7944F28FA3ECA77B8BCB56DC69814328F891E6065D108EEE7B8E695038090CCA10C0E68DD7A36CFAA1C26CDFEC369FBn,
 16 'The result of (0x123n ** 0x123n) is 0x37AA7FAA38F2F6026AABEFE979EA730BA9EA4CB99E2E3F645D515D3BBE2D84BCD89F8A034BADF3E3DC0CF417258371B31F4555DC0883DA96760AB157DB7DFFF5E3E97A3EAAB8328B2B178060B5A5E4C4DD8BC8D66B7F4D9F0E0B1AC3A566FDE0A15EBF8DBDBD0565C5FBDB7C123CF250E271DF5C38BC6746A1327F09C7FB4B96E0EDA45C429799CA80B1DB039692C70DFFE4E66F1D9CAB4270863B09A7918F774D686F685F560FEDC6B7B85CB45DE5EEEF6A5FE2FC8B5037FB421204641909347C91F2DC252F49B8F310E867E56D1CA2E81EE9A3AA568682C7B8B41D709A2E7F8D9A8D8C56D6BE78B6CA8365E362B81A64974C315FB8FA50CED4F7944F28FA3ECA77B8BCB56DC69814328F891E6065D108EEE7B8E695038090CCA10C0E68DD7A36CFAA1C26CDFEC369FBn'
 17);
 18
 19assert.sameValue(
 20 0x123n ** 0xFFn,
 21 0x8D5BB75861377EC967BF78FDF39CE51696FBD34722999943F8865938772B517167CD5ED775A78987F5106831F4978E0709032B26ED8F13F814699DB8AB3ACD5CF631F2D8B8B706FCF5EF441AAEE745A795EC5CB86A5E8D87D09F648EFC557B98F73E750FEC9AED061D47806F269CCCDFB6D513912A82AE79B171D76AF6D926BC4F4C4DA43A6EFB4D9D1672E356CC1F74A29AF80D53A8F27592F6191AB9B3D57FA2C435CB2CE8F18A3B3448F88F4BAD3606A9878DA9528B569BADAC0C1EC0B1A2B06CD4C64DEEC940807DFD05C56E3E17ADB1A88EDAF0D67C87C1F871BFB5C47CAE8365FE33538317EE2DF4EE52636CE1BDA9E41C7DA72826E4C097A53BD73D8D697E10D28Bn,
 22 'The result of (0x123n ** 0xFFn) is 0x8D5BB75861377EC967BF78FDF39CE51696FBD34722999943F8865938772B517167CD5ED775A78987F5106831F4978E0709032B26ED8F13F814699DB8AB3ACD5CF631F2D8B8B706FCF5EF441AAEE745A795EC5CB86A5E8D87D09F648EFC557B98F73E750FEC9AED061D47806F269CCCDFB6D513912A82AE79B171D76AF6D926BC4F4C4DA43A6EFB4D9D1672E356CC1F74A29AF80D53A8F27592F6191AB9B3D57FA2C435CB2CE8F18A3B3448F88F4BAD3606A9878DA9528B569BADAC0C1EC0B1A2B06CD4C64DEEC940807DFD05C56E3E17ADB1A88EDAF0D67C87C1F871BFB5C47CAE8365FE33538317EE2DF4EE52636CE1BDA9E41C7DA72826E4C097A53BD73D8D697E10D28Bn'
 23);
 24
 25assert.sameValue(0x123n ** 0x3n, 0x178027Bn, 'The result of (0x123n ** 0x3n) is 0x178027Bn');
 26assert.sameValue(0x123n ** 0x2n, 0x14AC9n, 'The result of (0x123n ** 0x2n) is 0x14AC9n');
 27assert.sameValue(0x123n ** 0x1n, 0x123n, 'The result of (0x123n ** 0x1n) is 0x123n');
 28
 29assert.sameValue(
 30 0xFFn ** 0x123n,
 31 0x51F5CA2E1A36F5FF1ED3D393D76FBC3612B38EB64E00EDAC5E95ADE0D16D0B044C8E9F2B77B3F31AF9159F482205541E9D3BE9D248FF39CE6524874EBCA60E06302E8B505D11EEEEE869C7F801A82B9739C197E6D63A1EB2D29B5AD5EED4773C762106E9F66BFCB6C11450218973C69DED3FE51FF881AD0430675BF54320513EA766117C50C554E86E22A5ACFD8047D5470B4FCBCB9EFC86196CA77C58F1BEB09F76160D641B82E2481BEDAE089207D49FE0FB7DE14B6C4BC82E9C58140746AC8E74C3353AAF5F9CF47ED1F87C52F463C053DB63CD08CC9866EBA274D39B6B357ADADAD4D210167EF7363453D42BC225D90070336861F2D259489D78B7F04B05FE65E29151ADD2B8F4D318011988550CE590DBA4C868AC65AA325051DF613D6C2E22FFn,
 32 'The result of (0xFFn ** 0x123n) is 0x51F5CA2E1A36F5FF1ED3D393D76FBC3612B38EB64E00EDAC5E95ADE0D16D0B044C8E9F2B77B3F31AF9159F482205541E9D3BE9D248FF39CE6524874EBCA60E06302E8B505D11EEEEE869C7F801A82B9739C197E6D63A1EB2D29B5AD5EED4773C762106E9F66BFCB6C11450218973C69DED3FE51FF881AD0430675BF54320513EA766117C50C554E86E22A5ACFD8047D5470B4FCBCB9EFC86196CA77C58F1BEB09F76160D641B82E2481BEDAE089207D49FE0FB7DE14B6C4BC82E9C58140746AC8E74C3353AAF5F9CF47ED1F87C52F463C053DB63CD08CC9866EBA274D39B6B357ADADAD4D210167EF7363453D42BC225D90070336861F2D259489D78B7F04B05FE65E29151ADD2B8F4D318011988550CE590DBA4C868AC65AA325051DF613D6C2E22FFn'
 33);
 34
 35assert.sameValue(
 36 0xFFn ** 0xFFn,
 37 0x5E5C8B0EB95AB08F9D37EF127FC01BD0E33DE52647528396D78D5F8DA31989E67814F6BBA1FB0F0207010FF5F2347B19D5F6598FC91BF5A88F77DAA3D7B382FEC484F3D205C06A34445384C0E7AB0D883788C68C012CB433055EDDA746A48409444EA91147273B79FC3EABB70ECA552AF650C234BB01ED404427F17CDDDD71D08E39EF9C3982E3CE44E670456AA8154C1FDBD9C35947F494636A425C69BF89E9C75AD3B7A0A559AF0F5DA9947C8DEBA64417310713B23E7EF4DE50BB2A3E90BC2AC3DA5201CCA8D6E5DFEA887C4F7A4E92175D9F88BD2779B57F9EB35BE7528F965A06DA0AC41DCB3A34F1D8AB7D8FEE620A94FAA42C395997756B007FFEFFn,
 38 'The result of (0xFFn ** 0xFFn) is 0x5E5C8B0EB95AB08F9D37EF127FC01BD0E33DE52647528396D78D5F8DA31989E67814F6BBA1FB0F0207010FF5F2347B19D5F6598FC91BF5A88F77DAA3D7B382FEC484F3D205C06A34445384C0E7AB0D883788C68C012CB433055EDDA746A48409444EA91147273B79FC3EABB70ECA552AF650C234BB01ED404427F17CDDDD71D08E39EF9C3982E3CE44E670456AA8154C1FDBD9C35947F494636A425C69BF89E9C75AD3B7A0A559AF0F5DA9947C8DEBA64417310713B23E7EF4DE50BB2A3E90BC2AC3DA5201CCA8D6E5DFEA887C4F7A4E92175D9F88BD2779B57F9EB35BE7528F965A06DA0AC41DCB3A34F1D8AB7D8FEE620A94FAA42C395997756B007FFEFFn'
 39);
 40
 41assert.sameValue(0xFFn ** 0x3n, 0xFD02FFn, 'The result of (0xFFn ** 0x3n) is 0xFD02FFn');
 42assert.sameValue(0xFFn ** 0x2n, 0xFE01n, 'The result of (0xFFn ** 0x2n) is 0xFE01n');
 43assert.sameValue(0xFFn ** 0x1n, 0xFFn, 'The result of (0xFFn ** 0x1n) is 0xFFn');
 44
 45assert.sameValue(
 46 0x3n ** 0x123n,
 47 0x25609213623D7D6219085CF49D306450BF6519835586C19D3A4F3A2C5F35B44A300C8A76E11708B5495B9C3EE756BBF19E3FD15CE625D3C0539Bn,
 48 'The result of (0x3n ** 0x123n) is 0x25609213623D7D6219085CF49D306450BF6519835586C19D3A4F3A2C5F35B44A300C8A76E11708B5495B9C3EE756BBF19E3FD15CE625D3C0539Bn'
 49);
 50
 51assert.sameValue(
 52 0x3n ** 0xFFn,
 53 0x11F1B08E87EC42C5D83C3218FC83C41DCFD9F4428F4F92AF1AAA80AA46162B1F71E981273601F4AD1DD4709B5ACA650265A6ABn,
 54 'The result of (0x3n ** 0xFFn) is 0x11F1B08E87EC42C5D83C3218FC83C41DCFD9F4428F4F92AF1AAA80AA46162B1F71E981273601F4AD1DD4709B5ACA650265A6ABn'
 55);
 56
 57assert.sameValue(0x3n ** 0x3n, 0x1Bn, 'The result of (0x3n ** 0x3n) is 0x1Bn');
 58assert.sameValue(0x3n ** 0x2n, 0x9n, 'The result of (0x3n ** 0x2n) is 0x9n');
 59assert.sameValue(0x3n ** 0x1n, 0x3n, 'The result of (0x3n ** 0x1n) is 0x3n');
 60
 61assert.sameValue(
 62 0x2n ** 0x123n,
 63 0x8000000000000000000000000000000000000000000000000000000000000000000000000n,
 64 'The result of (0x2n ** 0x123n) is 0x8000000000000000000000000000000000000000000000000000000000000000000000000n'
 65);
 66
 67assert.sameValue(
 68 0x2n ** 0xFFn,
 69 0x8000000000000000000000000000000000000000000000000000000000000000n,
 70 'The result of (0x2n ** 0xFFn) is 0x8000000000000000000000000000000000000000000000000000000000000000n'
 71);
 72
 73assert.sameValue(0x2n ** 0x3n, 0x8n, 'The result of (0x2n ** 0x3n) is 0x8n');
 74assert.sameValue(0x2n ** 0x2n, 0x4n, 'The result of (0x2n ** 0x2n) is 0x4n');
 75assert.sameValue(0x2n ** 0x1n, 0x2n, 'The result of (0x2n ** 0x1n) is 0x2n');
 76assert.sameValue(0x1n ** 0x123n, 0x1n, 'The result of (0x1n ** 0x123n) is 0x1n');
 77assert.sameValue(0x1n ** 0xFFn, 0x1n, 'The result of (0x1n ** 0xFFn) is 0x1n');
 78assert.sameValue(0x1n ** 0x3n, 0x1n, 'The result of (0x1n ** 0x3n) is 0x1n');
 79assert.sameValue(0x1n ** 0x2n, 0x1n, 'The result of (0x1n ** 0x2n) is 0x1n');
 80assert.sameValue(0x1n ** 0x1n, 0x1n, 'The result of (0x1n ** 0x1n) is 0x1n');
 81assert.sameValue(0n ** 0n, 1n, 'The result of (0n ** 0n) is 1n');
 82

JSTests/stress/big-int-exp-jit-osr.js

 1//@ runBigIntEnabled
 2
 3let assert = {
 4 sameValue: function(i, e, m) {
 5 if (i !== e)
 6 throw new Error(m);
 7 }
 8}
 9
 10function bigIntExp(x, y) {
 11 return x ** y;
 12}
 13noInline(bigIntExp);
 14
 15for (let i = 0; i < 10000; i++) {
 16 let r = bigIntExp(3n, 10n);
 17 assert.sameValue(r, 59049n, 3n + " ** " + 10n + " = " + r);
 18}
 19
 20let r = bigIntExp(3, 10);
 21assert.sameValue(r, 59049, 3 + " ** " + 10 + " = " + r);
 22
 23r = bigIntExp("3", "10");
 24assert.sameValue(r, 59049, "'" + 3 + "' ** '" + 10 + "' = " + r);
 25

JSTests/stress/big-int-exp-jit-untyped.js

 1//@ runBigIntEnabled
 2
 3let assert = {
 4 sameValue: function(i, e, m) {
 5 if (i !== e)
 6 throw new Error(m);
 7 }
 8}
 9
 10function bigIntExp(x, y) {
 11 return x ** y;
 12}
 13noInline(bigIntExp);
 14
 15let o = {valueOf: () => 10n};
 16
 17for (let i = 0; i < 10000; i++) {
 18 let r = bigIntExp(3n, o);
 19 assert.sameValue(r, 59049n, 3n + " ** {valueOf: () => 10n} = " + r);
 20}
 21
 22o2 = {valueOf: () => 3n};
 23
 24for (let i = 0; i < 10000; i++) {
 25 let r = bigIntExp(o2, o);
 26 assert.sameValue(r, 59049n, "{valueOf: () => 3n} ** {valueOf: () => 10n} = " + r);
 27}
 28
 29o = Object(10n);
 30let r = bigIntExp(3n, o);
 31assert.sameValue(r, 59049n, 3n + " ** Object(10n) = " + r);
 32
 33o2 = Object(3n);
 34r = bigIntExp(o2, o);
 35assert.sameValue(r, 59049n, "Object(3n) ** Object(10n) = " + r);
 36
 37r = bigIntExp(3, 3);
 38assert.sameValue(r, 27, "3 ** 3 = " + r);
 39

JSTests/stress/big-int-exp-jit.js

 1//@ runBigIntEnabled
 2
 3let assert = {
 4 sameValue: function(i, e, m) {
 5 if (i !== e)
 6 throw new Error(m);
 7 }
 8}
 9
 10function bigIntExp(x, y) {
 11 return x ** y;
 12}
 13noInline(bigIntExp);
 14
 15for (let i = 0; i < 10000; i++) {
 16 let r = bigIntExp(3n, 10n);
 17 assert.sameValue(r, 59049n, 3n + " ** " + 10n + " = " + r);
 18}
 19

JSTests/stress/big-int-exp-negative-exponent.js

 1//@ runBigIntEnabled
 2
 3function assert(a, message) {
 4 if (!a)
 5 throw new Error(message);
 6}
 7
 8function assertThrowRangeError(a, b) {
 9 try {
 10 let n = a ** b;
 11 assert(false, "Should throw RangeError, but executed without exception");
 12 } catch (e) {
 13 assert(e instanceof RangeError, "Expected RangeError, got: " + e);
 14 }
 15}
 16
 17assertThrowRangeError(1n, -1n);
 18assertThrowRangeError(0n, -1n);
 19assertThrowRangeError(-1n, -1n);
 20assertThrowRangeError(1n, -100000000000000000n);
 21

JSTests/stress/big-int-exp-to-primitive.js

 1//@ runBigIntEnabled
 2
 3function assert(a) {
 4 if (!a)
 5 throw new Error("Bad assertion");
 6}
 7
 8assert.sameValue = function (input, expected, message) {
 9 if (input !== expected)
 10 throw new Error(message);
 11}
 12
 13function testExp(x, y, z) {
 14 assert.sameValue(x ** y, z, x + " * " + y + " = " + z);
 15}
 16
 17let o = {
 18 [Symbol.toPrimitive]: function () { return 15n; }
 19}
 20
 21testExp(15n, o, 437893890380859375n);
 22
 23o.valueOf = function () {
 24 throw new Error("Should never execute it");
 25};
 26
 27testExp(22n, o, 136880068015412051968n);
 28
 29o.toString = function () {
 30 throw new Error("Should never execute it");
 31};
 32
 33testExp(103n, o, 1557967416600764580522382952407n);
 34

JSTests/stress/big-int-exp-type-error.js

 1//@ runBigIntEnabled
 2
 3function assert(a, message) {
 4 if (!a)
 5 throw new Error(message);
 6}
 7
 8function assertThrowTypeError(a, b, message) {
 9 try {
 10 let n = a ** b;
 11 assert(false, message + ": Should throw TypeError, but executed without exception");
 12 } catch (e) {
 13 assert(e instanceof TypeError, message + ": expected TypeError, got: " + e);
 14 }
 15}
 16
 17assertThrowTypeError(30n, "foo", "BigInt ** String");
 18assertThrowTypeError("bar", 18757382984821n, "String ** BigInt");
 19assertThrowTypeError(30n, Symbol("foo"), "BigInt ** Symbol");
 20assertThrowTypeError(Symbol("bar"), 18757382984821n, "Symbol ** BigInt");
 21assertThrowTypeError(30n, 3320, "BigInt ** Int32");
 22assertThrowTypeError(33256, 18757382984821n, "Int32 ** BigInt");
 23assertThrowTypeError(30n, 0.543, "BigInt ** Double");
 24assertThrowTypeError(230.19293, 18757382984821n, "Double ** BigInt");
 25assertThrowTypeError(30n, NaN, "BigInt ** NaN");
 26assertThrowTypeError(NaN, 18757382984821n, "NaN ** BigInt");
 27assertThrowTypeError(30n, NaN, "BigInt ** NaN");
 28assertThrowTypeError(NaN, 18757382984821n, "NaN ** BigInt");
 29assertThrowTypeError(30n, +Infinity, "BigInt ** NaN");
 30assertThrowTypeError(+Infinity, 18757382984821n, "NaN ** BigInt");
 31assertThrowTypeError(30n, -Infinity, "BigInt ** -Infinity");
 32assertThrowTypeError(-Infinity, 18757382984821n, "-Infinity ** BigInt");
 33assertThrowTypeError(30n, null, "BigInt ** null");
 34assertThrowTypeError(null, 18757382984821n, "null ** BigInt");
 35assertThrowTypeError(30n, undefined, "BigInt ** undefined");
 36assertThrowTypeError(undefined, 18757382984821n, "undefined ** BigInt");
 37assertThrowTypeError(30n, true, "BigInt ** true");
 38assertThrowTypeError(true, 18757382984821n, "true ** BigInt");
 39assertThrowTypeError(30n, false, "BigInt ** false");
 40assertThrowTypeError(false, 18757382984821n, "false ** BigInt");
 41
 42// Error when returning from object
 43
 44let o = {
 45 valueOf: function () { return Symbol("Foo"); }
 46};
 47
 48assertThrowTypeError(30n, o, "BigInt ** Object.valueOf returning Symbol");
 49assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Symbol ** BigInt");
 50
 51o = {
 52 valueOf: function () { return 33256; }
 53};
 54
 55assertThrowTypeError(30n, o, "BigInt ** Object.valueOf returning Int32");
 56assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Int32 ** BigInt");
 57
 58o = {
 59 valueOf: function () { return 0.453; }
 60};
 61
 62assertThrowTypeError(30n, o, "BigInt ** Object.valueOf returning Double");
 63assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Double ** BigInt");
 64
 65o = {
 66 toString: function () { return Symbol("Foo"); }
 67};
 68
 69assertThrowTypeError(30n, o, "BigInt ** Object.toString returning Symbol");
 70assertThrowTypeError(o, 18757382984821n, "Object.toString returning Symbol ** BigInt");
 71
 72o = {
 73 toString: function () { return 33256; }
 74};
 75
 76assertThrowTypeError(30n, o, "BigInt ** Object.toString returning Int32");
 77assertThrowTypeError(o, 18757382984821n, "Object.toString returning Int32 ** BigInt");
 78
 79o = {
 80 toString: function () { return 0.453; }
 81};
 82
 83assertThrowTypeError(30n, o, "BigInt ** Object.toString returning Double");
 84assertThrowTypeError(o, 18757382984821n, "Object.toString returning Double ** BigInt");
 85
 86o = {
 87 [Symbol.toPrimitive]: function () { return Symbol("Foo"); }
 88};
 89
 90assertThrowTypeError(30n, o, "BigInt ** Object.@@toPrimitive returning Symbol");
 91assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Symbol ** BigInt");
 92
 93o = {
 94 [Symbol.toPrimitive]: function () { return 33256; }
 95};
 96
 97assertThrowTypeError(30n, o, "BigInt ** Object.@@toPrimitive returning Int32");
 98assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Int32 ** BigInt");
 99
 100o = {
 101 [Symbol.toPrimitive]: function () { return 0.453; }
 102};
 103
 104assertThrowTypeError(30n, o, "BigInt ** Object.@@toPrimitive returning Double");
 105assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Double ** BigInt");
 106

JSTests/stress/big-int-exp-wrapped-value.js

 1//@ runBigIntEnabled
 2
 3assert = {
 4 sameValue: function (input, expected, message) {
 5 if (input !== expected)
 6 throw new Error(message);
 7 }
 8};
 9
 10function testExp(x, y, z, message) {
 11 assert.sameValue(x ** y, z, message);
 12}
 13
 14testExp(Object(2n), 1n, 2n, "ToPrimitive: unbox object with internal slot");
 15
 16let o = {
 17 [Symbol.toPrimitive]: function() {
 18 return 2n;
 19 }
 20};
 21testExp(o, 1n, 2n, "ToPrimitive: @@toPrimitive");
 22
 23o = {
 24 valueOf: function() {
 25 return 2n;
 26 }
 27};
 28testExp(o, 1n, 2n, "ToPrimitive: valueOf");
 29
 30o = {
 31 toString: function() {
 32 return 2n;
 33 }
 34}
 35testExp(o, 1n, 2n, "ToPrimitive: toString");
 36