<!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>[184933] 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/184933">184933</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-05-27 18:30:58 -0700 (Wed, 27 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Add undefined-&gt;double conversion to DoubleRep
https://bugs.webkit.org/show_bug.cgi?id=145293

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2015-05-27
Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch adds undefined to double conversion to the DoubleRep
node for the cases were we speculate &quot;undefined&quot; as part of the types
processed.

The use case is doing math with accidental out-of-bounds access. For example,
something like:
    for (var i = 0; i &lt;= length; ++i)
        ouptput += array[i];

would cause us to OSR exit every time i === length.

When hitting one of those cases, we would already speculate double math,
but the DoubleRep node was unable to convert the undefined and would exit.

With this patch the use kind NotCellUse cover this conversion for DoubleRep.
I have been quite conservative so in general we will not find &quot;undefined&quot;
until a few recompile but being optimistic seems better since this is a corner case.

This patch is a 80% progression on WebXPRT's DNA Sequencing test.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
* dfg/DFGNode.h:
(JSC::DFG::Node::sawUndefined):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::SafeToExecuteEdge::operator()):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileDoubleRep):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileDoubleRep):
(JSC::FTL::LowerDFGToLLVM::jsValueToDouble):
* tests/stress/double-rep-with-undefined.js: Added.
(addArgsNumberAndUndefined):
(addArgsInt32AndUndefined):
(testFallbackWithDouble):
(addArgsDoubleAndUndefined):
(testFallbackWithObject.):
(testFallbackWithObject):
(addArgsOnlyUndefined):
(testFallbackWithString):

LayoutTests:

