<!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>[161399] 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/161399">161399</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-01-06 20:52:48 -0800 (Mon, 06 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Make the different flavors of integer arithmetic more explicit, and don't rely on (possibly stale) results of the backwards propagator to decide integer arithmetic semantics
https://bugs.webkit.org/show_bug.cgi?id=125519

Reviewed by Geoffrey Garen.
        
Adds the Arith::Mode enum to arithmetic nodes, which makes it explicit what sorts of
checks and overflows the node should do. Previously this would be deduced from
backwards analysis results.
        
This also makes &quot;unchecked&quot; variants really mean that you want the int32 wrapped
result, so ArithIMul is now done in terms of ArithMul(Unchecked). That means that the
constant folder needs to compute exactly the result implied by ArithMode, instead of
just folding the double result.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGArithMode.cpp: Added.
(WTF::printInternal):
* dfg/DFGArithMode.h: Added.
(JSC::DFG::doesOverflow):
(JSC::DFG::shouldCheckOverflow):
(JSC::DFG::shouldCheckNegativeZero):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::pureCSE):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGNode.h:
(JSC::DFG::Node::Node):
(JSC::DFG::Node::hasArithMode):
(JSC::DFG::Node::arithMode):
(JSC::DFG::Node::setArithMode):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileUInt32ToNumber):
(JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
(JSC::DFG::SpeculativeJIT::compileAdd):
(JSC::DFG::SpeculativeJIT::compileArithSub):
(JSC::DFG::SpeculativeJIT::compileArithNegate):
(JSC::DFG::SpeculativeJIT::compileArithMul):
(JSC::DFG::SpeculativeJIT::compileArithDiv):
(JSC::DFG::SpeculativeJIT::compileArithMod):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileAddSub):
(JSC::FTL::LowerDFGToLLVM::compileArithMul):
(JSC::FTL::LowerDFGToLLVM::compileArithDivMod):
(JSC::FTL::LowerDFGToLLVM::compileArithNegate):
(JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreGNUmakefilelistam">trunk/Source/JavaScriptCore/GNUmakefile.list.am</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</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="#trunkSourceJavaScriptCoredfgDFGArithModecpp">trunk/Source/JavaScriptCore/dfg/DFGArithMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArithModeh">trunk/Source/JavaScriptCore/dfg/DFGArithMode.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -95,6 +95,7 @@
</span><span class="cx">     dfg/DFGAbstractHeap.cpp
</span><span class="cx">     dfg/DFGAbstractValue.cpp
</span><span class="cx">     dfg/DFGArgumentsSimplificationPhase.cpp
</span><ins>+    dfg/DFGArithMode.cpp
</ins><span class="cx">     dfg/DFGArrayMode.cpp
</span><span class="cx">     dfg/DFGAtTailAbstractState.cpp
</span><span class="cx">     dfg/DFGAvailability.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -1,3 +1,67 @@
</span><ins>+2014-01-06  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Make the different flavors of integer arithmetic more explicit, and don't rely on (possibly stale) results of the backwards propagator to decide integer arithmetic semantics
+        https://bugs.webkit.org/show_bug.cgi?id=125519
+
+        Reviewed by Geoffrey Garen.
+        
+        Adds the Arith::Mode enum to arithmetic nodes, which makes it explicit what sorts of
+        checks and overflows the node should do. Previously this would be deduced from
+        backwards analysis results.
+        
+        This also makes &quot;unchecked&quot; variants really mean that you want the int32 wrapped
+        result, so ArithIMul is now done in terms of ArithMul(Unchecked). That means that the
+        constant folder needs to compute exactly the result implied by ArithMode, instead of
+        just folding the double result.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGArithMode.cpp: Added.
+        (WTF::printInternal):
+        * dfg/DFGArithMode.h: Added.
+        (JSC::DFG::doesOverflow):
+        (JSC::DFG::shouldCheckOverflow):
+        (JSC::DFG::shouldCheckNegativeZero):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::pureCSE):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::Node):
+        (JSC::DFG::Node::hasArithMode):
+        (JSC::DFG::Node::arithMode):
+        (JSC::DFG::Node::setArithMode):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileUInt32ToNumber):
+        (JSC::DFG::SpeculativeJIT::compileDoubleAsInt32):
+        (JSC::DFG::SpeculativeJIT::compileAdd):
+        (JSC::DFG::SpeculativeJIT::compileArithSub):
+        (JSC::DFG::SpeculativeJIT::compileArithNegate):
+        (JSC::DFG::SpeculativeJIT::compileArithMul):
+        (JSC::DFG::SpeculativeJIT::compileArithDiv):
+        (JSC::DFG::SpeculativeJIT::compileArithMod):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileAddSub):
+        (JSC::FTL::LowerDFGToLLVM::compileArithMul):
+        (JSC::FTL::LowerDFGToLLVM::compileArithDivMod):
+        (JSC::FTL::LowerDFGToLLVM::compileArithNegate):
+        (JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
+
</ins><span class="cx"> 2014-01-06  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add write barriers to the LLInt
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreGNUmakefilelistam"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/GNUmakefile.list.am (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/GNUmakefile.list.am        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/GNUmakefile.list.am        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -211,6 +211,8 @@
</span><span class="cx">         Source/JavaScriptCore/dfg/DFGArgumentPosition.h \
</span><span class="cx">         Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp \
</span><span class="cx">         Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.h \
</span><ins>+        Source/JavaScriptCore/dfg/DFGArithMode.cpp \
+        Source/JavaScriptCore/dfg/DFGArithMode.h \
</ins><span class="cx">         Source/JavaScriptCore/dfg/DFGArrayMode.cpp \
</span><span class="cx">         Source/JavaScriptCore/dfg/DFGArrayMode.h \
</span><span class="cx">         Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -351,6 +351,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGAbstractHeap.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGAbstractValue.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGArgumentsSimplificationPhase.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGArithMode.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGArrayMode.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGAtTailAbstractState.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGAvailability.cpp&quot; /&gt;
</span><span class="lines">@@ -849,6 +850,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGArgumentPosition.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGArgumentsSimplificationPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGArrayifySlowPathGenerator.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGArithMode.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGArrayMode.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGAtTailAbstractState.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGAvailability.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -234,6 +234,8 @@
</span><span class="cx">                 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680CF14BBB3D100BFE272 /* LLIntData.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F4680D414BBD24900BFE272 /* HostCallReturnValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */; };
</span><span class="cx">                 0F4680D514BBD24B00BFE272 /* HostCallReturnValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F485321187750560083B687 /* DFGArithMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F48531F187750560083B687 /* DFGArithMode.cpp */; };
+                0F485322187750560083B687 /* DFGArithMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F485320187750560083B687 /* DFGArithMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F493AF816D0CAD10084508B /* SourceProvider.cpp */; };
</span><span class="cx">                 0F4B94DC17B9F07500DD03A4 /* TypedArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F4B94DB17B9F07500DD03A4 /* TypedArrayInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F5541B11613C1FB00CE3E25 /* SpecialPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */; };
</span><span class="lines">@@ -1578,6 +1580,8 @@
</span><span class="cx">                 0F4680CF14BBB3D100BFE272 /* LLIntData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntData.h; path = llint/LLIntData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HostCallReturnValue.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HostCallReturnValue.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F48531F187750560083B687 /* DFGArithMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArithMode.cpp; path = dfg/DFGArithMode.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F485320187750560083B687 /* DFGArithMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArithMode.h; path = dfg/DFGArithMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F493AF816D0CAD10084508B /* SourceProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProvider.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F4B94DB17B9F07500DD03A4 /* TypedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrayInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F5541AF1613C1FB00CE3E25 /* SpecialPointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpecialPointer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3855,8 +3859,6 @@
</span><span class="cx">                 86EC9DB31328DF44002B2AD7 /* dfg */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><del>-                                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */,
-                                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */,
</del><span class="cx">                                 A77A423617A0BBFD00A8DB81 /* DFGAbstractHeap.cpp */,
</span><span class="cx">                                 A77A423717A0BBFD00A8DB81 /* DFGAbstractHeap.h */,
</span><span class="cx">                                 A704D8FE17A0BAA8006BA554 /* DFGAbstractInterpreter.h */,
</span><span class="lines">@@ -3869,6 +3871,8 @@
</span><span class="cx">                                 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */,
</span><span class="cx">                                 0F16015A156198BF00C2587C /* DFGArgumentsSimplificationPhase.cpp */,
</span><span class="cx">                                 0F16015B156198BF00C2587C /* DFGArgumentsSimplificationPhase.h */,
</span><ins>+                                0F48531F187750560083B687 /* DFGArithMode.cpp */,
+                                0F485320187750560083B687 /* DFGArithMode.h */,
</ins><span class="cx">                                 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */,
</span><span class="cx">                                 0F63948115E48114006A597C /* DFGArrayMode.cpp */,
</span><span class="cx">                                 0F63948215E48114006A597C /* DFGArrayMode.h */,
</span><span class="lines">@@ -4043,6 +4047,8 @@
</span><span class="cx">                                 0FC20CB818556A3500C9E954 /* DFGSSALoweringPhase.h */,
</span><span class="cx">                                 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */,
</span><span class="cx">                                 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */,
</span><ins>+                                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */,
+                                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */,
</ins><span class="cx">                                 0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */,
</span><span class="cx">                                 0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */,
</span><span class="cx">                                 0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */,
</span><span class="lines">@@ -4799,6 +4805,7 @@
</span><span class="cx">                                 A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
</span><span class="cx">                                 0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
</span><span class="cx">                                 A7299D9E17D12837005F5FF9 /* JSSet.h in Headers */,
</span><ins>+                                0F485322187750560083B687 /* DFGArithMode.h in Headers */,
</ins><span class="cx">                                 BC18C45E0E16F5CD00B34460 /* JSStack.h in Headers */,
</span><span class="cx">                                 A7C1EAF017987AB600299DB2 /* JSStackInlines.h in Headers */,
</span><span class="cx">                                 BC18C4270E16F5CD00B34460 /* JSString.h in Headers */,
</span><span class="lines">@@ -5503,6 +5510,7 @@
</span><span class="cx">                                 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */,
</span><span class="cx">                                 A7A8AF3417ADB5F3005AB174 /* ArrayBuffer.cpp in Sources */,
</span><span class="cx">                                 A7A8AF3617ADB5F3005AB174 /* ArrayBufferView.cpp in Sources */,
</span><ins>+                                0F485321187750560083B687 /* DFGArithMode.cpp in Sources */,
</ins><span class="cx">                                 147F39BF107EC37600427A48 /* ArrayConstructor.cpp in Sources */,
</span><span class="cx">                                 A7BDAEC617F4EA1400F6140C /* ArrayIteratorConstructor.cpp in Sources */,
</span><span class="cx">                                 A7BDAEC817F4EA1400F6140C /* ArrayIteratorPrototype.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -202,11 +202,6 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case ZombieHint: {
-        RELEASE_ASSERT_NOT_REACHED();
-        break;
-    }
-            
</del><span class="cx">     case SetArgument:
</span><span class="cx">         // Assert that the state of arguments has been set.
</span><span class="cx">         ASSERT(!m_state.block()-&gt;valuesAtHead.operand(node-&gt;local()).isClear());
</span><span class="lines">@@ -254,18 +249,24 @@
</span><span class="cx">         
</span><span class="cx">     case UInt32ToNumber: {
</span><span class="cx">         JSValue child = forNode(node-&gt;child1()).value();
</span><del>-        if (child &amp;&amp; child.isNumber()) {
-            ASSERT(child.isInt32());
-            uint32_t value = child.asInt32();
-            setConstant(node, jsNumber(value));
</del><ins>+        if (doesOverflow(node-&gt;arithMode())) {
+            if (child &amp;&amp; child.isInt32()) {
+                uint32_t value = child.asInt32();
+                setConstant(node, jsNumber(value));
+                break;
+            }
+            forNode(node).setType(SpecDouble);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        if (!node-&gt;canSpeculateInt32())
-            forNode(node).setType(SpecDouble);
-        else {
-            forNode(node).setType(SpecInt32);
-            node-&gt;setCanExit(true);
</del><ins>+        if (child &amp;&amp; child.isInt32()) {
+            int32_t value = child.asInt32();
+            if (value &gt;= 0) {
+                setConstant(node, jsNumber(value));
+                break;
+            }
</ins><span class="cx">         }
</span><ins>+        forNode(node).setType(SpecInt32);
+        node-&gt;setCanExit(true);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">             
</span><span class="lines">@@ -341,12 +342,6 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case ValueAdd: {
</span><del>-        JSValue left = forNode(node-&gt;child1()).value();
-        JSValue right = forNode(node-&gt;child2()).value();
-        if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
-            setConstant(node, JSValue(left.asNumber() + right.asNumber()));
-            break;
-        }
</del><span class="cx">         ASSERT(node-&gt;binaryUseKind() == UntypedUse);
</span><span class="cx">         clobberWorld(node-&gt;codeOrigin, clobberLimit);
</span><span class="cx">         forNode(node).setType(SpecString | SpecBytecodeNumber);
</span><span class="lines">@@ -356,23 +351,41 @@
</span><span class="cx">     case ArithAdd: {
</span><span class="cx">         JSValue left = forNode(node-&gt;child1()).value();
</span><span class="cx">         JSValue right = forNode(node-&gt;child2()).value();
</span><del>-        if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
-            setConstant(node, JSValue(left.asNumber() + right.asNumber()));
-            break;
-        }
</del><span class="cx">         switch (node-&gt;binaryUseKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                if (!shouldCheckOverflow(node-&gt;arithMode())) {
+                    setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
+                    break;
+                }
+                JSValue result = jsNumber(left.asNumber() + right.asNumber());
+                if (result.isInt32()) {
+                    setConstant(node, result);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><del>-            if (!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</del><ins>+            if (shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case MachineIntUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isMachineInt() &amp;&amp; right.isMachineInt()) {
+                JSValue result = jsNumber(left.asMachineInt() + right.asMachineInt());
+                if (result.isMachineInt()) {
+                    setConstant(node, result);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt52);
</span><span class="cx">             if (!forNode(node-&gt;child1()).isType(SpecInt32)
</span><span class="cx">                 || !forNode(node-&gt;child2()).isType(SpecInt32))
</span><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                setConstant(node, jsNumber(left.asNumber() + right.asNumber()));
+                break;
+            }
</ins><span class="cx">             if (isFullRealNumberSpeculation(forNode(node-&gt;child1()).m_type)
</span><span class="cx">                 &amp;&amp; isFullRealNumberSpeculation(forNode(node-&gt;child2()).m_type))
</span><span class="cx">                 forNode(node).setType(SpecDoubleReal);
</span><span class="lines">@@ -394,23 +407,41 @@
</span><span class="cx">     case ArithSub: {
</span><span class="cx">         JSValue left = forNode(node-&gt;child1()).value();
</span><span class="cx">         JSValue right = forNode(node-&gt;child2()).value();
</span><del>-        if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
-            setConstant(node, JSValue(left.asNumber() - right.asNumber()));
-            break;
-        }
</del><span class="cx">         switch (node-&gt;binaryUseKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                if (!shouldCheckOverflow(node-&gt;arithMode())) {
+                    setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
+                    break;
+                }
+                JSValue result = jsNumber(left.asNumber() - right.asNumber());
+                if (result.isInt32()) {
+                    setConstant(node, result);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><del>-            if (!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</del><ins>+            if (shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case MachineIntUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isMachineInt() &amp;&amp; right.isMachineInt()) {
+                JSValue result = jsNumber(left.asMachineInt() - right.asMachineInt());
+                if (result.isMachineInt() || !shouldCheckOverflow(node-&gt;arithMode())) {
+                    setConstant(node, result);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt52);
</span><span class="cx">             if (!forNode(node-&gt;child1()).isType(SpecInt32)
</span><span class="cx">                 || !forNode(node-&gt;child2()).isType(SpecInt32))
</span><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                setConstant(node, jsNumber(left.asNumber() - right.asNumber()));
+                break;
+            }
</ins><span class="cx">             forNode(node).setType(SpecDouble);
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="lines">@@ -422,24 +453,52 @@
</span><span class="cx">         
</span><span class="cx">     case ArithNegate: {
</span><span class="cx">         JSValue child = forNode(node-&gt;child1()).value();
</span><del>-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, JSValue(-child.asNumber()));
-            break;
-        }
</del><span class="cx">         switch (node-&gt;child1().useKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (child &amp;&amp; child.isInt32()) {
+                if (!shouldCheckOverflow(node-&gt;arithMode())) {
+                    setConstant(node, jsNumber(-child.asInt32()));
+                    break;
+                }
+                double doubleResult;
+                if (shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult = -child.asNumber();
+                else
+                    doubleResult = 0 - child.asNumber();
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isInt32()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><del>-            if (!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</del><ins>+            if (shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case MachineIntUse:
</span><ins>+            if (child &amp;&amp; child.isMachineInt()) {
+                double doubleResult;
+                if (shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult = -child.asNumber();
+                else
+                    doubleResult = 0 - child.asNumber();
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isMachineInt()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt52);
</span><span class="cx">             if (m_state.forNode(node-&gt;child1()).couldBeType(SpecInt52))
</span><span class="cx">                 node-&gt;setCanExit(true);
</span><del>-            if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
</del><ins>+            if (shouldCheckNegativeZero(node-&gt;arithMode()))
</ins><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (child &amp;&amp; child.isNumber()) {
+                setConstant(node, jsNumber(-child.asNumber()));
+                break;
+            }
</ins><span class="cx">             forNode(node).setType(SpecDouble);
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="lines">@@ -452,22 +511,45 @@
</span><span class="cx">     case ArithMul: {
</span><span class="cx">         JSValue left = forNode(node-&gt;child1()).value();
</span><span class="cx">         JSValue right = forNode(node-&gt;child2()).value();
</span><del>-        if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
-            setConstant(node, JSValue(left.asNumber() * right.asNumber()));
-            break;
-        }
</del><span class="cx">         switch (node-&gt;binaryUseKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                if (!shouldCheckOverflow(node-&gt;arithMode())) {
+                    setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
+                    break;
+                }
+                double doubleResult = left.asNumber() * right.asNumber();
+                if (!shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult += 0; // Sanitizes zero.
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isInt32()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><del>-            if (!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())
-                || !bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
</del><ins>+            if (shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">                 node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case MachineIntUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isMachineInt() &amp;&amp; right.isMachineInt()) {
+                double doubleResult = left.asNumber() * right.asNumber();
+                if (!shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult += 0;
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isMachineInt()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt52);
</span><span class="cx">             node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                setConstant(node, jsNumber(left.asNumber() * right.asNumber()));
+                break;
+            }
</ins><span class="cx">             if (isFullRealNumberSpeculation(forNode(node-&gt;child1()).m_type)
</span><span class="cx">                 || isFullRealNumberSpeculation(forNode(node-&gt;child2()).m_type))
</span><span class="cx">                 forNode(node).setType(SpecDoubleReal);
</span><span class="lines">@@ -480,46 +562,122 @@
</span><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case ArithIMul: {
-        forNode(node).setType(SpecInt32);
</del><ins>+        
+    case ArithDiv: {
+        JSValue left = forNode(node-&gt;child1()).value();
+        JSValue right = forNode(node-&gt;child2()).value();
+        switch (node-&gt;binaryUseKind()) {
+        case Int32Use:
+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                double doubleResult = left.asNumber() / right.asNumber();
+                if (!shouldCheckOverflow(node-&gt;arithMode()))
+                    doubleResult = toInt32(doubleResult);
+                else if (!shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult += 0; // Sanitizes zero.
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isInt32()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
+            forNode(node).setType(SpecInt32);
+            node-&gt;setCanExit(true);
+            break;
+        case NumberUse:
+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                setConstant(node, jsNumber(left.asNumber() / right.asNumber()));
+                break;
+            }
+            forNode(node).setType(SpecDouble);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-        
-    case ArithDiv:
-    case ArithMin:
-    case ArithMax:
</del><ins>+
</ins><span class="cx">     case ArithMod: {
</span><span class="cx">         JSValue left = forNode(node-&gt;child1()).value();
</span><span class="cx">         JSValue right = forNode(node-&gt;child2()).value();
</span><del>-        if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
-            double a = left.asNumber();
-            double b = right.asNumber();
-            switch (node-&gt;op()) {
-            case ArithDiv:
-                setConstant(node, JSValue(a / b));
</del><ins>+        switch (node-&gt;binaryUseKind()) {
+        case Int32Use:
+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                double doubleResult = fmod(left.asNumber(), right.asNumber());
+                if (!shouldCheckOverflow(node-&gt;arithMode()))
+                    doubleResult = toInt32(doubleResult);
+                else if (!shouldCheckNegativeZero(node-&gt;arithMode()))
+                    doubleResult += 0; // Sanitizes zero.
+                JSValue valueResult = jsNumber(doubleResult);
+                if (valueResult.isInt32()) {
+                    setConstant(node, valueResult);
+                    break;
+                }
+            }
+            forNode(node).setType(SpecInt32);
+            node-&gt;setCanExit(true);
+            break;
+        case NumberUse:
+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                setConstant(node, jsNumber(fmod(left.asNumber(), right.asNumber())));
</ins><span class="cx">                 break;
</span><del>-            case ArithMin:
-                setConstant(node, JSValue(a &lt; b ? a : (b &lt;= a ? b : a + b)));
</del><ins>+            }
+            forNode(node).setType(SpecDouble);
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
+        }
+        break;
+    }
+
+    case ArithMin: {
+        JSValue left = forNode(node-&gt;child1()).value();
+        JSValue right = forNode(node-&gt;child2()).value();
+        switch (node-&gt;binaryUseKind()) {
+        case Int32Use:
+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
</ins><span class="cx">                 break;
</span><del>-            case ArithMax:
-                setConstant(node, JSValue(a &gt; b ? a : (b &gt;= a ? b : a + b)));
</del><ins>+            }
+            forNode(node).setType(SpecInt32);
+            node-&gt;setCanExit(true);
+            break;
+        case NumberUse:
+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                double a = left.asNumber();
+                double b = right.asNumber();
+                setConstant(node, jsNumber(a &lt; b ? a : (b &lt;= a ? b : a + b)));
</ins><span class="cx">                 break;
</span><del>-            case ArithMod:
-                setConstant(node, JSValue(fmod(a, b)));
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
</del><span class="cx">             }
</span><ins>+            forNode(node).setType(SpecDouble);
</ins><span class="cx">             break;
</span><ins>+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
</ins><span class="cx">         }
</span><ins>+        break;
+    }
+            
+    case ArithMax: {
+        JSValue left = forNode(node-&gt;child1()).value();
+        JSValue right = forNode(node-&gt;child2()).value();
</ins><span class="cx">         switch (node-&gt;binaryUseKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isInt32() &amp;&amp; right.isInt32()) {
+                setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
+                break;
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><span class="cx">             node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (left &amp;&amp; right &amp;&amp; left.isNumber() &amp;&amp; right.isNumber()) {
+                double a = left.asNumber();
+                double b = right.asNumber();
+                setConstant(node, jsNumber(a &gt; b ? a : (b &gt;= a ? b : a + b)));
+                break;
+            }
</ins><span class="cx">             forNode(node).setType(SpecDouble);
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="lines">@@ -531,16 +689,23 @@
</span><span class="cx">             
</span><span class="cx">     case ArithAbs: {
</span><span class="cx">         JSValue child = forNode(node-&gt;child1()).value();
</span><del>-        if (child &amp;&amp; child.isNumber()) {
-            setConstant(node, JSValue(fabs(child.asNumber())));
-            break;
-        }
</del><span class="cx">         switch (node-&gt;child1().useKind()) {
</span><span class="cx">         case Int32Use:
</span><ins>+            if (child &amp;&amp; child.isInt32()) {
+                JSValue result = jsNumber(fabs(child.asNumber()));
+                if (result.isInt32()) {
+                    setConstant(node, result);
+                    break;
+                }
+            }
</ins><span class="cx">             forNode(node).setType(SpecInt32);
</span><span class="cx">             node-&gt;setCanExit(true);
</span><span class="cx">             break;
</span><span class="cx">         case NumberUse:
</span><ins>+            if (child &amp;&amp; child.isNumber()) {
+                setConstant(node, jsNumber(child.asNumber()));
+                break;
+            }
</ins><span class="cx">             forNode(node).setType(SpecDouble);
</span><span class="cx">             break;
</span><span class="cx">         default:
</span><span class="lines">@@ -1621,11 +1786,10 @@
</span><span class="cx">         node-&gt;setCanExit(true);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><ins>+    case ZombieHint:
</ins><span class="cx">     case Unreachable:
</span><del>-        RELEASE_ASSERT_NOT_REACHED();
-        break;
-
</del><span class="cx">     case LastNodeType:
</span><ins>+    case ArithIMul:
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArithModecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGArithMode.cpp (0 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArithMode.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGArithMode.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -0,0 +1,60 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGArithMode.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &lt;wtf/PrintStream.h&gt;
+
+namespace WTF {
+
+void printInternal(PrintStream&amp; out, JSC::DFG::Arith::Mode mode)
+{
+    switch (mode) {
+    case JSC::DFG::Arith::NotSet:
+        out.print(&quot;NotSet&quot;);
+        return;
+    case JSC::DFG::Arith::Unchecked:
+        out.print(&quot;Unchecked&quot;);
+        return;
+    case JSC::DFG::Arith::CheckOverflow:
+        out.print(&quot;CheckOverflow&quot;);
+        return;
+    case JSC::DFG::Arith::CheckOverflowAndNegativeZero:
+        out.print(&quot;CheckOverflowAndNegativeZero&quot;);
+        return;
+    case JSC::DFG::Arith::DoOverflow:
+        out.print(&quot;DoOverflow&quot;);
+        return;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArithModeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGArithMode.h (0 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArithMode.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGArithMode.h        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -0,0 +1,109 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGArithMode_h
+#define DFGArithMode_h
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+// Arith::Mode describes the mode of an arithmetic operation that speculates integer.
+// Note that not all modes are valid for all operations.
+namespace Arith {
+enum Mode {
+    NotSet, // Arithmetic mode is either not relevant because we're using doubles anyway or we are at a phase in compilation where we don't know what we're doing, yet. Should never see this after FixupPhase except for nodes that take doubles as inputs already.
+    Unchecked, // Don't check anything and just do the direct hardware operation.
+    CheckOverflow, // Check for overflow but don't bother with negative zero.
+    CheckOverflowAndNegativeZero, // Check for both overflow and negative zero.
+    DoOverflow // Up-convert to the smallest type that soundly represents all possible results after input type speculation.
+};
+} // namespace Arith
+
+inline bool doesOverflow(Arith::Mode mode)
+{
+    switch (mode) {
+    case Arith::NotSet:
+        ASSERT_NOT_REACHED();
+    case Arith::Unchecked:
+    case Arith::CheckOverflow:
+    case Arith::CheckOverflowAndNegativeZero:
+        return false;
+    case Arith::DoOverflow:
+        return true;
+    }
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+// It's only valid to call this once you've determined that you don't need to *do*
+// overflow. For most nodes, that's implicit.
+inline bool shouldCheckOverflow(Arith::Mode mode)
+{
+    switch (mode) {
+    case Arith::NotSet:
+    case Arith::DoOverflow:
+        ASSERT_NOT_REACHED();
+        return true;
+    case Arith::Unchecked:
+        return false;
+    case Arith::CheckOverflow:
+    case Arith::CheckOverflowAndNegativeZero:
+        return true;
+    }
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+inline bool shouldCheckNegativeZero(Arith::Mode mode)
+{
+    switch (mode) {
+    case Arith::NotSet:
+    case Arith::DoOverflow:
+        ASSERT_NOT_REACHED();
+        return true;
+    case Arith::Unchecked:
+    case Arith::CheckOverflow:
+        return false;
+    case Arith::CheckOverflowAndNegativeZero:
+        return true;
+    }
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+class PrintStream;
+void printInternal(PrintStream&amp;, JSC::DFG::Arith::Mode);
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGArithMode_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -136,8 +136,10 @@
</span><span class="cx">             if (node-&gt;op() != otherNode-&gt;op())
</span><span class="cx">                 continue;
</span><span class="cx">             
</span><del>-            if (node-&gt;arithNodeFlags() != otherNode-&gt;arithNodeFlags())
-                continue;
</del><ins>+            if (node-&gt;hasArithMode()) {
+                if (node-&gt;arithMode() != otherNode-&gt;arithMode())
+                    continue;
+            }
</ins><span class="cx">             
</span><span class="cx">             Edge otherChild = otherNode-&gt;child1();
</span><span class="cx">             if (!otherChild)
</span><span class="lines">@@ -1082,7 +1084,6 @@
</span><span class="cx">         case ArithSub:
</span><span class="cx">         case ArithNegate:
</span><span class="cx">         case ArithMul:
</span><del>-        case ArithIMul:
</del><span class="cx">         case ArithMod:
</span><span class="cx">         case ArithDiv:
</span><span class="cx">         case ArithAbs:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -355,6 +355,21 @@
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="cx">             m_interpreter.execute(indexInBlock);
</span><ins>+            if (!m_state.isValid()) {
+                // If we invalidated then we shouldn't attempt to constant-fold. Here's an
+                // example:
+                //
+                //     c: JSConstant(4.2)
+                //     x: ValueToInt32(Check:Int32:@const)
+                //
+                // It would be correct for an analysis to assume that execution cannot
+                // proceed past @x. Therefore, constant-folding @x could be rather bad. But,
+                // the CFA may report that it found a constant even though it also reported
+                // that everything has been invalidated. This will only happen in a couple of
+                // the constant folding cases; most of them are also separately defensive
+                // about such things.
+                break;
+            }
</ins><span class="cx">             if (!node-&gt;shouldGenerate() || m_state.didClobber() || node-&gt;hasConstant())
</span><span class="cx">                 continue;
</span><span class="cx">             JSValue value = m_state.forNode(node).value();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -103,10 +103,19 @@
</span><span class="cx">         case BitXor:
</span><span class="cx">         case BitRShift:
</span><span class="cx">         case BitLShift:
</span><del>-        case BitURShift:
</del><ins>+        case BitURShift: {
+            fixIntEdge(node-&gt;child1());
+            fixIntEdge(node-&gt;child2());
+            break;
+        }
+            
</ins><span class="cx">         case ArithIMul: {
</span><span class="cx">             fixIntEdge(node-&gt;child1());
</span><span class="cx">             fixIntEdge(node-&gt;child2());
</span><ins>+            node-&gt;setOp(ArithMul);
+            node-&gt;setArithMode(Arith::Unchecked);
+            node-&gt;child1().setUseKind(Int32Use);
+            node-&gt;child2().setUseKind(Int32Use);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -114,6 +123,10 @@
</span><span class="cx">             fixEdge&lt;KnownInt32Use&gt;(node-&gt;child1());
</span><span class="cx">             if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</span><span class="cx">                 node-&gt;convertToIdentity();
</span><ins>+            else if (nodeCanSpeculateInt32(node-&gt;arithNodeFlags()))
+                node-&gt;setArithMode(Arith::CheckOverflow);
+            else
+                node-&gt;setArithMode(Arith::DoOverflow);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -210,10 +223,20 @@
</span><span class="cx">         case ArithNegate: {
</span><span class="cx">             if (m_graph.negateShouldSpeculateInt32(node)) {
</span><span class="cx">                 fixEdge&lt;Int32Use&gt;(node-&gt;child1());
</span><ins>+                if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::Unchecked);
+                else if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::CheckOverflow);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (m_graph.negateShouldSpeculateMachineInt(node)) {
</span><span class="cx">                 fixEdge&lt;MachineIntUse&gt;(node-&gt;child1());
</span><ins>+                if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::CheckOverflow);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             fixEdge&lt;NumberUse&gt;(node-&gt;child1());
</span><span class="lines">@@ -224,11 +247,21 @@
</span><span class="cx">             if (m_graph.mulShouldSpeculateInt32(node)) {
</span><span class="cx">                 fixEdge&lt;Int32Use&gt;(node-&gt;child1());
</span><span class="cx">                 fixEdge&lt;Int32Use&gt;(node-&gt;child2());
</span><ins>+                if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::Unchecked);
+                else if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::CheckOverflow);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             if (m_graph.mulShouldSpeculateMachineInt(node)) {
</span><span class="cx">                 fixEdge&lt;MachineIntUse&gt;(node-&gt;child1());
</span><span class="cx">                 fixEdge&lt;MachineIntUse&gt;(node-&gt;child2());
</span><ins>+                if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::CheckOverflow);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             fixEdge&lt;NumberUse&gt;(node-&gt;child1());
</span><span class="lines">@@ -243,6 +276,12 @@
</span><span class="cx">                 if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
</span><span class="cx">                     fixEdge&lt;Int32Use&gt;(node-&gt;child1());
</span><span class="cx">                     fixEdge&lt;Int32Use&gt;(node-&gt;child2());
</span><ins>+                    if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                        node-&gt;setArithMode(Arith::Unchecked);
+                    else if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                        node-&gt;setArithMode(Arith::CheckOverflow);
+                    else
+                        node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 Edge child1 = node-&gt;child1();
</span><span class="lines">@@ -258,6 +297,10 @@
</span><span class="cx">                 
</span><span class="cx">                 node-&gt;setOp(DoubleAsInt32);
</span><span class="cx">                 node-&gt;children.initialize(Edge(newDivision, KnownNumberUse), Edge(), Edge());
</span><ins>+                if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
+                    node-&gt;setArithMode(Arith::CheckOverflow);
+                else
+                    node-&gt;setArithMode(Arith::CheckOverflowAndNegativeZero);
</ins><span class="cx">                 
</span><span class="cx">                 m_insertionSet.insertNode(m_indexInBlock + 1, SpecNone, Phantom, node-&gt;codeOrigin, child1, child2);
</span><span class="cx">                 break;
</span><span class="lines">@@ -1655,12 +1698,17 @@
</span><span class="cx">             truncateConstantsIfNecessary(node, mode);
</span><span class="cx">             fixEdge&lt;Int32Use&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;Int32Use&gt;(node-&gt;child2());
</span><ins>+            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                node-&gt;setArithMode(Arith::Unchecked);
+            else
+                node-&gt;setArithMode(Arith::CheckOverflow);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (m_graph.addShouldSpeculateMachineInt(node)) {
</span><span class="cx">             fixEdge&lt;MachineIntUse&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;MachineIntUse&gt;(node-&gt;child2());
</span><ins>+            node-&gt;setArithMode(Arith::CheckOverflow);
</ins><span class="cx">             return true;
</span><span class="cx">         }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -198,6 +198,8 @@
</span><span class="cx">         out.print(comma, SpeculationDump(node-&gt;prediction()));
</span><span class="cx">     if (node-&gt;hasArrayMode())
</span><span class="cx">         out.print(comma, node-&gt;arrayMode());
</span><ins>+    if (node-&gt;hasArithMode())
+        out.print(comma, node-&gt;arithMode());
</ins><span class="cx">     if (node-&gt;hasVarNumber())
</span><span class="cx">         out.print(comma, node-&gt;varNumber());
</span><span class="cx">     if (node-&gt;hasRegisterPointer())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGAbstractValue.h&quot;
</span><span class="cx"> #include &quot;DFGAdjacencyList.h&quot;
</span><ins>+#include &quot;DFGArithMode.h&quot;
</ins><span class="cx"> #include &quot;DFGArrayMode.h&quot;
</span><span class="cx"> #include &quot;DFGCommon.h&quot;
</span><span class="cx"> #include &quot;DFGLazyJSValue.h&quot;
</span><span class="lines">@@ -180,6 +181,8 @@
</span><span class="cx">         , m_virtualRegister(VirtualRegister())
</span><span class="cx">         , m_refCount(1)
</span><span class="cx">         , m_prediction(SpecNone)
</span><ins>+        , m_opInfo(0)
+        , m_opInfo2(0)
</ins><span class="cx">     {
</span><span class="cx">         misc.replacement = 0;
</span><span class="cx">         setOpAndDefaultFlags(op);
</span><span class="lines">@@ -195,6 +198,7 @@
</span><span class="cx">         , m_refCount(1)
</span><span class="cx">         , m_prediction(SpecNone)
</span><span class="cx">         , m_opInfo(imm.m_value)
</span><ins>+        , m_opInfo2(0)
</ins><span class="cx">     {
</span><span class="cx">         misc.replacement = 0;
</span><span class="cx">         setOpAndDefaultFlags(op);
</span><span class="lines">@@ -1118,6 +1122,34 @@
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    bool hasArithMode()
+    {
+        switch (op()) {
+        case ArithAdd:
+        case ArithSub:
+        case ArithNegate:
+        case ArithMul:
+        case ArithDiv:
+        case ArithMod:
+        case UInt32ToNumber:
+        case DoubleAsInt32:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    Arith::Mode arithMode()
+    {
+        ASSERT(hasArithMode());
+        return static_cast&lt;Arith::Mode&gt;(m_opInfo);
+    }
+    
+    void setArithMode(Arith::Mode mode)
+    {
+        m_opInfo = mode;
+    }
+    
</ins><span class="cx">     bool hasVirtualRegister()
</span><span class="cx">     {
</span><span class="cx">         return m_virtualRegister.isValid();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -2017,7 +2017,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileUInt32ToNumber(Node* node)
</span><span class="cx"> {
</span><del>-    if (!nodeCanSpeculateInt32(node-&gt;arithNodeFlags())) {
</del><ins>+    if (doesOverflow(node-&gt;arithMode())) {
</ins><span class="cx">         // We know that this sometimes produces doubles. So produce a double every
</span><span class="cx">         // time. This at least allows subsequent code to not have weird conditionals.
</span><span class="cx">             
</span><span class="lines">@@ -2037,7 +2037,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    RELEASE_ASSERT(!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()));
</del><ins>+    RELEASE_ASSERT(node-&gt;arithMode() == Arith::CheckOverflow);
</ins><span class="cx"> 
</span><span class="cx">     SpeculateInt32Operand op1(this, node-&gt;child1());
</span><span class="cx">     GPRTemporary result(this);
</span><span class="lines">@@ -2060,8 +2060,10 @@
</span><span class="cx">     GPRReg resultGPR = result.gpr();
</span><span class="cx"> 
</span><span class="cx">     JITCompiler::JumpList failureCases;
</span><del>-    bool negZeroCheck = !bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags());
-    m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR, negZeroCheck);
</del><ins>+    RELEASE_ASSERT(shouldCheckOverflow(node-&gt;arithMode()));
+    m_jit.branchConvertDoubleToInt32(
+        valueFPR, resultGPR, failureCases, scratchFPR,
+        shouldCheckNegativeZero(node-&gt;arithMode()));
</ins><span class="cx">     speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
</span><span class="cx"> 
</span><span class="cx">     int32Result(resultGPR, node);
</span><span class="lines">@@ -2585,12 +2587,14 @@
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;binaryUseKind()) {
</span><span class="cx">     case Int32Use: {
</span><ins>+        ASSERT(!shouldCheckNegativeZero(node-&gt;arithMode()));
+        
</ins><span class="cx">         if (isNumberConstant(node-&gt;child1().node())) {
</span><span class="cx">             int32_t imm1 = valueOfInt32Constant(node-&gt;child1().node());
</span><span class="cx">             SpeculateInt32Operand op2(this, node-&gt;child2());
</span><span class="cx">             GPRTemporary result(this);
</span><span class="cx"> 
</span><del>-            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+            if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">                 m_jit.move(op2.gpr(), result.gpr());
</span><span class="cx">                 m_jit.add32(Imm32(imm1), result.gpr());
</span><span class="cx">             } else
</span><span class="lines">@@ -2605,7 +2609,7 @@
</span><span class="cx">             int32_t imm2 = valueOfInt32Constant(node-&gt;child2().node());
</span><span class="cx">             GPRTemporary result(this);
</span><span class="cx">                 
</span><del>-            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+            if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">                 m_jit.move(op1.gpr(), result.gpr());
</span><span class="cx">                 m_jit.add32(Imm32(imm2), result.gpr());
</span><span class="cx">             } else
</span><span class="lines">@@ -2623,7 +2627,7 @@
</span><span class="cx">         GPRReg gpr2 = op2.gpr();
</span><span class="cx">         GPRReg gprResult = result.gpr();
</span><span class="cx"> 
</span><del>-        if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+        if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             if (gpr1 == gprResult)
</span><span class="cx">                 m_jit.add32(gpr2, gprResult);
</span><span class="cx">             else {
</span><span class="lines">@@ -2647,6 +2651,9 @@
</span><span class="cx">         
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     case MachineIntUse: {
</span><ins>+        ASSERT(shouldCheckOverflow(node-&gt;arithMode()));
+        ASSERT(!shouldCheckNegativeZero(node-&gt;arithMode()));
+
</ins><span class="cx">         // Will we need an overflow check? If we can prove that neither input can be
</span><span class="cx">         // Int52 then the overflow check will not be necessary.
</span><span class="cx">         if (!m_state.forNode(node-&gt;child1()).couldBeType(SpecInt52)
</span><span class="lines">@@ -2760,12 +2767,14 @@
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;binaryUseKind()) {
</span><span class="cx">     case Int32Use: {
</span><ins>+        ASSERT(!shouldCheckNegativeZero(node-&gt;arithMode()));
+        
</ins><span class="cx">         if (isNumberConstant(node-&gt;child2().node())) {
</span><span class="cx">             SpeculateInt32Operand op1(this, node-&gt;child1());
</span><span class="cx">             int32_t imm2 = valueOfInt32Constant(node-&gt;child2().node());
</span><span class="cx">             GPRTemporary result(this);
</span><span class="cx"> 
</span><del>-            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+            if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">                 m_jit.move(op1.gpr(), result.gpr());
</span><span class="cx">                 m_jit.sub32(Imm32(imm2), result.gpr());
</span><span class="cx">             } else {
</span><span class="lines">@@ -2783,7 +2792,7 @@
</span><span class="cx">             GPRTemporary result(this);
</span><span class="cx">                 
</span><span class="cx">             m_jit.move(Imm32(imm1), result.gpr());
</span><del>-            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</del><ins>+            if (!shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">                 m_jit.sub32(op2.gpr(), result.gpr());
</span><span class="cx">             else
</span><span class="cx">                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
</span><span class="lines">@@ -2796,7 +2805,7 @@
</span><span class="cx">         SpeculateInt32Operand op2(this, node-&gt;child2());
</span><span class="cx">         GPRTemporary result(this);
</span><span class="cx"> 
</span><del>-        if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+        if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             m_jit.move(op1.gpr(), result.gpr());
</span><span class="cx">             m_jit.sub32(op2.gpr(), result.gpr());
</span><span class="cx">         } else
</span><span class="lines">@@ -2808,6 +2817,9 @@
</span><span class="cx">         
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     case MachineIntUse: {
</span><ins>+        ASSERT(shouldCheckOverflow(node-&gt;arithMode()));
+        ASSERT(!shouldCheckNegativeZero(node-&gt;arithMode()));
+
</ins><span class="cx">         // Will we need an overflow check? If we can prove that neither input can be
</span><span class="cx">         // Int52 then the overflow check will not be necessary.
</span><span class="cx">         if (!m_state.forNode(node-&gt;child1()).couldBeType(SpecInt52)
</span><span class="lines">@@ -2864,9 +2876,9 @@
</span><span class="cx">         // Note: there is no notion of being not used as a number, but someone
</span><span class="cx">         // caring about negative zero.
</span><span class="cx">         
</span><del>-        if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
</del><ins>+        if (!shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">             m_jit.neg32(result.gpr());
</span><del>-        else if (bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags()))
</del><ins>+        else if (!shouldCheckNegativeZero(node-&gt;arithMode()))
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
</span><span class="cx">         else {
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, result.gpr(), TrustedImm32(0x7fffffff)));
</span><span class="lines">@@ -2879,6 +2891,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     case MachineIntUse: {
</span><ins>+        ASSERT(shouldCheckOverflow(node-&gt;arithMode()));
+        
</ins><span class="cx">         if (!m_state.forNode(node-&gt;child1()).couldBeType(SpecInt52)) {
</span><span class="cx">             SpeculateWhicheverInt52Operand op1(this, node-&gt;child1());
</span><span class="cx">             GPRTemporary result(this);
</span><span class="lines">@@ -2886,7 +2900,7 @@
</span><span class="cx">             GPRReg resultGPR = result.gpr();
</span><span class="cx">             m_jit.move(op1GPR, resultGPR);
</span><span class="cx">             m_jit.neg64(resultGPR);
</span><del>-            if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+            if (!shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">                 speculationCheck(
</span><span class="cx">                     NegativeZero, JSValueRegs(), 0,
</span><span class="cx">                     m_jit.branchTest64(MacroAssembler::Zero, resultGPR));
</span><span class="lines">@@ -2903,7 +2917,7 @@
</span><span class="cx">         speculationCheck(
</span><span class="cx">             Int52Overflow, JSValueRegs(), 0,
</span><span class="cx">             m_jit.branchNeg64(MacroAssembler::Overflow, resultGPR));
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (!shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             speculationCheck(
</span><span class="cx">                 NegativeZero, JSValueRegs(), 0,
</span><span class="cx">                 m_jit.branchTest64(MacroAssembler::Zero, resultGPR));
</span><span class="lines">@@ -2928,21 +2942,6 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> }
</span><del>-void SpeculativeJIT::compileArithIMul(Node* node)
-{
-    SpeculateInt32Operand op1(this, node-&gt;child1());
-    SpeculateInt32Operand op2(this, node-&gt;child2());
-    GPRTemporary result(this);
-
-    GPRReg reg1 = op1.gpr();
-    GPRReg reg2 = op2.gpr();
-
-    m_jit.move(reg1, result.gpr());
-    m_jit.mul32(reg2, result.gpr());
-    int32Result(result.gpr(), node);
-    return;
-}
-
</del><span class="cx"> void SpeculativeJIT::compileArithMul(Node* node)
</span><span class="cx"> {
</span><span class="cx">     switch (node-&gt;binaryUseKind()) {
</span><span class="lines">@@ -2957,7 +2956,7 @@
</span><span class="cx">         // We can perform truncated multiplications if we get to this point, because if the
</span><span class="cx">         // fixup phase could not prove that it would be safe, it would have turned us into
</span><span class="cx">         // a double multiplication.
</span><del>-        if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags())) {
</del><ins>+        if (!shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             m_jit.move(reg1, result.gpr());
</span><span class="cx">             m_jit.mul32(reg2, result.gpr());
</span><span class="cx">         } else {
</span><span class="lines">@@ -2967,7 +2966,7 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         // Check for negative zero, if the users of this node care about such things.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
</span><span class="cx">             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
</span><span class="cx">             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
</span><span class="lines">@@ -2980,6 +2979,8 @@
</span><span class="cx">     
</span><span class="cx"> #if USE(JSVALUE64)   
</span><span class="cx">     case MachineIntUse: {
</span><ins>+        ASSERT(shouldCheckOverflow(node-&gt;arithMode()));
+        
</ins><span class="cx">         // This is super clever. We want to do an int52 multiplication and check the
</span><span class="cx">         // int52 overflow bit. There is no direct hardware support for this, but we do
</span><span class="cx">         // have the ability to do an int64 multiplication and check the int64 overflow
</span><span class="lines">@@ -3017,7 +3018,7 @@
</span><span class="cx">             Int52Overflow, JSValueRegs(), 0,
</span><span class="cx">             m_jit.branchMul64(MacroAssembler::Overflow, op2GPR, resultGPR));
</span><span class="cx">         
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             MacroAssembler::Jump resultNonZero = m_jit.branchTest64(
</span><span class="cx">                 MacroAssembler::NonZero, resultGPR);
</span><span class="cx">             speculationCheck(
</span><span class="lines">@@ -3087,7 +3088,7 @@
</span><span class="cx">         JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
</span><span class="cx">     
</span><span class="cx">         JITCompiler::JumpList done;
</span><del>-        if (bytecodeUsesAsNumber(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
</span><span class="cx">         } else {
</span><span class="lines">@@ -3115,7 +3116,7 @@
</span><span class="cx">     
</span><span class="cx">         // If the user cares about negative zero, then speculate that we're not about
</span><span class="cx">         // to produce negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
</span><span class="cx">             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
</span><span class="cx">             numeratorNonZero.link(&amp;m_jit);
</span><span class="lines">@@ -3135,7 +3136,7 @@
</span><span class="cx"> 
</span><span class="cx">         // Check that there was no remainder. If there had been, then we'd be obligated to
</span><span class="cx">         // produce a double result instead.
</span><del>-        if (bytecodeUsesAsNumber(node-&gt;arithNodeFlags()))
</del><ins>+        if (shouldCheckOverflow(node-&gt;arithMode()))
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
</span><span class="cx">         
</span><span class="cx">         done.link(&amp;m_jit);
</span><span class="lines">@@ -3150,7 +3151,7 @@
</span><span class="cx"> 
</span><span class="cx">         // If the user cares about negative zero, then speculate that we're not about
</span><span class="cx">         // to produce negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
</span><span class="cx">             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
</span><span class="cx">             numeratorNonZero.link(&amp;m_jit);
</span><span class="lines">@@ -3160,7 +3161,7 @@
</span><span class="cx"> 
</span><span class="cx">         // Check that there was no remainder. If there had been, then we'd be obligated to
</span><span class="cx">         // produce a double result instead.
</span><del>-        if (bytecodeUsesAsNumber(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotient.gpr(), op2GPR, multiplyAnswer.gpr()));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::NotEqual, multiplyAnswer.gpr(), op1GPR));
</span><span class="cx">         }
</span><span class="lines">@@ -3176,7 +3177,7 @@
</span><span class="cx"> 
</span><span class="cx">         // If the user cares about negative zero, then speculate that we're not about
</span><span class="cx">         // to produce negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
</span><span class="cx">             speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
</span><span class="cx">             numeratorNonZero.link(&amp;m_jit);
</span><span class="lines">@@ -3186,7 +3187,7 @@
</span><span class="cx"> 
</span><span class="cx">         // Check that there was no remainder. If there had been, then we'd be obligated to
</span><span class="cx">         // produce a double result instead.
</span><del>-        if (bytecodeUsesAsNumber(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotient.gpr(), op2GPR, multiplyAnswer.gpr()));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::NotEqual, multiplyAnswer.gpr(), op1GPR));
</span><span class="cx">         }
</span><span class="lines">@@ -3274,7 +3275,7 @@
</span><span class="cx">                 m_jit.neg32(resultGPR);
</span><span class="cx">                 m_jit.add32(dividendGPR, resultGPR);
</span><span class="cx">                 
</span><del>-                if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+                if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">                     // Check that we're not about to create negative zero.
</span><span class="cx">                     JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
</span><span class="cx">                     speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, resultGPR));
</span><span class="lines">@@ -3311,7 +3312,7 @@
</span><span class="cx">                 m_jit.move(TrustedImm32(divisor), scratchGPR);
</span><span class="cx">                 m_jit.assembler().cdq();
</span><span class="cx">                 m_jit.assembler().idivl_r(scratchGPR);
</span><del>-                if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+                if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">                     JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
</span><span class="cx">                     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
</span><span class="cx">                     numeratorPositive.link(&amp;m_jit);
</span><span class="lines">@@ -3368,7 +3369,7 @@
</span><span class="cx">         
</span><span class="cx">         // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
</span><span class="cx">         // separate case for that. But it probably doesn't matter so much.
</span><del>-        if (bytecodeUsesAsNumber(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckOverflow(node-&gt;arithMode())) {
</ins><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
</span><span class="cx">         } else {
</span><span class="lines">@@ -3407,7 +3408,7 @@
</span><span class="cx">             unlock(op2TempGPR);
</span><span class="cx"> 
</span><span class="cx">         // Check that we're not about to create negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
</span><span class="cx">             numeratorPositive.link(&amp;m_jit);
</span><span class="lines">@@ -3429,12 +3430,15 @@
</span><span class="cx">         GPRReg multiplyAnswerGPR = multiplyAnswer.gpr();
</span><span class="cx"> 
</span><span class="cx">         m_jit.assembler().sdiv(quotientThenRemainderGPR, dividendGPR, divisorGPR);
</span><ins>+        // FIXME: It seems like there are cases where we don't need this? What if we have
+        // arithMode() == Arith::Unchecked?
+        // https://bugs.webkit.org/show_bug.cgi?id=126444
</ins><span class="cx">         speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotientThenRemainderGPR, divisorGPR, multiplyAnswerGPR));
</span><span class="cx">         m_jit.assembler().sub(quotientThenRemainderGPR, dividendGPR, multiplyAnswerGPR);
</span><span class="cx"> 
</span><span class="cx">         // If the user cares about negative zero, then speculate that we're not about
</span><span class="cx">         // to produce negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             // Check that we're not about to create negative zero.
</span><span class="cx">             JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
</span><span class="lines">@@ -3452,12 +3456,15 @@
</span><span class="cx">         GPRReg multiplyAnswerGPR = multiplyAnswer.gpr();
</span><span class="cx"> 
</span><span class="cx">         m_jit.assembler().sdiv&lt;32&gt;(quotientThenRemainderGPR, dividendGPR, divisorGPR);
</span><ins>+        // FIXME: It seems like there are cases where we don't need this? What if we have
+        // arithMode() == Arith::Unchecked?
+        // https://bugs.webkit.org/show_bug.cgi?id=126444
</ins><span class="cx">         speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotientThenRemainderGPR, divisorGPR, multiplyAnswerGPR));
</span><span class="cx">         m_jit.assembler().sub&lt;32&gt;(quotientThenRemainderGPR, dividendGPR, multiplyAnswerGPR);
</span><span class="cx"> 
</span><span class="cx">         // If the user cares about negative zero, then speculate that we're not about
</span><span class="cx">         // to produce negative zero.
</span><del>-        if (!bytecodeCanIgnoreNegativeZero(node-&gt;arithNodeFlags())) {
</del><ins>+        if (shouldCheckNegativeZero(node-&gt;arithMode())) {
</ins><span class="cx">             // Check that we're not about to create negative zero.
</span><span class="cx">             JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
</span><span class="cx">             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -2052,7 +2052,6 @@
</span><span class="cx">     void compileArithSub(Node*);
</span><span class="cx">     void compileArithNegate(Node*);
</span><span class="cx">     void compileArithMul(Node*);
</span><del>-    void compileArithIMul(Node*);
</del><span class="cx">     void compileArithDiv(Node*);
</span><span class="cx">     void compileArithMod(Node*);
</span><span class="cx">     void compileConstantStoragePointer(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -2092,10 +2092,6 @@
</span><span class="cx">         compileArithMul(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><del>-    case ArithIMul:
-        compileArithIMul(node);
-        break;
-
</del><span class="cx">     case ArithDiv: {
</span><span class="cx">         compileArithDiv(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -4702,6 +4698,7 @@
</span><span class="cx">     case Int52ToDouble:
</span><span class="cx">     case Int52ToValue:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case ArithIMul:
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -2423,10 +2423,6 @@
</span><span class="cx">         compileArithMul(node);
</span><span class="cx">         break;
</span><span class="cx"> 
</span><del>-    case ArithIMul:
-        compileArithIMul(node);
-        break;
-
</del><span class="cx">     case ArithDiv: {
</span><span class="cx">         compileArithDiv(node);
</span><span class="cx">         break;
</span><span class="lines">@@ -5002,6 +4998,7 @@
</span><span class="cx">     case GetArgument:
</span><span class="cx">     case ExtractOSREntryLocal:
</span><span class="cx">     case CheckInBounds:
</span><ins>+    case ArithIMul:
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</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 (161398 => 161399)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-07 04:48:18 UTC (rev 161398)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-07 04:52:48 UTC (rev 161399)
</span><span class="lines">@@ -824,7 +824,7 @@
</span><span class="cx">             LValue right = lowInt32(m_node-&gt;child2());
</span><span class="cx">             LValue result = isSub ? m_out.sub(left, right) : m_out.add(left, right);
</span><span class="cx"> 
</span><del>-            if (bytecodeCanTruncateInteger(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (!shouldCheckOverflow(m_node-&gt;arithMode())) {
</ins><span class="cx">                 setInt32(result);
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -878,12 +878,12 @@
</span><span class="cx">             LValue right = lowInt32(m_node-&gt;child2());
</span><span class="cx">             LValue result = m_out.mul(left, right);
</span><span class="cx"> 
</span><del>-            if (!bytecodeCanTruncateInteger(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckOverflow(m_node-&gt;arithMode())) {
</ins><span class="cx">                 LValue overflowResult = m_out.mulWithOverflow32(left, right);
</span><span class="cx">                 speculate(Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            if (!bytecodeCanIgnoreNegativeZero(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckNegativeZero(m_node-&gt;arithMode())) {
</ins><span class="cx">                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, (&quot;ArithMul slow case&quot;));
</span><span class="cx">                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArithMul continuation&quot;));
</span><span class="cx">                 
</span><span class="lines">@@ -910,7 +910,7 @@
</span><span class="cx">             LValue overflowResult = m_out.mulWithOverflow64(left, right);
</span><span class="cx">             speculate(Int52Overflow, noValue(), 0, m_out.extractValue(overflowResult, 1));
</span><span class="cx"> 
</span><del>-            if (!bytecodeCanIgnoreNegativeZero(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckNegativeZero(m_node-&gt;arithMode())) {
</ins><span class="cx">                 LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, (&quot;ArithMul slow case&quot;));
</span><span class="cx">                 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArithMul continuation&quot;));
</span><span class="cx">                 
</span><span class="lines">@@ -960,7 +960,7 @@
</span><span class="cx">             
</span><span class="cx">             LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
</span><span class="cx">             
</span><del>-            if (bytecodeUsesAsNumber(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckOverflow(m_node-&gt;arithMode())) {
</ins><span class="cx">                 LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
</span><span class="cx">                 speculate(Overflow, noValue(), 0, cond);
</span><span class="cx">                 m_out.jump(continuation);
</span><span class="lines">@@ -990,7 +990,7 @@
</span><span class="cx">             
</span><span class="cx">             m_out.appendTo(continuation, done);
</span><span class="cx">             
</span><del>-            if (!bytecodeCanIgnoreNegativeZero(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckNegativeZero(m_node-&gt;arithMode())) {
</ins><span class="cx">                 LBasicBlock zeroNumerator = FTL_NEW_BLOCK(m_out, (&quot;ArithDivMod zero numerator&quot;));
</span><span class="cx">                 LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, (&quot;ArithDivMod numerator continuation&quot;));
</span><span class="cx">                 
</span><span class="lines">@@ -1010,7 +1010,7 @@
</span><span class="cx">                 ? m_out.div(numerator, denominator)
</span><span class="cx">                 : m_out.rem(numerator, denominator);
</span><span class="cx">             
</span><del>-            if (bytecodeUsesAsNumber(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckOverflow(m_node-&gt;arithMode())) {
</ins><span class="cx">                 speculate(
</span><span class="cx">                     Overflow, noValue(), 0,
</span><span class="cx">                     m_out.notEqual(m_out.mul(divModResult, denominator), numerator));
</span><span class="lines">@@ -1122,8 +1122,8 @@
</span><span class="cx">             LValue value = lowInt32(m_node-&gt;child1());
</span><span class="cx">             
</span><span class="cx">             LValue result = m_out.neg(value);
</span><del>-            if (!bytecodeCanTruncateInteger(m_node-&gt;arithNodeFlags())) {
-                if (bytecodeCanIgnoreNegativeZero(m_node-&gt;arithNodeFlags())) {
</del><ins>+            if (shouldCheckOverflow(m_node-&gt;arithMode())) {
+                if (!shouldCheckNegativeZero(m_node-&gt;arithMode())) {
</ins><span class="cx">                     // We don't have a negate-with-overflow intrinsic. Hopefully this
</span><span class="cx">                     // does the trick, though.
</span><span class="cx">                     LValue overflowResult = m_out.subWithOverflow32(m_out.int32Zero, value);
</span><span class="lines">@@ -1142,7 +1142,7 @@
</span><span class="cx">                 Int52Kind kind;
</span><span class="cx">                 LValue value = lowWhicheverInt52(m_node-&gt;child1(), kind);
</span><span class="cx">                 LValue result = m_out.neg(value);
</span><del>-                if (!bytecodeCanIgnoreNegativeZero(m_node-&gt;arithNodeFlags()))
</del><ins>+                if (shouldCheckNegativeZero(m_node-&gt;arithMode()))
</ins><span class="cx">                     speculate(NegativeZero, noValue(), 0, m_out.isZero64(result));
</span><span class="cx">                 setInt52(result, kind);
</span><span class="cx">                 break;
</span><span class="lines">@@ -1208,7 +1208,7 @@
</span><span class="cx">     {
</span><span class="cx">         LValue value = lowInt32(m_node-&gt;child1());
</span><span class="cx"> 
</span><del>-        if (!nodeCanSpeculateInt32(m_node-&gt;arithNodeFlags())) {
</del><ins>+        if (doesOverflow(m_node-&gt;arithMode())) {
</ins><span class="cx">             setDouble(m_out.unsignedToDouble(value));
</span><span class="cx">             return;
</span><span class="cx">         }
</span></span></pre>
</div>
</div>

</body>
</html>