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

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

<h3>Log Message</h3>
<pre>FTL should use cvttsd2si directly for double-to-int32 conversions
https://bugs.webkit.org/show_bug.cgi?id=125275

Source/JavaScriptCore: 

Reviewed by Michael Saboff.
        
Wow. This was an ordeal. Using cvttsd2si was actually easy, but I learned, and
sometimes even fixed, some interesting things:
        
- The llvm.x86.sse2.cvttsd2si intrinsic can actually result in LLVM emitting a
  vcvttsd2si. I guess the intrinsic doesn't actually imply the instruction.
        
- That whole thing about branchTruncateDoubleToUint32? Yeah we don't need that. It's
  better to use branchTruncateDoubleToInt32 instead. It has the right semantics for
  all of its callers (err, its one-and-only caller), and it's more likely to take
  fast path. This patch kills branchTruncateDoubleToUint32.
        
- &quot;a[i] = v; v = a[i]&quot;. Does this change v? OK, assume that 'a[i]' is a pure-ish
  operation - like an array access with 'i' being an integer index and we're not
  having a bad time. Now does this change v? CSE assumes that it doesn't. That's
  wrong. If 'a' is a typed array - the most sensible and pure kind of array - then
  this can be a truncating cast. For example 'v' could be a double and 'a' could be
  an integer array.
        
- &quot;v1 = a[i]; v2 = a[i]&quot;. Is v1 === v2 assuming that 'a[i]' is pure-ish? The answer
  is no. You could have a different arrayMode in each access. I know this sounds
  weird, but with concurrent JIT that might happen.
        
This patch adds tests for all of this stuff, except for the first issue (it's weird
but probably doesn't matter) and the last issue (it's too much of a freakshow).