* js/regress/math-with-out-of-bounds-array-values-expected.txt: Added.
* js/regress/math-with-out-of-bounds-array-values.html: Added.
* js/regress/script-tests/math-with-out-of-bounds-array-values.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</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="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressmathwithoutofboundsarrayvaluesexpectedtxt">trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmathwithoutofboundsarrayvalueshtml">trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmathwithoutofboundsarrayvaluesjs">trunk/LayoutTests/js/regress/script-tests/math-with-out-of-bounds-array-values.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdoublerepwithnoncelljs">trunk/Source/JavaScriptCore/tests/stress/double-rep-with-non-cell.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdoublerepwithnulljs">trunk/Source/JavaScriptCore/tests/stress/double-rep-with-null.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdoublerepwithundefinedjs">trunk/Source/JavaScriptCore/tests/stress/double-rep-with-undefined.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/LayoutTests/ChangeLog        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-05-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add undefined-&gt;double conversion to DoubleRep
+        https://bugs.webkit.org/show_bug.cgi?id=145293
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/math-with-out-of-bounds-array-values-expected.txt: Added.
+        * js/regress/math-with-out-of-bounds-array-values.html: Added.
+        * js/regress/script-tests/math-with-out-of-bounds-array-values.js: Added.
+
</ins><span class="cx"> 2015-05-27  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION (r183820): webkit.org/blog/ background painting issue on reload, when the page contains videos
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressmathwithoutofboundsarrayvaluesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values-expected.txt (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values-expected.txt        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/math-with-out-of-bounds-array-values
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmathwithoutofboundsarrayvalueshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values.html (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/math-with-out-of-bounds-array-values.html        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/math-with-out-of-bounds-array-values.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmathwithoutofboundsarrayvaluesjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/math-with-out-of-bounds-array-values.js (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/math-with-out-of-bounds-array-values.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/math-with-out-of-bounds-array-values.js        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+function mathWithOutOfBoundsAccess(arrayA, arrayB)
+{
+    var output = 0;
+    for (var i = 0; i &lt; 10; ++i) {
+        output += (arrayA[i] + arrayB[i]);
+    }
+    return output;
+}
+
+noInline(mathWithOutOfBoundsAccess);
+
+function test() {
+    var integerArray = [0, 1, 2, 3, 4];
+    var doubleArray = [0.1, 1.2, 2.3, 3.4, 4.5];
+
+    for (var i = 0; i &lt; 1e5; ++i)
+        mathWithOutOfBoundsAccess(integerArray, doubleArray);
+}
+test();
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2015-05-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add undefined-&gt;double conversion to DoubleRep
+        https://bugs.webkit.org/show_bug.cgi?id=145293
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds undefined to double conversion to the DoubleRep
+        node for the cases were we speculate &quot;undefined&quot; as part of the types
+        processed.
+
+        The use case is doing math with accidental out-of-bounds access. For example,
+        something like:
+            for (var i = 0; i &lt;= length; ++i)
+                ouptput += array[i];
+
+        would cause us to OSR exit every time i === length.
+
+        When hitting one of those cases, we would already speculate double math,
+        but the DoubleRep node was unable to convert the undefined and would exit.
+
+        With this patch the use kind NotCellUse cover this conversion for DoubleRep.
+        I have been quite conservative so in general we will not find &quot;undefined&quot;
+        until a few recompile but being optimistic seems better since this is a corner case.
+
+        This patch is a 80% progression on WebXPRT's DNA Sequencing test.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::sawUndefined):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::SafeToExecuteEdge::operator()):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+        * dfg/DFGUseKind.cpp:
+        (WTF::printInternal):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileDoubleRep):
+        (JSC::FTL::LowerDFGToLLVM::jsValueToDouble):
+        * tests/stress/double-rep-with-undefined.js: Added.
+        (addArgsNumberAndUndefined):
+        (addArgsInt32AndUndefined):
+        (testFallbackWithDouble):
+        (addArgsDoubleAndUndefined):
+        (testFallbackWithObject.):
+        (testFallbackWithObject):
+        (addArgsOnlyUndefined):
+        (testFallbackWithString):
+
</ins><span class="cx"> 2015-05-27  Dean Jackson  &lt;dino@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         img.currentSrc problem in strict mode with old picturefill
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -360,7 +360,30 @@
</span><span class="cx">             setConstant(node, jsDoubleNumber(child.asNumber()));
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        forNode(node).setType(m_graph, forNode(node-&gt;child1()).m_type);
</del><ins>+
+        SpeculatedType type = forNode(node-&gt;child1()).m_type;
+        switch (node-&gt;child1().useKind()) {
+        case NotCellUse: {
+            if (type &amp; SpecOther) {
+                type &amp;= ~SpecOther;
+                type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
+            }
+            if (type &amp; SpecBoolean) {
+                type &amp;= ~SpecBoolean;
+                type |= SpecBoolInt32; // True becomes 1, false becomes 0.
+            }
+            type &amp;= SpecBytecodeNumber;
+            break;
+        }
+
+        case Int52RepUse:
+        case NumberUse:
+            break;
+
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+        forNode(node).setType(type);
</ins><span class="cx">         forNode(node).fixTypeForRepresentation(m_graph, node);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -2128,9 +2128,13 @@
</span><span class="cx">                     m_indexInBlock, SpecInt52AsDouble, DoubleRep, node-&gt;origin,
</span><span class="cx">                     Edge(edge.node(), Int52RepUse));
</span><span class="cx">             } else {
</span><ins>+                UseKind useKind = NotCellUse;
+                if (edge-&gt;shouldSpeculateNumber())
+                    useKind = NumberUse;
+
</ins><span class="cx">                 result = m_insertionSet.insertNode(
</span><span class="cx">                     m_indexInBlock, SpecBytecodeDouble, DoubleRep, node-&gt;origin,
</span><del>-                    Edge(edge.node(), NumberUse));
</del><ins>+                    Edge(edge.node(), useKind));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             edge.setNode(result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -402,6 +402,12 @@
</span><span class="cx">                 SpecNone);
</span><span class="cx">             
</span><span class="cx">             switch (arrayMode.type()) {
</span><ins>+            case Array::Int32:
+                if (arrayMode.isOutOfBounds())
+                    changed |= mergePrediction(node-&gt;getHeapPrediction() | SpecInt32);
+                else
+                    changed |= mergePrediction(SpecInt32);
+                break;
</ins><span class="cx">             case Array::Double:
</span><span class="cx">                 if (arrayMode.isOutOfBounds())
</span><span class="cx">                     changed |= mergePrediction(node-&gt;getHeapPrediction() | SpecDoubleReal);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -2066,31 +2066,58 @@
</span><span class="cx"> void SpeculativeJIT::compileDoubleRep(Node* node)
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;child1().useKind()) {
</span><ins>+    case NotCellUse:
</ins><span class="cx">     case NumberUse: {
</span><span class="cx">         ASSERT(!node-&gt;child1()-&gt;isNumberConstant()); // This should have been constant folded.
</span><del>-    
-        if (isInt32Speculation(m_state.forNode(node-&gt;child1()).m_type)) {
</del><ins>+
+        SpeculatedType possibleTypes = m_state.forNode(node-&gt;child1()).m_type;
+        if (isInt32Speculation(possibleTypes)) {
</ins><span class="cx">             SpeculateInt32Operand op1(this, node-&gt;child1(), ManualOperandSpeculation);
</span><span class="cx">             FPRTemporary result(this);
</span><span class="cx">             m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
</span><span class="cx">             doubleResult(result.fpr(), node);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><del>-    
</del><ins>+
</ins><span class="cx">         JSValueOperand op1(this, node-&gt;child1(), ManualOperandSpeculation);
</span><span class="cx">         FPRTemporary result(this);
</span><del>-    
</del><ins>+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         GPRTemporary temp(this);
</span><span class="cx"> 
</span><span class="cx">         GPRReg op1GPR = op1.gpr();
</span><span class="cx">         GPRReg tempGPR = temp.gpr();
</span><span class="cx">         FPRReg resultFPR = result.fpr();
</span><del>-    
</del><ins>+        JITCompiler::JumpList done;
+
</ins><span class="cx">         JITCompiler::Jump isInteger = m_jit.branch64(
</span><span class="cx">             MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
</span><del>-    
-        if (needsTypeCheck(node-&gt;child1(), SpecBytecodeNumber)) {
</del><ins>+
+        if (node-&gt;child1().useKind() == NotCellUse) {
+            JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagTypeNumberRegister);
+            JITCompiler::Jump isUndefined = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueUndefined));
+
+            static const double zero = 0;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;zero), resultFPR);
+
+            JITCompiler::Jump isNull = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueNull));
+            done.append(isNull);
+
+            DFG_TYPE_CHECK(JSValueRegs(op1GPR), node-&gt;child1(), ~SpecCell,
+                m_jit.branchTest64(JITCompiler::NonZero, op1GPR, TrustedImm32(static_cast&lt;int32_t&gt;(~1))));
+
+            JITCompiler::Jump isFalse = m_jit.branch64(JITCompiler::Equal, op1GPR, TrustedImm64(ValueFalse));
+            static const double one = 1;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;one), resultFPR);
+            done.append(isFalse);
+
+            isUndefined.link(&amp;m_jit);
+            static const double NaN = PNaN;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;NaN), resultFPR);
+            done.append(m_jit.jump());
+
+            isNumber.link(&amp;m_jit);
+        } else if (needsTypeCheck(node-&gt;child1(), SpecBytecodeNumber)) {
</ins><span class="cx">             typeCheck(
</span><span class="cx">                 JSValueRegs(op1GPR), node-&gt;child1(), SpecBytecodeNumber,
</span><span class="cx">                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
</span><span class="lines">@@ -2098,7 +2125,7 @@
</span><span class="cx">     
</span><span class="cx">         m_jit.move(op1GPR, tempGPR);
</span><span class="cx">         unboxDouble(tempGPR, resultFPR);
</span><del>-        JITCompiler::Jump done = m_jit.jump();
</del><ins>+        done.append(m_jit.jump());
</ins><span class="cx">     
</span><span class="cx">         isInteger.link(&amp;m_jit);
</span><span class="cx">         m_jit.convertInt32ToDouble(op1GPR, resultFPR);
</span><span class="lines">@@ -2110,18 +2137,42 @@
</span><span class="cx">         GPRReg op1PayloadGPR = op1.payloadGPR();
</span><span class="cx">         FPRReg tempFPR = temp.fpr();
</span><span class="cx">         FPRReg resultFPR = result.fpr();
</span><ins>+        JITCompiler::JumpList done;
</ins><span class="cx">     
</span><span class="cx">         JITCompiler::Jump isInteger = m_jit.branch32(
</span><span class="cx">             MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
</span><del>-    
-        if (needsTypeCheck(node-&gt;child1(), SpecBytecodeNumber)) {
</del><ins>+
+        if (node-&gt;child1().useKind() == NotCellUse) {
+            JITCompiler::Jump isNumber = m_jit.branch32(JITCompiler::Below, op1TagGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1));
+            JITCompiler::Jump isUndefined = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::UndefinedTag));
+
+            static const double zero = 0;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;zero), resultFPR);
+
+            JITCompiler::Jump isNull = m_jit.branch32(JITCompiler::Equal, op1TagGPR, TrustedImm32(JSValue::NullTag));
+            done.append(isNull);
+
+            DFG_TYPE_CHECK(JSValueRegs(op1TagGPR, op1PayloadGPR), node-&gt;child1(), ~SpecCell, m_jit.branch32(JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::BooleanTag)));
+
+            JITCompiler::Jump isFalse = m_jit.branchTest32(JITCompiler::Zero, op1PayloadGPR, TrustedImm32(1));
+            static const double one = 1;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;one), resultFPR);
+            done.append(isFalse);
+
+            isUndefined.link(&amp;m_jit);
+            static const double NaN = PNaN;
+            m_jit.loadDouble(MacroAssembler::TrustedImmPtr(&amp;NaN), resultFPR);
+            done.append(m_jit.jump());
+
+            isNumber.link(&amp;m_jit);
+        } else if (needsTypeCheck(node-&gt;child1(), SpecBytecodeNumber)) {
</ins><span class="cx">             typeCheck(
</span><span class="cx">                 JSValueRegs(op1TagGPR, op1PayloadGPR), node-&gt;child1(), SpecBytecodeNumber,
</span><span class="cx">                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
</span><span class="cx">         }
</span><del>-    
</del><ins>+
</ins><span class="cx">         unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
</span><del>-        JITCompiler::Jump done = m_jit.jump();
</del><ins>+        done.append(m_jit.jump());
</ins><span class="cx">     
</span><span class="cx">         isInteger.link(&amp;m_jit);
</span><span class="cx">         m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (184932 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-28 00:39:35 UTC (rev 184932)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -958,9 +958,12 @@
</span><span class="cx">     void compileDoubleRep()
</span><span class="cx">     {
</span><span class="cx">         switch (m_node-&gt;child1().useKind()) {
</span><ins>+        case NotCellUse:
</ins><span class="cx">         case NumberUse: {
</span><ins>+            bool shouldConvertNonNumber = m_node-&gt;child1().useKind() == NotCellUse;
+
</ins><span class="cx">             LValue value = lowJSValue(m_node-&gt;child1(), ManualOperandSpeculation);
</span><del>-            setDouble(jsValueToDouble(m_node-&gt;child1(), value));
</del><ins>+            setDouble(jsValueToDouble(m_node-&gt;child1(), value, shouldConvertNonNumber));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -7199,10 +7202,12 @@
</span><span class="cx">     {
</span><span class="cx">         return m_out.sub(m_out.bitCast(doubleValue, m_out.int64), m_tagTypeNumber);
</span><span class="cx">     }
</span><del>-    LValue jsValueToDouble(Edge edge, LValue boxedValue)
</del><ins>+    LValue jsValueToDouble(Edge edge, LValue boxedValue, bool shouldConvertNonNumber)
</ins><span class="cx">     {
</span><span class="cx">         LBasicBlock intCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble unboxing int case&quot;));
</span><ins>+        LBasicBlock doubleTesting = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble testing double case&quot;));
</ins><span class="cx">         LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble unboxing double case&quot;));
</span><ins>+        LBasicBlock nonDoubleCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble testing undefined case&quot;));
</ins><span class="cx">         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble unboxing continuation&quot;));
</span><span class="cx">             
</span><span class="cx">         LValue isNotInt32;
</span><span class="lines">@@ -7212,24 +7217,70 @@
</span><span class="cx">             isNotInt32 = m_out.booleanTrue;
</span><span class="cx">         else
</span><span class="cx">             isNotInt32 = this-&gt;isNotInt32(boxedValue);
</span><del>-        m_out.branch(isNotInt32, unsure(doubleCase), unsure(intCase));
</del><ins>+        m_out.branch(isNotInt32, unsure(doubleTesting), unsure(intCase));
</ins><span class="cx">             
</span><del>-        LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
</del><ins>+        LBasicBlock lastNext = m_out.appendTo(intCase, doubleTesting);
</ins><span class="cx">             
</span><span class="cx">         ValueFromBlock intToDouble = m_out.anchor(
</span><span class="cx">             m_out.intToDouble(unboxInt32(boxedValue)));
</span><span class="cx">         m_out.jump(continuation);
</span><span class="cx">             
</span><del>-        m_out.appendTo(doubleCase, continuation);
-            
-        FTL_TYPE_CHECK(
-            jsValueValue(boxedValue), edge, SpecBytecodeNumber, isCellOrMisc(boxedValue));
-            
</del><ins>+        m_out.appendTo(doubleTesting, doubleCase);
+        LValue valueIsNumber = isNumber(boxedValue);
+        m_out.branch(valueIsNumber, usually(doubleCase), rarely(nonDoubleCase));
+
+        m_out.appendTo(doubleCase, nonDoubleCase);
</ins><span class="cx">         ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
</span><span class="cx">         m_out.jump(continuation);
</span><del>-            
</del><ins>+
+        if (shouldConvertNonNumber) {
+            LBasicBlock undefinedCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble converting undefined case&quot;));
+            LBasicBlock testNullCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble testing null case&quot;));
+            LBasicBlock nullCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble converting null case&quot;));
+            LBasicBlock testBooleanTrueCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble testing boolean true case&quot;));
+            LBasicBlock convertBooleanTrueCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble convert boolean true case&quot;));
+            LBasicBlock convertBooleanFalseCase = FTL_NEW_BLOCK(m_out, (&quot;jsValueToDouble convert boolean false case&quot;));
+
+            m_out.appendTo(nonDoubleCase, undefinedCase);
+            LValue valueIsUndefined = m_out.equal(boxedValue, m_out.constInt64(ValueUndefined));
+            m_out.branch(valueIsUndefined, unsure(undefinedCase), unsure(testNullCase));
+
+            m_out.appendTo(undefinedCase, testNullCase);
+            ValueFromBlock convertedUndefined = m_out.anchor(m_out.constDouble(PNaN));
+            m_out.jump(continuation);
+
+            m_out.appendTo(testNullCase, nullCase);
+            LValue valueIsNull = m_out.equal(boxedValue, m_out.constInt64(ValueNull));
+            m_out.branch(valueIsNull, unsure(nullCase), unsure(testBooleanTrueCase));
+
+            m_out.appendTo(nullCase, testBooleanTrueCase);
+            ValueFromBlock convertedNull = m_out.anchor(m_out.constDouble(0));
+            m_out.jump(continuation);
+
+            m_out.appendTo(testBooleanTrueCase, convertBooleanTrueCase);
+            LValue valueIsBooleanTrue = m_out.equal(boxedValue, m_out.constInt64(ValueTrue));
+            m_out.branch(valueIsBooleanTrue, unsure(convertBooleanTrueCase), unsure(convertBooleanFalseCase));
+
+            m_out.appendTo(convertBooleanTrueCase, convertBooleanFalseCase);
+            ValueFromBlock convertedTrue = m_out.anchor(m_out.constDouble(1));
+            m_out.jump(continuation);
+
+            m_out.appendTo(convertBooleanFalseCase, continuation);
+
+            LValue valueIsNotBooleanFalse = m_out.notEqual(boxedValue, m_out.constInt64(ValueFalse));
+            FTL_TYPE_CHECK(jsValueValue(boxedValue), edge, ~SpecCell, valueIsNotBooleanFalse);
+            ValueFromBlock convertedFalse = m_out.anchor(m_out.constDouble(0));
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble, convertedUndefined, convertedNull, convertedTrue, convertedFalse);
+        }
+        m_out.appendTo(nonDoubleCase, continuation);
+        FTL_TYPE_CHECK(jsValueValue(boxedValue), edge, SpecBytecodeNumber, m_out.booleanTrue);
+        m_out.unreachable();
+
</ins><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><del>-            
</del><ins>+
</ins><span class="cx">         return m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdoublerepwithnoncelljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/double-rep-with-non-cell.js (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/double-rep-with-non-cell.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/double-rep-with-non-cell.js        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+// Only bool, undefined and null
+function addNullBoolUndefined(a, b) {
+    return a + b;
+}
+noInline(addNullBoolUndefined);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addNullBoolUndefined(0.5, null);
+    if (value !== 0.5)
+        throw &quot;addNullBoolUndefined(0.5, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addNullBoolUndefined(null, undefined);
+    if (value === value)
+        throw &quot;addNullBoolUndefined(null, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addNullBoolUndefined(true, null);
+    if (value !== 1)
+        throw &quot;addNullBoolUndefined(true, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addNullBoolUndefined(undefined, false);
+    if (value === value)
+        throw &quot;addNullBoolUndefined(undefined, false) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addNullBoolUndefined(false, true);
+    if (value !== 1)
+        throw &quot;addNullBoolUndefined(false, true) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addNullBoolUndefined(null, 42);
+    if (value !== 42)
+        throw &quot;addNullBoolUndefined(null, 42) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdoublerepwithnulljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/double-rep-with-null.js (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/double-rep-with-null.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/double-rep-with-null.js        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,107 @@
</span><ins>+// Using full number + null for math.
+function addArgsNumberAndNull(a, b) {
+    return a + b;
+}
+noInline(addArgsNumberAndNull);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsNumberAndNull(i, 1);
+    if (value !== (i + 1))
+        throw &quot;addArgsNumberAndNull(i, 1) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndNull(0.5, i);
+    if (value !== (i + 0.5))
+        throw &quot;addArgsNumberAndNull(0.5, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndNull(null, i);
+    if (value !== i)
+        throw &quot;addArgsNumberAndNull(null, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndNull(i, null);
+    if (value !== i)
+        throw &quot;addArgsNumberAndNull(i, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndNull(null, null);
+    if (value !== 0)
+        throw &quot;addArgsNumberAndNull(null, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+
+// Using int32 + null for math.
+function addArgsInt32AndNull(a, b) {
+    return a + b;
+}
+noInline(addArgsInt32AndNull);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsInt32AndNull(i, 1);
+    if (value !== (i + 1))
+        throw &quot;addArgsInt32AndNull(i, 1) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndNull(null, i);
+    if (value !== i)
+        throw &quot;addArgsInt32AndNull(null, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndNull(i, null);
+    if (value !== i)
+        throw &quot;addArgsInt32AndNull(i, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndNull(null, null);
+    if (value !== 0)
+        throw &quot;addArgsInt32AndNull(null, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithDouble() {
+    var value = addArgsNumberAndNull(Math.PI, Math.PI);
+    if (value !== 2 * Math.PI)
+        throw &quot;addArgsNumberAndNull(Math.PI, Math.PI) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithDouble();
+
+
+// Using full number + null for math.
+function addArgsDoubleAndNull(a, b) {
+    return a + b;
+}
+noInline(addArgsDoubleAndNull);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsDoubleAndNull(0.5, i);
+    if (value !== (i + 0.5))
+        throw &quot;addArgsDoubleAndNull(0.5, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsDoubleAndNull(null, 0.1);
+    if (value !== 0.1)
+        throw &quot;addArgsDoubleAndNull(null, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsDoubleAndNull(0.6, null);
+    if (value !== 0.6)
+        throw &quot;addArgsDoubleAndNull(i, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithObject() {
+    var value = addArgsDoubleAndNull(Math.PI, { valueOf: function() { return 5; }});
+    if (value !== 5 + Math.PI)
+        throw &quot;addArgsDoubleAndNull(Math.PI, { valueOf: function() { return 5; }}) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithObject();
+
+
+// Using only null
+function addArgsOnlyNull(a, b) {
+    return a + b;
+}
+noInline(addArgsOnlyNull);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsOnlyNull(null, null);
+    if (value !== 0)
+        throw &quot;addArgsOnlyNull(null, null) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithString() {
+    var value = addArgsOnlyNull(&quot;foo&quot;, &quot;bar&quot;);
+    if (value !== &quot;foobar&quot;)
+        throw &quot;addArgsOnlyNull(\&quot;foo\&quot;, \&quot;bar\&quot;) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithString();
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdoublerepwithundefinedjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/double-rep-with-undefined.js (0 => 184933)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/double-rep-with-undefined.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/double-rep-with-undefined.js        2015-05-28 01:30:58 UTC (rev 184933)
</span><span class="lines">@@ -0,0 +1,131 @@
</span><ins>+// Using full number + undefined for math.
+function addArgsNumberAndUndefined(a, b) {
+    return a + b;
+}
+noInline(addArgsNumberAndUndefined);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsNumberAndUndefined(i, 1);
+    if (value !== (i + 1))
+        throw &quot;addArgsNumberAndUndefined(i, 1) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined(0.5, i);
+    if (value !== (i + 0.5))
+        throw &quot;addArgsNumberAndUndefined(0.5, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined(undefined, i);
+    if (value === value)
+        throw &quot;addArgsNumberAndUndefined(undefined, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined(i, undefined);
+    if (value === value)
+        throw &quot;addArgsNumberAndUndefined(i, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined(i);
+    if (value === value)
+        throw &quot;addArgsNumberAndUndefined(i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined(undefined, undefined);
+    if (value === value)
+        throw &quot;addArgsNumberAndUndefined(undefined, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsNumberAndUndefined();
+    if (value === value)
+        throw &quot;addArgsNumberAndUndefined() failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+
+// Using int32 + undefined for math.
+function addArgsInt32AndUndefined(a, b) {
+    return a + b;
+}
+noInline(addArgsInt32AndUndefined);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsInt32AndUndefined(i, 1);
+    if (value !== (i + 1))
+        throw &quot;addArgsInt32AndUndefined(i, 1) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndUndefined(undefined, i);
+    if (value === value)
+        throw &quot;addArgsInt32AndUndefined(undefined, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndUndefined(i, undefined);
+    if (value === value)
+        throw &quot;addArgsInt32AndUndefined(i, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndUndefined(i);
+    if (value === value)
+        throw &quot;addArgsInt32AndUndefined(i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndUndefined(undefined, undefined);
+    if (value === value)
+        throw &quot;addArgsInt32AndUndefined(undefined, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsInt32AndUndefined();
+    if (value === value)
+        throw &quot;addArgsInt32AndUndefined() failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithDouble() {
+    var value = addArgsNumberAndUndefined(Math.PI, Math.PI);
+    if (value !== 2 * Math.PI)
+        throw &quot;addArgsNumberAndUndefined(Math.PI, Math.PI) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithDouble();
+
+
+// Using full number + undefined for math.
+function addArgsDoubleAndUndefined(a, b) {
+    return a + b;
+}
+noInline(addArgsDoubleAndUndefined);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsDoubleAndUndefined(0.5, i);
+    if (value !== (i + 0.5))
+        throw &quot;addArgsDoubleAndUndefined(0.5, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsDoubleAndUndefined(undefined, 0.1);
+    if (value === value)
+        throw &quot;addArgsDoubleAndUndefined(undefined, i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsDoubleAndUndefined(0.6, undefined);
+    if (value === value)
+        throw &quot;addArgsDoubleAndUndefined(i, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsDoubleAndUndefined(42.8);
+    if (value === value)
+        throw &quot;addArgsDoubleAndUndefined(i) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithObject() {
+    var value = addArgsDoubleAndUndefined(Math.PI, { valueOf: function() { return 5; }});
+    if (value !== 5 + Math.PI)
+        throw &quot;addArgsDoubleAndUndefined(Math.PI, { valueOf: function() { return 5; }}) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithObject();
+
+
+// Using full number + undefined for math.
+function addArgsOnlyUndefined(a, b) {
+    return a + b;
+}
+noInline(addArgsOnlyUndefined);
+
+for (var i = 0; i &lt; 1e7; ++i) {
+    var value = addArgsOnlyUndefined(undefined, undefined);
+    if (value === value)
+        throw &quot;addArgsOnlyUndefined(undefined, undefined) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+
+    var value = addArgsOnlyUndefined();
+    if (value === value)
+        throw &quot;addArgsOnlyUndefined() failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+
+function testFallbackWithString() {
+    var value = addArgsOnlyUndefined(&quot;foo&quot;, &quot;bar&quot;);
+    if (value !== &quot;foobar&quot;)
+        throw &quot;addArgsOnlyUndefined(\&quot;foo\&quot;, \&quot;bar\&quot;) failed with i = &quot; + i + &quot; returned value = &quot; + value;
+}
+testFallbackWithString();
</ins><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>