<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[260834] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/260834">260834</a></dd>
<dt>Author</dt> <dd>ysuzuki@apple.com</dd>
<dt>Date</dt> <dd>2020-04-28 11:04:53 -0700 (Tue, 28 Apr 2020)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] NumberConstructor should accept BigInt
https://bugs.webkit.org/show_bug.cgi?id=210835

Reviewed by Mark Lam.

JSTests:

* stress/number-constructor-bigint-dfg.js: Added.
(shouldBe):
(convert):
* stress/number-constructor-bigint.js: Added.
(shouldBe):
* test262/expectations.yaml:

Source/JavaScriptCore:

This patch fixes our Number constructor behavior to accept BigInt. According to the spec[1],
Number constructor should accept BigInt and should generate numbers from that.

We port V8's BigInt to double conversion code as we did for the other HeapBigInt runtime functions.

And we introduce CallNumberConstructor DFG node and handle Number constructor call with BigInt correctly
in DFG and FTL. Previously we were emitting ToNumber DFG node for Number constructor. But this is wrong
now since ToNumber does not accept BigInt and throws an error, and Number constructor should not use
ToNumber to implement its implementation. So we should introduce slightly different semantics: CallNumberConstructor
as we introduced CallStringConstructor in addition to ToString DFG node. And we add appropriate BigInt32 path
to emit efficient CallNumberConstructor machine code.

