<!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>[163070] 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/163070">163070</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-01-29 23:30:24 -0800 (Wed, 29 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge final changesets from the jsCStack branch (<a href="http://trac.webkit.org/projects/webkit/changeset/162969">r162969</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/162975">r162975</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/162992">r162992</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/163004">r163004</a>, <a href="http://trac.webkit.org/projects/webkit/changeset/163069">r163069</a>).

    2014-01-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    DFG ArrayPop double array mishandles the NaN hole installation
    https://bugs.webkit.org/show_bug.cgi?id=127813
    
    Reviewed by Mark Rowe.
            
    Our object model for arrays inferred double dictates that we use quiet NaN (QNaN) to
    mark holes. Holes, in this context, are any entries in the allocated array buffer
    (i.e. from index 0 up to the vectorLength) that don't currently hold a value. Popping
    creates a hole, since it deletes the value at publicLength - 1.
            
    But, because of some sloppy copy-and-paste, we were storing (int64_t)0 when creating
    the hole, instead of storing QNaN. That's likely because for other kinds of arrays,
    64-bit zero is the hole marker, instead of QNaN.
            
    The attached test case illustrates the problem. In the LLInt and Baseline JIT, the
    result returned from foo() is &quot;1.5,2.5,,4.5&quot;, since array.pop() removes 3.5 and
    replaces it with a hole and then the assignment &quot;array[3] = 4.5&quot; creates an element
    just beyond that hole. But, once we tier-up to the DFG, the result previously became
    &quot;1.5,2.5,0,4.5&quot;, which is wrong. The 0 appeared because the IEEE double
    interpretation of 64-bit zero is simply zero.
            
    This patch fixes that problem. Now the DFG agrees with the other engines.
            
    This patch also fixes style. For some reason that copy-pasted code wasn't even
    indented correctly.
    
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * tests/stress/array-pop-double-hole.js: Added.
    (foo):
    
    2014-01-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    FTL should support ArrayPush
    https://bugs.webkit.org/show_bug.cgi?id=127748
    
    Not reviewed, remove some debug code.
    
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
    
    2014-01-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    FTL should support ArrayPush
    https://bugs.webkit.org/show_bug.cgi?id=127748
    
    Reviewed by Oliver Hunt.
    
    * ftl/FTLAbstractHeapRepository.h:
    (JSC::FTL::AbstractHeapRepository::forArrayType):
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLIntrinsicRepository.h:
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
    * tests/stress/array-push-contiguous.js: Added.
    (foo):
    * tests/stress/array-push-double.js: Added.
    (foo):
    
    2014-01-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
    
    FTL should support ArrayPop
    https://bugs.webkit.org/show_bug.cgi?id=127749
    
    Reviewed by Geoffrey Garen.
    
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLIntrinsicRepository.h:
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
    (JSC::FTL::LowerDFGToLLVM::compileArrayPop):
    * tests/stress/array-pop-contiguous.js: Added.
    (foo):
    * tests/stress/array-pop-double.js: Added.
    (foo):
    * tests/stress/array-pop-int32.js: Added.
    (foo):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypopcontiguousjs">trunk/Source/JavaScriptCore/tests/stress/array-pop-contiguous.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypopdoubleholejs">trunk/Source/JavaScriptCore/tests/stress/array-pop-double-hole.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypopdoublejs">trunk/Source/JavaScriptCore/tests/stress/array-pop-double.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypopint32js">trunk/Source/JavaScriptCore/tests/stress/array-pop-int32.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypushcontiguousjs">trunk/Source/JavaScriptCore/tests/stress/array-push-contiguous.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypushdoublethennanjs">trunk/Source/JavaScriptCore/tests/stress/array-push-double-then-nan.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressarraypushdoublejs">trunk/Source/JavaScriptCore/tests/stress/array-push-double.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -1,5 +1,93 @@