* assembler/MacroAssemblerARM64.h:
* assembler/MacroAssemblerARMv7.h:
* assembler/MacroAssemblerX86Common.h:
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::getByValLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
* ftl/FTLAbbreviations.h:
(JSC::FTL::vectorType):
(JSC::FTL::getUndef):
(JSC::FTL::buildInsertElement):
* ftl/FTLIntrinsicRepository.h:
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::doubleToInt32):
(JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
(JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32):
* ftl/FTLOutput.h:
(JSC::FTL::Output::insertElement):
(JSC::FTL::Output::hasSensibleDoubleToInt):
(JSC::FTL::Output::sensibleDoubleToInt):

LayoutTests: 

Reviewed by Michael Saboff.

* js/regress/double-to-int32-typed-array-expected.txt: Added.
* js/regress/double-to-int32-typed-array-no-inline-expected.txt: Added.
* js/regress/double-to-int32-typed-array-no-inline.html: Added.
* js/regress/double-to-int32-typed-array.html: Added.
* js/regress/double-to-uint32-typed-array-expected.txt: Added.
* js/regress/double-to-uint32-typed-array-no-inline-expected.txt: Added.
* js/regress/double-to-uint32-typed-array-no-inline.html: Added.
* js/regress/double-to-uint32-typed-array.html: Added.
* js/regress/script-tests/double-to-int32-typed-array-no-inline.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-int32-typed-array.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-uint32-typed-array-no-inline.js: Added.
(foo):
(test):
* js/regress/script-tests/double-to-uint32-typed-array.js: Added.
(foo):
(test):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARMv7h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbbreviationsh">trunk/Source/JavaScriptCore/ftl/FTLAbbreviations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressdoubletoint32typedarrayexpectedtxt">trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletoint32typedarraynoinlineexpectedtxt">trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletoint32typedarraynoinlinehtml">trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletoint32typedarrayhtml">trunk/LayoutTests/js/regress/double-to-int32-typed-array.html</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletouint32typedarrayexpectedtxt">trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletouint32typedarraynoinlineexpectedtxt">trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletouint32typedarraynoinlinehtml">trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html</a></li>
<li><a href="#trunkLayoutTestsjsregressdoubletouint32typedarrayhtml">trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdoubletoint32typedarraynoinlinejs">trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdoubletoint32typedarrayjs">trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdoubletouint32typedarraynoinlinejs">trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdoubletouint32typedarrayjs">trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/LayoutTests/ChangeLog        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2013-12-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should use cvttsd2si directly for double-to-int32 conversions
+        https://bugs.webkit.org/show_bug.cgi?id=125275
+
+        Reviewed by Michael Saboff.
+
+        * js/regress/double-to-int32-typed-array-expected.txt: Added.
+        * js/regress/double-to-int32-typed-array-no-inline-expected.txt: Added.
+        * js/regress/double-to-int32-typed-array-no-inline.html: Added.
+        * js/regress/double-to-int32-typed-array.html: Added.
+        * js/regress/double-to-uint32-typed-array-expected.txt: Added.
+        * js/regress/double-to-uint32-typed-array-no-inline-expected.txt: Added.
+        * js/regress/double-to-uint32-typed-array-no-inline.html: Added.
+        * js/regress/double-to-uint32-typed-array.html: Added.
+        * js/regress/script-tests/double-to-int32-typed-array-no-inline.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-int32-typed-array.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-uint32-typed-array-no-inline.js: Added.
+        (foo):
+        (test):
+        * js/regress/script-tests/double-to-uint32-typed-array.js: Added.
+        (foo):
+        (test):
+
</ins><span class="cx"> 2013-12-05  Bear Travis  &lt;betravis@adobe.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CSS Shapes] Enable CSS Shapes on Windows
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletoint32typedarrayexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-expected.txt        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/double-to-int32-typed-array
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletoint32typedarraynoinlineexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline-expected.txt        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/double-to-int32-typed-array-no-inline
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletoint32typedarraynoinlinehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array-no-inline.html        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/double-to-int32-typed-array-no-inline.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletoint32typedarrayhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-int32-typed-array.html (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-int32-typed-array.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-int32-typed-array.html        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/double-to-int32-typed-array.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletouint32typedarrayexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-expected.txt        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/double-to-uint32-typed-array
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletouint32typedarraynoinlineexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline-expected.txt        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/double-to-uint32-typed-array-no-inline
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletouint32typedarraynoinlinehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array-no-inline.html        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/double-to-uint32-typed-array-no-inline.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdoubletouint32typedarrayhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/double-to-uint32-typed-array.html        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/double-to-uint32-typed-array.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdoubletoint32typedarraynoinlinejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array-no-inline.js        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+var array = new Int32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+noInline(foo);
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw &quot;Error: &quot; + input + &quot; was supposed to result in &quot; + output + &quot; but instead got &quot; + result;
+}
+
+for (var i = 0; i &lt; 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, -100);
+test(3000000000, -1294967296);
+test(-3000000000, 1294967296);
+test(-2147483648, -2147483648);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdoubletoint32typedarrayjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-int32-typed-array.js        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+var array = new Int32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw &quot;Error: &quot; + input + &quot; was supposed to result in &quot; + output + &quot; but instead got &quot; + result;
+}
+
+for (var i = 0; i &lt; 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, -100);
+test(3000000000, -1294967296);
+test(-3000000000, 1294967296);
+test(-2147483648, -2147483648);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdoubletouint32typedarraynoinlinejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array-no-inline.js        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+var array = new Uint32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+noInline(foo);
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw &quot;Error: &quot; + input + &quot; was supposed to result in &quot; + output + &quot; but instead got &quot; + result;
+}
+
+for (var i = 0; i &lt; 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, 4294967196);
+test(3000000000, 3000000000);
+test(6000000000, 1705032704);
+test(-3000000000, 1294967296);
+test(-2147483648, 2147483648);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdoubletouint32typedarrayjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js (0 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/double-to-uint32-typed-array.js        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+var array = new Uint32Array(1);
+
+function foo(value) {
+    array[0] = value;
+    return array[0];
+}
+
+function test(input, output) {
+    var result = foo(input);
+    if (result != output)
+        throw &quot;Error: &quot; + input + &quot; was supposed to result in &quot; + output + &quot; but instead got &quot; + result;
+}
+
+for (var i = 0; i &lt; 100000; ++i)
+    test(i + 0.5, i);
+
+test(0, 0);
+test(100.5, 100);
+test(-100.5, 4294967196);
+test(3000000000, 3000000000);
+test(6000000000, 1705032704);
+test(-3000000000, 1294967296);
+test(-2147483648, 2147483648);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/ChangeLog        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2013-12-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL should use cvttsd2si directly for double-to-int32 conversions
+        https://bugs.webkit.org/show_bug.cgi?id=125275
+
+        Reviewed by Michael Saboff.
+        
+        Wow. This was an ordeal. Using cvttsd2si was actually easy, but I learned, and
+        sometimes even fixed, some interesting things:
+        
+        - The llvm.x86.sse2.cvttsd2si intrinsic can actually result in LLVM emitting a
+          vcvttsd2si. I guess the intrinsic doesn't actually imply the instruction.
+        
+        - That whole thing about branchTruncateDoubleToUint32? Yeah we don't need that. It's
+          better to use branchTruncateDoubleToInt32 instead. It has the right semantics for
+          all of its callers (err, its one-and-only caller), and it's more likely to take
+          fast path. This patch kills branchTruncateDoubleToUint32.
+        
+        - &quot;a[i] = v; v = a[i]&quot;. Does this change v? OK, assume that 'a[i]' is a pure-ish
+          operation - like an array access with 'i' being an integer index and we're not
+          having a bad time. Now does this change v? CSE assumes that it doesn't. That's
+          wrong. If 'a' is a typed array - the most sensible and pure kind of array - then
+          this can be a truncating cast. For example 'v' could be a double and 'a' could be
+          an integer array.
+        
+        - &quot;v1 = a[i]; v2 = a[i]&quot;. Is v1 === v2 assuming that 'a[i]' is pure-ish? The answer
+          is no. You could have a different arrayMode in each access. I know this sounds
+          weird, but with concurrent JIT that might happen.
+        
+        This patch adds tests for all of this stuff, except for the first issue (it's weird
+        but probably doesn't matter) and the last issue (it's too much of a freakshow).
+
+        * assembler/MacroAssemblerARM64.h:
+        * assembler/MacroAssemblerARMv7.h:
+        * assembler/MacroAssemblerX86Common.h:
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::getByValLoadElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        * ftl/FTLAbbreviations.h:
+        (JSC::FTL::vectorType):
+        (JSC::FTL::getUndef):
+        (JSC::FTL::buildInsertElement):
+        * ftl/FTLIntrinsicRepository.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::doubleToInt32):
+        (JSC::FTL::LowerDFGToLLVM::doubleToUInt32):
+        (JSC::FTL::LowerDFGToLLVM::sensibleDoubleToInt32):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::insertElement):
+        (JSC::FTL::Output::hasSensibleDoubleToInt):
+        (JSC::FTL::Output::sensibleDoubleToInt):
+
</ins><span class="cx"> 2013-12-05  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r160133.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -1196,15 +1196,6 @@
</span><span class="cx">         return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        // Truncate to a 64-bit integer in dataTempRegister, copy the low 32-bit to dest.
-        m_assembler.fcvtzs&lt;64, 64&gt;(dest, src);
-        // Check thlow 32-bits zero extend to be equal to the full value.
-        m_assembler.cmp&lt;64&gt;(dest, dest, ARM64Assembler::UXTW, 0);
-        return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));
-    }
-
</del><span class="cx">     void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         m_assembler.fcvt&lt;32, 64&gt;(dest, src);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARMv7h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -1074,23 +1074,6 @@
</span><span class="cx">         return failure;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src);
-        m_assembler.vmov(dest, fpTempRegisterAsSingle());
-        
-        Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff));
-        Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0));
-        overflow.link(this);
-
-        if (branchType == BranchIfTruncateSuccessful)
-            return success;
-        
-        Jump failure = jump();
-        success.link(this);
-        return failure;
-    }
-
</del><span class="cx">     // Result is undefined if the value is outside of the integer range.
</span><span class="cx">     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86Commonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -885,13 +885,6 @@
</span><span class="cx">         return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
-    {
-        ASSERT(isSSE2Present());
-        m_assembler.cvttsd2si_rr(src, dest);
-        return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));
-    }
-
</del><span class="cx">     void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(isSSE2Present());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -331,7 +331,7 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Node* getByValLoadElimination(Node* child1, Node* child2)
</del><ins>+    Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode)
</ins><span class="cx">     {
</span><span class="cx">         for (unsigned i = m_indexInBlock; i--;) {
</span><span class="cx">             Node* node = m_currentBlock-&gt;at(i);
</span><span class="lines">@@ -342,7 +342,9 @@
</span><span class="cx">             case GetByVal:
</span><span class="cx">                 if (!m_graph.byValIsPure(node))
</span><span class="cx">                     return 0;
</span><del>-                if (node-&gt;child1() == child1 &amp;&amp; node-&gt;child2() == child2)
</del><ins>+                if (node-&gt;child1() == child1
+                    &amp;&amp; node-&gt;child2() == child2
+                    &amp;&amp; node-&gt;arrayMode().type() == arrayMode.type())
</ins><span class="cx">                     return node;
</span><span class="cx">                 break;
</span><span class="cx">                     
</span><span class="lines">@@ -351,7 +353,12 @@
</span><span class="cx">             case PutByValAlias: {
</span><span class="cx">                 if (!m_graph.byValIsPure(node))
</span><span class="cx">                     return 0;
</span><del>-                if (m_graph.varArgChild(node, 0) == child1 &amp;&amp; m_graph.varArgChild(node, 1) == child2)
</del><ins>+                // Typed arrays 
+                if (arrayMode.typedArrayType() != NotTypedArray)
+                    return 0;
+                if (m_graph.varArgChild(node, 0) == child1
+                    &amp;&amp; m_graph.varArgChild(node, 1) == child2
+                    &amp;&amp; node-&gt;arrayMode().type() == arrayMode.type())
</ins><span class="cx">                     return m_graph.varArgChild(node, 2).node();
</span><span class="cx">                 // We must assume that the PutByVal will clobber the location we're getting from.
</span><span class="cx">                 // FIXME: We can do better; if we know that the PutByVal is accessing an array of a
</span><span class="lines">@@ -1216,7 +1223,7 @@
</span><span class="cx">             if (cseMode == StoreElimination)
</span><span class="cx">                 break;
</span><span class="cx">             if (m_graph.byValIsPure(node))
</span><del>-                setReplacement(getByValLoadElimination(node-&gt;child1().node(), node-&gt;child2().node()));
</del><ins>+                setReplacement(getByValLoadElimination(node-&gt;child1().node(), node-&gt;child2().node(), node-&gt;arrayMode()));
</ins><span class="cx">             break;
</span><span class="cx">                 
</span><span class="cx">         case PutByValDirect:
</span><span class="lines">@@ -1226,7 +1233,7 @@
</span><span class="cx">             Edge child1 = m_graph.varArgChild(node, 0);
</span><span class="cx">             Edge child2 = m_graph.varArgChild(node, 1);
</span><span class="cx">             if (node-&gt;arrayMode().canCSEStorage()) {
</span><del>-                Node* replacement = getByValLoadElimination(child1.node(), child2.node());
</del><ins>+                Node* replacement = getByValLoadElimination(child1.node(), child2.node(), node-&gt;arrayMode());
</ins><span class="cx">                 if (!replacement)
</span><span class="cx">                     break;
</span><span class="cx">                 node-&gt;setOp(PutByValAlias);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -2506,11 +2506,8 @@
</span><span class="cx">                 MacroAssembler::Jump fixed = m_jit.jump();
</span><span class="cx">                 notNaN.link(&amp;m_jit);
</span><span class="cx">                 
</span><del>-                MacroAssembler::Jump failed;
-                if (isSigned(type))
-                    failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
-                else
-                    failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
</del><ins>+                MacroAssembler::Jump failed = m_jit.branchTruncateDoubleToInt32(
+                    fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
</ins><span class="cx">                 
</span><span class="cx">                 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr));
</span><span class="cx">                 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbbreviationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbbreviations.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbbreviations.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbbreviations.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx"> static inline LType doubleType(LContext context) { return llvm-&gt;DoubleTypeInContext(context); }
</span><span class="cx"> 
</span><span class="cx"> static inline LType pointerType(LType type) { return llvm-&gt;PointerType(type, 0); }
</span><ins>+static inline LType vectorType(LType type, unsigned count) { return llvm-&gt;VectorType(type, count); }
</ins><span class="cx"> 
</span><span class="cx"> enum PackingMode { NotPacked, Packed };
</span><span class="cx"> static inline LType structType(LContext context, LType* elementTypes, unsigned elementCount, PackingMode packing = NotPacked)
</span><span class="lines">@@ -140,6 +141,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static inline LValue getParam(LValue function, unsigned index) { return llvm-&gt;GetParam(function, index); }
</span><ins>+static inline LValue getUndef(LType type) { return llvm-&gt;GetUndef(type); }
</ins><span class="cx"> 
</span><span class="cx"> enum BitExtension { ZeroExtend, SignExtend };
</span><span class="cx"> static inline LValue constInt(LType type, unsigned long long value, BitExtension extension = ZeroExtend) { return llvm-&gt;ConstInt(type, value, extension == SignExtend); }
</span><span class="lines">@@ -217,6 +219,7 @@
</span><span class="cx"> static inline LValue buildBitCast(LBuilder builder, LValue value, LType type) { return llvm-&gt;BuildBitCast(builder, value, type, &quot;&quot;); }
</span><span class="cx"> static inline LValue buildICmp(LBuilder builder, LIntPredicate cond, LValue left, LValue right) { return llvm-&gt;BuildICmp(builder, cond, left, right, &quot;&quot;); }
</span><span class="cx"> static inline LValue buildFCmp(LBuilder builder, LRealPredicate cond, LValue left, LValue right) { return llvm-&gt;BuildFCmp(builder, cond, left, right, &quot;&quot;); }
</span><ins>+static inline LValue buildInsertElement(LBuilder builder, LValue vector, LValue element, LValue index) { return llvm-&gt;BuildInsertElement(builder, vector, element, index, &quot;&quot;); }
</ins><span class="cx"> 
</span><span class="cx"> enum SynchronizationScope { SingleThread, CrossThread };
</span><span class="cx"> static inline LValue buildFence(LBuilder builder, LAtomicOrdering ordering, SynchronizationScope scope = CrossThread)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -42,12 +42,13 @@
</span><span class="cx">     macro(doubleAbs, &quot;llvm.fabs.f64&quot;, functionType(doubleType, doubleType)) \
</span><span class="cx">     macro(mulWithOverflow32, &quot;llvm.smul.with.overflow.i32&quot;, functionType(structType(m_context, int32, boolean), int32, int32)) \
</span><span class="cx">     macro(mulWithOverflow64, &quot;llvm.smul.with.overflow.i64&quot;, functionType(structType(m_context, int64, boolean), int64, int64)) \
</span><del>-    macro(subWithOverflow32, &quot;llvm.ssub.with.overflow.i32&quot;, functionType(structType(m_context, int32, boolean), int32, int32)) \
-    macro(subWithOverflow64, &quot;llvm.ssub.with.overflow.i64&quot;, functionType(structType(m_context, int64, boolean), int64, int64)) \
</del><span class="cx">     macro(patchpointInt64, &quot;llvm.experimental.patchpoint.i64&quot;, functionType(int64, int32, int32, ref8, int32, Variadic)) \
</span><span class="cx">     macro(patchpointVoid, &quot;llvm.experimental.patchpoint.void&quot;, functionType(voidType, int32, int32, ref8, int32, Variadic)) \
</span><span class="cx">     macro(stackmap, &quot;llvm.experimental.stackmap&quot;, functionType(voidType, int32, int32, Variadic)) \
</span><del>-    macro(trap, &quot;llvm.trap&quot;, functionType(voidType))
</del><ins>+    macro(subWithOverflow32, &quot;llvm.ssub.with.overflow.i32&quot;, functionType(structType(m_context, int32, boolean), int32, int32)) \
+    macro(subWithOverflow64, &quot;llvm.ssub.with.overflow.i64&quot;, functionType(structType(m_context, int64, boolean), int64, int64)) \
+    macro(trap, &quot;llvm.trap&quot;, functionType(voidType)) \
+    macro(x86SSE2CvtTSD2SI, &quot;llvm.x86.sse2.cvttsd2si&quot;, functionType(int32, vectorType(doubleType, 2)))
</ins><span class="cx"> 
</span><span class="cx"> #define FOR_EACH_FUNCTION_TYPE(macro) \
</span><span class="cx">     macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -3011,15 +3011,41 @@
</span><span class="cx">     
</span><span class="cx">     LValue doubleToInt32(LValue doubleValue)
</span><span class="cx">     {
</span><ins>+        if (Output::hasSensibleDoubleToInt())
+            return sensibleDoubleToInt32(doubleValue);
+        
</ins><span class="cx">         double limit = pow(2, 31) - 1;
</span><span class="cx">         return doubleToInt32(doubleValue, -limit, limit);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     LValue doubleToUInt32(LValue doubleValue)
</span><span class="cx">     {
</span><ins>+        if (Output::hasSensibleDoubleToInt())
+            return sensibleDoubleToInt32(doubleValue);
+        
</ins><span class="cx">         return doubleToInt32(doubleValue, 0, pow(2, 32) - 1, false);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    LValue sensibleDoubleToInt32(LValue doubleValue)
+    {
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;sensible doubleToInt32 slow path&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;sensible doubleToInt32 continuation&quot;));
+        
+        ValueFromBlock fastResult = m_out.anchor(
+            m_out.sensibleDoubleToInt(doubleValue));
+        m_out.branch(
+            m_out.equal(fastResult.value(), m_out.constInt32(0x80000000)),
+            slowPath, continuation);
+        
+        LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
+        ValueFromBlock slowResult = m_out.anchor(
+            m_out.call(m_out.operation(toInt32), doubleValue));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        return m_out.phi(m_out.int32, fastResult, slowResult);
+    }
+    
</ins><span class="cx">     void speculateBackward(
</span><span class="cx">         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (160204 => 160205)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2013-12-06 01:19:42 UTC (rev 160204)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h        2013-12-06 01:47:19 UTC (rev 160205)
</span><span class="lines">@@ -154,6 +154,8 @@
</span><span class="cx">     LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); }
</span><span class="cx">     LValue bitNot(LValue value) { return buildNot(m_builder, value); }
</span><span class="cx">     
</span><ins>+    LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); }
+    
</ins><span class="cx">     LValue addWithOverflow32(LValue left, LValue right)
</span><span class="cx">     {
</span><span class="cx">         return call(addWithOverflow32Intrinsic(), left, right);
</span><span class="lines">@@ -183,6 +185,17 @@
</span><span class="cx">         return call(doubleAbsIntrinsic(), value);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    static bool hasSensibleDoubleToInt() { return isX86(); }
+    LValue sensibleDoubleToInt(LValue value)
+    {
+        RELEASE_ASSERT(isX86());
+        return call(
+            x86SSE2CvtTSD2SIIntrinsic(),
+            insertElement(
+                insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero),
+                doubleZero, int32One));
+    }
+    
</ins><span class="cx">     LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
</span><span class="cx">     LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
</span><span class="cx">     LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
</span></span></pre>
</div>
</div>

</body>
</html>