[1]: https://tc39.es/ecma262/#sec-number-constructor-number-value

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixupToNumberOrToNumericOrCallNumberConstructor):
(JSC::DFG::FixupPhase::fixupToNumeric): Deleted.
(JSC::DFG::FixupPhase::fixupToNumber): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileToNumeric):
(JSC::DFG::SpeculativeJIT::compileCallNumberConstructor):
* 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::compileCallNumberConstructor):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::decideRounding):
(JSC::JSBigInt::toNumberHeap):
* runtime/JSBigInt.h:
* runtime/NumberConstructor.cpp:
(JSC::constructNumberConstructor):
(JSC::callNumberConstructor):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTeststest262expectationsyaml">trunk/JSTests/test262/expectations.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSBigIntcpp">trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSBigInth">trunk/Source/JavaScriptCore/runtime/JSBigInt.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeNumberConstructorcpp">trunk/Source/JavaScriptCore/runtime/NumberConstructor.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressnumberconstructorbigintdfgjs">trunk/JSTests/stress/number-constructor-bigint-dfg.js</a></li>
<li><a href="#trunkJSTestsstressnumberconstructorbigintjs">trunk/JSTests/stress/number-constructor-bigint.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/JSTests/ChangeLog     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2020-04-28  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] NumberConstructor should accept BigInt
+        https://bugs.webkit.org/show_bug.cgi?id=210835
+
+        Reviewed by Mark Lam.
+
+        * stress/number-constructor-bigint-dfg.js: Added.
+        (shouldBe):
+        (convert):
+        * stress/number-constructor-bigint.js: Added.
+        (shouldBe):
+        * test262/expectations.yaml:
+
</ins><span class="cx"> 2020-04-27  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [JSC] Throw OutOfMemoryError instead of RangeError if BigInt is too big
</span></span></pre></div>
<a id="trunkJSTestsstressnumberconstructorbigintdfgjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/number-constructor-bigint-dfg.js (0 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/number-constructor-bigint-dfg.js                            (rev 0)
+++ trunk/JSTests/stress/number-constructor-bigint-dfg.js       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function convert(bigInt)
+{
+    return Number(bigInt);
+}
+noInline(convert);
+
+for (var i = 0; i < 1e4; ++i) {
+    shouldBe(convert(0n), 0);
+    shouldBe(convert(0x7fffffffn), 0x7fffffff);
+    shouldBe(convert(-0x7fffffffn - 1n), -0x80000000);
+}
+
+for (var i = 0; i < 1e4; ++i) {
+    shouldBe(convert(0x80000000n), 0x80000000);
+    shouldBe(convert(0x7fffffffn + 1n), 0x80000000);
+    shouldBe(convert(0x7fffffffn + 2n), 0x80000001);
+    shouldBe(convert(-0x7fffffffn - 2n), -0x80000001);
+}
+
+for (var i = 0; i < 1e4; ++i) {
+    shouldBe(convert(0x20000000000000n), 9007199254740992);
+    shouldBe(convert(0x20000000000000n + 1n), 9007199254740992);
+    shouldBe(convert(0x20000000000000n + 2n), 9007199254740994);
+    shouldBe(convert(0x20000000000000n + 3n), 9007199254740996);
+    shouldBe(convert(0x20000000000000n + 4n), 9007199254740996);
+
+    shouldBe(convert(-(0x20000000000000n)), -9007199254740992);
+    shouldBe(convert(-(0x20000000000000n + 1n)), -9007199254740992);
+    shouldBe(convert(-(0x20000000000000n + 2n)), -9007199254740994);
+    shouldBe(convert(-(0x20000000000000n + 3n)), -9007199254740996);
+    shouldBe(convert(-(0x20000000000000n + 4n)), -9007199254740996);
+
+    shouldBe(convert(2n ** (1024n - 1n)), 8.98846567431158e+307);
+    shouldBe(convert(2n ** (1024n - 1n)), 8.98846567431158e+307);
+    shouldBe(convert(0x1fffffffffffffn << 971n), Number.MAX_VALUE);
+    shouldBe(convert(0x20000000000000n << 971n), Infinity);
+    shouldBe(convert(0x1ffffffffffffffn << 966n), 8.98846567431158e+307);
+    shouldBe(convert(0x3fffffffffffffn << 970n), Infinity);
+    shouldBe(convert(0x3fffffffffffffn << 969n), 8.98846567431158e+307);
+
+    shouldBe(convert(-(2n ** (1024n - 1n))), -8.98846567431158e+307);
+    shouldBe(convert(-(2n ** (1024n - 1n))), -8.98846567431158e+307);
+    shouldBe(convert(-0x1fffffffffffffn << 971n), -Number.MAX_VALUE);
+    shouldBe(convert(-0x20000000000000n << 971n), -Infinity);
+    shouldBe(convert(-0x1ffffffffffffffn << 966n), -8.98846567431158e+307);
+    shouldBe(convert(-0x3fffffffffffffn << 970n), -Infinity);
+    shouldBe(convert(-0x3fffffffffffffn << 969n), -8.98846567431158e+307);
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressnumberconstructorbigintjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/number-constructor-bigint.js (0 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/number-constructor-bigint.js                                (rev 0)
+++ trunk/JSTests/stress/number-constructor-bigint.js   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -0,0 +1,108 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+shouldBe(Number(0n), 0);
+
+// Around Int32 max/min.
+shouldBe(Number(0x7fffffffn), 0x7fffffff);
+shouldBe(Number(0x80000000n), 0x80000000);
+shouldBe(Number(0x7fffffffn + 1n), 0x80000000);
+shouldBe(Number(0x7fffffffn + 2n), 0x80000001);
+shouldBe(Number(-0x7fffffffn - 1n), -0x80000000);
+shouldBe(Number(-0x7fffffffn - 2n), -0x80000001);
+
+// Around Int52 max/min.
+shouldBe(Number(0x20000000000000n), 9007199254740992);
+shouldBe(Number(0x20000000000000n + 1n), 9007199254740992);
+shouldBe(Number(0x20000000000000n + 2n), 9007199254740994);
+shouldBe(Number(0x20000000000000n + 3n), 9007199254740996);
+shouldBe(Number(0x20000000000000n + 4n), 9007199254740996);
+
+shouldBe(Number(-(0x20000000000000n)), -9007199254740992);
+shouldBe(Number(-(0x20000000000000n + 1n)), -9007199254740992);
+shouldBe(Number(-(0x20000000000000n + 2n)), -9007199254740994);
+shouldBe(Number(-(0x20000000000000n + 3n)), -9007199254740996);
+shouldBe(Number(-(0x20000000000000n + 4n)), -9007199254740996);
+
+// mantissa rounding.
+shouldBe(Number(0x3fffffffffffffn), 18014398509481984);
+shouldBe(Number(-0x3fffffffffffffn), -18014398509481984);
+shouldBe(Number(0b1000000000000000000000000000000000000111111111111111111111n), 144115188077953020);
+shouldBe(Number(0b1000000000000000000000000000000000000000000000000000000001n), 144115188075855870);
+shouldBe(Number(0b1000000000000000000000000000000000000000000000000001000000n), 144115188075855940);
+shouldBe(Number(0b1000000000000000000000000000000000000000000000000001000001n), 144115188075855940);
+shouldBe(Number(0b1000000000000000000000000000000000000000000000000001000001n), 144115188075855940);
+shouldBe(Number(0b10000000000000000000000000000000000000000000000000001n), 4503599627370497);
+shouldBe(Number(0b100000000000000000000000000000000000000000000000000010n), 9007199254740994);
+shouldBe(Number(0b100000000000000000000000000000000000000000000000000011n), 9007199254740996);
+
+// Around Infinity.
+shouldBe(Number(2n ** (1024n - 1n)), 8.98846567431158e+307);
+shouldBe(Number(2n ** (1024n - 1n)), 8.98846567431158e+307);
+shouldBe(Number(0x1fffffffffffffn << 971n), Number.MAX_VALUE);
+shouldBe(Number(0x20000000000000n << 971n), Infinity);
+shouldBe(Number(0x1ffffffffffffffn << 966n), 8.98846567431158e+307);
+shouldBe(Number(0x3fffffffffffffn << 970n), Infinity);
+shouldBe(Number(0x3fffffffffffffn << 969n), 8.98846567431158e+307);
+
+shouldBe(Number(-(2n ** (1024n - 1n))), -8.98846567431158e+307);
+shouldBe(Number(-(2n ** (1024n - 1n))), -8.98846567431158e+307);
+shouldBe(Number(-0x1fffffffffffffn << 971n), -Number.MAX_VALUE);
+shouldBe(Number(-0x20000000000000n << 971n), -Infinity);
+shouldBe(Number(-0x1ffffffffffffffn << 966n), -8.98846567431158e+307);
+shouldBe(Number(-0x3fffffffffffffn << 970n), -Infinity);
+shouldBe(Number(-0x3fffffffffffffn << 969n), -8.98846567431158e+307);
+
+shouldBe(+new Number(0n), +new Number(0));
+
+// Around Int32 max/min.
+shouldBe(+new Number(0x7fffffffn), +new Number(0x7fffffff));
+shouldBe(+new Number(0x80000000n), +new Number(0x80000000));
+shouldBe(+new Number(0x7fffffffn + 1n), +new Number(0x80000000));
+shouldBe(+new Number(0x7fffffffn + 2n), +new Number(0x80000001));
+shouldBe(+new Number(-0x7fffffffn - 1n), +new Number(-0x80000000));
+shouldBe(+new Number(-0x7fffffffn - 2n), +new Number(-0x80000001));
+
+// Around Int52 max/min.
+shouldBe(+new Number(0x20000000000000n), +new Number(9007199254740992));
+shouldBe(+new Number(0x20000000000000n + 1n), +new Number(9007199254740992));
+shouldBe(+new Number(0x20000000000000n + 2n), +new Number(9007199254740994));
+shouldBe(+new Number(0x20000000000000n + 3n), +new Number(9007199254740996));
+shouldBe(+new Number(0x20000000000000n + 4n), +new Number(9007199254740996));
+
+shouldBe(+new Number(-(0x20000000000000n)), +new Number(-9007199254740992));
+shouldBe(+new Number(-(0x20000000000000n + 1n)), +new Number(-9007199254740992));
+shouldBe(+new Number(-(0x20000000000000n + 2n)), +new Number(-9007199254740994));
+shouldBe(+new Number(-(0x20000000000000n + 3n)), +new Number(-9007199254740996));
+shouldBe(+new Number(-(0x20000000000000n + 4n)), +new Number(-9007199254740996));
+
+// mantissa rounding.
+shouldBe(+new Number(0x3fffffffffffffn), +new Number(18014398509481984));
+shouldBe(+new Number(-0x3fffffffffffffn), +new Number(-18014398509481984));
+shouldBe(+new Number(0b1000000000000000000000000000000000000111111111111111111111n), +new Number(144115188077953020));
+shouldBe(+new Number(0b1000000000000000000000000000000000000000000000000000000001n), +new Number(144115188075855870));
+shouldBe(+new Number(0b1000000000000000000000000000000000000000000000000001000000n), +new Number(144115188075855940));
+shouldBe(+new Number(0b1000000000000000000000000000000000000000000000000001000001n), +new Number(144115188075855940));
+shouldBe(+new Number(0b1000000000000000000000000000000000000000000000000001000001n), +new Number(144115188075855940));
+shouldBe(+new Number(0b10000000000000000000000000000000000000000000000000001n), +new Number(4503599627370497));
+shouldBe(+new Number(0b100000000000000000000000000000000000000000000000000010n), +new Number(9007199254740994));
+shouldBe(+new Number(0b100000000000000000000000000000000000000000000000000011n), +new Number(9007199254740996));
+
+// Around Infinity.
+shouldBe(+new Number(2n ** (1024n - 1n)), +new Number(8.98846567431158e+307));
+shouldBe(+new Number(2n ** (1024n - 1n)), +new Number(8.98846567431158e+307));
+shouldBe(+new Number(0x1fffffffffffffn << 971n), +new Number(Number.MAX_VALUE));
+shouldBe(+new Number(0x20000000000000n << 971n), +new Number(Infinity));
+shouldBe(+new Number(0x1ffffffffffffffn << 966n), +new Number(8.98846567431158e+307));
+shouldBe(+new Number(0x3fffffffffffffn << 970n), +new Number(Infinity));
+shouldBe(+new Number(0x3fffffffffffffn << 969n), +new Number(8.98846567431158e+307));
+
+shouldBe(+new Number(-(2n ** (1024n - 1n))), +new Number(-8.98846567431158e+307));
+shouldBe(+new Number(-(2n ** (1024n - 1n))), +new Number(-8.98846567431158e+307));
+shouldBe(+new Number(-0x1fffffffffffffn << 971n), +new Number(-Number.MAX_VALUE));
+shouldBe(+new Number(-0x20000000000000n << 971n), +new Number(-Infinity));
+shouldBe(+new Number(-0x1ffffffffffffffn << 966n), +new Number(-8.98846567431158e+307));
+shouldBe(+new Number(-0x3fffffffffffffn << 970n), +new Number(-Infinity));
+shouldBe(+new Number(-0x3fffffffffffffn << 969n), +new Number(-8.98846567431158e+307));
</ins></span></pre></div>
<a id="trunkJSTeststest262expectationsyaml"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/test262/expectations.yaml (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/test262/expectations.yaml  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/JSTests/test262/expectations.yaml     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1068,9 +1068,6 @@
</span><span class="cx"> test/built-ins/JSON/parse/reviver-object-non-configurable-prop-create.js:
</span><span class="cx">   default: 'Test262Error: Expected SameValue(«22», «2») to be true'
</span><span class="cx">   strict mode: 'Test262Error: Expected SameValue(«22», «2») to be true'
</span><del>-test/built-ins/Number/bigint-conversion.js:
-  default: "TypeError: Conversion from 'BigInt' to 'number' is not allowed."
-  strict mode: "TypeError: Conversion from 'BigInt' to 'number' is not allowed."
</del><span class="cx"> test/built-ins/Object/entries/order-after-define-property.js:
</span><span class="cx">   default: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
</span><span class="cx">   strict mode: 'Test262Error: Expected [b, a] and [a, b] to have the same contents. '
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/ChangeLog       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1,3 +1,70 @@
</span><ins>+2020-04-28  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] NumberConstructor should accept BigInt
+        https://bugs.webkit.org/show_bug.cgi?id=210835
+
+        Reviewed by Mark Lam.
+
+        This patch fixes our Number constructor behavior to accept BigInt. According to the spec[1],
+        Number constructor should accept BigInt and should generate numbers from that.
+
+        We port V8's BigInt to double conversion code as we did for the other HeapBigInt runtime functions.
+
+        And we introduce CallNumberConstructor DFG node and handle Number constructor call with BigInt correctly
+        in DFG and FTL. Previously we were emitting ToNumber DFG node for Number constructor. But this is wrong
+        now since ToNumber does not accept BigInt and throws an error, and Number constructor should not use
+        ToNumber to implement its implementation. So we should introduce slightly different semantics: CallNumberConstructor
+        as we introduced CallStringConstructor in addition to ToString DFG node. And we add appropriate BigInt32 path
+        to emit efficient CallNumberConstructor machine code.
+
+        [1]: https://tc39.es/ecma262/#sec-number-constructor-number-value
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupToNumberOrToNumericOrCallNumberConstructor):
+        (JSC::DFG::FixupPhase::fixupToNumeric): Deleted.
+        (JSC::DFG::FixupPhase::fixupToNumber): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasHeapPrediction):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToNumeric):
+        (JSC::DFG::SpeculativeJIT::compileCallNumberConstructor):
+        * 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::compileCallNumberConstructor):
+        * runtime/JSBigInt.cpp:
+        (JSC::JSBigInt::decideRounding):
+        (JSC::JSBigInt::toNumberHeap):
+        * runtime/JSBigInt.h:
+        * runtime/NumberConstructor.cpp:
+        (JSC::constructNumberConstructor):
+        (JSC::callNumberConstructor):
+
</ins><span class="cx"> 2020-04-27  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><span class="cx">         [JSC] Throw OutOfMemoryError instead of RangeError if BigInt is too big
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -2711,6 +2711,45 @@
</span><span class="cx">         setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+
+    case CallNumberConstructor: {
+        JSValue childConst = forNode(node->child1()).value();
+        if (childConst) {
+            if (childConst.isNumber()) {
+                if (node->child1().useKind() == UntypedUse)
+                    didFoldClobberWorld();
+                setConstant(node, childConst);
+                break;
+            }
+#if USE(BIGINT32)
+            if (childConst.isBigInt32()) {
+                if (node->child1().useKind() == UntypedUse)
+                    didFoldClobberWorld();
+                setConstant(node, jsNumber(childConst.bigInt32AsInt32()));
+                break;
+            }
+#endif
+        }
+
+        ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == BigInt32Use);
+
+        if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
+            m_state.setShouldTryConstantFolding(true);
+            if (node->child1().useKind() == UntypedUse)
+                didFoldClobberWorld();
+            setForNode(node, forNode(node->child1()));
+            break;
+        }
+
+        if (node->child1().useKind() == BigInt32Use) {
+            setTypeForNode(node, SpecInt32Only);
+            break;
+        }
+
+        clobberWorld();
+        setNonCellTypeForNode(node, SpecBytecodeNumber);
+        break;
+    }
</ins><span class="cx">         
</span><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp 2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp    2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -415,7 +415,8 @@
</span><span class="cx">             
</span><span class="cx">         case ToPrimitive:
</span><span class="cx">         case ToNumber:
</span><del>-        case ToNumeric: {
</del><ins>+        case ToNumeric:
+        case CallNumberConstructor: {
</ins><span class="cx">             node->child1()->mergeFlags(flags);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp    2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -4027,7 +4027,7 @@
</span><span class="cx">         if (argumentCountIncludingThis <= 1)
</span><span class="cx">             set(result, jsConstant(jsNumber(0)));
</span><span class="cx">         else
</span><del>-            set(result, addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgumentIncludingThis(1, registerOffset))));
</del><ins>+            set(result, addToGraph(CallNumberConstructor, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgumentIncludingThis(1, registerOffset))));
</ins><span class="cx"> 
</span><span class="cx">         return true;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -692,6 +692,19 @@
</span><span class="cx">         write(Heap);
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    case CallNumberConstructor:
+        switch (node->child1().useKind()) {
+        case BigInt32Use:
+            def(PureValue(node));
+            return;
+        case UntypedUse:
+            read(World);
+            write(Heap);
+            return;
+        default:
+            DFG_CRASH(graph, node, "Bad use kind");
+        }
+
</ins><span class="cx">     case Inc:
</span><span class="cx">     case Dec:
</span><span class="cx">         switch (node->child1().useKind()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp      2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp 2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -951,7 +951,8 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            case ToNumber: {
</del><ins>+            case ToNumber:
+            case CallNumberConstructor: {
</ins><span class="cx">                 if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
</span><span class="cx">                     break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp    2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -413,6 +413,15 @@
</span><span class="cx"> #endif // not ASSERT_ENABLED
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><ins>+    case CallNumberConstructor:
+        switch (node->child1().useKind()) {
+        case BigInt32Use:
+            return false;
+        default:
+            break;
+        }
+        return true;
+
</ins><span class="cx">     case CallStringConstructor:
</span><span class="cx">     case ToString:
</span><span class="cx">         switch (node->child1().useKind()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1536,16 +1536,13 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case ToNumber: {
-            fixupToNumber(node);
</del><ins>+        case ToNumber:
+        case ToNumeric:
+        case CallNumberConstructor: {
+            fixupToNumberOrToNumericOrCallNumberConstructor(node);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case ToNumeric: {
-            fixupToNumeric(node);
-            break;
-        }
-            
</del><span class="cx">         case ToString:
</span><span class="cx">         case CallStringConstructor: {
</span><span class="cx">             fixupToStringOrCallStringConstructor(node);
</span><span class="lines">@@ -3090,29 +3087,37 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void fixupToNumeric(Node* node)
</del><ins>+    void fixupToNumberOrToNumericOrCallNumberConstructor(Node* node)
</ins><span class="cx">     {
</span><ins>+#if USE(BIGINT32)
+        if (node->op() == CallNumberConstructor) {
+            if (node->child1()->shouldSpeculateBigInt32()) {
+                fixEdge<BigInt32Use>(node->child1());
+                node->clearFlags(NodeMustGenerate);
+                node->setResult(NodeResultInt32);
+                return;
+            }
+        }
+#endif
+
</ins><span class="cx">         // If the prediction of the child is BigInt, we attempt to convert ToNumeric to Identity, since it can only return a BigInt when fed a BigInt.
</span><del>-        if (node->child1()->shouldSpeculateBigInt()) {
</del><ins>+        if (node->op() == ToNumeric) {
+            if (node->child1()->shouldSpeculateBigInt()) {
</ins><span class="cx"> #if USE(BIGINT32)
</span><del>-            if (node->child1()->shouldSpeculateBigInt32())
-                fixEdge<BigInt32Use>(node->child1());
-            else if (node->child1()->shouldSpeculateHeapBigInt())
</del><ins>+                if (node->child1()->shouldSpeculateBigInt32())
+                    fixEdge<BigInt32Use>(node->child1());
+                else if (node->child1()->shouldSpeculateHeapBigInt())
+                    fixEdge<HeapBigIntUse>(node->child1());
+                else
+                    fixEdge<AnyBigIntUse>(node->child1());
+#else
</ins><span class="cx">                 fixEdge<HeapBigIntUse>(node->child1());
</span><del>-            else
-                fixEdge<AnyBigIntUse>(node->child1());
-#else
-            fixEdge<HeapBigIntUse>(node->child1());
</del><span class="cx"> #endif
</span><del>-            node->convertToIdentity();
-            return;
</del><ins>+                node->convertToIdentity();
+                return;
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        fixupToNumber(node);
-    }
-
-    void fixupToNumber(Node* node)
-    {
</del><span class="cx">         // At first, attempt to fold Boolean or Int32 to Int32.
</span><span class="cx">         if (node->child1()->shouldSpeculateInt32OrBoolean()) {
</span><span class="cx">             if (isInt32Speculation(node->getHeapPrediction())) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1795,6 +1795,7 @@
</span><span class="cx">         case ToNumber:
</span><span class="cx">         case ToNumeric:
</span><span class="cx">         case ToObject:
</span><ins>+        case CallNumberConstructor:
</ins><span class="cx">         case ValueBitAnd:
</span><span class="cx">         case ValueBitOr:
</span><span class="cx">         case ValueBitXor:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h    2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -412,6 +412,7 @@
</span><span class="cx">     macro(ToObject, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(CallObjectConstructor, NodeResultJS) \
</span><span class="cx">     macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \
</span><ins>+    macro(CallNumberConstructor, NodeResultJS | NodeMustGenerate) \
</ins><span class="cx">     macro(NumberToStringWithRadix, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(NumberToStringWithValidRadixConstant, NodeResultJS) \
</span><span class="cx">     macro(MakeRope, NodeResultJS) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1531,6 +1531,22 @@
</span><span class="cx">     return JSValue::encode(JSValue::decode(value).toNumeric(globalObject));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JIT_OPERATION operationCallNumberConstructor(JSGlobalObject* globalObject, EncodedJSValue encodedValue)
+{
+    VM& vm = globalObject->vm();
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue numeric = value.toNumeric(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+    if (numeric.isNumber())
+        return JSValue::encode(numeric);
+    ASSERT(numeric.isBigInt());
+    return JSValue::encode(JSBigInt::toNumber(numeric));
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValWithThis(JSGlobalObject* globalObject, EncodedJSValue encodedBase, EncodedJSValue encodedThis, EncodedJSValue encodedSubscript)
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToPropertyKey(JSGlobalObject*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToNumber(JSGlobalObject*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToNumeric(JSGlobalObject*, EncodedJSValue) WTF_INTERNAL;
</span><ins>+EncodedJSValue JIT_OPERATION operationCallNumberConstructor(JSGlobalObject*, EncodedJSValue);
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValWithThis(JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetPrototypeOf(JSGlobalObject*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetPrototypeOfObject(JSGlobalObject*, JSObject*) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -897,6 +897,7 @@
</span><span class="cx">         case ToNumber:
</span><span class="cx">         case ToNumeric:
</span><span class="cx">         case ToObject:
</span><ins>+        case CallNumberConstructor:
</ins><span class="cx">         case ValueBitAnd:
</span><span class="cx">         case ValueBitXor:
</span><span class="cx">         case ValueBitOr:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h       2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h  2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -565,6 +565,7 @@
</span><span class="cx">     case ToNumber:
</span><span class="cx">     case ToNumeric:
</span><span class="cx">     case ToObject:
</span><ins>+    case CallNumberConstructor:
</ins><span class="cx">     case NumberToStringWithRadix:
</span><span class="cx">     case SetFunctionName:
</span><span class="cx">     case NewStringObject:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp    2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp       2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -13336,7 +13336,8 @@
</span><span class="cx">     JSValueRegs argumentRegs = argument.jsValueRegs();
</span><span class="cx">     JSValueRegs resultRegs = result.regs();
</span><span class="cx">     GPRReg scratch = temp.gpr();
</span><del>-    // FIXME: add a fast path for BigInt32 here (and for typeOf, and for boolify or whatever it is called in this file).
</del><ins>+    // FIXME: add a fast path for BigInt32 here.
+    // https://bugs.webkit.org/show_bug.cgi?id=211064
</ins><span class="cx"> 
</span><span class="cx">     MacroAssembler::JumpList slowCases;
</span><span class="cx"> 
</span><span class="lines">@@ -13355,6 +13356,41 @@
</span><span class="cx">     jsValueResult(resultRegs, node, DataFormatJS);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileCallNumberConstructor(Node* node)
+{
+#if USE(BIGINT32)
+    if (node->child1().useKind() == BigInt32Use) {
+        SpeculateBigInt32Operand operand(this, node->child1());
+        GPRTemporary result(this);
+
+        GPRReg operandGPR = operand.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.unboxBigInt32(operandGPR, resultGPR);
+        strictInt32Result(resultGPR, node);
+        return;
+    }
+#endif
+
+    DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse, node->child1().useKind());
+    JSValueOperand argument(this, node->child1());
+    JSValueRegsTemporary result(this);
+    GPRTemporary temp(this);
+
+    JSValueRegs argumentRegs = argument.jsValueRegs();
+    JSValueRegs resultRegs = result.regs();
+    GPRReg tempGPR = temp.gpr();
+    // FIXME: add a fast path for BigInt32 here.
+    // https://bugs.webkit.org/show_bug.cgi?id=211064
+
+    CCallHelpers::JumpList slowCases;
+    slowCases.append(m_jit.branchIfNotNumber(argumentRegs, tempGPR));
+    m_jit.moveValueRegs(argumentRegs, resultRegs);
+    addSlowPathGenerator(slowPathCall(slowCases, this, operationCallNumberConstructor, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), argumentRegs));
+
+    jsValueResult(resultRegs, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileLogShadowChickenPrologue(Node* node)
</span><span class="cx"> {
</span><span class="cx">     flushRegisters();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h      2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h 2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1474,6 +1474,7 @@
</span><span class="cx">     void compileToPrimitive(Node*);
</span><span class="cx">     void compileToPropertyKey(Node*);
</span><span class="cx">     void compileToNumeric(Node*);
</span><ins>+    void compileCallNumberConstructor(Node*);
</ins><span class="cx">     void compileLogShadowChickenPrologue(Node*);
</span><span class="cx">     void compileLogShadowChickenTail(Node*);
</span><span class="cx">     void compileHasIndexedProperty(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp       2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp  2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -3151,6 +3151,10 @@
</span><span class="cx">         compileToNumeric(node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+
+    case CallNumberConstructor:
+        compileCallNumberConstructor(node);
+        break;
</ins><span class="cx">         
</span><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp  2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp     2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -3720,6 +3720,10 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case CallNumberConstructor:
+        compileCallNumberConstructor(node);
+        break;
+
</ins><span class="cx">     case ToString:
</span><span class="cx">     case CallStringConstructor:
</span><span class="cx">     case StringValueOf: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp      2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp 2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -219,6 +219,7 @@
</span><span class="cx">     case ToObject:
</span><span class="cx">     case CallObjectConstructor:
</span><span class="cx">     case CallStringConstructor:
</span><ins>+    case CallNumberConstructor:
</ins><span class="cx">     case ObjectCreate:
</span><span class="cx">     case ObjectKeys:
</span><span class="cx">     case MakeRope:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp      2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp 2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -1134,6 +1134,9 @@
</span><span class="cx">         case ToNumeric:
</span><span class="cx">             compileToNumeric();
</span><span class="cx">             break;
</span><ins>+        case CallNumberConstructor:
+            compileCallNumberConstructor();
+            break;
</ins><span class="cx">         case ToString:
</span><span class="cx">         case CallStringConstructor:
</span><span class="cx">         case StringValueOf:
</span><span class="lines">@@ -7590,6 +7593,35 @@
</span><span class="cx">         } else
</span><span class="cx">             setJSValue(vmCall(Int64, operationToNumeric, weakPointer(globalObject), value));
</span><span class="cx">     }
</span><ins>+
+    void compileCallNumberConstructor()
+    {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
+#if USE(BIGINT32)
+        if (m_node->child1().useKind() == BigInt32Use) {
+            LValue value = lowBigInt32(m_node->child1());
+            setInt32(unboxBigInt32(value));
+            return;
+        }
+#endif
+        LValue value = lowJSValue(m_node->child1());
+
+        LBasicBlock notNumber = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        ValueFromBlock fastResult = m_out.anchor(value);
+        m_out.branch(isNumber(value, provenType(m_node->child1())), unsure(continuation), unsure(notNumber));
+
+        // notNumber case.
+        LBasicBlock lastNext = m_out.appendTo(notNumber, continuation);
+        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operationCallNumberConstructor, weakPointer(globalObject), value));
+        m_out.jump(continuation);
+
+        // continuation case.
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(Int64, fastResult, slowResult));
+    }
+
</ins><span class="cx">     
</span><span class="cx">     void compileToStringOrCallStringConstructorOrStringValueOf()
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSBigIntcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp 2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/runtime/JSBigInt.cpp    2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -2547,4 +2547,118 @@
</span><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSBigInt::RoundingResult JSBigInt::decideRounding(JSBigInt* bigInt, int32_t mantissaBitsUnset, int32_t digitIndex, uint64_t currentDigit)
+{
+    if (mantissaBitsUnset > 0)
+        return RoundingResult::RoundDown;
+    int32_t topUnconsumedBit = 0;
+    if (mantissaBitsUnset < 0) {
+        // There are unconsumed bits in currentDigit.
+        topUnconsumedBit = -mantissaBitsUnset - 1;
+    } else {
+        ASSERT(mantissaBitsUnset == 0);
+        // currentDigit fit the mantissa exactly; look at the next digit.
+        if (digitIndex == 0)
+            return RoundingResult::RoundDown;
+        digitIndex--;
+        currentDigit = static_cast<uint64_t>(bigInt->digit(digitIndex));
+        topUnconsumedBit = digitBits - 1;
+    }
+    // If the most significant remaining bit is 0, round down.
+    uint64_t bitmask = static_cast<uint64_t>(1) << topUnconsumedBit;
+    if ((currentDigit & bitmask) == 0)
+        return RoundingResult::RoundDown;
+    // If any other remaining bit is set, round up.
+    bitmask -= 1;
+    if ((currentDigit & bitmask) != 0)
+        return RoundingResult::RoundUp;
+    while (digitIndex > 0) {
+        digitIndex--;
+        if (bigInt->digit(digitIndex) != 0)
+            return RoundingResult::RoundUp;
+    }
+    return RoundingResult::Tie;
+}
+
+JSValue JSBigInt::toNumberHeap(JSBigInt* bigInt)
+{
+    if (bigInt->isZero())
+        return jsNumber(0);
+    ASSERT(bigInt->length());
+
+    // Conversion mechanism is the following.
+    //
+    // 1. Get exponent bits.
+    // 2. Collect mantissa 52 bits.
+    // 3. Add rounding result of unused bits to mantissa and adjust mantissa & exponent bits.
+    // 4. Generate double by combining (1) and (3).
+
+    const unsigned length = bigInt->length();
+    const bool sign = bigInt->sign();
+    const Digit msd = bigInt->digit(length - 1);
+    const unsigned msdLeadingZeros = clz(msd);
+    const size_t bitLength = length * digitBits - msdLeadingZeros;
+    // Double's exponent bits overflow.
+    if (bitLength > 1024)
+        return jsDoubleNumber(sign ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
+    uint64_t exponent = bitLength - 1;
+    uint64_t currentDigit = msd;
+    int32_t digitIndex = length - 1;
+    int32_t shiftAmount = msdLeadingZeros + 1 + (64 - digitBits);
+    ASSERT(1 <= shiftAmount);
+    ASSERT(shiftAmount <= 64);
+    uint64_t mantissa = (shiftAmount == 64) ? 0 : currentDigit << shiftAmount;
+
+    // unsetBits = 64 - setBits - 12 // 12 for non-mantissa bits
+    //     setBits = 64 - (msdLeadingZeros + 1 + bitsNotAvailableDueToDigitSize);  // 1 for hidden mantissa bit.
+    //                 = 64 - (msdLeadingZeros + 1 + (64 - digitBits))
+    //                 = 64 - shiftAmount
+    // Hence, unsetBits = 64 - (64 - shiftAmount) - 12 = shiftAmount - 12
+
+    mantissa >>= 12; // (12 = 64 - 52), we shift 12 bits to put 12 zeros in uint64_t mantissa.
+    int32_t mantissaBitsUnset = shiftAmount - 12;
+
+    // If not all mantissa bits are defined yet, get more digits as needed.
+    // Collect mantissa 52bits from several digits.
+
+    if constexpr (digitBits < 64) {
+        if (mantissaBitsUnset >= static_cast<int32_t>(digitBits) && digitIndex > 0) {
+            digitIndex--;
+            currentDigit = static_cast<uint64_t>(bigInt->digit(digitIndex));
+            mantissa |= (currentDigit << (mantissaBitsUnset - digitBits));
+            mantissaBitsUnset -= digitBits;
+        }
+    }
+
+    if (mantissaBitsUnset > 0 && digitIndex > 0) {
+        ASSERT(mantissaBitsUnset < static_cast<int32_t>(digitBits));
+        digitIndex--;
+        currentDigit = static_cast<uint64_t>(bigInt->digit(digitIndex));
+        mantissa |= (currentDigit >> (digitBits - mantissaBitsUnset));
+        mantissaBitsUnset -= digitBits;
+    }
+
+    // If there are unconsumed digits left, we may have to round.
+    RoundingResult rounding = decideRounding(bigInt, mantissaBitsUnset, digitIndex, currentDigit);
+    if (rounding == RoundingResult::RoundUp || (rounding == RoundingResult::Tie && (mantissa & 1) == 1)) {
+        ++mantissa;
+        // Incrementing the mantissa can overflow the mantissa bits. In that case the new mantissa will be all zero (plus hidden bit).
+        if ((mantissa >> doublePhysicalMantissaSize) != 0) {
+            mantissa = 0;
+            exponent++;
+            // Incrementing the exponent can overflow too.
+            if (exponent > 1023)
+                return jsDoubleNumber(sign ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
+        }
+    }
+
+    uint64_t signBit = sign ? (static_cast<uint64_t>(1) << 63) : 0;
+    exponent = (exponent + 0x3ff) << doublePhysicalMantissaSize; // 0x3ff is double exponent bias.
+    uint64_t doubleBits = signBit | exponent | mantissa;
+    ASSERT((doubleBits & (static_cast<uint64_t>(1) << 63)) == signBit);
+    ASSERT((doubleBits & (static_cast<uint64_t>(0x7ff) << 52)) == exponent);
+    ASSERT((doubleBits & ((static_cast<uint64_t>(1) << 52) - 1)) == mantissa);
+    return jsNumber(bitwise_cast<double>(doubleBits));
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSBigInth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSBigInt.h (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSBigInt.h   2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/runtime/JSBigInt.h      2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -393,6 +393,17 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    static JSValue toNumberHeap(JSBigInt*);
+    static JSValue toNumber(JSValue bigInt)
+    {
+        ASSERT(bigInt.isBigInt());
+#if USE(BIGINT32)
+        if (bigInt.isBigInt32())
+            return jsNumber(bigInt.bigInt32AsInt32());
+#endif
+        return toNumberHeap(jsCast<JSBigInt*>(bigInt));
+    }
+
</ins><span class="cx">     Digit digit(unsigned);
</span><span class="cx">     void setDigit(unsigned, Digit); // Use only when initializing.
</span><span class="cx">     JS_EXPORT_PRIVATE JSBigInt* rightTrim(VM&);
</span><span class="lines">@@ -405,6 +416,8 @@
</span><span class="cx">     static constexpr unsigned halfDigitBits = digitBits / 2;
</span><span class="cx">     static constexpr Digit halfDigitMask = (1ull << halfDigitBits) - 1;
</span><span class="cx">     static constexpr int maxInt = 0x7FFFFFFF;
</span><ins>+
+    static constexpr unsigned doublePhysicalMantissaSize = 52;
</ins><span class="cx">     
</span><span class="cx">     // The maximum length that the current implementation supports would be
</span><span class="cx">     // maxInt / digitBits. However, we use a lower limit for now, because
</span><span class="lines">@@ -439,6 +452,14 @@
</span><span class="cx">     Digit absoluteInplaceSub(JSBigInt* subtrahend, unsigned startIndex);
</span><span class="cx">     void inplaceRightShift(unsigned shift);
</span><span class="cx"> 
</span><ins>+    enum class RoundingResult {
+        RoundDown,
+        Tie,
+        RoundUp
+    };
+
+    static RoundingResult decideRounding(JSBigInt*, int32_t mantissaBitsUnset, int32_t digitIndex, uint64_t currentDigit);
+
</ins><span class="cx">     enum class ExtraDigitsHandling {
</span><span class="cx">         Copy,
</span><span class="cx">         Skip
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeNumberConstructorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/NumberConstructor.cpp (260833 => 260834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/NumberConstructor.cpp        2020-04-28 18:04:41 UTC (rev 260833)
+++ trunk/Source/JavaScriptCore/runtime/NumberConstructor.cpp   2020-04-28 18:04:53 UTC (rev 260834)
</span><span class="lines">@@ -90,8 +90,19 @@
</span><span class="cx"> {
</span><span class="cx">     VM& vm = globalObject->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    double n = callFrame->argumentCount() ? callFrame->uncheckedArgument(0).toNumber(globalObject) : 0;
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+    double n = 0;
+    if (callFrame->argumentCount()) {
+        JSValue numeric = callFrame->uncheckedArgument(0).toNumeric(globalObject);
+        RETURN_IF_EXCEPTION(scope, { });
+        if (numeric.isNumber())
+            n = numeric.asNumber();
+        else {
+            ASSERT(numeric.isBigInt());
+            numeric = JSBigInt::toNumber(numeric);
+            ASSERT(numeric.isNumber());
+            n = numeric.asNumber();
+        }
+    }
</ins><span class="cx"> 
</span><span class="cx">     JSObject* newTarget = asObject(callFrame->newTarget());
</span><span class="cx">     Structure* structure = newTarget == callFrame->jsCallee()
</span><span class="lines">@@ -107,7 +118,16 @@
</span><span class="cx"> // ECMA 15.7.2
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL callNumberConstructor(JSGlobalObject* globalObject, CallFrame* callFrame)
</span><span class="cx"> {
</span><del>-    return JSValue::encode(jsNumber(!callFrame->argumentCount() ? 0 : callFrame->uncheckedArgument(0).toNumber(globalObject)));
</del><ins>+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    if (!callFrame->argumentCount())
+        return JSValue::encode(jsNumber(0));
+    JSValue numeric = callFrame->uncheckedArgument(0).toNumeric(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+    if (numeric.isNumber())
+        return JSValue::encode(numeric);
+    ASSERT(numeric.isBigInt());
+    return JSValue::encode(JSBigInt::toNumber(numeric));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // ECMA-262 20.1.2.3
</span></span></pre>
</div>
</div>

</body>
</html>