<!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>[203693] trunk/Source/JavaScriptCore</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/203693">203693</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2016-07-25 12:04:16 -0700 (Mon, 25 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>op_mul/ArithMul(Untyped,Untyped) should be an IC
https://bugs.webkit.org/show_bug.cgi?id=160108

Reviewed by Mark Lam.

This patch makes Mul a type based IC in much the same way that we made
Add a type-based IC. I implemented Mul in the same way. I abstracted the
implementation of the Add IC in the various JITs to allow for it to
work over arbitrary IC snippets. This will make adding Div/Sub/Pow in the
future easy. This patch also adds a new boolean argument to the various
snippet generateFastPath() methods to indicate if we should emit result profiling.
I added this because we want this profiling to be emitted for Mul in
the baseline, but not in the DFG. We used to indicate this through passing
in a nullptr for the ArithProfile, but we no longer do that in the upper
JIT tiers. So we are passing an explicit request from the JIT tier about
whether or not it's worth it for the IC to emit profiling.

We now emit much less code for Mul. Here is some data on the average
Mul snippet/IC size:

           |   JetStream  |  Unity 3D  |
     ------| -------------|--------------
      Old  |  ~280 bytes  | ~280 bytes |
     ------| -------------|--------------
      New  |   210  bytes |  185 bytes |
     ------------------------------------

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::addJITAddIC):
(JSC::CodeBlock::addJITMulIC):
(JSC::CodeBlock::findStubInfo):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::stubInfoBegin):
(JSC::CodeBlock::stubInfoEnd):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::GPRTemporary::adopt):
(JSC::DFG::FPRTemporary::FPRTemporary):
(JSC::DFG::SpeculativeJIT::compileValueAdd):
(JSC::DFG::SpeculativeJIT::compileMathIC):
(JSC::DFG::SpeculativeJIT::compileArithMul):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
(JSC::DFG::GPRTemporary::GPRTemporary):
(JSC::DFG::GPRTemporary::operator=):
(JSC::DFG::FPRTemporary::~FPRTemporary):
(JSC::DFG::FPRTemporary::fpr):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileToThis):
(JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
(JSC::FTL::DFG::LowerDFGToB3::compileMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileArithMul):
* jit/JIT.h:
(JSC::JIT::getSlowCase):
* jit/JITAddGenerator.cpp:
(JSC::JITAddGenerator::generateInline):
(JSC::JITAddGenerator::generateFastPath):
* jit/JITAddGenerator.h:
(JSC::JITAddGenerator::JITAddGenerator):
(JSC::JITAddGenerator::isLeftOperandValidConstant):
(JSC::JITAddGenerator::isRightOperandValidConstant):
* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_add):
(JSC::JIT::emitSlow_op_add):
(JSC::JIT::emitMathICFast):
(JSC::JIT::emitMathICSlow):
(JSC::JIT::emit_op_mul):
(JSC::JIT::emitSlow_op_mul):
(JSC::JIT::emit_op_sub):
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITMathIC.h:
(JSC::JITMathIC::slowPathStartLocation):
(JSC::JITMathIC::slowPathCallLocation):
(JSC::JITMathIC::isLeftOperandValidConstant):
(JSC::JITMathIC::isRightOperandValidConstant):
(JSC::JITMathIC::generateInline):
(JSC::JITMathIC::generateOutOfLine):
* jit/JITMathICForwards.h:
* jit/JITMulGenerator.cpp:
(JSC::JITMulGenerator::generateInline):
(JSC::JITMulGenerator::generateFastPath):
* jit/JITMulGenerator.h:
(JSC::JITMulGenerator::JITMulGenerator):
(JSC::JITMulGenerator::isLeftOperandValidConstant):
(JSC::JITMulGenerator::isRightOperandValidConstant):
(JSC::JITMulGenerator::didEmitFastPath): Deleted.
(JSC::JITMulGenerator::endJumpList): Deleted.
(JSC::JITMulGenerator::slowPathJumpList): Deleted.
* jit/JITOperations.cpp:
* jit/JITOperations.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITAddGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITAddGeneratorh">trunk/Source/JavaScriptCore/jit/JITAddGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITArithmeticcpp">trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMathICh">trunk/Source/JavaScriptCore/jit/JITMathIC.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMathICForwardsh">trunk/Source/JavaScriptCore/jit/JITMathICForwards.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMulGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITMulGeneratorh">trunk/Source/JavaScriptCore/jit/JITMulGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -1,3 +1,96 @@
</span><ins>+2016-07-25  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        op_mul/ArithMul(Untyped,Untyped) should be an IC
+        https://bugs.webkit.org/show_bug.cgi?id=160108
+
+        Reviewed by Mark Lam.
+
+        This patch makes Mul a type based IC in much the same way that we made
+        Add a type-based IC. I implemented Mul in the same way. I abstracted the
+        implementation of the Add IC in the various JITs to allow for it to
+        work over arbitrary IC snippets. This will make adding Div/Sub/Pow in the
+        future easy. This patch also adds a new boolean argument to the various
+        snippet generateFastPath() methods to indicate if we should emit result profiling.
+        I added this because we want this profiling to be emitted for Mul in
+        the baseline, but not in the DFG. We used to indicate this through passing
+        in a nullptr for the ArithProfile, but we no longer do that in the upper
+        JIT tiers. So we are passing an explicit request from the JIT tier about
+        whether or not it's worth it for the IC to emit profiling.
+
+        We now emit much less code for Mul. Here is some data on the average
+        Mul snippet/IC size:
+
+                   |   JetStream  |  Unity 3D  |
+             ------| -------------|--------------
+              Old  |  ~280 bytes  | ~280 bytes |
+             ------| -------------|--------------
+              New  |   210  bytes |  185 bytes |
+             ------------------------------------
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::addJITAddIC):
+        (JSC::CodeBlock::addJITMulIC):
+        (JSC::CodeBlock::findStubInfo):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::stubInfoBegin):
+        (JSC::CodeBlock::stubInfoEnd):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::GPRTemporary::adopt):
+        (JSC::DFG::FPRTemporary::FPRTemporary):
+        (JSC::DFG::SpeculativeJIT::compileValueAdd):
+        (JSC::DFG::SpeculativeJIT::compileMathIC):
+        (JSC::DFG::SpeculativeJIT::compileArithMul):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        (JSC::DFG::GPRTemporary::GPRTemporary):
+        (JSC::DFG::GPRTemporary::operator=):
+        (JSC::DFG::FPRTemporary::~FPRTemporary):
+        (JSC::DFG::FPRTemporary::fpr):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileToThis):
+        (JSC::FTL::DFG::LowerDFGToB3::compileValueAdd):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMathIC):
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithMul):
+        * jit/JIT.h:
+        (JSC::JIT::getSlowCase):
+        * jit/JITAddGenerator.cpp:
+        (JSC::JITAddGenerator::generateInline):
+        (JSC::JITAddGenerator::generateFastPath):
+        * jit/JITAddGenerator.h:
+        (JSC::JITAddGenerator::JITAddGenerator):
+        (JSC::JITAddGenerator::isLeftOperandValidConstant):
+        (JSC::JITAddGenerator::isRightOperandValidConstant):
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_add):
+        (JSC::JIT::emitSlow_op_add):
+        (JSC::JIT::emitMathICFast):
+        (JSC::JIT::emitMathICSlow):
+        (JSC::JIT::emit_op_mul):
+        (JSC::JIT::emitSlow_op_mul):
+        (JSC::JIT::emit_op_sub):
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITMathIC.h:
+        (JSC::JITMathIC::slowPathStartLocation):
+        (JSC::JITMathIC::slowPathCallLocation):
+        (JSC::JITMathIC::isLeftOperandValidConstant):
+        (JSC::JITMathIC::isRightOperandValidConstant):
+        (JSC::JITMathIC::generateInline):
+        (JSC::JITMathIC::generateOutOfLine):
+        * jit/JITMathICForwards.h:
+        * jit/JITMulGenerator.cpp:
+        (JSC::JITMulGenerator::generateInline):
+        (JSC::JITMulGenerator::generateFastPath):
+        * jit/JITMulGenerator.h:
+        (JSC::JITMulGenerator::JITMulGenerator):
+        (JSC::JITMulGenerator::isLeftOperandValidConstant):
+        (JSC::JITMulGenerator::isRightOperandValidConstant):
+        (JSC::JITMulGenerator::didEmitFastPath): Deleted.
+        (JSC::JITMulGenerator::endJumpList): Deleted.
+        (JSC::JITMulGenerator::slowPathJumpList): Deleted.
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+
</ins><span class="cx"> 2016-07-25  Darin Adler  &lt;darin@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Speed up make process slightly by improving &quot;list of files&quot; idiom
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -3013,6 +3013,11 @@
</span><span class="cx">     return m_addICs.add();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JITMulIC* CodeBlock::addJITMulIC()
+{
+    return m_mulICs.add();
+}
+
</ins><span class="cx"> StructureStubInfo* CodeBlock::findStubInfo(CodeOrigin codeOrigin)
</span><span class="cx"> {
</span><span class="cx">     for (StructureStubInfo* stubInfo : m_stubInfos) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -250,6 +250,7 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     StructureStubInfo* addStubInfo(AccessType);
</span><span class="cx">     JITAddIC* addJITAddIC();
</span><ins>+    JITMulIC* addJITMulIC();
</ins><span class="cx">     Bag&lt;StructureStubInfo&gt;::iterator stubInfoBegin() { return m_stubInfos.begin(); }
</span><span class="cx">     Bag&lt;StructureStubInfo&gt;::iterator stubInfoEnd() { return m_stubInfos.end(); }
</span><span class="cx">     
</span><span class="lines">@@ -1014,6 +1015,7 @@
</span><span class="cx">     std::unique_ptr&lt;RegisterAtOffsetList&gt; m_calleeSaveRegisters;
</span><span class="cx">     Bag&lt;StructureStubInfo&gt; m_stubInfos;
</span><span class="cx">     Bag&lt;JITAddIC&gt; m_addICs;
</span><ins>+    Bag&lt;JITMulIC&gt; m_mulICs;
</ins><span class="cx">     Bag&lt;ByValInfo&gt; m_byValInfos;
</span><span class="cx">     Bag&lt;CallLinkInfo&gt; m_callLinkInfos;
</span><span class="cx">     SentinelLinkedList&lt;CallLinkInfo, BasicRawSentinelNode&lt;CallLinkInfo&gt;&gt; m_incomingCalls;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -44,7 +44,6 @@
</span><span class="cx"> #include &quot;JITBitXorGenerator.h&quot;
</span><span class="cx"> #include &quot;JITDivGenerator.h&quot;
</span><span class="cx"> #include &quot;JITLeftShiftGenerator.h&quot;
</span><del>-#include &quot;JITMathIC.h&quot;
</del><span class="cx"> #include &quot;JITMulGenerator.h&quot;
</span><span class="cx"> #include &quot;JITRightShiftGenerator.h&quot;
</span><span class="cx"> #include &quot;JITSubGenerator.h&quot;
</span><span class="lines">@@ -1317,6 +1316,16 @@
</span><span class="cx">     other.m_gpr = InvalidGPRReg;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FPRTemporary::FPRTemporary(FPRTemporary&amp;&amp; other)
+{
+    ASSERT(other.m_jit);
+    ASSERT(other.m_fpr != InvalidFPRReg);
+    m_jit = other.m_jit;
+    m_fpr = other.m_fpr;
+
+    other.m_jit = nullptr;
+}
+
</ins><span class="cx"> FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
</span><span class="cx">     : m_jit(jit)
</span><span class="cx">     , m_fpr(InvalidFPRReg)
</span><span class="lines">@@ -3336,6 +3345,27 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+    bool needsScratchGPRReg = true;
+    bool needsScratchFPRReg = false;
+#else
+    bool needsScratchGPRReg = true;
+    bool needsScratchFPRReg = true;
+#endif
+
+    JITAddIC* addIC = m_jit.codeBlock()-&gt;addJITAddIC();
+    auto repatchingFunction = operationValueAddOptimize;
+    auto nonRepatchingFunction = operationValueAdd;
+    
+    compileMathIC(node, addIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
+}
+
+template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
+void SpeculativeJIT::compileMathIC(Node* node, JITMathIC&lt;Generator&gt;* mathIC, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
+{
+    Edge&amp; leftChild = node-&gt;child1();
+    Edge&amp; rightChild = node-&gt;child2();
+
</ins><span class="cx">     Optional&lt;JSValueOperand&gt; left;
</span><span class="cx">     Optional&lt;JSValueOperand&gt; right;
</span><span class="cx"> 
</span><span class="lines">@@ -3347,19 +3377,29 @@
</span><span class="cx">     FPRReg leftFPR = leftNumber.fpr();
</span><span class="cx">     FPRReg rightFPR = rightNumber.fpr();
</span><span class="cx"> 
</span><ins>+    GPRReg scratchGPR = InvalidGPRReg;
+    FPRReg scratchFPR = InvalidFPRReg;
+
+    Optional&lt;FPRTemporary&gt; fprScratch;
+    if (needsScratchFPRReg) {
+        fprScratch = FPRTemporary(this);
+        scratchFPR = fprScratch-&gt;fpr();
+    }
+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    Optional&lt;GPRTemporary&gt; gprScratch;
+    if (needsScratchGPRReg) {
+        gprScratch = GPRTemporary(this);
+        scratchGPR = gprScratch-&gt;gpr();
+    }
</ins><span class="cx">     GPRTemporary result(this);
</span><span class="cx">     JSValueRegs resultRegs = JSValueRegs(result.gpr());
</span><del>-    GPRTemporary scratch(this);
-    GPRReg scratchGPR = scratch.gpr();
-    FPRReg scratchFPR = InvalidFPRReg;
</del><span class="cx"> #else
</span><span class="cx">     GPRTemporary resultTag(this);
</span><span class="cx">     GPRTemporary resultPayload(this);
</span><span class="cx">     JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
</span><del>-    GPRReg scratchGPR = resultTag.gpr();
-    FPRTemporary fprScratch(this);
-    FPRReg scratchFPR = fprScratch.fpr();
</del><ins>+    if (needsScratchGPRReg)
+        scratchGPR = resultRegs.tagGPR();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
</span><span class="lines">@@ -3374,21 +3414,21 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
</span><span class="cx"> 
</span><del>-    if (!leftOperand.isConst()) {
</del><ins>+    if (!mathIC-&gt;isLeftOperandValidConstant()) {
</ins><span class="cx">         left = JSValueOperand(this, leftChild);
</span><span class="cx">         leftRegs = left-&gt;jsValueRegs();
</span><span class="cx">     }
</span><del>-    if (!rightOperand.isConst()) {
</del><ins>+    if (!mathIC-&gt;isRightOperandValidConstant()) {
</ins><span class="cx">         right = JSValueOperand(this, rightChild);
</span><span class="cx">         rightRegs = right-&gt;jsValueRegs();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    JITAddIC* addIC = m_jit.codeBlock()-&gt;addJITAddIC();
</del><span class="cx">     Box&lt;MathICGenerationState&gt; addICGenerationState = Box&lt;MathICGenerationState&gt;::create();
</span><span class="cx">     ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
</span><del>-    addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, leftFPR, rightFPR, scratchGPR, scratchFPR, arithProfile);
</del><ins>+    mathIC-&gt;m_generator = Generator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, leftFPR, rightFPR, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><del>-    bool generatedInline = addIC-&gt;generateInline(m_jit, *addICGenerationState);
</del><ins>+    bool shouldEmitProfiling = false;
+    bool generatedInline = mathIC-&gt;generateInline(m_jit, *addICGenerationState, shouldEmitProfiling);
</ins><span class="cx"> 
</span><span class="cx">     if (generatedInline) {
</span><span class="cx">         ASSERT(!addICGenerationState-&gt;slowPathJumps.empty());
</span><span class="lines">@@ -3406,18 +3446,18 @@
</span><span class="cx"> 
</span><span class="cx">             auto innerLeftRegs = leftRegs;
</span><span class="cx">             auto innerRightRegs = rightRegs;
</span><del>-            if (leftOperand.isConst()) {
</del><ins>+            if (mathIC-&gt;isLeftOperandValidConstant()) {
</ins><span class="cx">                 innerLeftRegs = resultRegs;
</span><span class="cx">                 m_jit.moveValue(leftChild-&gt;asJSValue(), innerLeftRegs);
</span><del>-            } else if (rightOperand.isConst()) {
</del><ins>+            } else if (mathIC-&gt;isRightOperandValidConstant()) {
</ins><span class="cx">                 innerRightRegs = resultRegs;
</span><span class="cx">                 m_jit.moveValue(rightChild-&gt;asJSValue(), innerRightRegs);
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if (addICGenerationState-&gt;shouldSlowPathRepatch)
</span><del>-                addICGenerationState-&gt;slowPathCall = callOperation(operationValueAddOptimize, resultRegs, innerLeftRegs, innerRightRegs, TrustedImmPtr(addIC));
</del><ins>+                addICGenerationState-&gt;slowPathCall = callOperation(bitwise_cast&lt;J_JITOperation_EJJMic&gt;(repatchingFunction), resultRegs, innerLeftRegs, innerRightRegs, TrustedImmPtr(mathIC));
</ins><span class="cx">             else
</span><del>-                addICGenerationState-&gt;slowPathCall = callOperation(operationValueAdd, resultRegs, innerLeftRegs, innerRightRegs);
</del><ins>+                addICGenerationState-&gt;slowPathCall = callOperation(nonRepatchingFunction, resultRegs, innerLeftRegs, innerRightRegs);
</ins><span class="cx"> 
</span><span class="cx">             silentFill(savePlans);
</span><span class="cx">             m_jit.exceptionCheck();
</span><span class="lines">@@ -3424,20 +3464,20 @@
</span><span class="cx">             m_jit.jump().linkTo(done, &amp;m_jit);
</span><span class="cx"> 
</span><span class="cx">             m_jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
</span><del>-                addIC-&gt;finalizeInlineCode(*addICGenerationState, linkBuffer);
</del><ins>+                mathIC-&gt;finalizeInlineCode(*addICGenerationState, linkBuffer);
</ins><span class="cx">             });
</span><span class="cx">         });
</span><span class="cx">     } else {
</span><del>-        if (leftOperand.isConst()) {
</del><ins>+        if (mathIC-&gt;isLeftOperandValidConstant()) {
</ins><span class="cx">             left = JSValueOperand(this, leftChild);
</span><span class="cx">             leftRegs = left-&gt;jsValueRegs();
</span><del>-        } else if (rightOperand.isConst()) {
</del><ins>+        } else if (mathIC-&gt;isRightOperandValidConstant()) {
</ins><span class="cx">             right = JSValueOperand(this, rightChild);
</span><span class="cx">             rightRegs = right-&gt;jsValueRegs();
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         flushRegisters();
</span><del>-        callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
</del><ins>+        callOperation(nonRepatchingFunction, resultRegs, leftRegs, rightRegs);
</ins><span class="cx">         m_jit.exceptionCheck();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -4156,78 +4196,18 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        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();
-
</del><span class="cx"> #if USE(JSVALUE64)
</span><del>-        GPRTemporary result(this);
-        JSValueRegs resultRegs = JSValueRegs(result.gpr());
-        GPRTemporary scratch(this);
-        GPRReg scratchGPR = scratch.gpr();
-        FPRReg scratchFPR = InvalidFPRReg;
</del><ins>+        bool needsScratchGPRReg = true;
+        bool needsScratchFPRReg = false;
</ins><span class="cx"> #else
</span><del>-        GPRTemporary resultTag(this);
-        GPRTemporary resultPayload(this);
-        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
-        GPRReg scratchGPR = resultTag.gpr();
-        FPRTemporary fprScratch(this);
-        FPRReg scratchFPR = fprScratch.fpr();
</del><ins>+        bool needsScratchGPRReg = true;
+        bool needsScratchFPRReg = true;
</ins><span class="cx"> #endif
</span><del>-
-        SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
-        SnippetOperand rightOperand(m_state.forNode(rightChild).resultType());
-
-        // The snippet generator does not support both operands being constant. If the left
-        // operand is already const, we'll ignore the right operand's constness.
-        if (leftChild-&gt;isInt32Constant())
-            leftOperand.setConstInt32(leftChild-&gt;asInt32());
-        else if (rightChild-&gt;isInt32Constant())
-            rightOperand.setConstInt32(rightChild-&gt;asInt32());
-
-        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;
-            m_jit.moveValue(leftChild-&gt;asJSValue(), leftRegs);
-        } else if (rightOperand.isPositiveConstInt32()) {
-            rightRegs = resultRegs;
-            m_jit.moveValue(rightChild-&gt;asJSValue(), rightRegs);
-        }
-
-        callOperation(operationValueMul, resultRegs, leftRegs, rightRegs);
-
-        silentFillAllRegisters(resultRegs);
-        m_jit.exceptionCheck();
-
-        gen.endJumpList().link(&amp;m_jit);
-        jsValueResult(resultRegs, node);
</del><ins>+        JITMulIC* mulIC = m_jit.codeBlock()-&gt;addJITMulIC();
+        auto repatchingFunction = operationValueMulOptimize;
+        auto nonRepatchingFunction = operationValueMul;
+        
+        compileMathIC(node, mulIC, needsScratchGPRReg, needsScratchFPRReg, repatchingFunction, nonRepatchingFunction);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;DFGOSRExitJumpPlaceholder.h&quot;
</span><span class="cx"> #include &quot;DFGSilentRegisterSavePlan.h&quot;
</span><span class="cx"> #include &quot;DFGValueSource.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> #include &quot;JITOperations.h&quot;
</span><span class="cx"> #include &quot;MarkedAllocator.h&quot;
</span><span class="cx"> #include &quot;PutKind.h&quot;
</span><span class="lines">@@ -1288,9 +1289,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> 
</span><del>-    JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr ptr)
</del><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
</ins><span class="cx">     {
</span><del>-        m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), ptr);
</del><ins>+        m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), mathIC);
</ins><span class="cx">         return appendCallSetResult(operation, result.gpr());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1711,9 +1712,9 @@
</span><span class="cx">     }
</span><span class="cx"> #else // USE(JSVALUE32_64)
</span><span class="cx"> 
</span><del>-    JITCompiler::Call callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr ptr)
</del><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
</ins><span class="cx">     {
</span><del>-        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), ptr);
</del><ins>+        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), mathIC);
</ins><span class="cx">         return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2451,6 +2452,9 @@
</span><span class="cx">     void emitUntypedRightShiftBitOp(Node*);
</span><span class="cx">     void compileShiftOp(Node*);
</span><span class="cx"> 
</span><ins>+    template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
+    void compileMathIC(Node*, JITMathIC&lt;Generator&gt;*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);
+
</ins><span class="cx">     void compileValueAdd(Node*);
</span><span class="cx">     void compileArithAdd(Node*);
</span><span class="cx">     void compileMakeRope(Node*);
</span><span class="lines">@@ -3045,6 +3049,16 @@
</span><span class="cx"> 
</span><span class="cx">     GPRTemporary(GPRTemporary&amp; other) = delete;
</span><span class="cx"> 
</span><ins>+    GPRTemporary(GPRTemporary&amp;&amp; other)
+    {
+        ASSERT(other.m_jit);
+        ASSERT(other.m_gpr != InvalidGPRReg);
+        m_jit = other.m_jit;
+        m_gpr = other.m_gpr;
+        other.m_jit = nullptr;
+        other.m_gpr = InvalidGPRReg;
+    }
+
</ins><span class="cx">     GPRTemporary&amp; operator=(GPRTemporary&amp;&amp; other)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(!m_jit);
</span><span class="lines">@@ -3093,7 +3107,9 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> class FPRTemporary {
</span><ins>+    WTF_MAKE_NONCOPYABLE(FPRTemporary);
</ins><span class="cx"> public:
</span><ins>+    FPRTemporary(FPRTemporary&amp;&amp;);
</ins><span class="cx">     FPRTemporary(SpeculativeJIT*);
</span><span class="cx">     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&amp;);
</span><span class="cx">     FPRTemporary(SpeculativeJIT*, SpeculateDoubleOperand&amp;, SpeculateDoubleOperand&amp;);
</span><span class="lines">@@ -3103,11 +3119,13 @@
</span><span class="cx"> 
</span><span class="cx">     ~FPRTemporary()
</span><span class="cx">     {
</span><del>-        m_jit-&gt;unlock(fpr());
</del><ins>+        if (LIKELY(m_jit))
+            m_jit-&gt;unlock(fpr());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     FPRReg fpr() const
</span><span class="cx">     {
</span><ins>+        ASSERT(m_jit);
</ins><span class="cx">         ASSERT(m_fpr != InvalidFPRReg);
</span><span class="cx">         return m_fpr;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -1536,9 +1536,18 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">         setJSValue(m_out.phi(Int64, fastResult, slowResult));
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     void compileValueAdd()
</span><span class="cx">     {
</span><ins>+        JITAddIC* addIC = codeBlock()-&gt;addJITAddIC();
+        auto repatchingFunction = operationValueAddOptimize;
+        auto nonRepatchingFunction = operationValueAdd;
+        compileMathIC(addIC, repatchingFunction, nonRepatchingFunction);
+    }
+
+    template &lt;typename Generator&gt;
+    void compileMathIC(JITMathIC&lt;Generator&gt;* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)
+    {
</ins><span class="cx">         Node* node = m_node;
</span><span class="cx">         
</span><span class="cx">         LValue left = lowJSValue(node-&gt;child1());
</span><span class="lines">@@ -1565,42 +1574,42 @@
</span><span class="cx">                 Box&lt;CCallHelpers::JumpList&gt; exceptions =
</span><span class="cx">                     exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
</span><span class="cx"> 
</span><del>-                JITAddIC* addIC = jit.codeBlock()-&gt;addJITAddIC();
-                Box&lt;MathICGenerationState&gt; addICGenerationState = Box&lt;MathICGenerationState&gt;::create();
</del><ins>+                Box&lt;MathICGenerationState&gt; mathICGenerationState = Box&lt;MathICGenerationState&gt;::create();
</ins><span class="cx">                 ArithProfile* arithProfile = state-&gt;graph.baselineCodeBlockFor(node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
</span><del>-                addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
</del><ins>+                mathIC-&gt;m_generator = Generator(leftOperand, rightOperand, JSValueRegs(params[0].gpr()),
</ins><span class="cx">                     JSValueRegs(params[1].gpr()), JSValueRegs(params[2].gpr()), params.fpScratch(0),
</span><span class="cx">                     params.fpScratch(1), params.gpScratch(0), InvalidFPRReg, arithProfile);
</span><span class="cx"> 
</span><del>-                bool generatedInline = addIC-&gt;generateInline(jit, *addICGenerationState);
</del><ins>+                bool shouldEmitProfiling = false;
+                bool generatedInline = mathIC-&gt;generateInline(jit, *mathICGenerationState, shouldEmitProfiling);
</ins><span class="cx"> 
</span><span class="cx">                 if (generatedInline) {
</span><del>-                    ASSERT(!addICGenerationState-&gt;slowPathJumps.empty());
</del><ins>+                    ASSERT(!mathICGenerationState-&gt;slowPathJumps.empty());
</ins><span class="cx">                     auto done = jit.label();
</span><span class="cx">                     params.addLatePath([=] (CCallHelpers&amp; jit) {
</span><span class="cx">                         AllowMacroScratchRegisterUsage allowScratch(jit);
</span><del>-                        addICGenerationState-&gt;slowPathJumps.link(&amp;jit);
-                        addICGenerationState-&gt;slowPathStart = jit.label();
</del><ins>+                        mathICGenerationState-&gt;slowPathJumps.link(&amp;jit);
+                        mathICGenerationState-&gt;slowPathStart = jit.label();
</ins><span class="cx"> 
</span><del>-                        if (addICGenerationState-&gt;shouldSlowPathRepatch) {
</del><ins>+                        if (mathICGenerationState-&gt;shouldSlowPathRepatch) {
</ins><span class="cx">                             SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
</span><del>-                                operationValueAddOptimize, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(addIC));
-                            addICGenerationState-&gt;slowPathCall = call.call();
</del><ins>+                                repatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr(), CCallHelpers::TrustedImmPtr(mathIC));
+                            mathICGenerationState-&gt;slowPathCall = call.call();
</ins><span class="cx">                         } else {
</span><span class="cx">                             SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic,
</span><del>-                                exceptions.get(), operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
-                            addICGenerationState-&gt;slowPathCall = call.call();
</del><ins>+                                exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr());
+                            mathICGenerationState-&gt;slowPathCall = call.call();
</ins><span class="cx">                         }
</span><span class="cx">                         jit.jump().linkTo(done, &amp;jit);
</span><span class="cx"> 
</span><span class="cx">                         jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
</span><del>-                            addIC-&gt;finalizeInlineCode(*addICGenerationState, linkBuffer);
</del><ins>+                            mathIC-&gt;finalizeInlineCode(*mathICGenerationState, linkBuffer);
</ins><span class="cx">                         });
</span><span class="cx">                     });
</span><span class="cx">                 } else {
</span><span class="cx">                     callOperation(
</span><span class="cx">                         *state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
</span><del>-                        operationValueAdd, params[0].gpr(), params[1].gpr(), params[2].gpr());
</del><ins>+                        nonRepatchingFunction, params[0].gpr(), params[1].gpr(), params[2].gpr());
</ins><span class="cx">                 }
</span><span class="cx">             });
</span><span class="cx"> 
</span><span class="lines">@@ -1762,7 +1771,10 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case UntypedUse: {
</span><del>-            emitBinarySnippet&lt;JITMulGenerator&gt;(operationValueMul);
</del><ins>+            JITMulIC* mulIC = codeBlock()-&gt;addJITMulIC();
+            auto repatchingFunction = operationValueMulOptimize;
+            auto nonRepatchingFunction = operationValueMul;
+            compileMathIC(mulIC, repatchingFunction, nonRepatchingFunction);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -711,6 +711,12 @@
</span><span class="cx">         bool isOperandConstantInt(int src);
</span><span class="cx">         bool isOperandConstantChar(int src);
</span><span class="cx"> 
</span><ins>+        template &lt;typename Generator, typename ProfiledFunction, typename NonProfiledFunction&gt;
+        void emitMathICFast(JITMathIC&lt;Generator&gt;*, Instruction*, ProfiledFunction, NonProfiledFunction);
+
+        template &lt;typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction&gt;
+        void emitMathICSlow(JITMathIC&lt;Generator&gt;*, Instruction*, ProfiledRepatchFunction, ProfiledFunction, RepatchFunction);
+
</ins><span class="cx">         Jump getSlowCase(Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx">         {
</span><span class="cx">             return iter++-&gt;from;
</span><span class="lines">@@ -765,8 +771,8 @@
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJArp, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJ, JSValueRegs, JSValueRegs, JSValueRegs);
</span><del>-        MacroAssembler::Call callOperation(J_JITOperation_EJJArpJaic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, JITAddIC*);
-        MacroAssembler::Call callOperation(J_JITOperation_EJJJaic, JSValueRegs, JSValueRegs, JSValueRegs, JITAddIC*);
</del><ins>+        MacroAssembler::Call callOperation(J_JITOperation_EJJArpMic, JSValueRegs, JSValueRegs, JSValueRegs, ArithProfile*, TrustedImmPtr);
+        MacroAssembler::Call callOperation(J_JITOperation_EJJMic, JSValueRegs, JSValueRegs, JSValueRegs, TrustedImmPtr);
</ins><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*);
</span><span class="cx">         MacroAssembler::Call callOperation(Z_JITOperation_EJOJ, GPRReg, GPRReg, GPRReg);
</span><span class="lines">@@ -956,8 +962,8 @@
</span><span class="cx"> 
</span><span class="cx">         PCToCodeOriginMapBuilder m_pcToCodeOriginMapBuilder;
</span><span class="cx"> 
</span><del>-        HashMap&lt;Instruction*, JITAddIC*&gt; m_instructionToJITAddIC;
-        HashMap&lt;Instruction*, MathICGenerationState&gt; m_instructionToJITAddICGenerationState;
</del><ins>+        HashMap&lt;Instruction*, void*&gt; m_instructionToMathIC;
+        HashMap&lt;Instruction*, MathICGenerationState&gt; m_instructionToMathICGenerationState;
</ins><span class="cx"> 
</span><span class="cx">         bool m_canBeOptimized;
</span><span class="cx">         bool m_canBeOptimizedOrInlined;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITAddGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITAddGenerator.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx">         lhs = m_arithProfile-&gt;lhsObservedType();
</span><span class="cx">         rhs = m_arithProfile-&gt;rhsObservedType();
</span><span class="cx">         if (lhs.isEmpty() || rhs.isEmpty()) {
</span><ins>+            // FIXME: ICs should be able to repatch without emitting an inline path:
+            // https://bugs.webkit.org/show_bug.cgi?id=160110
</ins><span class="cx">             lhs = ObservedType().withInt32();
</span><span class="cx">             rhs = ObservedType().withInt32();
</span><span class="cx">         }
</span><span class="lines">@@ -71,7 +73,7 @@
</span><span class="cx">     return JITMathICInlineResult::GenerateFullSnippet;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JITAddGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList)
</del><ins>+bool JITAddGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList, bool shouldEmitProfiling)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_scratchGPR != InvalidGPRReg);
</span><span class="cx">     ASSERT(m_scratchGPR != m_left.payloadGPR());
</span><span class="lines">@@ -166,7 +168,7 @@
</span><span class="cx"> 
</span><span class="cx">     // Do doubleVar + doubleVar.
</span><span class="cx">     jit.addDouble(m_rightFPR, m_leftFPR);
</span><del>-    if (m_arithProfile)
</del><ins>+    if (m_arithProfile &amp;&amp; shouldEmitProfiling)
</ins><span class="cx">         m_arithProfile-&gt;emitSetDouble(jit);
</span><span class="cx">         
</span><span class="cx">     jit.boxDouble(m_leftFPR, m_result);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITAddGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITAddGenerator.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITAddGenerator.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITAddGenerator.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -61,8 +61,11 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JITMathICInlineResult generateInline(CCallHelpers&amp;, MathICGenerationState&amp;);
</span><del>-    bool generateFastPath(CCallHelpers&amp;, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList);
</del><ins>+    bool generateFastPath(CCallHelpers&amp;, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList, bool shouldEmitProfiling);
</ins><span class="cx"> 
</span><ins>+    bool isLeftOperandValidConstant() const { return m_leftOperand.isConstInt32(); }
+    bool isRightOperandValidConstant() const { return m_rightOperand.isConstInt32(); }
+
</ins><span class="cx"> private:
</span><span class="cx">     SnippetOperand m_leftOperand;
</span><span class="cx">     SnippetOperand m_rightOperand;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmeticcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -684,6 +684,22 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_add(Instruction* currentInstruction)
</span><span class="cx"> {
</span><ins>+    JITAddIC* addIC = m_codeBlock-&gt;addJITAddIC();
+    m_instructionToMathIC.add(currentInstruction, addIC);
+    emitMathICFast(addIC, currentInstruction, operationValueAddProfiled, operationValueAdd);
+}
+
+void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
+
+    JITAddIC* addIC = bitwise_cast&lt;JITAddIC*&gt;(m_instructionToMathIC.get(currentInstruction));
+    emitMathICSlow(addIC, currentInstruction, operationValueAddProfiledOptimize, operationValueAddProfiled, operationValueAddOptimize);
+}
+
+template &lt;typename Generator, typename ProfiledFunction, typename NonProfiledFunction&gt;
+void JIT::emitMathICFast(JITMathIC&lt;Generator&gt;* mathIC, Instruction* currentInstruction, ProfiledFunction profiledFunction, NonProfiledFunction nonProfiledFunction)
+{
</ins><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><span class="lines">@@ -692,9 +708,9 @@
</span><span class="cx">     OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</span><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><del>-    JSValueRegs resultRegs = leftRegs;
-    GPRReg scratchGPR = regT2;
-    FPRReg scratchFPR = InvalidFPRReg;
</del><ins>+    JSValueRegs resultRegs = JSValueRegs(regT2);
+    GPRReg scratchGPR = regT3;
+    FPRReg scratchFPR = fpRegT2;
</ins><span class="cx"> #else
</span><span class="cx">     OperandTypes types = getOperandTypes(currentInstruction);
</span><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="lines">@@ -718,41 +734,36 @@
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
</span><span class="cx"> 
</span><del>-    if (!leftOperand.isConst())
</del><ins>+    if (!mathIC-&gt;isLeftOperandValidConstant())
</ins><span class="cx">         emitGetVirtualRegister(op1, leftRegs);
</span><del>-    if (!rightOperand.isConst())
</del><ins>+    if (!mathIC-&gt;isRightOperandValidConstant())
</ins><span class="cx">         emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><del>-    JITAddIC* addIC = m_codeBlock-&gt;addJITAddIC();
</del><ins>+    MathICGenerationState&amp; mathICGenerationState = m_instructionToMathICGenerationState.add(currentInstruction, MathICGenerationState()).iterator-&gt;value;
</ins><span class="cx"> 
</span><del>-    m_instructionToJITAddIC.add(currentInstruction, addIC);
-    MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.add(currentInstruction, MathICGenerationState()).iterator-&gt;value;
</del><ins>+    mathIC-&gt;m_generator = Generator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
</ins><span class="cx"> 
</span><del>-    addIC-&gt;m_generator = JITAddGenerator(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
-
-    bool generatedInlineCode = addIC-&gt;generateInline(*this, addICGenerationState);
</del><ins>+    bool generatedInlineCode = mathIC-&gt;generateInline(*this, mathICGenerationState);
</ins><span class="cx">     if (!generatedInlineCode) {
</span><span class="cx">         if (leftOperand.isConst())
</span><span class="cx">             emitGetVirtualRegister(op1, leftRegs);
</span><span class="cx">         else if (rightOperand.isConst())
</span><span class="cx">             emitGetVirtualRegister(op2, rightRegs);
</span><del>-
</del><span class="cx">         if (arithProfile)
</span><del>-            callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
</del><ins>+            callOperation(profiledFunction, resultRegs, leftRegs, rightRegs, arithProfile);
</ins><span class="cx">         else
</span><del>-            callOperation(operationValueAdd, resultRegs, leftRegs, rightRegs);
</del><ins>+            callOperation(nonProfiledFunction, resultRegs, leftRegs, rightRegs);
</ins><span class="cx">     } else
</span><del>-        addSlowCase(addICGenerationState.slowPathJumps);
</del><ins>+        addSlowCase(mathICGenerationState.slowPathJumps);
</ins><span class="cx">     emitPutVirtualRegister(result, resultRegs);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emitSlow_op_add(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</del><ins>+template &lt;typename Generator, typename ProfiledRepatchFunction, typename ProfiledFunction, typename RepatchFunction&gt;
+void JIT::emitMathICSlow(JITMathIC&lt;Generator&gt;* mathIC, Instruction* currentInstruction, ProfiledRepatchFunction profiledRepatchFunction, ProfiledFunction profiledFunction, RepatchFunction repatchFunction)
</ins><span class="cx"> {
</span><del>-    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
</del><ins>+    MathICGenerationState&amp; mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)-&gt;value;
+    mathICGenerationState.slowPathStart = label();
</ins><span class="cx"> 
</span><del>-    MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)-&gt;value;
-    addICGenerationState.slowPathStart = label();
-
</del><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><span class="lines">@@ -761,7 +772,7 @@
</span><span class="cx">     OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
</span><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT0);
</span><span class="cx">     JSValueRegs rightRegs = JSValueRegs(regT1);
</span><del>-    JSValueRegs resultRegs = leftRegs;
</del><ins>+    JSValueRegs resultRegs = JSValueRegs(regT2);
</ins><span class="cx"> #else
</span><span class="cx">     OperandTypes types = getOperandTypes(currentInstruction);
</span><span class="cx">     JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
</span><span class="lines">@@ -777,25 +788,24 @@
</span><span class="cx">     else if (isOperandConstantInt(op2))
</span><span class="cx">         rightOperand.setConstInt32(getOperandConstantInt(op2));
</span><span class="cx"> 
</span><del>-    if (leftOperand.isConst())
</del><ins>+    if (mathIC-&gt;isLeftOperandValidConstant())
</ins><span class="cx">         emitGetVirtualRegister(op1, leftRegs);
</span><del>-    if (rightOperand.isConst())
</del><ins>+    if (mathIC-&gt;isRightOperandValidConstant())
</ins><span class="cx">         emitGetVirtualRegister(op2, rightRegs);
</span><span class="cx"> 
</span><del>-    JITAddIC* addIC = m_instructionToJITAddIC.get(currentInstruction);
</del><span class="cx">     if (shouldEmitProfiling()) {
</span><span class="cx">         ArithProfile&amp; arithProfile = m_codeBlock-&gt;arithProfileForPC(currentInstruction);
</span><del>-        if (addICGenerationState.shouldSlowPathRepatch)
-            addICGenerationState.slowPathCall = callOperation(operationValueAddProfiledOptimize, resultRegs, leftRegs, rightRegs, &amp;arithProfile, addIC);
</del><ins>+        if (mathICGenerationState.shouldSlowPathRepatch)
+            mathICGenerationState.slowPathCall = callOperation(bitwise_cast&lt;J_JITOperation_EJJArpMic&gt;(profiledRepatchFunction), resultRegs, leftRegs, rightRegs, &amp;arithProfile, TrustedImmPtr(mathIC));
</ins><span class="cx">         else
</span><del>-            addICGenerationState.slowPathCall = callOperation(operationValueAddProfiled, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
</del><ins>+            mathICGenerationState.slowPathCall = callOperation(profiledFunction, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
</ins><span class="cx">     } else
</span><del>-        addICGenerationState.slowPathCall = callOperation(operationValueAddOptimize, resultRegs, leftRegs, rightRegs, addIC);
</del><ins>+        mathICGenerationState.slowPathCall = callOperation(bitwise_cast&lt;J_JITOperation_EJJMic&gt;(repatchFunction), resultRegs, leftRegs, rightRegs, TrustedImmPtr(mathIC));
</ins><span class="cx">     emitPutVirtualRegister(result, resultRegs);
</span><span class="cx"> 
</span><span class="cx">     addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
</span><del>-        MathICGenerationState&amp; addICGenerationState = m_instructionToJITAddICGenerationState.find(currentInstruction)-&gt;value;
-        addIC-&gt;finalizeInlineCode(addICGenerationState, linkBuffer);
</del><ins>+        MathICGenerationState&amp; mathICGenerationState = m_instructionToMathICGenerationState.find(currentInstruction)-&gt;value;
+        mathIC-&gt;finalizeInlineCode(mathICGenerationState, linkBuffer);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -875,112 +885,17 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_mul(Instruction* currentInstruction)
</span><span class="cx"> {
</span><del>-    int result = currentInstruction[1].u.operand;
-    int op1 = currentInstruction[2].u.operand;
-    int op2 = currentInstruction[3].u.operand;
-
-#if USE(JSVALUE64)
-    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
-    JSValueRegs leftRegs = JSValueRegs(regT0);
-    JSValueRegs rightRegs = JSValueRegs(regT1);
-    JSValueRegs resultRegs = JSValueRegs(regT2);
-    GPRReg scratchGPR = regT3;
-    FPRReg scratchFPR = InvalidFPRReg;
-#else
-    OperandTypes types = getOperandTypes(currentInstruction);
-    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
-    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
-    JSValueRegs resultRegs = leftRegs;
-    GPRReg scratchGPR = regT4;
-    FPRReg scratchFPR = fpRegT2;
-#endif
-
-    ArithProfile* arithProfile = nullptr;
-    if (shouldEmitProfiling())
-        arithProfile = &amp;m_codeBlock-&gt;arithProfileForPC(currentInstruction);
-
-    SnippetOperand leftOperand(types.first());
-    SnippetOperand rightOperand(types.second());
-
-    if (isOperandConstantInt(op1))
-        leftOperand.setConstInt32(getOperandConstantInt(op1));
-    else if (isOperandConstantInt(op2))
-        rightOperand.setConstInt32(getOperandConstantInt(op2));
-
-    RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
-
-    if (!leftOperand.isPositiveConstInt32())
-        emitGetVirtualRegister(op1, leftRegs);
-    if (!rightOperand.isPositiveConstInt32())
-        emitGetVirtualRegister(op2, rightRegs);
-
-    JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
-        fpRegT0, fpRegT1, scratchGPR, scratchFPR, arithProfile);
-
-    gen.generateFastPath(*this);
-
-    if (gen.didEmitFastPath()) {
-        gen.endJumpList().link(this);
-        emitPutVirtualRegister(result, resultRegs);
-
-        addSlowCase(gen.slowPathJumpList());
-    } else {
-        ASSERT(gen.endJumpList().empty());
-        ASSERT(gen.slowPathJumpList().empty());
-        if (arithProfile) {
-            if (leftOperand.isPositiveConstInt32())
-                emitGetVirtualRegister(op1, leftRegs);
-            if (rightOperand.isPositiveConstInt32())
-                emitGetVirtualRegister(op2, rightRegs);
-            callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, arithProfile);
-            emitPutVirtualRegister(result, resultRegs);
-        } else {
-            JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
-            slowPathCall.call();
-        }
-    }
</del><ins>+    JITMulIC* mulIC = m_codeBlock-&gt;addJITMulIC();
+    m_instructionToMathIC.add(currentInstruction, mulIC);
+    emitMathICFast(mulIC, currentInstruction, operationValueMulProfiled, operationValueMul);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><span class="cx">     linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
</span><del>-    
-    int result = currentInstruction[1].u.operand;
-    int op1 = currentInstruction[2].u.operand;
-    int op2 = currentInstruction[3].u.operand;
</del><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-    OperandTypes types = getOperandTypes(copiedInstruction(currentInstruction));
-    JSValueRegs leftRegs = JSValueRegs(regT0);
-    JSValueRegs rightRegs = JSValueRegs(regT1);
-    JSValueRegs resultRegs = leftRegs;
-#else
-    OperandTypes types = getOperandTypes(currentInstruction);
-    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
-    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
-    JSValueRegs resultRegs = leftRegs;
-#endif
-
-    SnippetOperand leftOperand(types.first());
-    SnippetOperand rightOperand(types.second());
-
-    if (isOperandConstantInt(op1))
-        leftOperand.setConstInt32(getOperandConstantInt(op1));
-    else if (isOperandConstantInt(op2))
-        rightOperand.setConstInt32(getOperandConstantInt(op2));
-
-    if (shouldEmitProfiling()) {
-        if (leftOperand.isPositiveConstInt32())
-            emitGetVirtualRegister(op1, leftRegs);
-        if (rightOperand.isPositiveConstInt32())
-            emitGetVirtualRegister(op2, rightRegs);
-        ArithProfile&amp; arithProfile = m_codeBlock-&gt;arithProfileForPC(currentInstruction);
-        callOperation(operationValueMulProfiled, resultRegs, leftRegs, rightRegs, &amp;arithProfile);
-        emitPutVirtualRegister(result, resultRegs);
-    } else {
-        JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);
-        slowPathCall.call();
-    }
</del><ins>+    JITMulIC* mulIC = bitwise_cast&lt;JITMulIC*&gt;(m_instructionToMathIC.get(currentInstruction));
+    emitMathICSlow(mulIC, currentInstruction, operationValueMulProfiledOptimize, operationValueMulProfiled, operationValueMulOptimize);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_sub(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -432,17 +432,17 @@
</span><span class="cx">     return call;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJArpJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile, JITAddIC* addIC)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJArpMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, ArithProfile* arithProfile, TrustedImmPtr mathIC)
</ins><span class="cx"> {
</span><del>-    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile), TrustedImmPtr(addIC));
</del><ins>+    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arithProfile), mathIC);
</ins><span class="cx">     Call call = appendCallWithExceptionCheck(operation);
</span><span class="cx">     setupResults(result);
</span><span class="cx">     return call;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJJaic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, JITAddIC* addIC)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
</ins><span class="cx"> {
</span><del>-    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(addIC));
</del><ins>+    setupArgumentsWithExecState(arg1, arg2, mathIC);
</ins><span class="cx">     Call call = appendCallWithExceptionCheck(operation);
</span><span class="cx">     setupResults(result);
</span><span class="cx">     return call;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMathICh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMathIC.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMathIC.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITMathIC.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;JITAddGenerator.h&quot;
</span><span class="cx"> #include &quot;JITMathICInlineResult.h&quot;
</span><ins>+#include &quot;JITMulGenerator.h&quot;
</ins><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;Repatch.h&quot;
</span><span class="cx"> #include &quot;SnippetOperand.h&quot;
</span><span class="lines">@@ -54,7 +55,10 @@
</span><span class="cx">     CodeLocationLabel slowPathStartLocation() { return m_inlineStart.labelAtOffset(m_deltaFromStartToSlowPathStart); }
</span><span class="cx">     CodeLocationCall slowPathCallLocation() { return m_inlineStart.callAtOffset(m_deltaFromStartToSlowPathCallLocation); }
</span><span class="cx"> 
</span><del>-    bool generateInline(CCallHelpers&amp; jit, MathICGenerationState&amp; state)
</del><ins>+    bool isLeftOperandValidConstant() const { return m_generator.isLeftOperandValidConstant(); }
+    bool isRightOperandValidConstant() const { return m_generator.isRightOperandValidConstant(); }
+
+    bool generateInline(CCallHelpers&amp; jit, MathICGenerationState&amp; state, bool shouldEmitProfiling = true)
</ins><span class="cx">     {
</span><span class="cx">         state.fastPathStart = jit.label();
</span><span class="cx">         size_t startSize = jit.m_assembler.buffer().codeSize();
</span><span class="lines">@@ -73,7 +77,7 @@
</span><span class="cx">         }
</span><span class="cx">         case JITMathICInlineResult::GenerateFullSnippet: {
</span><span class="cx">             MacroAssembler::JumpList endJumpList;
</span><del>-            bool result = m_generator.generateFastPath(jit, endJumpList, state.slowPathJumps);
</del><ins>+            bool result = m_generator.generateFastPath(jit, endJumpList, state.slowPathJumps, shouldEmitProfiling);
</ins><span class="cx">             if (result) {
</span><span class="cx">                 state.fastPathEnd = jit.label();
</span><span class="cx">                 state.shouldSlowPathRepatch = false;
</span><span class="lines">@@ -104,7 +108,9 @@
</span><span class="cx"> 
</span><span class="cx">             MacroAssembler::JumpList endJumpList; 
</span><span class="cx">             MacroAssembler::JumpList slowPathJumpList; 
</span><del>-            bool emittedFastPath = m_generator.generateFastPath(jit, endJumpList, slowPathJumpList);
</del><ins>+
+            bool shouldEmitProfiling = !JITCode::isOptimizingJIT(codeBlock-&gt;jitType());
+            bool emittedFastPath = m_generator.generateFastPath(jit, endJumpList, slowPathJumpList, shouldEmitProfiling);
</ins><span class="cx">             if (!emittedFastPath)
</span><span class="cx">                 return;
</span><span class="cx">             endJumpList.append(jit.jump());
</span><span class="lines">@@ -157,6 +163,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> typedef JITMathIC&lt;JITAddGenerator&gt; JITAddIC;
</span><ins>+typedef JITMathIC&lt;JITMulGenerator&gt; JITMulIC;
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMathICForwardsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMathICForwards.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMathICForwards.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITMathICForwards.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -31,8 +31,10 @@
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename Generator&gt; class JITMathIC;
</span><span class="cx"> class JITAddGenerator;
</span><ins>+class JITMulGenerator;
</ins><span class="cx"> 
</span><span class="cx"> typedef JITMathIC&lt;JITAddGenerator&gt; JITAddIC;
</span><ins>+typedef JITMathIC&lt;JITMulGenerator&gt; JITMulIC;
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMulGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITMulGenerator.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -29,11 +29,73 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ArithProfile.h&quot;
</span><ins>+#include &quot;JITMathIC.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-void JITMulGenerator::generateFastPath(CCallHelpers&amp; jit)
</del><ins>+JITMathICInlineResult JITMulGenerator::generateInline(CCallHelpers&amp; jit, MathICGenerationState&amp; state)
</ins><span class="cx"> {
</span><ins>+    // We default to speculating int32.
+    ObservedType lhs = ObservedType().withInt32();
+    ObservedType rhs = ObservedType().withInt32();
+
+    if (m_arithProfile) {
+        lhs = m_arithProfile-&gt;lhsObservedType();
+        rhs = m_arithProfile-&gt;rhsObservedType();
+        if (lhs.isEmpty() || rhs.isEmpty()) {
+            // FIXME: ICs should be able to repatch without emitting an inline path:
+            // https://bugs.webkit.org/show_bug.cgi?id=160110
+            lhs = ObservedType().withInt32();
+            rhs = ObservedType().withInt32();
+        }
+    }
+
+    if (lhs.isOnlyNonNumber() &amp;&amp; rhs.isOnlyNonNumber())
+        return JITMathICInlineResult::DontGenerate;
+
+    if (lhs.isOnlyNumber() &amp;&amp; rhs.isOnlyNumber()) {
+        if (!jit.supportsFloatingPoint())
+            return JITMathICInlineResult::DontGenerate;
+
+        if (!m_leftOperand.definitelyIsNumber())
+            state.slowPathJumps.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
+        if (!m_rightOperand.definitelyIsNumber())
+            state.slowPathJumps.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
+        state.slowPathJumps.append(jit.branchIfInt32(m_left));
+        state.slowPathJumps.append(jit.branchIfInt32(m_right));
+        jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR);
+        jit.unboxDoubleNonDestructive(m_right, m_rightFPR, m_scratchGPR, m_scratchFPR);
+        jit.mulDouble(m_rightFPR, m_leftFPR);
+        jit.boxDouble(m_leftFPR, m_result);
+
+        return JITMathICInlineResult::GeneratedFastPath;
+    }
+
+    if ((lhs.isOnlyInt32() || m_leftOperand.isPositiveConstInt32()) &amp;&amp; (rhs.isOnlyInt32() || m_rightOperand.isPositiveConstInt32())) {
+        ASSERT(!m_leftOperand.isPositiveConstInt32() || !m_rightOperand.isPositiveConstInt32());
+        if (!m_leftOperand.isPositiveConstInt32())
+            state.slowPathJumps.append(jit.branchIfNotInt32(m_left));
+        if (!m_rightOperand.isPositiveConstInt32())
+            state.slowPathJumps.append(jit.branchIfNotInt32(m_right));
+
+        if (m_leftOperand.isPositiveConstInt32() || m_rightOperand.isPositiveConstInt32()) {
+            JSValueRegs var = m_leftOperand.isPositiveConstInt32() ? m_right : m_left;
+            int32_t constValue = m_leftOperand.isPositiveConstInt32() ? m_leftOperand.asConstInt32() : m_rightOperand.asConstInt32();
+            state.slowPathJumps.append(jit.branchMul32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constValue), m_scratchGPR));
+        } else {
+            state.slowPathJumps.append(jit.branchMul32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
+            state.slowPathJumps.append(jit.branchTest32(CCallHelpers::Zero, m_scratchGPR)); // Go slow if potential negative zero.
+        }
+        jit.boxInt32(m_scratchGPR, m_result);
+
+        return JITMathICInlineResult::GeneratedFastPath;
+    }
+
+    return JITMathICInlineResult::GenerateFullSnippet;
+}
+
+bool JITMulGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList, bool shouldEmitProfiling)
+{
</ins><span class="cx">     ASSERT(m_scratchGPR != InvalidGPRReg);
</span><span class="cx">     ASSERT(m_scratchGPR != m_left.payloadGPR());
</span><span class="cx">     ASSERT(m_scratchGPR != m_right.payloadGPR());
</span><span class="lines">@@ -47,13 +109,9 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(!m_leftOperand.isPositiveConstInt32() || !m_rightOperand.isPositiveConstInt32());
</span><span class="cx"> 
</span><del>-    if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber()) {
-        ASSERT(!m_didEmitFastPath);
-        return;
-    }
</del><ins>+    if (!m_leftOperand.mightBeNumber() || !m_rightOperand.mightBeNumber())
+        return false;
</ins><span class="cx"> 
</span><del>-    m_didEmitFastPath = true;
-
</del><span class="cx">     if (m_leftOperand.isPositiveConstInt32() || m_rightOperand.isPositiveConstInt32()) {
</span><span class="cx">         JSValueRegs var = m_leftOperand.isPositiveConstInt32() ? m_right : m_left;
</span><span class="cx">         SnippetOperand&amp; varOpr = m_leftOperand.isPositiveConstInt32() ? m_rightOperand : m_leftOperand;
</span><span class="lines">@@ -66,20 +124,20 @@
</span><span class="cx">         if (multiplyResultGPR == var.payloadGPR())
</span><span class="cx">             multiplyResultGPR = m_scratchGPR;
</span><span class="cx"> 
</span><del>-        m_slowPathJumpList.append(jit.branchMul32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), multiplyResultGPR));
</del><ins>+        slowPathJumpList.append(jit.branchMul32(CCallHelpers::Overflow, var.payloadGPR(), CCallHelpers::Imm32(constOpr.asConstInt32()), multiplyResultGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.boxInt32(multiplyResultGPR, m_result);
</span><del>-        m_endJumpList.append(jit.jump());
</del><ins>+        endJumpList.append(jit.jump());
</ins><span class="cx"> 
</span><span class="cx">         if (!jit.supportsFloatingPoint()) {
</span><del>-            m_slowPathJumpList.append(notInt32);
-            return;
</del><ins>+            slowPathJumpList.append(notInt32);
+            return true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Try to do doubleVar * double(intConstant).
</span><span class="cx">         notInt32.link(&amp;jit);
</span><span class="cx">         if (!varOpr.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(var, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.unboxDoubleNonDestructive(var, m_leftFPR, m_scratchGPR, m_scratchFPR);
</span><span class="cx"> 
</span><span class="lines">@@ -98,23 +156,23 @@
</span><span class="cx">         leftNotInt = jit.branchIfNotInt32(m_left);
</span><span class="cx">         rightNotInt = jit.branchIfNotInt32(m_right);
</span><span class="cx"> 
</span><del>-        m_slowPathJumpList.append(jit.branchMul32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
-        m_slowPathJumpList.append(jit.branchTest32(CCallHelpers::Zero, m_scratchGPR)); // Go slow if potential negative zero.
</del><ins>+        slowPathJumpList.append(jit.branchMul32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR(), m_scratchGPR));
+        slowPathJumpList.append(jit.branchTest32(CCallHelpers::Zero, m_scratchGPR)); // Go slow if potential negative zero.
</ins><span class="cx"> 
</span><span class="cx">         jit.boxInt32(m_scratchGPR, m_result);
</span><del>-        m_endJumpList.append(jit.jump());
</del><ins>+        endJumpList.append(jit.jump());
</ins><span class="cx"> 
</span><span class="cx">         if (!jit.supportsFloatingPoint()) {
</span><del>-            m_slowPathJumpList.append(leftNotInt);
-            m_slowPathJumpList.append(rightNotInt);
-            return;
</del><ins>+            slowPathJumpList.append(leftNotInt);
+            slowPathJumpList.append(rightNotInt);
+            return true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         leftNotInt.link(&amp;jit);
</span><span class="cx">         if (!m_leftOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
</ins><span class="cx">         if (!m_rightOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.unboxDoubleNonDestructive(m_left, m_leftFPR, m_scratchGPR, m_scratchFPR);
</span><span class="cx">         CCallHelpers::Jump rightIsDouble = jit.branchIfNotInt32(m_right);
</span><span class="lines">@@ -124,7 +182,7 @@
</span><span class="cx"> 
</span><span class="cx">         rightNotInt.link(&amp;jit);
</span><span class="cx">         if (!m_rightOperand.definitelyIsNumber())
</span><del>-            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</del><ins>+            slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
</ins><span class="cx"> 
</span><span class="cx">         jit.convertInt32ToDouble(m_left.payloadGPR(), m_leftFPR);
</span><span class="cx"> 
</span><span class="lines">@@ -139,7 +197,7 @@
</span><span class="cx">     // Do doubleVar * doubleVar.
</span><span class="cx">     jit.mulDouble(m_rightFPR, m_leftFPR);
</span><span class="cx"> 
</span><del>-    if (!m_arithProfile)
</del><ins>+    if (!m_arithProfile || !shouldEmitProfiling)
</ins><span class="cx">         jit.boxDouble(m_leftFPR, m_result);
</span><span class="cx">     else {
</span><span class="cx">         // The Int52 overflow check below intentionally omits 1ll &lt;&lt; 51 as a valid negative Int52 value.
</span><span class="lines">@@ -149,6 +207,7 @@
</span><span class="cx">         const int64_t negativeZeroBits = 1ll &lt;&lt; 63;
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         jit.moveDoubleTo64(m_leftFPR, m_result.payloadGPR());
</span><ins>+
</ins><span class="cx">         CCallHelpers::Jump notNegativeZero = jit.branch64(CCallHelpers::NotEqual, m_result.payloadGPR(), CCallHelpers::TrustedImm64(negativeZeroBits));
</span><span class="cx"> 
</span><span class="cx">         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::NegZeroDouble), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</span><span class="lines">@@ -186,13 +245,15 @@
</span><span class="cx">         
</span><span class="cx">         jit.or32(CCallHelpers::TrustedImm32(ArithProfile::Int52Overflow), CCallHelpers::AbsoluteAddress(m_arithProfile-&gt;addressOfBits()));
</span><span class="cx"> 
</span><del>-        m_endJumpList.append(noInt52Overflow);
</del><ins>+        endJumpList.append(noInt52Overflow);
</ins><span class="cx">         if (m_scratchGPR == m_result.tagGPR() || m_scratchGPR == m_result.payloadGPR())
</span><span class="cx">             jit.boxDouble(m_leftFPR, m_result);
</span><span class="cx"> 
</span><del>-        m_endJumpList.append(done);
</del><ins>+        endJumpList.append(done);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><ins>+
+    return true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITMulGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITMulGenerator.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITMulGenerator.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -29,12 +29,17 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><ins>+#include &quot;JITMathICInlineResult.h&quot;
</ins><span class="cx"> #include &quot;SnippetOperand.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+struct MathICGenerationState;
+
</ins><span class="cx"> class JITMulGenerator {
</span><span class="cx"> public:
</span><ins>+    JITMulGenerator() { }
+
</ins><span class="cx">     JITMulGenerator(SnippetOperand leftOperand, SnippetOperand rightOperand,
</span><span class="cx">         JSValueRegs result, JSValueRegs left, JSValueRegs right,
</span><span class="cx">         FPRReg leftFPR, FPRReg rightFPR, GPRReg scratchGPR, FPRReg scratchFPR,
</span><span class="lines">@@ -53,11 +58,11 @@
</span><span class="cx">         ASSERT(!m_leftOperand.isPositiveConstInt32() || !m_rightOperand.isPositiveConstInt32());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void generateFastPath(CCallHelpers&amp;);
</del><ins>+    JITMathICInlineResult generateInline(CCallHelpers&amp;, MathICGenerationState&amp;);
+    bool generateFastPath(CCallHelpers&amp;, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowJumpList, bool shouldEmitProfiling);
</ins><span class="cx"> 
</span><del>-    bool didEmitFastPath() const { return m_didEmitFastPath; }
-    CCallHelpers::JumpList&amp; endJumpList() { return m_endJumpList; }
-    CCallHelpers::JumpList&amp; slowPathJumpList() { return m_slowPathJumpList; }
</del><ins>+    bool isLeftOperandValidConstant() const { return m_leftOperand.isPositiveConstInt32(); }
+    bool isRightOperandValidConstant() const { return m_rightOperand.isPositiveConstInt32(); }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     SnippetOperand m_leftOperand;
</span><span class="lines">@@ -70,10 +75,6 @@
</span><span class="cx">     GPRReg m_scratchGPR;
</span><span class="cx">     FPRReg m_scratchFPR;
</span><span class="cx">     ArithProfile* m_arithProfile;
</span><del>-    bool m_didEmitFastPath { false };
-
-    CCallHelpers::JumpList m_endJumpList;
-    CCallHelpers::JumpList m_slowPathJumpList;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -2336,11 +2336,8 @@
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JIT_OPERATION operationValueMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</del><ins>+ALWAYS_INLINE static EncodedJSValue unprofiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</ins><span class="cx"> {
</span><del>-    VM* vm = &amp;exec-&gt;vm();
-    NativeCallFrameTracer tracer(vm, exec);
-
</del><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><span class="lines">@@ -2349,14 +2346,14 @@
</span><span class="cx">     return JSValue::encode(jsNumber(a * b));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
</del><ins>+ALWAYS_INLINE static EncodedJSValue profiledMul(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, bool shouldObserveLHSAndRHSTypes = true)
</ins><span class="cx"> {
</span><del>-    VM* vm = &amp;exec-&gt;vm();
-    NativeCallFrameTracer tracer(vm, exec);
-
</del><span class="cx">     JSValue op1 = JSValue::decode(encodedOp1);
</span><span class="cx">     JSValue op2 = JSValue::decode(encodedOp2);
</span><span class="cx"> 
</span><ins>+    if (shouldObserveLHSAndRHSTypes)
+        arithProfile-&gt;observeLHSAndRHS(op1, op2);
+
</ins><span class="cx">     double a = op1.toNumber(exec);
</span><span class="cx">     double b = op2.toNumber(exec);
</span><span class="cx">     
</span><span class="lines">@@ -2365,6 +2362,61 @@
</span><span class="cx">     return JSValue::encode(result);
</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);
+
+    return unprofiledMul(exec, encodedOp1, encodedOp2);
+}
+
+EncodedJSValue JIT_OPERATION operationValueMulNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return unprofiledMul(exec, encodedOp1, encodedOp2);
+}
+
+EncodedJSValue JIT_OPERATION operationValueMulOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC* mulIC)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    auto nonOptimizeVariant = operationValueMulNoOptimize;
+    mulIC-&gt;generateOutOfLine(*vm, exec-&gt;codeBlock(), nonOptimizeVariant);
+
+    return unprofiledMul(exec, encodedOp1, encodedOp2);
+}
+
+EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
+}
+
+EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC* mulIC)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    arithProfile-&gt;observeLHSAndRHS(JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
+    auto nonOptimizeVariant = operationValueMulProfiledNoOptimize;
+    mulIC-&gt;generateOutOfLine(*vm, exec-&gt;codeBlock(), nonOptimizeVariant);
+
+    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile, false);
+}
+
+EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile* arithProfile, JITMulIC*)
+{
+    VM* vm = &amp;exec-&gt;vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return profiledMul(exec, encodedOp1, encodedOp2, arithProfile);
+}
+
</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="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (203692 => 203693)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-07-25 18:45:31 UTC (rev 203692)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2016-07-25 19:04:16 UTC (rev 203693)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">     Icf: InlineCallFrame*
</span><span class="cx">     Idc: const Identifier*
</span><span class="cx">     J: EncodedJSValue
</span><del>-    Jaic: JITAddIC*
</del><ins>+    Mic: JITMathIC* (can be JITAddIC*, JITMulIC*, etc).
</ins><span class="cx">     Jcp: const JSValue*
</span><span class="cx">     Jsc: JSScope*
</span><span class="cx">     Jsf: JSFunction*
</span><span class="lines">@@ -137,8 +137,8 @@
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArp)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*);
</span><del>-typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArpJaic)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*, JITAddIC*);
-typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJJaic)(ExecState*, EncodedJSValue, EncodedJSValue, JITAddIC*);
</del><ins>+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJArpMic)(ExecState*, EncodedJSValue, EncodedJSValue, ArithProfile*, void*);
+typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJJMic)(ExecState*, EncodedJSValue, EncodedJSValue, void*);
</ins><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReo)(ExecState*, JSString*, RegExpObject*);
</span><span class="cx"> typedef EncodedJSValue (JIT_OPERATION *J_JITOperation_EJssReoJss)(ExecState*, JSString*, RegExpObject*, JSString*);
</span><span class="lines">@@ -419,6 +419,10 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAddOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueAddNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITAddIC*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMul(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><ins>+EncodedJSValue JIT_OPERATION operationValueMulOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueMulNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, JITMulIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueMulProfiledOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITMulIC*) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueMulProfiledNoOptimize(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*, JITMulIC*) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationValueMulProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSub(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationValueSubProfiled(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2, ArithProfile*) WTF_INTERNAL;
</span></span></pre>
</div>
</div>

</body>
</html>