<!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>[192993] 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/192993">192993</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-12-02 21:42:56 -0800 (Wed, 02 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Polymorphic operand types for DFG and FTL mul.
https://bugs.webkit.org/show_bug.cgi?id=151746

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Perf on benchmarks is neutral except for the newly added JSRegress ftl-object-mul
test which shows a 2.16x speed up on x86_64 FTL, 1.27x speed up on x86_64 DFG,
and 1.56x on x86 DFG. 

The speed up comes not from the mul operator itself, but from the fact that the
polymorphic operand types support now allow the test function to run without OSR
exiting, thereby realizing the DFG and FTL's speed up on other work that the test
function does.

This patch has passed the layout tests on x86_64 with a debug build.
It passed the JSC tests with x86 and x86_64 debug builds.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithMul):
* ftl/FTLCompile.cpp:
- Changed to call generateBinaryOpFastPath() instead now, and let it dispatch to
  the appropriate snippet generator.

* ftl/FTLCompileBinaryOp.cpp:
(JSC::FTL::generateBinaryArithOpFastPath):
(JSC::FTL::generateBinaryOpFastPath):
(JSC::FTL::generateArithSubFastPath): Deleted.
(JSC::FTL::generateValueAddFastPath): Deleted.
- Refactored these functions to eliminate the need for copy-pasting every time
  we add support for another binary arithmetic snippet.

* ftl/FTLCompileBinaryOp.h:
* ftl/FTLInlineCacheDescriptor.h:
* ftl/FTLInlineCacheDescriptorInlines.h:
(JSC::FTL::ArithMulDescriptor::ArithMulDescriptor):
(JSC::FTL::ArithMulDescriptor::icSize):
* ftl/FTLInlineCacheSize.cpp:
(JSC::FTL::sizeOfArithMul):
* ftl/FTLInlineCacheSize.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::lower):
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
* jit/JITMulGenerator.h:
(JSC::JITMulGenerator::JITMulGenerator):

* tests/stress/op_mul.js:
- Updated a test value: the interesting value for imminent overflow from an
  int32 is 0x7fffffff, not 0x7ffffff.

LayoutTests:

* js/regress/ftl-object-mul-expected.txt: Added.
* js/regress/ftl-object-mul.html: Added.
* js/regress/script-tests/ftl-object-mul.js: Added.
(o1.valueOf):
(foo):</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="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</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="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompileBinaryOpcpp">trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompileBinaryOph">trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLInlineCacheDescriptorh">trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLInlineCacheDescriptorInlinesh">trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLInlineCacheSizecpp">trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLInlineCacheSizeh">trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMulGeneratorh">trunk/Source/JavaScriptCore/jit/JITMulGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressop_muljs">trunk/Source/JavaScriptCore/tests/stress/op_mul.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressftlobjectmulexpectedtxt">trunk/LayoutTests/js/regress/ftl-object-mul-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressftlobjectmulhtml">trunk/LayoutTests/js/regress/ftl-object-mul.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsftlobjectmuljs">trunk/LayoutTests/js/regress/script-tests/ftl-object-mul.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/LayoutTests/ChangeLog        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-12-02  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Polymorphic operand types for DFG and FTL mul.
+        https://bugs.webkit.org/show_bug.cgi?id=151746
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/ftl-object-mul-expected.txt: Added.
+        * js/regress/ftl-object-mul.html: Added.
+        * js/regress/script-tests/ftl-object-mul.js: Added.
+        (o1.valueOf):
+        (foo):
+
</ins><span class="cx"> 2015-12-02  Myles C. Maxfield  &lt;mmaxfield@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unify font-variant-* with font-variant shorthand
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressftlobjectmulexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/ftl-object-mul-expected.txt (0 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/ftl-object-mul-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-object-mul-expected.txt        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/ftl-object-mul
+
+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="trunkLayoutTestsjsregressftlobjectmulhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/ftl-object-mul.html (0 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/ftl-object-mul.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-object-mul.html        2015-12-03 05:42:56 UTC (rev 192993)
</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/ftl-object-mul.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="trunkLayoutTestsjsregressscripttestsftlobjectmuljs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/ftl-object-mul.js (0 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/ftl-object-mul.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-object-mul.js        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+//@ runFTLNoCJIT
+var o1 = {
+    i: 0,
+    valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+    var result = 0;
+    for (var j = 0; j &lt; 10; j++) {
+        if (a &gt; b)
+            result += a * b;
+        else
+            result += b * 1;
+    }
+    for (var i = 0; i &lt; 1000; i++)
+        result += i;
+    return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+    // The layout test doesn't like too many iterations and may time out.
+    iterations = 10000;
+    expectedResult = 9997995200;
+} else {
+    iterations = 100000;
+    expectedResult = 549975495200;
+}
+
+
+for (var i = 0; i &lt;= iterations; i++) {
+    o1.i = i + 2;
+    result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+    throw &quot;Bad result: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -1,3 +1,64 @@
</span><ins>+2015-12-02  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Polymorphic operand types for DFG and FTL mul.
+        https://bugs.webkit.org/show_bug.cgi?id=151746
+
+        Reviewed by Filip Pizlo.
+
+        Perf on benchmarks is neutral except for the newly added JSRegress ftl-object-mul
+        test which shows a 2.16x speed up on x86_64 FTL, 1.27x speed up on x86_64 DFG,
+        and 1.56x on x86 DFG. 
+
+        The speed up comes not from the mul operator itself, but from the fact that the
+        polymorphic operand types support now allow the test function to run without OSR
+        exiting, thereby realizing the DFG and FTL's speed up on other work that the test
+        function does.
+
+        This patch has passed the layout tests on x86_64 with a debug build.
+        It passed the JSC tests with x86 and x86_64 debug builds.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithMul):
+        * ftl/FTLCompile.cpp:
+        - Changed to call generateBinaryOpFastPath() instead now, and let it dispatch to
+          the appropriate snippet generator.
+
+        * ftl/FTLCompileBinaryOp.cpp:
+        (JSC::FTL::generateBinaryArithOpFastPath):
+        (JSC::FTL::generateBinaryOpFastPath):
+        (JSC::FTL::generateArithSubFastPath): Deleted.
+        (JSC::FTL::generateValueAddFastPath): Deleted.
+        - Refactored these functions to eliminate the need for copy-pasting every time
+          we add support for another binary arithmetic snippet.
+
+        * ftl/FTLCompileBinaryOp.h:
+        * ftl/FTLInlineCacheDescriptor.h:
+        * ftl/FTLInlineCacheDescriptorInlines.h:
+        (JSC::FTL::ArithMulDescriptor::ArithMulDescriptor):
+        (JSC::FTL::ArithMulDescriptor::icSize):
+        * ftl/FTLInlineCacheSize.cpp:
+        (JSC::FTL::sizeOfArithMul):
+        * ftl/FTLInlineCacheSize.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMul):
+        * jit/JITMulGenerator.h:
+        (JSC::JITMulGenerator::JITMulGenerator):
+
+        * tests/stress/op_mul.js:
+        - Updated a test value: the interesting value for imminent overflow from an
+          int32 is 0x7fffffff, not 0x7ffffff.
+
</ins><span class="cx"> 2015-12-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r192753): Remote Web Inspector: Applications and Debuggables not showing up in debuggers
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -634,6 +634,10 @@
</span><span class="cx">                 typeOfDoubleProduct(
</span><span class="cx">                     forNode(node-&gt;child1()).m_type, forNode(node-&gt;child2()).m_type));
</span><span class="cx">             break;
</span><ins>+        case UntypedUse:
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
+            forNode(node).setType(m_graph, SpecBytecodeNumber);
+            break;
</ins><span class="cx">         default:
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -248,7 +248,6 @@
</span><span class="cx"> 
</span><span class="cx">     case ArithAdd:
</span><span class="cx">     case ArithNegate:
</span><del>-    case ArithMul:
</del><span class="cx">     case ArithDiv:
</span><span class="cx">     case ArithMod:
</span><span class="cx">     case DoubleAsInt32:
</span><span class="lines">@@ -257,6 +256,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case ArithSub:
</span><ins>+    case ArithMul:
</ins><span class="cx">         switch (node-&gt;binaryUseKind()) {
</span><span class="cx">         case Int32Use:
</span><span class="cx">         case Int52RepUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -227,9 +227,18 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case ArithMul: {
</span><ins>+            Edge&amp; leftChild = node-&gt;child1();
+            Edge&amp; rightChild = node-&gt;child2();
+            if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())
+                || m_graph.hasExitSite(node-&gt;origin.semantic, BadType)) {
+                fixEdge&lt;UntypedUse&gt;(leftChild);
+                fixEdge&lt;UntypedUse&gt;(rightChild);
+                node-&gt;setResult(NodeResultJS);
+                break;
+            }
</ins><span class="cx">             if (m_graph.mulShouldSpeculateInt32(node, FixupPass)) {
</span><del>-                fixIntOrBooleanEdge(node-&gt;child1());
-                fixIntOrBooleanEdge(node-&gt;child2());
</del><ins>+                fixIntOrBooleanEdge(leftChild);
+                fixIntOrBooleanEdge(rightChild);
</ins><span class="cx">                 if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</span><span class="cx">                     node-&gt;setArithMode(Arith::Unchecked);
</span><span class="cx">                 else if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
</span><span class="lines">@@ -239,8 +248,8 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (m_graph.mulShouldSpeculateMachineInt(node, FixupPass)) {
</span><del>-                fixEdge&lt;Int52RepUse&gt;(node-&gt;child1());
-                fixEdge&lt;Int52RepUse&gt;(node-&gt;child2());
</del><ins>+                fixEdge&lt;Int52RepUse&gt;(leftChild);
+                fixEdge&lt;Int52RepUse&gt;(rightChild);
</ins><span class="cx">                 if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
</span><span class="cx">                     node-&gt;setArithMode(Arith::CheckOverflow);
</span><span class="cx">                 else
</span><span class="lines">@@ -248,8 +257,8 @@
</span><span class="cx">                 node-&gt;setResult(NodeResultInt52);
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            fixDoubleOrBooleanEdge(node-&gt;child1());
-            fixDoubleOrBooleanEdge(node-&gt;child2());
</del><ins>+            fixDoubleOrBooleanEdge(leftChild);
+            fixDoubleOrBooleanEdge(rightChild);
</ins><span class="cx">             node-&gt;setResult(NodeResultDouble);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -200,6 +200,19 @@
</span><span class="cx">     return JSValue::encode(jsAddSlowCase(exec, op1, op2));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    JSValue op1 = JSValue::decode(encodedOp1);
+    JSValue op2 = JSValue::decode(encodedOp2);
+
+    double a = op1.toNumber(exec);
+    double b = op2.toNumber(exec);
+    return JSValue::encode(jsNumber(a * b));
+}
+
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSub(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><ins>+EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValCell(ExecState*, JSCell*, EncodedJSValue encodedProperty) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -334,12 +334,16 @@
</span><span class="cx">             SpeculatedType right = node-&gt;child2()-&gt;prediction();
</span><span class="cx">             
</span><span class="cx">             if (left &amp;&amp; right) {
</span><del>-                if (m_graph.mulShouldSpeculateInt32(node, m_pass))
-                    changed |= mergePrediction(SpecInt32);
-                else if (m_graph.mulShouldSpeculateMachineInt(node, m_pass))
-                    changed |= mergePrediction(SpecInt52);
-                else
-                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
</del><ins>+                if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
+                    &amp;&amp; isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
+                    if (m_graph.mulShouldSpeculateInt32(node, m_pass))
+                        changed |= mergePrediction(SpecInt32);
+                    else if (m_graph.mulShouldSpeculateMachineInt(node, m_pass))
+                        changed |= mergePrediction(SpecInt52);
+                    else
+                        changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
+                } else
+                    changed |= mergePrediction(SpecInt32 | SpecBytecodeDouble);
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &quot;DFGSlowPathGenerator.h&quot;
</span><span class="cx"> #include &quot;DirectArguments.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><ins>+#include &quot;JITMulGenerator.h&quot;
</ins><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="cx"> #include &quot;JSArrowFunction.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="lines">@@ -3443,7 +3444,108 @@
</span><span class="cx">         doubleResult(result.fpr(), node);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-        
</del><ins>+
+    case UntypedUse: {
+        Edge&amp; leftChild = node-&gt;child1();
+        Edge&amp; rightChild = node-&gt;child2();
+
+        if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
+            JSValueOperand left(this, leftChild);
+            JSValueOperand right(this, rightChild);
+            JSValueRegs leftRegs = left.jsValueRegs();
+            JSValueRegs rightRegs = right.jsValueRegs();
+#if USE(JSVALUE64)
+            GPRTemporary result(this);
+            JSValueRegs resultRegs = JSValueRegs(result.gpr());
+#else
+            GPRTemporary resultTag(this);
+            GPRTemporary resultPayload(this);
+            JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+            flushRegisters();
+            callOperation(operationValueMul, resultRegs, leftRegs, rightRegs);
+            m_jit.exceptionCheck();
+
+            jsValueResult(resultRegs, node);
+            return;
+        }
+
+        Optional&lt;JSValueOperand&gt; left;
+        Optional&lt;JSValueOperand&gt; right;
+
+        JSValueRegs leftRegs;
+        JSValueRegs rightRegs;
+
+        FPRTemporary leftNumber(this);
+        FPRTemporary rightNumber(this);
+        FPRReg leftFPR = leftNumber.fpr();
+        FPRReg rightFPR = rightNumber.fpr();
+
+#if USE(JSVALUE64)
+        GPRTemporary result(this);
+        JSValueRegs resultRegs = JSValueRegs(result.gpr());
+        GPRTemporary scratch(this);
+        GPRReg scratchGPR = scratch.gpr();
+        FPRReg scratchFPR = InvalidFPRReg;
+#else
+        GPRTemporary resultTag(this);
+        GPRTemporary resultPayload(this);
+        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+        GPRReg scratchGPR = resultTag.gpr();
+        FPRTemporary fprScratch(this);
+        FPRReg scratchFPR = fprScratch.fpr();
+#endif
+
+        SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
+        SnippetOperand rightOperand(m_state.forNode(rightChild).resultType());
+
+        if (leftChild-&gt;isInt32Constant())
+            leftOperand.setConstInt32(leftChild-&gt;asInt32());
+        if (rightChild-&gt;isInt32Constant())
+            rightOperand.setConstInt32(rightChild-&gt;asInt32());
+
+        RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+        if (!leftOperand.isPositiveConstInt32()) {
+            left = JSValueOperand(this, leftChild);
+            leftRegs = left-&gt;jsValueRegs();
+        }
+        if (!rightOperand.isPositiveConstInt32()) {
+            right = JSValueOperand(this, rightChild);
+            rightRegs = right-&gt;jsValueRegs();
+        }
+
+        JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
+            leftFPR, rightFPR, scratchGPR, scratchFPR);
+        gen.generateFastPath(m_jit);
+
+        ASSERT(gen.didEmitFastPath());
+        gen.endJumpList().append(m_jit.jump());
+
+        gen.slowPathJumpList().link(&amp;m_jit);
+        silentSpillAllRegisters(resultRegs);
+
+        if (leftOperand.isPositiveConstInt32()) {
+            leftRegs = resultRegs;
+            int64_t leftConst = leftOperand.asConstInt32();
+            m_jit.moveValue(JSValue(leftConst), leftRegs);
+        }
+        if (rightOperand.isPositiveConstInt32()) {
+            rightRegs = resultRegs;
+            int64_t rightConst = rightOperand.asConstInt32();
+            m_jit.moveValue(JSValue(rightConst), rightRegs);
+        }
+
+        callOperation(operationValueMul, resultRegs, leftRegs, rightRegs);
+
+        silentFillAllRegisters(resultRegs);
+        m_jit.exceptionCheck();
+
+        gen.endJumpList().link(&amp;m_jit);
+        jsValueResult(resultRegs, node);
+        return;
+    }
+
</ins><span class="cx">     default:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -336,16 +336,7 @@
</span><span class="cx">         CCallHelpers::Jump done;
</span><span class="cx">         CCallHelpers::Jump slowPathStart;
</span><span class="cx"> 
</span><del>-        switch (ic.nodeType()) {
-        case ArithSub:
-            generateArithSubFastPath(ic, fastPathJIT, result, left, right, usedRegisters, done, slowPathStart);
-            break;
-        case ValueAdd:
-            generateValueAddFastPath(ic, fastPathJIT, result, left, right, usedRegisters, done, slowPathStart);
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-        }
</del><ins>+        generateBinaryOpFastPath(ic, fastPathJIT, result, left, right, usedRegisters, done, slowPathStart);
</ins><span class="cx"> 
</span><span class="cx">         char* startOfIC = bitwise_cast&lt;char*&gt;(generatedFunction) + record.instructionOffset;
</span><span class="cx">         const char* fastPathICName = ic.fastPathICName();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompileBinaryOpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;FTLInlineCacheDescriptor.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><ins>+#include &quot;JITMulGenerator.h&quot;
</ins><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="cx"> #include &quot;ScratchRegisterAllocator.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -152,11 +153,11 @@
</span><span class="cx">     GPRReg m_savedTagTypeNumberRegister { InvalidGPRReg };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-void generateArithSubFastPath(BinaryOpDescriptor&amp; ic, CCallHelpers&amp; jit,
</del><ins>+template&lt;typename BinaryArithOpGenerator&gt;
+void generateBinaryArithOpFastPath(BinaryOpDescriptor&amp; ic, CCallHelpers&amp; jit,
</ins><span class="cx">     GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
</span><span class="cx">     CCallHelpers::Jump&amp; done, CCallHelpers::Jump&amp; slowPathStart)
</span><span class="cx"> {
</span><del>-    ASSERT(ic.nodeType() == ArithSub);
</del><span class="cx">     ScratchRegisterAllocator allocator(usedRegisters);
</span><span class="cx"> 
</span><span class="cx">     BinarySnippetRegisterContext context(allocator, result, left, right);
</span><span class="lines">@@ -166,7 +167,7 @@
</span><span class="cx">     FPRReg rightFPR = allocator.allocateScratchFPR();
</span><span class="cx">     FPRReg scratchFPR = InvalidFPRReg;
</span><span class="cx"> 
</span><del>-    JITSubGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
</del><ins>+    BinaryArithOpGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
</ins><span class="cx">         JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
</span><span class="cx"> 
</span><span class="cx">     auto numberOfBytesUsedToPreserveReusedRegisters =
</span><span class="lines">@@ -189,41 +190,23 @@
</span><span class="cx">     slowPathStart = jit.jump();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void generateValueAddFastPath(BinaryOpDescriptor&amp; ic, CCallHelpers&amp; jit,
</del><ins>+void generateBinaryOpFastPath(BinaryOpDescriptor&amp; ic, CCallHelpers&amp; jit,
</ins><span class="cx">     GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
</span><span class="cx">     CCallHelpers::Jump&amp; done, CCallHelpers::Jump&amp; slowPathStart)
</span><span class="cx"> {
</span><del>-    ASSERT(ic.nodeType() == ValueAdd);
-    ScratchRegisterAllocator allocator(usedRegisters);
-
-    BinarySnippetRegisterContext context(allocator, result, left, right);
-
-    GPRReg scratchGPR = allocator.allocateScratchGPR();
-    FPRReg leftFPR = allocator.allocateScratchFPR();
-    FPRReg rightFPR = allocator.allocateScratchFPR();
-    FPRReg scratchFPR = InvalidFPRReg;
-
-    JITAddGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
-        JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
-
-    auto numberOfBytesUsedToPreserveReusedRegisters =
-    allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
-
-    context.initializeRegisters(jit);
-    gen.generateFastPath(jit);
-
-    ASSERT(gen.didEmitFastPath());
-    gen.endJumpList().link(&amp;jit);
-    context.restoreRegisters(jit);
-    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
-        ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
-    done = jit.jump();
-
-    gen.slowPathJumpList().link(&amp;jit);
-    context.restoreRegisters(jit);
-    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
-        ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
-    slowPathStart = jit.jump();
</del><ins>+    switch (ic.nodeType()) {
+    case ArithMul:
+        generateBinaryArithOpFastPath&lt;JITMulGenerator&gt;(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+        break;
+    case ArithSub:
+        generateBinaryArithOpFastPath&lt;JITSubGenerator&gt;(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+        break;
+    case ValueAdd:
+        generateBinaryArithOpFastPath&lt;JITAddGenerator&gt;(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+        break;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompileBinaryOph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -35,14 +35,10 @@
</span><span class="cx"> 
</span><span class="cx"> class BinaryOpDescriptor;
</span><span class="cx"> 
</span><del>-void generateArithSubFastPath(BinaryOpDescriptor&amp;, CCallHelpers&amp;,
</del><ins>+void generateBinaryOpFastPath(BinaryOpDescriptor&amp;, CCallHelpers&amp;,
</ins><span class="cx">     GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
</span><span class="cx">     CCallHelpers::Jump&amp; done, CCallHelpers::Jump&amp; slowPathStart);
</span><span class="cx"> 
</span><del>-void generateValueAddFastPath(BinaryOpDescriptor&amp;, CCallHelpers&amp;,
-    GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
-    CCallHelpers::Jump&amp; done, CCallHelpers::Jump&amp; slowPathStart);
-
</del><span class="cx"> } // namespace FTL
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLInlineCacheDescriptorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -165,6 +165,12 @@
</span><span class="cx">     SnippetOperand m_rightOperand;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class ArithMulDescriptor : public BinaryOpDescriptor {
+public:
+    ArithMulDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand&amp; leftOperand, const SnippetOperand&amp; rightOperand);
+    static size_t icSize();
+};
+
</ins><span class="cx"> class ArithSubDescriptor : public BinaryOpDescriptor {
</span><span class="cx"> public:
</span><span class="cx">     ArithSubDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand&amp; leftOperand, const SnippetOperand&amp; rightOperand);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLInlineCacheDescriptorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -35,6 +35,18 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="cx"> 
</span><ins>+ArithMulDescriptor::ArithMulDescriptor(unsigned stackmapID, CodeOrigin codeOrigin,
+    const SnippetOperand&amp; leftOperand, const SnippetOperand&amp; rightOperand)
+    : BinaryOpDescriptor(DFG::ArithMul, stackmapID, codeOrigin, icSize(),
+        &quot;ArithMul&quot;, &quot;ArithMul IC fast path&quot;, DFG::operationValueMul, leftOperand, rightOperand)
+{
+}
+
+size_t ArithMulDescriptor::icSize()
+{
+    return sizeOfArithMul();
+}
+
</ins><span class="cx"> ArithSubDescriptor::ArithSubDescriptor(unsigned stackmapID, CodeOrigin codeOrigin,
</span><span class="cx">     const SnippetOperand&amp; leftOperand, const SnippetOperand&amp; rightOperand)
</span><span class="cx">     : BinaryOpDescriptor(DFG::ArithSub, stackmapID, codeOrigin, icSize(),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLInlineCacheSizecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -128,6 +128,23 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+size_t sizeOfArithMul()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+    return 180; // ARM64 release.
+#else
+    return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+    return 199; // X86_64 release.
+#else
+    return 286; // X86_64 debug.
+#endif
+#endif
+}
+
</ins><span class="cx"> size_t sizeOfArithSub()
</span><span class="cx"> {
</span><span class="cx"> #if CPU(ARM64)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLInlineCacheSizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> size_t sizeOfConstructVarargs();
</span><span class="cx"> size_t sizeOfConstructForwardVarargs();
</span><span class="cx"> size_t sizeOfIn();
</span><ins>+size_t sizeOfArithMul();
</ins><span class="cx"> size_t sizeOfArithSub();
</span><span class="cx"> size_t sizeOfValueAdd();
</span><span class="cx"> #if ENABLE(MASM_PROBE)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -232,6 +232,7 @@
</span><span class="cx">                             maxNumberOfCatchSpills = std::max(maxNumberOfCatchSpills, m_graph.localsLiveInBytecode(opCatchOrigin).bitCount());
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><ins>+                    case ArithMul:
</ins><span class="cx">                     case ArithSub:
</span><span class="cx">                     case GetById:
</span><span class="cx">                     case GetByIdFlush:
</span><span class="lines">@@ -1485,8 +1486,8 @@
</span><span class="cx">     
</span><span class="cx">     void compileValueAdd()
</span><span class="cx">     {
</span><del>-        auto leftChild = m_node-&gt;child1();
-        auto rightChild = m_node-&gt;child2();
</del><ins>+        Edge&amp; leftChild = m_node-&gt;child1();
+        Edge&amp; rightChild = m_node-&gt;child2();
</ins><span class="cx"> 
</span><span class="cx">         if (!(provenType(leftChild) &amp; SpecFullNumber) || !(provenType(rightChild) &amp; SpecFullNumber)) {
</span><span class="cx">             setJSValue(vmCall(m_out.int64, m_out.operation(operationValueAddNotNumber), m_callFrame,
</span><span class="lines">@@ -1809,7 +1810,60 @@
</span><span class="cx">                 m_out.doubleMul(lowDouble(m_node-&gt;child1()), lowDouble(m_node-&gt;child2())));
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-            
</del><ins>+
+        case UntypedUse: {
+            Edge&amp; leftChild = m_node-&gt;child1();
+            Edge&amp; rightChild = m_node-&gt;child2();
+
+            if (!(provenType(leftChild) &amp; SpecFullNumber) || !(provenType(rightChild) &amp; SpecFullNumber)) {
+                setJSValue(vmCall(m_out.int64, m_out.operation(operationValueMul), m_callFrame,
+                    lowJSValue(leftChild), lowJSValue(rightChild)));
+                return;
+            }
+
+            unsigned stackmapID = m_stackmapIDs++;
+
+            if (Options::verboseCompilation())
+                dataLog(&quot;    Emitting ArithMul patchpoint with stackmap #&quot;, stackmapID, &quot;\n&quot;);
+
+#if FTL_USES_B3
+            CRASH();
+#else
+            LValue left = lowJSValue(leftChild);
+            LValue right = lowJSValue(rightChild);
+
+            SnippetOperand leftOperand(abstractValue(leftChild).resultType());
+            SnippetOperand rightOperand(abstractValue(rightChild).resultType());
+
+            if (leftChild-&gt;isInt32Constant())
+                leftOperand.setConstInt32(leftChild-&gt;asInt32());
+            if (rightChild-&gt;isInt32Constant())
+                rightOperand.setConstInt32(rightChild-&gt;asInt32());
+
+            RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+            // Arguments: id, bytes, target, numArgs, args...
+            StackmapArgumentList arguments;
+            arguments.append(m_out.constInt64(stackmapID));
+            arguments.append(m_out.constInt32(ArithSubDescriptor::icSize()));
+            arguments.append(constNull(m_out.ref8));
+            arguments.append(m_out.constInt32(2));
+            arguments.append(left);
+            arguments.append(right);
+
+            appendOSRExitArgumentsForPatchpointIfWillCatchException(arguments,
+                ExceptionType::BinaryOpGenerator, 3); // left, right, and result show up in the stackmap locations.
+
+            LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments);
+            setInstructionCallingConvention(call, LLVMAnyRegCallConv);
+
+            m_ftlState.binaryOps.append(ArithMulDescriptor(stackmapID, m_node-&gt;origin.semantic, leftOperand, rightOperand));
+
+            setJSValue(call);
+#endif
+            break;
+        }
+
</ins><span class="cx">         default:
</span><span class="cx">             DFG_CRASH(m_graph, m_node, &quot;Bad use kind&quot;);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMulGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMulGenerator.h (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> public:
</span><span class="cx">     JITMulGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><del>-        FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, uint32_t* profilingCounter)
</del><ins>+        FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR, uint32_t* profilingCounter = nullptr)
</ins><span class="cx">         : m_leftOperand(leftOperand)
</span><span class="cx">         , m_rightOperand(rightOperand)
</span><span class="cx">         , m_result(result)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressop_muljs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/op_mul.js (192992 => 192993)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/op_mul.js        2015-12-03 04:08:41 UTC (rev 192992)
+++ trunk/Source/JavaScriptCore/tests/stress/op_mul.js        2015-12-03 05:42:56 UTC (rev 192993)
</span><span class="lines">@@ -43,8 +43,8 @@
</span><span class="cx">     '-0x7fff',
</span><span class="cx">     '0x10000',
</span><span class="cx">     '-0x10000',
</span><del>-    '0x7ffffff',
-    '-0x7ffffff',
</del><ins>+    '0x7fffffff',
+    '-0x7fffffff',
</ins><span class="cx">     '0x100000000',
</span><span class="cx">     '-0x100000000',
</span><span class="cx"> 
</span><span class="lines">@@ -59,8 +59,8 @@
</span><span class="cx">     '&quot;-0x7fff&quot;',
</span><span class="cx">     '&quot;0x10000&quot;',
</span><span class="cx">     '&quot;-0x10000&quot;',
</span><del>-    '&quot;0x7ffffff&quot;',
-    '&quot;-0x7ffffff&quot;',
</del><ins>+    '&quot;0x7fffffff&quot;',
+    '&quot;-0x7fffffff&quot;',
</ins><span class="cx">     '&quot;0x100000000&quot;',
</span><span class="cx">     '&quot;-0x100000000&quot;',
</span><span class="cx"> ];
</span></span></pre>
</div>
</div>

</body>
</html>