</span><span class="cx"> 2014-01-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge final changesets from the jsCStack branch (r162969, r162975, r162992, r163004, r163069).
+
+    2014-01-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            DFG ArrayPop double array mishandles the NaN hole installation
+            https://bugs.webkit.org/show_bug.cgi?id=127813
+    
+            Reviewed by Mark Rowe.
+            
+            Our object model for arrays inferred double dictates that we use quiet NaN (QNaN) to
+            mark holes. Holes, in this context, are any entries in the allocated array buffer
+            (i.e. from index 0 up to the vectorLength) that don't currently hold a value. Popping
+            creates a hole, since it deletes the value at publicLength - 1.
+            
+            But, because of some sloppy copy-and-paste, we were storing (int64_t)0 when creating
+            the hole, instead of storing QNaN. That's likely because for other kinds of arrays,
+            64-bit zero is the hole marker, instead of QNaN.
+            
+            The attached test case illustrates the problem. In the LLInt and Baseline JIT, the
+            result returned from foo() is &quot;1.5,2.5,,4.5&quot;, since array.pop() removes 3.5 and
+            replaces it with a hole and then the assignment &quot;array[3] = 4.5&quot; creates an element
+            just beyond that hole. But, once we tier-up to the DFG, the result previously became
+            &quot;1.5,2.5,0,4.5&quot;, which is wrong. The 0 appeared because the IEEE double
+            interpretation of 64-bit zero is simply zero.
+            
+            This patch fixes that problem. Now the DFG agrees with the other engines.
+            
+            This patch also fixes style. For some reason that copy-pasted code wasn't even
+            indented correctly.
+    
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * tests/stress/array-pop-double-hole.js: Added.
+            (foo):
+    
+    2014-01-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            FTL should support ArrayPush
+            https://bugs.webkit.org/show_bug.cgi?id=127748
+    
+            Not reviewed, remove some debug code.
+    
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
+    
+    2014-01-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            FTL should support ArrayPush
+            https://bugs.webkit.org/show_bug.cgi?id=127748
+    
+            Reviewed by Oliver Hunt.
+    
+            * ftl/FTLAbstractHeapRepository.h:
+            (JSC::FTL::AbstractHeapRepository::forArrayType):
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLIntrinsicRepository.h:
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
+            * tests/stress/array-push-contiguous.js: Added.
+            (foo):
+            * tests/stress/array-push-double.js: Added.
+            (foo):
+    
+    2014-01-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+    
+            FTL should support ArrayPop
+            https://bugs.webkit.org/show_bug.cgi?id=127749
+    
+            Reviewed by Geoffrey Garen.
+    
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLIntrinsicRepository.h:
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compileArrayPush):
+            (JSC::FTL::LowerDFGToLLVM::compileArrayPop):
+            * tests/stress/array-pop-contiguous.js: Added.
+            (foo):
+            * tests/stress/array-pop-double.js: Added.
+            (foo):
+            * tests/stress/array-pop-int32.js: Added.
+            (foo):
+    
+2014-01-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         DFG::ByteCodeParser::m_dfgCodeBlock is sometimes uninitialized
</span><span class="cx">         &lt;rdar://problem/15939032&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -3302,7 +3302,7 @@
</span><span class="cx">                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
</span><span class="cx">                 // length and the new length.
</span><span class="cx">                 m_jit.store64(
</span><del>-                MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
</del><ins>+                    MacroAssembler::TrustedImm64(bitwise_cast&lt;int64_t&gt;(QNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
</ins><span class="cx">                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
</span><span class="cx">                 boxDouble(tempFPR, valueGPR);
</span><span class="cx">             } else {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGArrayMode.h&quot;
</ins><span class="cx"> #include &quot;FTLAbstractHeap.h&quot;
</span><span class="cx"> #include &quot;IndexingType.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -136,6 +137,24 @@
</span><span class="cx">             return 0;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    
+    IndexedAbstractHeap&amp; forArrayType(DFG::Array::Type type)
+    {
+        switch (type) {
+        case DFG::Array::Int32:
+            return indexedInt32Properties;
+        case DFG::Array::Double:
+            return indexedDoubleProperties;
+        case DFG::Array::Contiguous:
+            return indexedContiguousProperties;
+        case DFG::Array::ArrayStorage:
+        case DFG::Array::SlowPutArrayStorage:
+            return indexedArrayStorageProperties;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return indexedInt32Properties;
+        }
+    }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class AbstractHeap;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -201,6 +201,17 @@
</span><span class="cx">             return CannotCompile;
</span><span class="cx">         }
</span><span class="cx">         break;
</span><ins>+    case ArrayPush:
+    case ArrayPop:
+        switch (node-&gt;arrayMode().type()) {
+        case Array::Int32:
+        case Array::Contiguous:
+        case Array::Double:
+            break;
+        default:
+            return CannotCompile;
+        }
+        break;
</ins><span class="cx">     case CompareEq:
</span><span class="cx">         if (node-&gt;isBinaryUseKind(Int32Use))
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLIntrinsicRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -62,7 +62,10 @@
</span><span class="cx">     macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
</span><span class="cx">     macro(I_JITOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
</span><span class="cx">     macro(J_JITOperation_E, functionType(int64, intPtr)) \
</span><ins>+    macro(J_JITOperation_EA, functionType(int64, intPtr, intPtr)) \
</ins><span class="cx">     macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \
</span><ins>+    macro(J_JITOperation_EDA, functionType(int64, intPtr, doubleType, intPtr)) \
+    macro(J_JITOperation_EJA, functionType(int64, intPtr, int64, intPtr)) \
</ins><span class="cx">     macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \
</span><span class="cx">     macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \
</span><span class="cx">     macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (163069 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-30 05:44:51 UTC (rev 163069)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -416,6 +416,12 @@
</span><span class="cx">         case PutByValDirect:
</span><span class="cx">             compilePutByVal();
</span><span class="cx">             break;
</span><ins>+        case ArrayPush:
+            compileArrayPush();
+            break;
+        case ArrayPop:
+            compileArrayPop();
+            break;
</ins><span class="cx">         case NewObject:
</span><span class="cx">             compileNewObject();
</span><span class="cx">             break;
</span><span class="lines">@@ -2181,6 +2187,132 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void compileArrayPush()
+    {
+        LValue base = lowCell(m_node-&gt;child1());
+        LValue storage = lowStorage(m_node-&gt;child3());
+        
+        switch (m_node-&gt;arrayMode().type()) {
+        case Array::Int32:
+        case Array::Contiguous:
+        case Array::Double: {
+            LValue value;
+            LType refType;
+            
+            if (m_node-&gt;arrayMode().type() != Array::Double) {
+                value = lowJSValue(m_node-&gt;child2(), ManualOperandSpeculation);
+                if (m_node-&gt;arrayMode().type() == Array::Int32) {
+                    FTL_TYPE_CHECK(
+                        jsValueValue(value), m_node-&gt;child2(), SpecInt32, isNotInt32(value));
+                }
+                refType = m_out.ref64;
+            } else {
+                value = lowDouble(m_node-&gt;child2());
+                FTL_TYPE_CHECK(
+                    doubleValue(value), m_node-&gt;child2(), SpecFullRealNumber,
+                    m_out.doubleNotEqualOrUnordered(value, value));
+                refType = m_out.refDouble;
+            }
+            
+            IndexedAbstractHeap&amp; heap = m_heaps.forArrayType(m_node-&gt;arrayMode().type());
+
+            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
+            
+            LBasicBlock fastPath = FTL_NEW_BLOCK(m_out, (&quot;ArrayPush fast path&quot;));
+            LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;ArrayPush slow path&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArrayPush continuation&quot;));
+            
+            m_out.branch(
+                m_out.aboveOrEqual(
+                    prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
+                slowPath, fastPath);
+            
+            LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
+            m_out.store(
+                value,
+                m_out.baseIndex(heap, storage, m_out.zeroExt(prevLength, m_out.intPtr)),
+                refType);
+            LValue newLength = m_out.add(prevLength, m_out.int32One);
+            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+            
+            ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(slowPath, continuation);
+            LValue operation;
+            if (m_node-&gt;arrayMode().type() != Array::Double)
+                operation = m_out.operation(operationArrayPush);
+            else
+                operation = m_out.operation(operationArrayPushDouble);
+            ValueFromBlock slowResult = m_out.anchor(
+                vmCall(operation, m_callFrame, value, base));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            setJSValue(m_out.phi(m_out.int64, fastResult, slowResult));
+            return;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+    
+    void compileArrayPop()
+    {
+        LValue base = lowCell(m_node-&gt;child1());
+        LValue storage = lowStorage(m_node-&gt;child2());
+        
+        switch (m_node-&gt;arrayMode().type()) {
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous: {
+            IndexedAbstractHeap&amp; heap = m_heaps.forArrayType(m_node-&gt;arrayMode().type());
+            
+            LBasicBlock fastCase = FTL_NEW_BLOCK(m_out, (&quot;ArrayPop fast case&quot;));
+            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, (&quot;ArrayPop slow case&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ArrayPop continuation&quot;));
+            
+            LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
+            
+            Vector&lt;ValueFromBlock, 3&gt; results;
+            results.append(m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined()))));
+            m_out.branch(m_out.isZero32(prevLength), continuation, fastCase);
+            
+            LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
+            LValue newLength = m_out.sub(prevLength, m_out.int32One);
+            m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+            TypedPointer pointer = m_out.baseIndex(
+                heap, storage, m_out.zeroExt(newLength, m_out.intPtr));
+            if (m_node-&gt;arrayMode().type() != Array::Double) {
+                LValue result = m_out.load64(pointer);
+                m_out.store64(m_out.int64Zero, pointer);
+                results.append(m_out.anchor(result));
+                m_out.branch(m_out.notZero64(result), continuation, slowCase);
+            } else {
+                LValue result = m_out.loadDouble(pointer);
+                m_out.store64(m_out.constInt64(bitwise_cast&lt;int64_t&gt;(QNaN)), pointer);
+                results.append(m_out.anchor(boxDouble(result)));
+                m_out.branch(m_out.doubleEqual(result, result), continuation, slowCase);
+            }
+            
+            m_out.appendTo(slowCase, continuation);
+            results.append(m_out.anchor(vmCall(
+                m_out.operation(operationArrayPopAndRecoverLength), m_callFrame, base)));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            setJSValue(m_out.phi(m_out.int64, results));
+            return;
+        }
+
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+    
</ins><span class="cx">     void compileNewObject()
</span><span class="cx">     {
</span><span class="cx">         Structure* structure = m_node-&gt;structure();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypopcontiguousjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-pop-contiguous.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-pop-contiguous.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-pop-contiguous.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo(array) {
+    return [array.pop(), array.pop(), array.pop(), array.pop()];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo([&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;]);
+    if (result.toString() != &quot;baz,bar,foo,&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypopdoubleholejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-pop-double-hole.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-pop-double-hole.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-pop-double-hole.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+function foo() {
+    var array = [1.5, 2, 3.5];
+    array.pop();
+    array[3] = 4.5;
+    return array;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo();
+    if (result.toString() != &quot;1.5,2,,4.5&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypopdoublejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-pop-double.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-pop-double.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-pop-double.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo(array) {
+    return [array.pop(), array.pop(), array.pop(), array.pop()];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo([1.5, 2.5, 3.5]);
+    if (result.toString() != &quot;3.5,2.5,1.5,&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypopint32js"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-pop-int32.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-pop-int32.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-pop-int32.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+function foo(array) {
+    return [array.pop(), array.pop(), array.pop(), array.pop()];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo([1, 2, 3]);
+    if (result.toString() != &quot;3,2,1,&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypushcontiguousjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-push-contiguous.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-push-contiguous.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-push-contiguous.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+function foo() {
+    var array = [];
+    var result = [];
+    for (var i = 0; i &lt; 42; ++i)
+        result.push(array.push(&quot;hello&quot;));
+    return [array, result];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo();
+    if (result[0].toString() != &quot;hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello,hello&quot;)
+        throw &quot;Error: bad array: &quot; + result[0];
+    if (result[1].toString() != &quot;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42&quot;)
+        throw &quot;Error: bad array: &quot; + result[1];
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypushdoublethennanjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-push-double-then-nan.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-push-double-then-nan.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-push-double-then-nan.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+function foo(x) {
+    var array = [];
+    var result = [];
+    for (var i = 0; i &lt; 42; ++i)
+        result.push(array.push(x));
+    return [array, result];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo(5.5);
+    if (result[0].toString() != &quot;5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5,5.5&quot;)
+        throw &quot;Error: bad array: &quot; + result[0];
+    if (result[1].toString() != &quot;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42&quot;)
+        throw &quot;Error: bad array: &quot; + result[1];
+}
+
+var result = foo(0/0);
+if (result[0].toString() != &quot;NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN&quot;)
+    throw &quot;Error: bad array: &quot; + result[0];
+if (result[1].toString() != &quot;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42&quot;)
+    throw &quot;Error: bad array: &quot; + result[1];
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressarraypushdoublejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/array-push-double.js (0 => 163070)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/array-push-double.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/array-push-double.js        2014-01-30 07:30:24 UTC (rev 163070)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+function foo() {
+    var array = [];
+    var result = [];
+    for (var i = 0; i &lt; 42; ++i)
+        result.push(array.push(7.5 - i));
+    return [array, result];
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100000; ++i) {
+    var result = foo();
+    if (result[0].toString() != &quot;7.5,6.5,5.5,4.5,3.5,2.5,1.5,0.5,-0.5,-1.5,-2.5,-3.5,-4.5,-5.5,-6.5,-7.5,-8.5,-9.5,-10.5,-11.5,-12.5,-13.5,-14.5,-15.5,-16.5,-17.5,-18.5,-19.5,-20.5,-21.5,-22.5,-23.5,-24.5,-25.5,-26.5,-27.5,-28.5,-29.5,-30.5,-31.5,-32.5,-33.5&quot;)
+        throw &quot;Error: bad array: &quot; + result[0];
+    if (result[1].toString() != &quot;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42&quot;)
+        throw &quot;Error: bad array: &quot; + result[1];
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>