<!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>[196726] 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/196726">196726</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-02-17 15:35:11 -0800 (Wed, 17 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Remove the overflow check on ArithAbs when possible
https://bugs.webkit.org/show_bug.cgi?id=154325

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2016-02-17
Reviewed by Filip Pizlo.

This patch adds support for ArithMode for ArithAbs.

It is useful for kraken tests where Math.abs() is used
on values for which the range is known.

For example, imaging-gaussian-blur has two Math.abs() with
integers that are always in a small range around zero.
The IntegerRangeOptimizationPhase detects the range correctly
so we can just update the ArithMode depending on the input.

* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGIntegerRangeOptimizationPhase.cpp:
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToArithNegate):
(JSC::DFG::Node::hasArithMode):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileArithAbs):
* tests/stress/arith-abs-integer-range-optimization.js: Added.
(negativeRange):
(negativeRangeIncludingZero):
(negativeRangeWithOverflow):
(positiveRange):
(positiveRangeIncludingZero):
(rangeWithoutOverflow):
* tests/stress/arith-abs-with-bitwise-or-zero.js: Added.
(opaqueAbs):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</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="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressarithabsintegerrangeoptimizationjs">trunk/Source/JavaScriptCore/tests/stress/arith-abs-integer-range-optimization.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarithabswithbitwiseorzerojs">trunk/Source/JavaScriptCore/tests/stress/arith-abs-with-bitwise-or-zero.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2016-02-17  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Remove the overflow check on ArithAbs when possible
+        https://bugs.webkit.org/show_bug.cgi?id=154325
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds support for ArithMode for ArithAbs.
+
+        It is useful for kraken tests where Math.abs() is used
+        on values for which the range is known.
+
+        For example, imaging-gaussian-blur has two Math.abs() with
+        integers that are always in a small range around zero.
+        The IntegerRangeOptimizationPhase detects the range correctly
+        so we can just update the ArithMode depending on the input.
+
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToArithNegate):
+        (JSC::DFG::Node::hasArithMode):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileArithAbs):
+        * tests/stress/arith-abs-integer-range-optimization.js: Added.
+        (negativeRange):
+        (negativeRangeIncludingZero):
+        (negativeRangeWithOverflow):
+        (positiveRange):
+        (positiveRangeIncludingZero):
+        (rangeWithoutOverflow):
+        * tests/stress/arith-abs-with-bitwise-or-zero.js: Added.
+        (opaqueAbs):
+
</ins><span class="cx"> 2016-02-17  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         SES selftest page crashes on nightly r196694
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -334,6 +334,10 @@
</span><span class="cx">         case ArithAbs: {
</span><span class="cx">             if (m_graph.unaryArithShouldSpeculateInt32(node, FixupPass)) {
</span><span class="cx">                 fixIntOrBooleanEdge(node-&gt;child1());
</span><ins>+                if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::Unchecked);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflow);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             fixDoubleOrBooleanEdge(node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -1203,6 +1203,43 @@
</span><span class="cx">                 // optimize by using the relationships before the operation, but we need to
</span><span class="cx">                 // call executeNode() before we optimize.
</span><span class="cx">                 switch (node-&gt;op()) {
</span><ins>+                case ArithAbs: {
+                    if (node-&gt;child1().useKind() != Int32Use)
+                        break;
+
+                    auto iter = m_relationships.find(node-&gt;child1().node());
+                    if (iter == m_relationships.end())
+                        break;
+
+                    int minValue = std::numeric_limits&lt;int&gt;::min();
+                    int maxValue = std::numeric_limits&lt;int&gt;::max();
+                    for (Relationship relationship : iter-&gt;value) {
+                        minValue = std::max(minValue, relationship.minValueOfLeft());
+                        maxValue = std::min(maxValue, relationship.maxValueOfLeft());
+                    }
+
+                    executeNode(block-&gt;at(nodeIndex));
+
+                    if (minValue &gt;= 0) {
+                        node-&gt;convertToIdentityOn(node-&gt;child1().node());
+                        changed = true;
+                        break;
+                    }
+                    if (maxValue &lt;= 0) {
+                        node-&gt;convertToArithNegate();
+                        if (minValue &gt; std::numeric_limits&lt;int&gt;::min())
+                            node-&gt;setArithMode(Arith::Unchecked);
+                        changed = true;
+                        break;
+                    }
+                    if (minValue &gt; std::numeric_limits&lt;int&gt;::min()) {
+                        node-&gt;setArithMode(Arith::Unchecked);
+                        changed = true;
+                        break;
+                    }
+
+                    break;
+                }
</ins><span class="cx">                 case ArithAdd: {
</span><span class="cx">                     if (!node-&gt;isBinaryUseKind(Int32Use))
</span><span class="cx">                         break;
</span><span class="lines">@@ -1309,6 +1346,13 @@
</span><span class="cx">             setRelationship(Relationship::safeCreate(node-&gt;child1().node(), m_zero, Relationship::GreaterThan, -1));
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+
+        case ArithAbs: {
+            if (node-&gt;child1().useKind() != Int32Use)
+                break;
+            setRelationship(Relationship(node, m_zero, Relationship::GreaterThan, -1));
+            break;
+        }
</ins><span class="cx">             
</span><span class="cx">         case ArithAdd: {
</span><span class="cx">             // We're only interested in int32 additions and we currently only know how to
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -650,6 +650,12 @@
</span><span class="cx">         child2() = Edge();
</span><span class="cx">         m_op = ArithSqrt;
</span><span class="cx">     }
</span><ins>+
+    void convertToArithNegate()
+    {
+        ASSERT(m_op == ArithAbs &amp;&amp; child1().useKind() == Int32Use);
+        m_op = ArithNegate;
+    }
</ins><span class="cx">     
</span><span class="cx">     JSValue asJSValue()
</span><span class="cx">     {
</span><span class="lines">@@ -1678,6 +1684,7 @@
</span><span class="cx">     bool hasArithMode()
</span><span class="cx">     {
</span><span class="cx">         switch (op()) {
</span><ins>+        case ArithAbs:
</ins><span class="cx">         case ArithAdd:
</span><span class="cx">         case ArithSub:
</span><span class="cx">         case ArithNegate:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -2302,7 +2302,8 @@
</span><span class="cx">             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
</span><span class="cx">             m_jit.add32(scratch.gpr(), result.gpr());
</span><span class="cx">             m_jit.xor32(scratch.gpr(), result.gpr());
</span><del>-            speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 &lt;&lt; 31)));
</del><ins>+            if (shouldCheckOverflow(node-&gt;arithMode()))
+                speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 &lt;&lt; 31)));
</ins><span class="cx">             int32Result(result.gpr(), node);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (196725 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-02-17 23:25:20 UTC (rev 196725)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -2124,12 +2124,13 @@
</span><span class="cx">         switch (m_node-&gt;child1().useKind()) {
</span><span class="cx">         case Int32Use: {
</span><span class="cx">             LValue value = lowInt32(m_node-&gt;child1());
</span><del>-            
</del><ins>+
</ins><span class="cx">             LValue mask = m_out.aShr(value, m_out.constInt32(31));
</span><span class="cx">             LValue result = m_out.bitXor(mask, m_out.add(mask, value));
</span><del>-            
-            speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 &lt;&lt; 31)));
-            
</del><ins>+
+            if (shouldCheckOverflow(m_node-&gt;arithMode()))
+                speculate(Overflow, noValue(), 0, m_out.equal(result, m_out.constInt32(1 &lt;&lt; 31)));
+
</ins><span class="cx">             setInt32(result);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarithabsintegerrangeoptimizationjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/arith-abs-integer-range-optimization.js (0 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/arith-abs-integer-range-optimization.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/arith-abs-integer-range-optimization.js        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+function negativeRange(results)
+{
+    for (var i = -1; i &gt; -10; --i) {
+        results[Math.abs(i)] = i;
+    }
+}
+noInline(negativeRange);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    negativeRange(results);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 10; ++j) {
+        if (j &lt; 1) {
+            if (results[j] !== undefined)
+                throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+            continue;
+        }
+        if (results[j] !== -j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+function negativeRangeIncludingZero(results)
+{
+    for (var i = 0; i &gt; -10; --i) {
+        results[Math.abs(i)] = i;
+    }
+}
+noInline(negativeRangeIncludingZero);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    negativeRangeIncludingZero(results);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 10; ++j) {
+        if (results[j] !== -j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+function negativeRangeWithOverflow(results, limit)
+{
+    var i = -2147483648 + 10;
+    do {
+        results.push(Math.abs(i));
+        --i;
+    } while (i !== limit);
+}
+noInline(negativeRangeWithOverflow);
+
+// First, we warm up without overflow.
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    negativeRangeWithOverflow(results, -2147483647);
+    if (results.length != 9)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 9; ++j) {
+        if (results[j] !== 2147483638 + j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+// Then we overflow.
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    negativeRangeWithOverflow(results, -2147483648);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 10; ++j) {
+        if (results[j] !== 2147483638 + j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+function positiveRange(results)
+{
+    for (var i = 1; i &lt; 10; ++i) {
+        results[Math.abs(i)] = i;
+    }
+}
+noInline(positiveRange);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    positiveRange(results);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 10; ++j) {
+        if (j &lt; 1) {
+            if (results[j] !== undefined)
+                throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+            continue;
+        }
+        if (results[j] !== j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+function positiveRangeIncludingZero(results)
+{
+    for (var i = 0; i &lt; 10; ++i) {
+        results[Math.abs(i)] = i;
+    }
+}
+noInline(positiveRangeIncludingZero);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    positiveRangeIncludingZero(results);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = 0; j &lt; 10; ++j) {
+        if (results[j] !== j)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
+
+function rangeWithoutOverflow(results)
+{
+    for (var i = -10; i &lt; 10; ++i) {
+        results[i] = Math.abs(i);
+    }
+}
+noInline(rangeWithoutOverflow);
+
+for (var i = 0; i &lt; 1e4; ++i) {
+    var results = [];
+    rangeWithoutOverflow(results);
+    if (results.length != 10)
+        throw &quot;Wrong result length: &quot; + results.length;
+    for (var j = -10; j &lt; 10; ++j) {
+        var expected = (j &lt; 0) ? -j : j;
+        if (results[j] !== expected)
+            throw &quot;Wrong result, results[j] = &quot; + results[j] + &quot; at j = &quot; + j;
+    }
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarithabswithbitwiseorzerojs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/arith-abs-with-bitwise-or-zero.js (0 => 196726)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/arith-abs-with-bitwise-or-zero.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/arith-abs-with-bitwise-or-zero.js        2016-02-17 23:35:11 UTC (rev 196726)
</span><span class="lines">@@ -0,0 +1,54 @@
</span><ins>+function opaqueAbs(value)
+{
+    return Math.abs(value)|0;
+}
+noInline(opaqueAbs);
+
+for (let i = 0; i &lt; 1e4; ++i) {
+    var positiveResult = opaqueAbs(i);
+    if (positiveResult !== i)
+        throw &quot;Incorrect result at i = &quot; + i + &quot; result = &quot; + positiveResult;
+    var negativeResult = opaqueAbs(-i);
+    if (negativeResult !== i)
+        throw &quot;Incorrect result at -i = &quot; + -i + &quot; result = &quot; + negativeResult;
+}
+
+
+var intMax = 2147483647;
+var intMin = 2147483647;
+
+var intMaxResult = opaqueAbs(intMax);
+if (intMaxResult !== intMax)
+    throw &quot;Incorrect result at intMax result = &quot; + intMaxResult;
+var intMaxResult = opaqueAbs(intMin);
+if (intMaxResult !== intMin)
+    throw &quot;Incorrect result at intMax result = &quot; + intMaxResult;
+
+// Numbers around IntMax/IntMin. Numbers outside the bounds are doubles and opaqueAbs()
+// has to OSR Exit to handle them correctly.
+for (let i = intMax - 1e4; i &lt; intMax + 1e4; ++i) {
+    var positiveResult = opaqueAbs(i);
+    if (positiveResult !== (i|0))
+        throw &quot;Incorrect result at i = &quot; + i + &quot; result = &quot; + positiveResult;
+    var negativeResult = opaqueAbs(-i);
+    if (negativeResult !== (i|0))
+        throw &quot;Incorrect result at -i = &quot; + -i + &quot; result = &quot; + negativeResult;
+}
+
+// Edge cases and exits.
+if (opaqueAbs(NaN) !== 0)
+    throw &quot;opaqueAbs(NaN) failed.&quot;;
+if (opaqueAbs(Infinity) !== 0)
+    throw &quot;opaqueAbs(Infinity) failed.&quot;;
+if (opaqueAbs(-Infinity) !== 0)
+    throw &quot;opaqueAbs(-Infinity) failed.&quot;;
+if (opaqueAbs(null) !== 0)
+    throw &quot;opaqueAbs(null) failed.&quot;;
+if (opaqueAbs(undefined) !== 0)
+    throw &quot;opaqueAbs(undefined) failed.&quot;;
+if (opaqueAbs(true) !== 1)
+    throw &quot;opaqueAbs(true) failed.&quot;;
+if (opaqueAbs(false) !== 0)
+    throw &quot;opaqueAbs(false) failed.&quot;;
+if (opaqueAbs({foo:&quot;bar&quot;}) !== 0)
+    throw &quot;opaqueAbs({foo:'bar'}) failed.&quot;;
</ins></span></pre>
</div>
</div>

</body>
</html>