<!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>[184032] 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/184032">184032</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-08 17:18:43 -0700 (Fri, 08 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Extend the SaneChain optimization to Contiguous arrays
https://bugs.webkit.org/show_bug.cgi?id=144664

Reviewed by Mark Lam.
        
Previously if you loaded from a hole, you'd either have to take slow path for the array
load (which means C++ calls and prototype chain walks) or you'd exit (if you hadn't
gathered the necessary profiling yet). But that's unnecessary if we know that the
prototype chain is sane - i.e. has no indexed properties. Then we can just return
Undefined for the hole.
        
Making this change requires setting more watchpoints on the array prototype chain. But
that hit a horrible bug: ArrayPrototype still uses the static lookup tables and builds
itself up lazily. This means that this increased the number of recompilations we'd get
due to the array prototype chain being built up.
        
So, this change also removes the laziness and static tables from ArrayPrototype.
        
But to make that change, I also had to add a helper for eagerly building up a prototype
that has builtin functions.

* CMakeLists.txt:
* DerivedSources.make:
* dfg/DFGArrayMode.h:
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
(JSC::ArrayPrototype::getOwnPropertySlot): Deleted.
* runtime/ArrayPrototype.h:
* runtime/JSObject.h:</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="#trunkSourceJavaScriptCoreDerivedSourcesmake">trunk/Source/JavaScriptCore/DerivedSources.make</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModeh">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</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>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayPrototypecpp">trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArrayPrototypeh">trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.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 (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -605,7 +605,6 @@
</span><span class="cx"> set(JavaScriptCore_LUT_FILES
</span><span class="cx">     runtime/ArrayConstructor.cpp
</span><span class="cx">     runtime/ArrayIteratorPrototype.cpp
</span><del>-    runtime/ArrayPrototype.cpp
</del><span class="cx">     runtime/BooleanPrototype.cpp
</span><span class="cx">     runtime/DateConstructor.cpp
</span><span class="cx">     runtime/DatePrototype.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2015-05-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Extend the SaneChain optimization to Contiguous arrays
+        https://bugs.webkit.org/show_bug.cgi?id=144664
+
+        Reviewed by Mark Lam.
+        
+        Previously if you loaded from a hole, you'd either have to take slow path for the array
+        load (which means C++ calls and prototype chain walks) or you'd exit (if you hadn't
+        gathered the necessary profiling yet). But that's unnecessary if we know that the
+        prototype chain is sane - i.e. has no indexed properties. Then we can just return
+        Undefined for the hole.
+        
+        Making this change requires setting more watchpoints on the array prototype chain. But
+        that hit a horrible bug: ArrayPrototype still uses the static lookup tables and builds
+        itself up lazily. This means that this increased the number of recompilations we'd get
+        due to the array prototype chain being built up.
+        
+        So, this change also removes the laziness and static tables from ArrayPrototype.
+        
+        But to make that change, I also had to add a helper for eagerly building up a prototype
+        that has builtin functions.
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * dfg/DFGArrayMode.h:
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileGetByVal):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::ArrayPrototype::finishCreation):
+        (JSC::ArrayPrototype::getOwnPropertySlot): Deleted.
+        * runtime/ArrayPrototype.h:
+        * runtime/JSObject.h:
+
</ins><span class="cx"> 2015-05-08  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Creating a large MarkedBlock sometimes results in more than one cell in the block
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreDerivedSourcesmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/DerivedSources.make (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/DerivedSources.make        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/DerivedSources.make        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-# Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013 Apple Inc. All rights reserved.
</del><ins>+# Copyright (C) 2006, 2007, 2008, 2009, 2011, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx"> #
</span><span class="cx"> # Redistribution and use in source and binary forms, with or without
</span><span class="cx"> # modification, are permitted provided that the following conditions
</span><span class="lines">@@ -37,7 +37,6 @@
</span><span class="cx"> all : \
</span><span class="cx">     ArrayConstructor.lut.h \
</span><span class="cx">     ArrayIteratorPrototype.lut.h \
</span><del>-    ArrayPrototype.lut.h \
</del><span class="cx">     BooleanPrototype.lut.h \
</span><span class="cx">     DateConstructor.lut.h \
</span><span class="cx">     DatePrototype.lut.h \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.h        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -89,6 +89,7 @@
</span><span class="cx"> 
</span><span class="cx"> enum Speculation {
</span><span class="cx">     SaneChain, // In bounds and the array prototype chain is still intact, i.e. loading a hole doesn't require special treatment.
</span><ins>+    
</ins><span class="cx">     InBounds, // In bounds and not loading a hole.
</span><span class="cx">     ToHole, // Potentially storing to a hole.
</span><span class="cx">     OutOfBounds // Out-of-bounds access and anything can happen.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -538,17 +538,61 @@
</span><span class="cx">             
</span><span class="cx">             ArrayMode arrayMode = node-&gt;arrayMode();
</span><span class="cx">             switch (arrayMode.type()) {
</span><ins>+            case Array::Contiguous:
</ins><span class="cx">             case Array::Double:
</span><span class="cx">                 if (arrayMode.arrayClass() == Array::OriginalArray
</span><span class="cx">                     &amp;&amp; arrayMode.speculation() == Array::InBounds) {
</span><span class="cx">                     JSGlobalObject* globalObject = m_graph.globalObjectFor(node-&gt;origin.semantic);
</span><del>-                    if (globalObject-&gt;arrayPrototypeChainIsSane()
-                        &amp;&amp; !(node-&gt;flags() &amp; NodeBytecodeUsesAsOther)) {
-                        m_graph.watchpoints().addLazily(
-                            globalObject-&gt;arrayPrototype()-&gt;structure()-&gt;transitionWatchpointSet());
-                        m_graph.watchpoints().addLazily(
-                            globalObject-&gt;objectPrototype()-&gt;structure()-&gt;transitionWatchpointSet());
-                        node-&gt;setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
</del><ins>+                    if (globalObject-&gt;arrayPrototypeChainIsSane()) {
+                        // Check if SaneChain will work on a per-type basis. Note that:
+                        //
+                        // 1) We don't want double arrays to sometimes return undefined, since
+                        // that would require a change to the return type and it would pessimise
+                        // things a lot. So, we'd only want to do that if we actually had
+                        // evidence that we could read from a hole. That's pretty annoying.
+                        // Likely the best way to handle that case is with an equivalent of
+                        // SaneChain for OutOfBounds. For now we just detect when Undefined and
+                        // NaN are indistinguishable according to backwards propagation, and just
+                        // use SaneChain in that case. This happens to catch a lot of cases.
+                        //
+                        // 2) We don't want int32 array loads to have to do a hole check just to
+                        // coerce to Undefined, since that would mean twice the checks.
+                        //
+                        // This has two implications. First, we have to do more checks than we'd
+                        // like. It's unfortunate that we have to do the hole check. Second,
+                        // some accesses that hit a hole will now need to take the full-blown
+                        // out-of-bounds slow path. We can fix that with:
+                        // https://bugs.webkit.org/show_bug.cgi?id=144668
+                        
+                        bool canDoSaneChain = false;
+                        switch (arrayMode.type()) {
+                        case Array::Contiguous:
+                            // This is happens to be entirely natural. We already would have
+                            // returned any JSValue, and now we'll return Undefined. We still do
+                            // the check but it doesn't require taking any kind of slow path.
+                            canDoSaneChain = true;
+                            break;
+                            
+                        case Array::Double:
+                            if (!(node-&gt;flags() &amp; NodeBytecodeUsesAsOther)) {
+                                // Holes look like NaN already, so if the user doesn't care
+                                // about the difference between Undefined and NaN then we can
+                                // do this.
+                                canDoSaneChain = true;
+                            }
+                            break;
+                            
+                        default:
+                            break;
+                        }
+                        
+                        if (canDoSaneChain) {
+                            m_graph.watchpoints().addLazily(
+                                globalObject-&gt;arrayPrototype()-&gt;structure()-&gt;transitionWatchpointSet());
+                            m_graph.watchpoints().addLazily(
+                                globalObject-&gt;objectPrototype()-&gt;structure()-&gt;transitionWatchpointSet());
+                            node-&gt;setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
+                        }
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -2309,21 +2309,46 @@
</span><span class="cx">             
</span><span class="cx">                 GPRTemporary resultPayload(this);
</span><span class="cx">                 if (node-&gt;arrayMode().type() == Array::Int32) {
</span><ins>+                    ASSERT(!node-&gt;arrayMode().isSaneChain());
+                    
</ins><span class="cx">                     speculationCheck(
</span><span class="cx">                         OutOfBounds, JSValueRegs(), 0,
</span><span class="cx">                         m_jit.branch32(
</span><span class="cx">                             MacroAssembler::Equal,
</span><del>-                            MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
</del><ins>+                            MacroAssembler::BaseIndex(
+                                storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
</ins><span class="cx">                             TrustedImm32(JSValue::EmptyValueTag)));
</span><del>-                    m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
</del><ins>+                    m_jit.load32(
+                        MacroAssembler::BaseIndex(
+                            storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
+                        resultPayload.gpr());
</ins><span class="cx">                     int32Result(resultPayload.gpr(), node);
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                 
</span><span class="cx">                 GPRTemporary resultTag(this);
</span><del>-                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
-                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
-                m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
</del><ins>+                m_jit.load32(
+                    MacroAssembler::BaseIndex(
+                        storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
+                    resultTag.gpr());
+                m_jit.load32(
+                    MacroAssembler::BaseIndex(
+                        storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
+                    resultPayload.gpr());
+                if (node-&gt;arrayMode().isSaneChain()) {
+                    JITCompiler::Jump notHole = m_jit.branch32(
+                        MacroAssembler::NotEqual, resultTag.gpr(),
+                        TrustedImm32(JSValue::EmptyValueTag));
+                    m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
+                    m_jit.move(TrustedImm32(0), resultPayload.gpr());
+                    notHole.link(&amp;m_jit);
+                } else {
+                    speculationCheck(
+                        LoadFromHole, JSValueRegs(), 0,
+                        m_jit.branch32(
+                            MacroAssembler::Equal, resultTag.gpr(),
+                            TrustedImm32(JSValue::EmptyValueTag)));
+                }
</ins><span class="cx">                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
</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 (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -2447,7 +2447,17 @@
</span><span class="cx">                 
</span><span class="cx">                 GPRTemporary result(this);
</span><span class="cx">                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
</span><del>-                speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
</del><ins>+                if (node-&gt;arrayMode().isSaneChain()) {
+                    ASSERT(node-&gt;arrayMode().type() == Array::Contiguous);
+                    JITCompiler::Jump notHole = m_jit.branchTest64(
+                        MacroAssembler::NonZero, result.gpr());
+                    m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
+                    notHole.link(&amp;m_jit);
+                } else {
+                    speculationCheck(
+                        LoadFromHole, JSValueRegs(), 0,
+                        m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
+                }
</ins><span class="cx">                 jsValueResult(result.gpr(), node, node-&gt;arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
</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 (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -2263,7 +2263,14 @@
</span><span class="cx">             
</span><span class="cx">             if (m_node-&gt;arrayMode().isInBounds()) {
</span><span class="cx">                 LValue result = m_out.load64(baseIndex(heap, storage, index, m_node-&gt;child2()));
</span><del>-                speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
</del><ins>+                LValue isHole = m_out.isZero64(result);
+                if (m_node-&gt;arrayMode().isSaneChain()) {
+                    DFG_ASSERT(
+                        m_graph, m_node, m_node-&gt;arrayMode().type() == Array::Contiguous);
+                    result = m_out.select(
+                        isHole, m_out.constInt64(JSValue::encode(jsUndefined())), result);
+                } else
+                    speculate(LoadFromHole, noValue(), 0, isHole);
</ins><span class="cx">                 setJSValue(result);
</span><span class="cx">                 return;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -32,12 +32,13 @@
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><span class="cx"> #include &quot;JSArrayIterator.h&quot;
</span><ins>+#include &quot;JSCBuiltins.h&quot;
+#include &quot;JSCInlines.h&quot;
</ins><span class="cx"> #include &quot;JSStringBuilder.h&quot;
</span><span class="cx"> #include &quot;JSStringJoiner.h&quot;
</span><span class="cx"> #include &quot;Lookup.h&quot;
</span><span class="cx"> #include &quot;ObjectConstructor.h&quot;
</span><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><del>-#include &quot;JSCInlines.h&quot;
</del><span class="cx"> #include &quot;StringRecursionChecker.h&quot;
</span><span class="cx"> #include &lt;algorithm&gt;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><span class="lines">@@ -63,48 +64,10 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL arrayProtoFuncKeys(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL arrayProtoFuncEntries(ExecState*);
</span><span class="cx"> 
</span><del>-}
-
-#include &quot;ArrayPrototype.lut.h&quot;
-
-namespace JSC {
-
</del><span class="cx"> // ------------------------------ ArrayPrototype ----------------------------
</span><span class="cx"> 
</span><del>-const ClassInfo ArrayPrototype::s_info = {&quot;Array&quot;, &amp;JSArray::s_info, &amp;arrayPrototypeTable, CREATE_METHOD_TABLE(ArrayPrototype)};
</del><ins>+const ClassInfo ArrayPrototype::s_info = {&quot;Array&quot;, &amp;JSArray::s_info, nullptr, CREATE_METHOD_TABLE(ArrayPrototype)};
</ins><span class="cx"> 
</span><del>-/* Source for ArrayPrototype.lut.h
-@begin arrayPrototypeTable 16
-  toString       arrayProtoFuncToString       DontEnum|Function 0
-  toLocaleString arrayProtoFuncToLocaleString DontEnum|Function 0
-  concat         arrayProtoFuncConcat         DontEnum|Function 1
-  fill           arrayProtoFuncFill           DontEnum|Function 1
-  join           arrayProtoFuncJoin           DontEnum|Function 1
-  pop            arrayProtoFuncPop            DontEnum|Function 0
-  push           arrayProtoFuncPush           DontEnum|Function 1
-  reverse        arrayProtoFuncReverse        DontEnum|Function 0
-  shift          arrayProtoFuncShift          DontEnum|Function 0
-  slice          arrayProtoFuncSlice          DontEnum|Function 2
-  sort           arrayProtoFuncSort           DontEnum|Function 1
-  splice         arrayProtoFuncSplice         DontEnum|Function 2
-  unshift        arrayProtoFuncUnShift        DontEnum|Function 1
-  every          arrayProtoFuncEvery          DontEnum|Function 1
-  forEach        arrayProtoFuncForEach        DontEnum|Function 1
-  some           arrayProtoFuncSome           DontEnum|Function 1
-  indexOf        arrayProtoFuncIndexOf        DontEnum|Function 1
-  lastIndexOf    arrayProtoFuncLastIndexOf    DontEnum|Function 1
-  filter         arrayProtoFuncFilter         DontEnum|Function 1
-  reduce         arrayProtoFuncReduce         DontEnum|Function 1
-  reduceRight    arrayProtoFuncReduceRight    DontEnum|Function 1
-  map            arrayProtoFuncMap            DontEnum|Function 1
-  entries        arrayProtoFuncEntries        DontEnum|Function 0
-  keys           arrayProtoFuncKeys           DontEnum|Function 0
-  find           arrayProtoFuncFind           DontEnum|Function 1
-  findIndex      arrayProtoFuncFindIndex      DontEnum|Function 1
-  includes       arrayProtoFuncIncludes       DontEnum|Function 1
-@end
-*/
-
</del><span class="cx"> ArrayPrototype* ArrayPrototype::create(VM&amp; vm, JSGlobalObject* globalObject, Structure* structure)
</span><span class="cx"> {
</span><span class="cx">     ArrayPrototype* prototype = new (NotNull, allocateCell&lt;ArrayPrototype&gt;(vm.heap)) ArrayPrototype(vm, structure);
</span><span class="lines">@@ -126,7 +89,35 @@
</span><span class="cx"> 
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames-&gt;values, globalObject-&gt;arrayProtoValuesFunction(), DontEnum);
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames-&gt;iteratorSymbol, globalObject-&gt;arrayProtoValuesFunction(), DontEnum);
</span><del>-
</del><ins>+    
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;toString, arrayProtoFuncToString, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;toLocaleString, arrayProtoFuncToLocaleString, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(&quot;concat&quot;, arrayProtoFuncConcat, DontEnum, 1);
+    JSC_BUILTIN_FUNCTION(&quot;fill&quot;, arrayPrototypeFillCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;join, arrayProtoFuncJoin, DontEnum, 1);
+    JSC_NATIVE_INTRINSIC_FUNCTION(&quot;pop&quot;, arrayProtoFuncPop, DontEnum, 0, ArrayPopIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION(&quot;push&quot;, arrayProtoFuncPush, DontEnum, 1, ArrayPushIntrinsic);
+    JSC_NATIVE_FUNCTION(&quot;reverse&quot;, arrayProtoFuncReverse, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(&quot;shift&quot;, arrayProtoFuncShift, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;slice, arrayProtoFuncSlice, DontEnum, 2);
+    JSC_BUILTIN_FUNCTION(&quot;sort&quot;, arrayPrototypeSortCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION(&quot;splice&quot;, arrayProtoFuncSplice, DontEnum, 2);
+    JSC_NATIVE_FUNCTION(&quot;unshift&quot;, arrayProtoFuncUnShift, DontEnum, 1);
+    JSC_BUILTIN_FUNCTION(&quot;every&quot;, arrayPrototypeEveryCodeGenerator, DontEnum);
+    JSC_BUILTIN_FUNCTION(&quot;forEach&quot;, arrayPrototypeForEachCodeGenerator, DontEnum);
+    JSC_BUILTIN_FUNCTION(&quot;some&quot;, arrayPrototypeSomeCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION(&quot;indexOf&quot;, arrayProtoFuncIndexOf, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(&quot;lastIndexOf&quot;, arrayProtoFuncLastIndexOf, DontEnum, 1);
+    JSC_BUILTIN_FUNCTION(&quot;filter&quot;, arrayPrototypeFilterCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION(&quot;reduce&quot;, arrayProtoFuncReduce, DontEnum, 1);
+    JSC_NATIVE_FUNCTION(&quot;reduceRight&quot;, arrayProtoFuncReduceRight, DontEnum, 1);
+    JSC_BUILTIN_FUNCTION(&quot;map&quot;, arrayPrototypeMapCodeGenerator, DontEnum);
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;entries, arrayProtoFuncEntries, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(vm.propertyNames-&gt;keys, arrayProtoFuncKeys, DontEnum, 0);
+    JSC_BUILTIN_FUNCTION(&quot;find&quot;, arrayPrototypeFindCodeGenerator, DontEnum);
+    JSC_BUILTIN_FUNCTION(&quot;findIndex&quot;, arrayPrototypeFindIndexCodeGenerator, DontEnum);
+    JSC_BUILTIN_FUNCTION(&quot;includes&quot;, arrayPrototypeIncludesCodeGenerator, DontEnum);
+    
</ins><span class="cx">     if (!globalObject-&gt;runtimeFlags().isSymbolDisabled()) {
</span><span class="cx">         JSObject* unscopables = constructEmptyObject(globalObject-&gt;globalExec(), globalObject-&gt;nullPrototypeObjectStructure());
</span><span class="cx">         const char* unscopableNames[] = {
</span><span class="lines">@@ -144,11 +135,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool ArrayPrototype::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot)
-{
-    return getStaticFunctionSlot&lt;JSArray&gt;(exec, arrayPrototypeTable, jsCast&lt;ArrayPrototype*&gt;(object), propertyName, slot);
-}
-
</del><span class="cx"> // ------------------------------ Array Functions ----------------------------
</span><span class="cx"> 
</span><span class="cx"> // Helper function
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArrayPrototypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/runtime/ArrayPrototype.h        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><del>- *  Copyright (C) 2007, 2011 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2007, 2011, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -35,8 +35,6 @@
</span><span class="cx"> 
</span><span class="cx">     static ArrayPrototype* create(VM&amp;, JSGlobalObject*, Structure*);
</span><span class="cx">         
</span><del>-    static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&amp;);
-
</del><span class="cx">     DECLARE_INFO;
</span><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (184031 => 184032)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2015-05-09 00:13:52 UTC (rev 184031)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2015-05-09 00:18:43 UTC (rev 184032)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2009, 2012-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -1557,6 +1557,12 @@
</span><span class="cx"> #define JSC_NATIVE_FUNCTION(jsName, cppName, attributes, length) \
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION(jsName, cppName, (attributes), (length), NoIntrinsic)
</span><span class="cx"> 
</span><ins>+// Identical helpers but for builtins. Note that currently, we don't support builtins that are
+// also intrinsics, but we probably will do that eventually.
+#define JSC_BUILTIN_FUNCTION(jsName, generatorName, attributes) \
+    putDirectBuiltinFunction(\
+        vm, globalObject, makeIdentifier(vm, (jsName)), (generatorName)(vm), (attributes))
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // JSObject_h
</span></span></pre>
</div>
</div>

</body>
</html>