<!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>[207369] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>[JSC] op_negate should with any type
https://bugs.webkit.org/show_bug.cgi?id=162587

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2016-10-14
Reviewed by Saam Barati.

JSTests:

* stress/arith-abs-to-arith-negate-range-optimizaton.js: Added.
Cover OSR Exits when converting Math.abs() into ArithNegate.

* stress/arith-negate-on-various-types.js: Added.
Cover ArithNegate with all types.

Source/JavaScriptCore:

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
ArithNegate is quite simple. If the input is double, the output
is double. The other cases are set from the LLInt slow case.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::makeSafe):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):

* dfg/DFGIntegerRangeOptimizationPhase.cpp:
Tweak a bit the IntegerRangeOptimizationPhase when simplifying
ArithAbs to ArithNegate.
We should not do the conversion if the target nodes OSR Exits
on different input than the source node.

In particular, Checked ArithNegate exits on zero while
ArithAbs has not problem with it.
Unchecked ArithAbs() do not OSR Exit on INT_MIN, ArithNeg
should not either.

* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithNegate):
(JSC::DFG::SpeculativeJIT::compileMathIC):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileMathIC):
(JSC::FTL::DFG::LowerDFGToB3::compileArithNegate):

* jit/JITNegGenerator.cpp:
(JSC::JITNegGenerator::generateFastPath):
* jit/JITOperations.cpp:
Add result profiling in baseline to have types we can use
in DFG and FTL.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITNegGeneratorcpp">trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressarithabstoarithnegaterangeoptimizatonjs">trunk/JSTests/stress/arith-abs-to-arith-negate-range-optimizaton.js</a></li>
<li><a href="#trunkJSTestsstressarithnegateonvarioustypesjs">trunk/JSTests/stress/arith-negate-on-various-types.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/JSTests/ChangeLog        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-10-14  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] op_negate should with any type
+        https://bugs.webkit.org/show_bug.cgi?id=162587
+
+        Reviewed by Saam Barati.
+
+        * stress/arith-abs-to-arith-negate-range-optimizaton.js: Added.
+        Cover OSR Exits when converting Math.abs() into ArithNegate.
+
+        * stress/arith-negate-on-various-types.js: Added.
+        Cover ArithNegate with all types.
+
</ins><span class="cx"> 2016-10-14  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Basic WebAssembly testing
</span></span></pre></div>
<a id="trunkJSTestsstressarithabstoarithnegaterangeoptimizatonjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/arith-abs-to-arith-negate-range-optimizaton.js (0 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-abs-to-arith-negate-range-optimizaton.js                                (rev 0)
+++ trunk/JSTests/stress/arith-abs-to-arith-negate-range-optimizaton.js        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -0,0 +1,426 @@
</span><ins>+//@ defaultNoEagerRun
+&quot;use strict&quot;;
+
+// Checked int_min &lt; value &lt; 0
+function opaqueCheckedBetweenIntMinAndZeroExclusive(arg) {
+    if (arg &lt; 0) {
+        if (arg &gt; (0x80000000|0)) {
+            return Math.abs(arg);
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedBetweenIntMinAndZeroExclusive);
+
+function testCheckedBetweenIntMinAndZeroExclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinAndZeroExclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroExclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinAndZeroExclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroExclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinAndZeroExclusive) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedBetweenIntMinAndZeroExclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testCheckedBetweenIntMinAndZeroExclusive();
+
+
+// Checked int_min &lt; value &lt;= 0
+function opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive(arg) {
+    if (arg &lt;= 0) {
+        if (arg &gt; (0x80000000|0)) {
+            return Math.abs(arg);
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive);
+
+function testCheckedBetweenIntMinExclusiveAndZeroInclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinExclusiveAndZeroInclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive(0) !== 0) {
+            throw &quot;Failed testCheckedBetweenIntMinExclusiveAndZeroInclusive() on 0&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedBetweenIntMinExclusiveAndZeroInclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinExclusiveAndZeroInclusive) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedBetweenIntMinExclusiveAndZeroInclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testCheckedBetweenIntMinExclusiveAndZeroInclusive();
+
+
+// Checked int_min &lt;= value &lt; 0
+function opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive(arg) {
+    if (arg &lt; 0) {
+        if (arg &gt;= (0x80000000|0)) {
+            return Math.abs(arg);
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive);
+
+function testCheckedBetweenIntMinInclusiveAndZeroExclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinInclusiveAndZeroExclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedBetweenIntMinInclusiveAndZeroExclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedBetweenIntMinInclusiveAndZeroExclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinInclusiveAndZeroExclusive()&quot;;
+        }
+        let result = opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive(-2147483648);
+        if (result !== 2147483648) {
+            throw &quot;Failed testCheckedBetweenIntMinInclusiveAndZeroExclusive() on -2147483648, got &quot; + result;
+        }
+    }
+
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinInclusiveAndZeroExclusive) &gt; 2) {
+        throw &quot;Math.abs() on IntMin can OSR Exit but we should quickly settle on double.&quot;;
+    }
+}
+testCheckedBetweenIntMinInclusiveAndZeroExclusive();
+
+
+// Checked int_min &lt;= value &lt;= 0
+function opaqueCheckedBetweenIntMinAndZeroInclusive(arg) {
+    if (arg &lt;= 0) {
+        if (arg &gt;= (0x80000000|0)) {
+            return Math.abs(arg);
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedBetweenIntMinAndZeroInclusive);
+
+function testCheckedBetweenIntMinAndZeroInclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(0) !== 0) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinAndZeroInclusive) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedBetweenIntMinAndZeroInclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(-i) !== i) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(0) !== 0) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueCheckedBetweenIntMinAndZeroInclusive(-2147483648) !== 2147483648) {
+            throw &quot;Failed testCheckedBetweenIntMinAndZeroInclusive() on -2147483648&quot;;
+        }
+    }
+
+    if (numberOfDFGCompiles(opaqueCheckedBetweenIntMinAndZeroInclusive) &gt; 2) {
+        throw &quot;Math.abs() on IntMin can OSR Exit but we should quickly settle on double.&quot;;
+    }
+}
+testCheckedBetweenIntMinAndZeroInclusive();
+
+
+// Unchecked int_min &lt; value &lt; 0
+function opaqueUncheckedBetweenIntMinAndZeroExclusive(arg) {
+    if (arg &lt; 0) {
+        if (arg &gt; (0x80000000|0)) {
+            return Math.abs(arg)|0;
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedBetweenIntMinAndZeroExclusive);
+
+function testUncheckedBetweenIntMinAndZeroExclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedBetweenIntMinAndZeroExclusive(-i) !== i) {
+            throw &quot;Failed testUncheckedBetweenIntMinAndZeroExclusive()&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinAndZeroExclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedBetweenIntMinAndZeroExclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedBetweenIntMinAndZeroExclusive) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedBetweenIntMinAndZeroExclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testUncheckedBetweenIntMinAndZeroExclusive();
+
+
+// Unchecked int_min &lt; value &lt;= 0
+function opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive(arg) {
+    if (arg &lt;= 0) {
+        if (arg &gt; (0x80000000|0)) {
+            return Math.abs(arg)|0;
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive);
+
+function testUncheckedBetweenIntMinExclusiveAndZeroInclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive(-i) !== i) {
+            throw &quot;Failed testUncheckedBetweenIntMinExclusiveAndZeroInclusive()&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive(0) !== 0) {
+            throw &quot;Failed testUncheckedBetweenIntMinExclusiveAndZeroInclusive() on 0&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedBetweenIntMinExclusiveAndZeroInclusive() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedBetweenIntMinExclusiveAndZeroInclusive) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedBetweenIntMinExclusiveAndZeroInclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testUncheckedBetweenIntMinExclusiveAndZeroInclusive();
+
+
+// Unchecked int_min &lt;= value &lt; 0
+function opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive(arg) {
+    if (arg &lt; 0) {
+        if (arg &gt;= (0x80000000|0)) {
+            return Math.abs(arg)|0;
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive);
+
+function testUncheckedBetweenIntMinInclusiveAndZeroExclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive(-i) !== i) {
+            throw &quot;Failed testUncheckedBetweenIntMinInclusiveAndZeroExclusive()&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedBetweenIntMinInclusiveAndZeroExclusive() on -2147483647&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive(-2147483648) !== -2147483648) {
+            throw &quot;Failed testUncheckedBetweenIntMinInclusiveAndZeroExclusive() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedBetweenIntMinInclusiveAndZeroExclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testUncheckedBetweenIntMinInclusiveAndZeroExclusive();
+
+
+// Unchecked int_min &lt;= value &lt;= 0
+function opaqueUncheckedBetweenIntMinAndZeroInclusive(arg) {
+    if (arg &lt;= 0) {
+        if (arg &gt;= (0x80000000|0)) {
+            return Math.abs(arg)|0;
+        }
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedBetweenIntMinAndZeroInclusive);
+
+function testUncheckedBetweenIntMinAndZeroInclusive()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedBetweenIntMinAndZeroInclusive(-i) !== i) {
+            throw &quot;Failed testUncheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinAndZeroInclusive(0) !== 0) {
+            throw &quot;Failed testUncheckedBetweenIntMinAndZeroInclusive()&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinAndZeroInclusive(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedBetweenIntMinAndZeroInclusive() on -2147483647&quot;;
+        }
+        if (opaqueUncheckedBetweenIntMinInclusiveAndZeroExclusive(-2147483648) !== -2147483648) {
+            throw &quot;Failed testUncheckedBetweenIntMinInclusiveAndZeroExclusive() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedBetweenIntMinAndZeroInclusive) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedBetweenIntMinAndZeroInclusive(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testUncheckedBetweenIntMinAndZeroInclusive();
+
+
+// Checked value &lt; 0
+function opaqueCheckedLessThanZero(arg) {
+    if (arg &lt; 0) {
+        return Math.abs(arg);
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedLessThanZero);
+
+function testCheckedLessThanZero()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedLessThanZero(-i) !== i) {
+            throw &quot;Failed testCheckedLessThanZero()&quot;;
+        }
+        if (opaqueCheckedLessThanZero(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedLessThanZero() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedLessThanZero) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedLessThanZero(). None of the tested case need to OSR Exit.&quot;;
+    }
+
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedLessThanZero(-i) !== i) {
+            throw &quot;Failed testCheckedLessThanZero()&quot;;
+        }
+        let result = opaqueCheckedLessThanZero(-2147483648);
+        if (result !== 2147483648) {
+            throw &quot;Failed testCheckedLessThanZero() on -2147483648, got &quot; + result;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedLessThanZero) &gt; 2) {
+        throw &quot;Math.abs() on IntMin can OSR Exit but we should quickly settle on double.&quot;;
+    }
+}
+testCheckedLessThanZero();
+
+
+// Checked value &lt;= 0
+function opaqueCheckedLessThanOrEqualZero(arg) {
+    if (arg &lt;= 0) {
+        return Math.abs(arg);
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueCheckedLessThanOrEqualZero);
+
+function testCheckedLessThanOrEqualZero()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedLessThanOrEqualZero(-i) !== i) {
+            throw &quot;Failed testCheckedLessThanOrEqualZero()&quot;;
+        }
+        if (opaqueCheckedLessThanOrEqualZero(0) !== 0) {
+            throw &quot;Failed testCheckedLessThanOrEqualZero() on 0&quot;;
+        }
+        if (opaqueCheckedLessThanOrEqualZero(-2147483647) !== 2147483647) {
+            throw &quot;Failed testCheckedLessThanOrEqualZero() on -2147483647&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedLessThanOrEqualZero) &gt; 1) {
+        throw &quot;Failed optimizing testCheckedLessThanOrEqualZero(). None of the tested case need to OSR Exit.&quot;;
+    }
+
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueCheckedLessThanOrEqualZero(-i) !== i) {
+            throw &quot;Failed testCheckedLessThanOrEqualZero()&quot;;
+        }
+        if (opaqueCheckedLessThanOrEqualZero(-2147483648) !== 2147483648) {
+            throw &quot;Failed testCheckedLessThanOrEqualZero() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueCheckedLessThanOrEqualZero) &gt; 2) {
+        throw &quot;Math.abs() on IntMin can OSR Exit but we should quickly settle on double.&quot;;
+    }
+}
+testCheckedLessThanOrEqualZero();
+
+
+// Unchecked value &lt; 0
+function opaqueUncheckedLessThanZero(arg) {
+    if (arg &lt; 0) {
+        return Math.abs(arg)|0;
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedLessThanZero);
+
+function testUncheckedLessThanZero()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedLessThanZero(-i) !== i) {
+            throw &quot;Failed testUncheckedLessThanZero()&quot;;
+        }
+        if (opaqueUncheckedLessThanZero(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedLessThanZero() on -2147483647&quot;;
+        }
+        if (opaqueUncheckedLessThanZero(-2147483648) !== -2147483648) {
+            throw &quot;Failed testUncheckedLessThanOrEqualZero() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedLessThanZero) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedLessThanZero(). None of the tested case need to OSR Exit.&quot;;
+    }
+
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedLessThanZero(-i) !== i) {
+            throw &quot;Failed testUncheckedLessThanZero()&quot;;
+        }
+        if (opaqueUncheckedLessThanZero(-2147483648) !== -2147483648) {
+            throw &quot;Failed testUncheckedLessThanZero() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedLessThanZero) &gt; 2) {
+        throw &quot;Math.abs() on IntMin can OSR Exit but we should quickly settle on double.&quot;;
+    }
+}
+testUncheckedLessThanZero();
+
+
+// Unchecked value &lt;= 0
+function opaqueUncheckedLessThanOrEqualZero(arg) {
+    if (arg &lt;= 0) {
+        return Math.abs(arg)|0;
+    }
+    throw &quot;We should not be here&quot;;
+}
+noInline(opaqueUncheckedLessThanOrEqualZero);
+
+function testUncheckedLessThanOrEqualZero()
+{
+    for (let i = 1; i &lt; 1e5; ++i) {
+        if (opaqueUncheckedLessThanOrEqualZero(-i) !== i) {
+            throw &quot;Failed testUncheckedLessThanOrEqualZero()&quot;;
+        }
+        if (opaqueUncheckedLessThanOrEqualZero(0) !== 0) {
+            throw &quot;Failed testUncheckedLessThanOrEqualZero() on 0&quot;;
+        }
+        if (opaqueUncheckedLessThanOrEqualZero(-2147483647) !== 2147483647) {
+            throw &quot;Failed testUncheckedLessThanOrEqualZero() on -2147483647&quot;;
+        }
+        if (opaqueUncheckedLessThanOrEqualZero(-2147483648) !== -2147483648) {
+            throw &quot;Failed testUncheckedLessThanOrEqualZero() on -2147483648&quot;;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueUncheckedLessThanOrEqualZero) &gt; 1) {
+        throw &quot;Failed optimizing testUncheckedLessThanOrEqualZero(). None of the tested case need to OSR Exit.&quot;;
+    }
+}
+testUncheckedLessThanOrEqualZero();
</ins></span></pre></div>
<a id="trunkJSTestsstressarithnegateonvarioustypesjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/arith-negate-on-various-types.js (0 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/arith-negate-on-various-types.js                                (rev 0)
+++ trunk/JSTests/stress/arith-negate-on-various-types.js        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -0,0 +1,283 @@
</span><ins>+//@ defaultNoEagerRun
+&quot;use strict&quot;;
+
+let validInputTestCases = [
+    // input as string, expected result as string.
+    [&quot;undefined&quot;, &quot;NaN&quot;],
+    [&quot;null&quot;, &quot;-0&quot;],
+    [&quot;0&quot;, &quot;-0&quot;],
+    [&quot;-0.&quot;, &quot;0&quot;],
+    [&quot;0.5&quot;, &quot;-0.5&quot;],
+    [&quot;-0.5&quot;, &quot;0.5&quot;],
+    [&quot;4&quot;, &quot;-4&quot;],
+    [&quot;42.1&quot;, &quot;-42.1&quot;],
+    [&quot;42.5&quot;, &quot;-42.5&quot;],
+    [&quot;42.9&quot;, &quot;-42.9&quot;],
+    [&quot;-42.1&quot;, &quot;42.1&quot;],
+    [&quot;-42.5&quot;, &quot;42.5&quot;],
+    [&quot;-42.9&quot;, &quot;42.9&quot;],
+    [&quot;Math.PI&quot;, &quot;-Math.PI&quot;],
+    [&quot;Infinity&quot;, &quot;-Infinity&quot;],
+    [&quot;-Infinity&quot;, &quot;Infinity&quot;],
+    [&quot;NaN&quot;, &quot;NaN&quot;],
+    [&quot;\&quot;WebKit\&quot;&quot;, &quot;NaN&quot;],
+    [&quot;\&quot;4\&quot;&quot;, &quot;-4&quot;],
+    [&quot;\&quot;42.5\&quot;&quot;, &quot;-42.5&quot;],
+    [&quot;{ valueOf: () =&gt; { return 4; } }&quot;, &quot;-4&quot;],
+    [&quot;{ valueOf: () =&gt; { return 0; } }&quot;, &quot;-0&quot;],
+    [&quot;{ valueOf: () =&gt; { return -0; } }&quot;, &quot;0&quot;],
+    [&quot;{ valueOf: () =&gt; { return 0.5; } }&quot;, &quot;-0.5&quot;],
+    [&quot;{ valueOf: () =&gt; { return -0.5; } }&quot;, &quot;0.5&quot;],
+    [&quot;{ valueOf: () =&gt; { return Number.MIN_SAFE_INTEGER; } }&quot;, &quot;9007199254740991&quot;],
+    [&quot;{ valueOf: () =&gt; { return Number.MAX_SAFE_INTEGER; } }&quot;, &quot;-9007199254740991&quot;],
+    [&quot;{ valueOf: () =&gt; { return 0x80000000|0; } }&quot;, &quot;2147483648&quot;],
+    [&quot;{ valueOf: () =&gt; { return 0x7fffffff|0; } }&quot;, &quot;-2147483647&quot;],
+    [&quot;{ valueOf: () =&gt; { return (0x80000000|0) - 0.5; } }&quot;, &quot;2147483648.5&quot;],
+    [&quot;{ valueOf: () =&gt; { return (0x7fffffff|0) + 0.5; } }&quot;, &quot;-2147483647.5&quot;],
+];
+
+let validInputTypedTestCases = validInputTestCases.map((element) =&gt; { return [eval(&quot;(&quot; + element[0] + &quot;)&quot;), eval(element[1])] });
+
+function isIdentical(result, expected)
+{
+    if (expected === expected) {
+        if (result !== expected)
+            return false;
+        if (!expected &amp;&amp; (1 / expected) !== (1 / result))
+            return false;
+
+        return true;
+    }
+    return result !== result;
+}
+
+
+// Test negate with a very polymorphic input. All test cases are seen at each iteration.
+function opaqueAllTypesNegate(argument) {
+    return -(argument);
+}
+noInline(opaqueAllTypesNegate);
+noOSRExitFuzzing(opaqueAllTypesNegate);
+
+function testAllTypesCall() {
+    for (let i = 0; i &lt; 1e3; ++i) {
+        for (let testCaseInput of validInputTypedTestCases) {
+            let output = opaqueAllTypesNegate(testCaseInput[0]);
+            if (!isIdentical(output, testCaseInput[1]))
+                throw &quot;Failed testAllTypesCall for input &quot; + testCaseInput[0] + &quot; expected &quot; + testCaseInput[1] + &quot; got &quot; + output;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueAllTypesNegate) &gt; 3)
+        throw &quot;We should have detected negate was polymorphic and generated a generic version.&quot;;
+}
+testAllTypesCall();
+
+
+// Polymorphic input but negative zero is not observable.
+function opaqueAllTypesNegateWithoutNegativeZero(argument) {
+    return -(argument) + 0;
+}
+noInline(opaqueAllTypesNegateWithoutNegativeZero);
+noOSRExitFuzzing(opaqueAllTypesNegateWithoutNegativeZero);
+
+function testAllTypesWithoutNegativeZeroCall() {
+    for (let i = 0; i &lt; 1e3; ++i) {
+        for (let testCaseInput of validInputTypedTestCases) {
+            let output = opaqueAllTypesNegateWithoutNegativeZero(testCaseInput[0]);
+            if (!isIdentical(output, testCaseInput[1] + 0))
+                throw &quot;Failed testAllTypesWithoutNegativeZeroCall for input &quot; + testCaseInput[0] + &quot; expected &quot; + testCaseInput[1] + &quot; got &quot; + output;
+        }
+    }
+    if (numberOfDFGCompiles(opaqueAllTypesNegate) &gt; 3)
+        throw &quot;We should have detected negate was polymorphic and generated a generic version.&quot;;
+}
+testAllTypesWithoutNegativeZeroCall();
+
+
+// Test negate on a completely typed input. Every call see only one type.
+function testSingleTypeCall() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueNegate(argument) {
+                return -(argument);
+            }
+            noInline(opaqueNegate);
+            noOSRExitFuzzing(opaqueNegate);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueNegate(${testCaseInput[0]}), ${testCaseInput[1]})) {
+                    throw &quot;Failed testSingleTypeCall()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueNegate) &gt; 1)
+                throw &quot;Failed testSingleTypeCall(). We should have compiled a single negate for the expected type.&quot;;
+        `);
+    }
+}
+testSingleTypeCall();
+
+
+function checkCompileCountForUselessNegativeZero(testFunction)
+{
+    if (jscOptions().useMaximalFlushInsertionPhase) {
+        // If we forced a flush after the operation, the negative zero becomes
+        // observable and we may be overly optimistic.
+        return numberOfDFGCompiles(testFunction) &lt;= 2;
+    }
+    return numberOfDFGCompiles(testFunction) &lt;= 1;
+}
+
+
+// Test negate on a completely typed input, but without negative zero.
+function testSingleTypeWithoutNegativeZeroCall() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueNegate(argument) {
+                return -(argument) + 0;
+            }
+            noInline(opaqueNegate);
+            noOSRExitFuzzing(opaqueNegate);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueNegate(${testCaseInput[0]}), ${testCaseInput[1]} + 0)) {
+                    throw &quot;Failed testSingleTypeWithoutNegativeZeroCall()&quot;;
+                }
+            }
+            if (!checkCompileCountForUselessNegativeZero(opaqueNegate))
+                throw &quot;Failed testSingleTypeWithoutNegativeZeroCall(). We should have compiled a single negate for the expected type.&quot;;
+        `);
+    }
+}
+testSingleTypeWithoutNegativeZeroCall();
+
+
+// Test negate on constants
+function testConstant() {
+    for (let testCaseInput of validInputTestCases) {
+        eval(`
+            function opaqueNegateOnConstant() {
+                return -(${testCaseInput[0]});
+            }
+            noInline(opaqueNegateOnConstant);
+            noOSRExitFuzzing(opaqueNegateOnConstant);
+
+            for (let i = 0; i &lt; 1e4; ++i) {
+                if (!isIdentical(opaqueNegateOnConstant(), ${testCaseInput[1]})) {
+                    throw &quot;Failed testConstant()&quot;;
+                }
+            }
+            if (numberOfDFGCompiles(opaqueNegateOnConstant) &gt; 1)
+                throw &quot;Failed testConstant(). We should have compiled a single negate for the expected type.&quot;;
+        `);
+    }
+}
+testConstant();
+
+
+// Verify we call valueOf() exactly once per call.
+function opaqueNegateForSideEffects(argument) {
+    return -(argument);
+}
+noInline(opaqueNegateForSideEffects);
+noOSRExitFuzzing(opaqueNegateForSideEffects);
+
+function testSideEffect() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i &lt; 1e4; ++i) {
+        if (opaqueNegateForSideEffects(testObject) !== -16)
+            throw &quot;Incorrect result in testSideEffect()&quot;;
+    }
+    if (testObject.counter !== 1e4)
+        throw &quot;Failed testSideEffect()&quot;;
+    if (numberOfDFGCompiles(opaqueNegateForSideEffects) &gt; 1)
+        throw &quot;opaqueNegateForSideEffects() is predictable, it should only be compiled once.&quot;;
+}
+testSideEffect();
+
+
+// Verify negate is not subject to CSE if the argument has side effects.
+function opaqueNegateForCSE(argument) {
+    return -(argument) + -(argument) + -(argument);
+}
+noInline(opaqueNegateForCSE);
+noOSRExitFuzzing(opaqueNegateForCSE);
+
+function testCSE() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i &lt; 1e4; ++i) {
+        if (opaqueNegateForCSE(testObject) !== -48)
+            throw &quot;Incorrect result in testCSE()&quot;;
+    }
+    if (testObject.counter !== 3e4)
+        throw &quot;Failed testCSE()&quot;;
+    if (numberOfDFGCompiles(opaqueNegateForCSE) &gt; 1)
+        throw &quot;opaqueNegateForCSE() is predictable, it should only be compiled once.&quot;;
+}
+testCSE();
+
+
+// Verify negate is not subject to DCE if the argument has side effects.
+function opaqueNegateForDCE(argument) {
+    -(argument);
+}
+noInline(opaqueNegateForDCE);
+noOSRExitFuzzing(opaqueNegateForDCE);
+
+function testDCE() {
+    let testObject = {
+        counter: 0,
+        valueOf: function() { ++this.counter; return 16; }
+    };
+    for (let i = 0; i &lt; 1e4; ++i) {
+        opaqueNegateForDCE(testObject);
+    }
+    if (testObject.counter !== 1e4)
+        throw &quot;Failed testDCE()&quot;;
+    if (numberOfDFGCompiles(opaqueNegateForDCE) &gt; 1)
+        throw &quot;opaqueNegateForDCE() is predictable, it should only be compiled once.&quot;;
+}
+testDCE();
+
+
+// Test exceptions in the argument.
+function testException() {
+    let counter = 0;
+    function opaqueNegateWithException(argument) {
+        let result = -(argument);
+        ++counter;
+        return result;
+    }
+    noInline(opaqueNegateWithException);
+
+    let testObject = { valueOf: () =&gt; {  return 64; } };
+
+    // Warm up without exception.
+    for (let i = 0; i &lt; 1e3; ++i) {
+        if (opaqueNegateWithException(testObject) !== -64)
+            throw &quot;Incorrect result in opaqueNegateWithException()&quot;;
+    }
+
+    let testThrowObject = { valueOf: () =&gt; { throw testObject; return 64; } };
+
+    for (let i = 0; i &lt; 1e2; ++i) {
+        try {
+            if (opaqueNegateWithException(testThrowObject) !== 8)
+                throw &quot;This code should not be reached!!&quot;;
+        } catch (e) {
+            if (e !== testObject) {
+                throw &quot;Wrong object thrown from opaqueNegateWithException.&quot;
+            }
+        }
+    }
+
+    if (counter !== 1e3) {
+        throw &quot;Invalid count in testException()&quot;;
+    }
+}
+testException();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2016-10-14  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] op_negate should with any type
+        https://bugs.webkit.org/show_bug.cgi?id=162587
+
+        Reviewed by Saam Barati.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        ArithNegate is quite simple. If the input is double, the output
+        is double. The other cases are set from the LLInt slow case.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::makeSafe):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+
+        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
+        Tweak a bit the IntegerRangeOptimizationPhase when simplifying
+        ArithAbs to ArithNegate.
+        We should not do the conversion if the target nodes OSR Exits
+        on different input than the source node.
+
+        In particular, Checked ArithNegate exits on zero while
+        ArithAbs has not problem with it.
+        Unchecked ArithAbs() do not OSR Exit on INT_MIN, ArithNeg
+        should not either.
+
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithNegate):
+        (JSC::DFG::SpeculativeJIT::compileMathIC):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileMathIC):
+        (JSC::FTL::DFG::LowerDFGToB3::compileArithNegate):
+
+        * jit/JITNegGenerator.cpp:
+        (JSC::JITNegGenerator::generateFastPath):
+        * jit/JITOperations.cpp:
+        Add result profiling in baseline to have types we can use
+        in DFG and FTL.
+
</ins><span class="cx"> 2016-10-14  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         B3 needs a special WasmAddress Opcode
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -657,7 +657,8 @@
</span><span class="cx">                     forNode(node-&gt;child1()).m_type));
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><del>-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            DFG_ASSERT(m_graph, node, node-&gt;child1().useKind() == UntypedUse);
+            forNode(node).setType(SpecBytecodeNumber);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -974,6 +974,17 @@
</span><span class="cx">                         node-&gt;mergeFlags(NodeMayHaveNonNumberResult);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><ins>+                case ArithNegate: {
+                    ASSERT_WITH_MESSAGE(!arithProfile-&gt;didObserveNonNumber(), &quot;op_negate starts with a toNumber() on the argument, it should only produce numbers.&quot;);
+
+                    if (arithProfile-&gt;lhsObservedType().sawNumber() || arithProfile-&gt;didObserveDouble())
+                        node-&gt;mergeFlags(NodeMayHaveDoubleResult);
+                    if (arithProfile-&gt;didObserveNegZeroDouble() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
+                        node-&gt;mergeFlags(NodeMayNegZeroInBaseline);
+                    if (arithProfile-&gt;didObserveInt32Overflow() || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, Overflow))
+                        node-&gt;mergeFlags(NodeMayOverflowInt32InBaseline);
+                    break;
+                }
</ins><span class="cx">                 
</span><span class="cx">                 default:
</span><span class="cx">                     break;
</span><span class="lines">@@ -991,14 +1002,6 @@
</span><span class="cx">                 node-&gt;mergeFlags(NodeMayOverflowInt32InBaseline);
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><del>-            case ArithNegate:
-                // Currently we can't tell the difference between a negation overflowing
-                // (i.e. -(1 &lt;&lt; 31)) or generating negative zero (i.e. -0). If it took slow
-                // path then we assume that it did both of those things.
-                node-&gt;mergeFlags(NodeMayOverflowInt32InBaseline);
-                node-&gt;mergeFlags(NodeMayNegZeroInBaseline);
-                break;
-                
</del><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -211,6 +211,17 @@
</span><span class="cx">         }
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    case ArithNegate:
+        if (node-&gt;child1().useKind() == Int32Use
+            || node-&gt;child1().useKind() == DoubleRepUse
+            || node-&gt;child1().useKind() == Int52RepUse)
+            def(PureValue(node));
+        else {
+            read(World);
+            write(Heap);
+        }
+        return;
+
</ins><span class="cx">     case IsCellWithType:
</span><span class="cx">         def(PureValue(node, node-&gt;queriedType()));
</span><span class="cx">         return;
</span><span class="lines">@@ -334,7 +345,6 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case ArithAdd:
</span><del>-    case ArithNegate:
</del><span class="cx">     case ArithMod:
</span><span class="cx">     case DoubleAsInt32:
</span><span class="cx">     case UInt32ToNumber:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -209,7 +209,7 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case ArithNegate: {
</span><del>-            if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
</del><ins>+            if (node-&gt;child1()-&gt;shouldSpeculateInt32OrBoolean() &amp;&amp; node-&gt;canSpeculateInt32(FixupPass)) {
</ins><span class="cx">                 fixIntOrBooleanEdge(node-&gt;child1());
</span><span class="cx">                 if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</span><span class="cx">                     node-&gt;setArithMode(Arith::Unchecked);
</span><span class="lines">@@ -217,6 +217,8 @@
</span><span class="cx">                     node-&gt;setArithMode(Arith::CheckOverflow);
</span><span class="cx">                 else
</span><span class="cx">                     node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</span><ins>+                node-&gt;setResult(NodeResultInt32);
+                node-&gt;clearFlags(NodeMustGenerate);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (m_graph.unaryArithShouldSpeculateAnyInt(node, FixupPass)) {
</span><span class="lines">@@ -226,10 +228,15 @@
</span><span class="cx">                 else
</span><span class="cx">                     node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</span><span class="cx">                 node-&gt;setResult(NodeResultInt52);
</span><ins>+                node-&gt;clearFlags(NodeMustGenerate);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            fixDoubleOrBooleanEdge(node-&gt;child1());
-            node-&gt;setResult(NodeResultDouble);
</del><ins>+            if (node-&gt;child1()-&gt;shouldSpeculateNotCell()) {
+                fixDoubleOrBooleanEdge(node-&gt;child1());
+                node-&gt;setResult(NodeResultDouble);
+                node-&gt;clearFlags(NodeMustGenerate);
+            } else
+                fixEdge&lt;UntypedUse&gt;(node-&gt;child1());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -1252,9 +1252,10 @@
</span><span class="cx">                         changed = true;
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><del>-                    if (maxValue &lt;= 0) {
</del><ins>+                    bool absIsUnchecked = !shouldCheckOverflow(node-&gt;arithMode());
+                    if (maxValue &lt; 0 || (absIsUnchecked &amp;&amp; maxValue &lt;= 0)) {
</ins><span class="cx">                         node-&gt;convertToArithNegate();
</span><del>-                        if (minValue &gt; std::numeric_limits&lt;int&gt;::min())
</del><ins>+                        if (absIsUnchecked || minValue &gt; std::numeric_limits&lt;int&gt;::min())
</ins><span class="cx">                             node-&gt;setArithMode(Arith::Unchecked);
</span><span class="cx">                         changed = true;
</span><span class="cx">                         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -245,17 +245,23 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case ArithNegate:
-            if (node-&gt;child1()-&gt;prediction()) {
-                if (m_graph.unaryArithShouldSpeculateInt32(node, m_pass))
</del><ins>+        case ArithNegate: {
+            SpeculatedType prediction = node-&gt;child1()-&gt;prediction();
+            if (prediction) {
+                if (isInt32OrBooleanSpeculation(prediction) &amp;&amp; node-&gt;canSpeculateInt32(m_pass))
</ins><span class="cx">                     changed |= mergePrediction(SpecInt32Only);
</span><span class="cx">                 else if (m_graph.unaryArithShouldSpeculateAnyInt(node, m_pass))
</span><span class="cx">                     changed |= mergePrediction(SpecInt52Only);
</span><del>-                else
</del><ins>+                else if (isBytecodeNumberSpeculation(prediction))
</ins><span class="cx">                     changed |= mergePrediction(speculatedDoubleTypeForPrediction(node-&gt;child1()-&gt;prediction()));
</span><ins>+                else {
+                    changed |= mergePrediction(SpecInt32Only);
+                    if (node-&gt;mayHaveDoubleResult())
+                        changed |= mergePrediction(SpecBytecodeDouble);
+                }
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><del>-            
</del><ins>+        }
</ins><span class="cx">         case ArithMin:
</span><span class="cx">         case ArithMax: {
</span><span class="cx">             SpeculatedType left = node-&gt;child1()-&gt;prediction();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -4237,11 +4237,106 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    default:
-        RELEASE_ASSERT_NOT_REACHED();
</del><ins>+    default: {
+        ArithProfile* arithProfile = m_jit.graph().baselineCodeBlockFor(node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(node-&gt;origin.semantic.bytecodeIndex);
+        JITNegIC* negIC = m_jit.codeBlock()-&gt;addJITNegIC(arithProfile);
+        auto repatchingFunction = operationArithNegateOptimize;
+        auto nonRepatchingFunction = operationArithNegate;
+        bool needsScratchGPRReg = true;
+        compileMathIC(node, negIC, needsScratchGPRReg, repatchingFunction, nonRepatchingFunction);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    }
</ins><span class="cx"> }
</span><ins>+
+template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
+void SpeculativeJIT::compileMathIC(Node* node, JITUnaryMathIC&lt;Generator&gt;* mathIC, bool needsScratchGPRReg, RepatchingFunction repatchingFunction, NonRepatchingFunction nonRepatchingFunction)
+{
+    GPRReg scratchGPR = InvalidGPRReg;
+    Optional&lt;GPRTemporary&gt; gprScratch;
+    if (needsScratchGPRReg) {
+        gprScratch = GPRTemporary(this);
+        scratchGPR = gprScratch-&gt;gpr();
+    }
+    JSValueOperand childOperand(this, node-&gt;child1());
+    JSValueRegs childRegs = childOperand.jsValueRegs();
+#if USE(JSVALUE64)
+    GPRTemporary result(this, Reuse, childOperand);
+    JSValueRegs resultRegs(result.gpr());
+#else
+    GPRTemporary resultTag(this);
+    GPRTemporary resultPayload(this);
+    JSValueRegs resultRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+
+#if ENABLE(MATH_IC_STATS)
+    auto inlineStart = m_jit.label();
+#endif
+
+    Box&lt;MathICGenerationState&gt; icGenerationState = Box&lt;MathICGenerationState&gt;::create();
+    mathIC-&gt;m_generator = Generator(resultRegs, childRegs, scratchGPR);
+
+    bool shouldEmitProfiling = false;
+    bool generatedInline = mathIC-&gt;generateInline(m_jit, *icGenerationState, shouldEmitProfiling);
+
+    if (generatedInline) {
+        ASSERT(!icGenerationState-&gt;slowPathJumps.empty());
+
+        Vector&lt;SilentRegisterSavePlan&gt; savePlans;
+        silentSpillAllRegistersImpl(false, savePlans, resultRegs);
+
+        auto done = m_jit.label();
+
+        addSlowPathGenerator([=, savePlans = WTFMove(savePlans)] () {
+            icGenerationState-&gt;slowPathJumps.link(&amp;m_jit);
+            icGenerationState-&gt;slowPathStart = m_jit.label();
+#if ENABLE(MATH_IC_STATS)
+            auto slowPathStart = m_jit.label();
+#endif
+
+            silentSpill(savePlans);
+
+            if (icGenerationState-&gt;shouldSlowPathRepatch)
+                icGenerationState-&gt;slowPathCall = callOperation(bitwise_cast&lt;J_JITOperation_EJMic&gt;(repatchingFunction), resultRegs, childRegs, TrustedImmPtr(mathIC));
+            else
+                icGenerationState-&gt;slowPathCall = callOperation(nonRepatchingFunction, resultRegs, childRegs);
+
+            silentFill(savePlans);
+            m_jit.exceptionCheck();
+            m_jit.jump().linkTo(done, &amp;m_jit);
+
+            m_jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                mathIC-&gt;finalizeInlineCode(*icGenerationState, linkBuffer);
+            });
+
+#if ENABLE(MATH_IC_STATS)
+            auto slowPathEnd = m_jit.label();
+            m_jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                size_t size = static_cast&lt;char*&gt;(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast&lt;char*&gt;(linkBuffer.locationOf(slowPathStart).executableAddress());
+                mathIC-&gt;m_generatedCodeSize += size;
+            });
+#endif
+
+        });
+    } else {
+        flushRegisters();
+        callOperation(nonRepatchingFunction, resultRegs, childRegs);
+        m_jit.exceptionCheck();
+    }
+
+#if ENABLE(MATH_IC_STATS)
+    auto inlineEnd = m_jit.label();
+    m_jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+        size_t size = static_cast&lt;char*&gt;(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast&lt;char*&gt;(linkBuffer.locationOf(inlineStart).executableAddress());
+        mathIC-&gt;m_generatedCodeSize += size;
+    });
+#endif
+
+    jsValueResult(resultRegs, node);
+    return;
+}
+
+
</ins><span class="cx"> void SpeculativeJIT::compileArithMul(Node* node)
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;binaryUseKind()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -1312,6 +1312,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC)
+    {
+        m_jit.setupArgumentsWithExecState(arg.gpr(), mathIC);
+        return appendCallSetResult(operation, result.gpr());
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1.gpr(), arg2.gpr(), mathIC);
</span><span class="lines">@@ -1799,7 +1804,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3);
</span><span class="cx">         return appendCallSetResult(operation, result);
</span><span class="cx">     }
</span><del>-
</del><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJMic operation, JSValueRegs result, JSValueRegs arg, TrustedImmPtr mathIC)
+    {
+        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg.payloadGPR(), arg.tagGPR(), mathIC);
+        return appendCallSetResult(operation, result.payloadGPR(), result.tagGPR());
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR(), arg2.payloadGPR(), arg2.tagGPR(), mathIC);
</span><span class="lines">@@ -2595,6 +2604,8 @@
</span><span class="cx"> 
</span><span class="cx">     template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
</span><span class="cx">     void compileMathIC(Node*, JITBinaryMathIC&lt;Generator&gt;*, bool needsScratchGPRReg, bool needsScratchFPRReg, RepatchingFunction, NonRepatchingFunction);
</span><ins>+    template &lt;typename Generator, typename RepatchingFunction, typename NonRepatchingFunction&gt;
+    void compileMathIC(Node*, JITUnaryMathIC&lt;Generator&gt;*, bool needsScratchGPRReg, RepatchingFunction, NonRepatchingFunction);
</ins><span class="cx"> 
</span><span class="cx">     void compileArithDoubleUnaryOp(Node*, double (*doubleFunction)(double), double (*operation)(ExecState*, EncodedJSValue));
</span><span class="cx">     void compileValueAdd(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -1580,6 +1580,90 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     template &lt;typename Generator&gt;
</span><ins>+    void compileMathIC(JITUnaryMathIC&lt;Generator&gt;* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)
+    {
+        Node* node = m_node;
+
+        LValue operand = lowJSValue(node-&gt;child1());
+
+        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
+        patchpoint-&gt;appendSomeRegister(operand);
+        patchpoint-&gt;append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
+        patchpoint-&gt;append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
+        RefPtr&lt;PatchpointExceptionHandle&gt; exceptionHandle = preparePatchpointForExceptions(patchpoint);
+        patchpoint-&gt;numGPScratchRegisters = 1;
+        patchpoint-&gt;clobber(RegisterSet::macroScratchRegisters());
+        State* state = &amp;m_ftlState;
+        patchpoint-&gt;setGenerator(
+            [=] (CCallHelpers&amp; jit, const StackmapGenerationParams&amp; params) {
+                AllowMacroScratchRegisterUsage allowScratch(jit);
+
+                Box&lt;CCallHelpers::JumpList&gt; exceptions =
+                    exceptionHandle-&gt;scheduleExitCreation(params)-&gt;jumps(jit);
+
+#if ENABLE(MATH_IC_STATS)
+                auto inlineStart = jit.label();
+#endif
+
+                Box&lt;MathICGenerationState&gt; mathICGenerationState = Box&lt;MathICGenerationState&gt;::create();
+                mathIC-&gt;m_generator = Generator(JSValueRegs(params[0].gpr()), JSValueRegs(params[1].gpr()), params.gpScratch(0));
+
+                bool shouldEmitProfiling = false;
+                bool generatedInline = mathIC-&gt;generateInline(jit, *mathICGenerationState, shouldEmitProfiling);
+
+                if (generatedInline) {
+                    ASSERT(!mathICGenerationState-&gt;slowPathJumps.empty());
+                    auto done = jit.label();
+                    params.addLatePath([=] (CCallHelpers&amp; jit) {
+                        AllowMacroScratchRegisterUsage allowScratch(jit);
+                        mathICGenerationState-&gt;slowPathJumps.link(&amp;jit);
+                        mathICGenerationState-&gt;slowPathStart = jit.label();
+#if ENABLE(MATH_IC_STATS)
+                        auto slowPathStart = jit.label();
+#endif
+
+                        if (mathICGenerationState-&gt;shouldSlowPathRepatch) {
+                            SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
+                                repatchingFunction, params[0].gpr(), params[1].gpr(), CCallHelpers::TrustedImmPtr(mathIC));
+                            mathICGenerationState-&gt;slowPathCall = call.call();
+                        } else {
+                            SlowPathCall call = callOperation(*state, params.unavailableRegisters(), jit, node-&gt;origin.semantic,
+                                exceptions.get(), nonRepatchingFunction, params[0].gpr(), params[1].gpr());
+                            mathICGenerationState-&gt;slowPathCall = call.call();
+                        }
+                        jit.jump().linkTo(done, &amp;jit);
+
+                        jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                            mathIC-&gt;finalizeInlineCode(*mathICGenerationState, linkBuffer);
+                        });
+
+#if ENABLE(MATH_IC_STATS)
+                        auto slowPathEnd = jit.label();
+                        jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                            size_t size = static_cast&lt;char*&gt;(linkBuffer.locationOf(slowPathEnd).executableAddress()) - static_cast&lt;char*&gt;(linkBuffer.locationOf(slowPathStart).executableAddress());
+                            mathIC-&gt;m_generatedCodeSize += size;
+                        });
+#endif
+                    });
+                } else {
+                    callOperation(
+                        *state, params.unavailableRegisters(), jit, node-&gt;origin.semantic, exceptions.get(),
+                        nonRepatchingFunction, params[0].gpr(), params[1].gpr());
+                }
+
+#if ENABLE(MATH_IC_STATS)
+                auto inlineEnd = jit.label();
+                jit.addLinkTask([=] (LinkBuffer&amp; linkBuffer) {
+                    size_t size = static_cast&lt;char*&gt;(linkBuffer.locationOf(inlineEnd).executableAddress()) - static_cast&lt;char*&gt;(linkBuffer.locationOf(inlineStart).executableAddress());
+                    mathIC-&gt;m_generatedCodeSize += size;
+                });
+#endif
+            });
+
+        setJSValue(patchpoint);
+    }
+
+    template &lt;typename Generator&gt;
</ins><span class="cx">     void compileMathIC(JITBinaryMathIC&lt;Generator&gt;* mathIC, FunctionPtr repatchingFunction, FunctionPtr nonRepatchingFunction)
</span><span class="cx">     {
</span><span class="cx">         Node* node = m_node;
</span><span class="lines">@@ -2451,7 +2535,12 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         default:
</span><del>-            DFG_CRASH(m_graph, m_node, &quot;Bad use kind&quot;);
</del><ins>+            DFG_ASSERT(m_graph, m_node, m_node-&gt;child1().useKind() == UntypedUse);
+            ArithProfile* arithProfile = m_ftlState.graph.baselineCodeBlockFor(m_node-&gt;origin.semantic)-&gt;arithProfileForBytecodeOffset(m_node-&gt;origin.semantic.bytecodeIndex);
+            JITNegIC* negIC = codeBlock()-&gt;addJITNegIC(arithProfile);
+            auto repatchingFunction = operationArithNegateOptimize;
+            auto nonRepatchingFunction = operationArithNegate;
+            compileMathIC(negIC, repatchingFunction, nonRepatchingFunction);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITNegGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/jit/JITNegGenerator.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -82,7 +82,7 @@
</span><span class="cx">     return JITMathICInlineResult::GenerateFullSnippet;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool JITNegGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList, const ArithProfile*, bool)
</del><ins>+bool JITNegGenerator::generateFastPath(CCallHelpers&amp; jit, CCallHelpers::JumpList&amp; endJumpList, CCallHelpers::JumpList&amp; slowPathJumpList, const ArithProfile* arithProfile, bool shouldEmitProfiling)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_scratchGPR != m_src.payloadGPR());
</span><span class="cx">     ASSERT(m_scratchGPR != m_result.payloadGPR());
</span><span class="lines">@@ -115,6 +115,10 @@
</span><span class="cx"> #else
</span><span class="cx">     jit.xor32(CCallHelpers::TrustedImm32(1 &lt;&lt; 31), m_result.tagGPR());
</span><span class="cx"> #endif
</span><ins>+    // The flags of ArithNegate are basic in DFG.
+    // We only need to know if we ever produced a number.
+    if (shouldEmitProfiling &amp;&amp; arithProfile &amp;&amp; !arithProfile-&gt;lhsObservedType().sawNumber() &amp;&amp; !arithProfile-&gt;didObserveDouble())
+        arithProfile-&gt;emitSetDouble(jit);
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (207368 => 207369)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-10-15 01:48:36 UTC (rev 207368)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-10-15 02:19:16 UTC (rev 207369)
</span><span class="lines">@@ -2470,7 +2470,10 @@
</span><span class="cx">     double number = operand.toNumber(exec);
</span><span class="cx">     if (UNLIKELY(scope.exception()))
</span><span class="cx">         return JSValue::encode(JSValue());
</span><del>-    return JSValue::encode(jsNumber(-number));
</del><ins>+
+    JSValue result = jsNumber(-number);
+    arithProfile.observeResult(result);
+    return JSValue::encode(result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArithNegate(ExecState* exec, EncodedJSValue operand)
</span><span class="lines">@@ -2504,7 +2507,9 @@
</span><span class="cx">     double number = operand.toNumber(exec);
</span><span class="cx">     if (UNLIKELY(scope.exception()))
</span><span class="cx">         return JSValue::encode(JSValue());
</span><del>-    return JSValue::encode(jsNumber(-number));
</del><ins>+    JSValue result = jsNumber(-number);
+    arithProfile-&gt;observeResult(result);
+    return JSValue::encode(result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, EncodedJSValue encodedOperand, JITNegIC* negIC)
</span></span></pre>
</div>
</div>

</body>
</html>