<!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>[210865] branches/safari-603-branch</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/210865">210865</a></dd>
<dt>Author</dt> <dd>matthew_hanson@apple.com</dd>
<dt>Date</dt> <dd>2017-01-18 12:42:19 -0800 (Wed, 18 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/210695">r210695</a>. rdar://problem/29913445</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari603branchJSTestsChangeLog">branches/safari-603-branch/JSTests/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreChangeLog">branches/safari-603-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGCallArrayAllocatorSlowPathGeneratorh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGClobberizeh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGDoesGCcpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGFixupPhasecpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGNodeTypeh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGSafeToExecuteh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJITcpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJITh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreftlFTLCapabilitiescpp">branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCorejitAssemblyHelperscpp">branches/safari-603-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeArrayPrototypecpp">branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeArrayPrototypeh">branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeIntrinsich">branches/safari-603-branch/Source/JavaScriptCore/runtime/Intrinsic.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeJSGlobalObjectcpp">branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeJSGlobalObjecth">branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeStructureh">branches/safari-603-branch/Source/JavaScriptCore/runtime/Structure.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari603branchJSTestsstressarraysliceintrinsicjs">branches/safari-603-branch/JSTests/stress/array-slice-intrinsic.js</a></li>
<li><a href="#branchessafari603branchJSTestsstressarrayslicejettisononconstructorchangejs">branches/safari-603-branch/JSTests/stress/array-slice-jettison-on-constructor-change.js</a></li>
<li><a href="#branchessafari603branchJSTestsstressarraysliceosrexit2js">branches/safari-603-branch/JSTests/stress/array-slice-osr-exit-2.js</a></li>
<li><a href="#branchessafari603branchJSTestsstressarraysliceosrexitjs">branches/safari-603-branch/JSTests/stress/array-slice-osr-exit.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari603branchJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/JSTests/ChangeLog (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/JSTests/ChangeLog        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/JSTests/ChangeLog        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -1,5 +1,45 @@
</span><span class="cx"> 2017-01-18  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r210695. rdar://problem/29913445
+
+    2017-01-12  Saam Barati  &lt;sbarati@apple.com&gt;
+
+            Add a slice intrinsic to the DFG/FTL
+            https://bugs.webkit.org/show_bug.cgi?id=166707
+            &lt;rdar://problem/29913445&gt;
+
+            Reviewed by Filip Pizlo.
+
+            * stress/array-slice-intrinsic.js: Added.
+            (assert):
+            (shallowEq):
+            (runTest1):
+            (runTest2):
+            * stress/array-slice-jettison-on-constructor-change.js: Added.
+            (assert):
+            (runTest1):
+            (runTest2):
+            (addRandomProperties):
+            (runTests):
+            * stress/array-slice-osr-exit-2.js: Added.
+            (assert):
+            (Foo):
+            (shallowEq):
+            (runTest1):
+            (runTest2):
+            (addRandomProperties):
+            (runTests):
+            * stress/array-slice-osr-exit.js: Added.
+            (assert):
+            (Foo):
+            (shallowEq):
+            (runTest1):
+            (runTest2):
+            (addRandomProperties):
+            (runTests):
+
+2017-01-18  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r210837. rdar://problem/29432371
</span><span class="cx"> 
</span><span class="cx">     2017-01-17  Michael Saboff  &lt;msaboff@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchJSTestsstressarraysliceintrinsicjs"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/JSTests/stress/array-slice-intrinsic.js (0 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/JSTests/stress/array-slice-intrinsic.js                                (rev 0)
+++ branches/safari-603-branch/JSTests/stress/array-slice-intrinsic.js        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+function assert(b, ...m) {
+    if (!b)
+        throw new Error(&quot;Bad: &quot;, ...m);
+}
+noInline(assert);
+
+function shallowEq(a, b) {
+    assert(a.length === b.length, a, b);
+    for (let i = 0; i &lt; a.length; i++)
+        assert(a[i] === b[i], a, b);
+}
+noInline(shallowEq);
+
+let tests = [
+    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
+    [[1,2,3,4,5], [1,2,3,4,5], 0],
+    [[1,2,3,4,5], [4], -2, -1],
+    [[1,2,3,4,5], [5], -1],
+    [[1,2,3,4,5], [5], -1, 5],
+    [[1,2,3,4,5], [], -10, -20],
+    [[1,2,3,4,5], [], -20, -10],
+    [[1,2,3,4,5], [], 6, 4],
+    [[1,2,3,4,5], [], 3, 2],
+    [[1,2,3,4,5], [4,5], 3, 10],
+    [[1,2,3,4,5], [3,4,5], 2, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
+    [[1,2,3,4,5], [2,3,4,5], -4, 10],
+];
+
+function runTest1(a, b) {
+    return a.slice(b);
+}
+noInline(runTest1);
+
+function runTest2(a, b, c) {
+    return a.slice(b, c);
+}
+noInline(runTest2);
+
+for (let i = 0; i &lt; 10000; i++) {
+    for (let [input, output, ...args] of tests) {
+        assert(args.length === 1 || args.length === 2);
+        if (args.length === 1)
+            shallowEq(runTest1(input, args[0]), output);
+        else
+            shallowEq(runTest2(input, args[0], args[1]), output);
+    }
+}
</ins></span></pre></div>
<a id="branchessafari603branchJSTestsstressarrayslicejettisononconstructorchangejs"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/JSTests/stress/array-slice-jettison-on-constructor-change.js (0 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/JSTests/stress/array-slice-jettison-on-constructor-change.js                                (rev 0)
+++ branches/safari-603-branch/JSTests/stress/array-slice-jettison-on-constructor-change.js        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+function assert(b, ...m) {
+    if (!b)
+        throw new Error(&quot;Bad: &quot;, ...m)
+}
+noInline(assert);
+
+let shouldBeNewConstructor = false;
+const newConstructor = {};
+
+function shallowEq(a, b) {
+    assert(a.length === b.length, a, b);
+    if (shouldBeNewConstructor)
+        assert(b.constructor === newConstructor);
+    for (let i = 0; i &lt; a.length; i++)
+        assert(a[i] === b[i], a, b);
+}
+noInline(shallowEq);
+
+let tests = [
+    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
+    [[1,2,3,4,5], [1,2,3,4,5], 0],
+    [[1,2,3,4,5], [4], -2, -1],
+    [[1,2,3,4,5], [5], -1],
+    [[1,2,3,4,5], [5], -1, 5],
+    [[1,2,3,4,5], [], -10, -20],
+    [[1,2,3,4,5], [], -20, -10],
+    [[1,2,3,4,5], [], 6, 4],
+    [[1,2,3,4,5], [], 3, 2],
+    [[1,2,3,4,5], [4,5], 3, 10],
+    [[1,2,3,4,5], [3,4,5], 2, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
+    [[1,2,3,4,5], [2,3,4,5], -4, 10],
+];
+
+function runTest1(a, b) {
+    let result = a.slice(b);
+    return result;
+}
+noInline(runTest1);
+
+function runTest2(a, b, c) {
+    let result = a.slice(b, c);
+    return result;
+}
+noInline(runTest2);
+
+function addRandomProperties(input) {
+    for (let i = 0; i &lt; 4; i++) {
+        input[&quot;prop&quot; + i + ((Math.random() * 100000) | 0)] = i;
+    }
+}
+noInline(addRandomProperties);
+
+function runTests() {
+    for (let i = 0; i &lt; 10000; i++) {
+        for (let [input, output, ...args] of tests) {
+            addRandomProperties(input);
+            assert(args.length === 1 || args.length === 2);
+            if (args.length === 1)
+                shallowEq(runTest1(input, args[0]), output);
+            else
+                shallowEq(runTest2(input, args[0], args[1]), output);
+        }
+    }
+}
+
+runTests();
+
+Array.prototype.constructor = newConstructor;
+shouldBeNewConstructor = true;
+runTests();
</ins></span></pre></div>
<a id="branchessafari603branchJSTestsstressarraysliceosrexit2js"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/JSTests/stress/array-slice-osr-exit-2.js (0 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/JSTests/stress/array-slice-osr-exit-2.js                                (rev 0)
+++ branches/safari-603-branch/JSTests/stress/array-slice-osr-exit-2.js        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -0,0 +1,76 @@
</span><ins>+function assert(b, ...m) {
+    if (!b)
+        throw new Error(&quot;Bad: &quot;, ...m)
+}
+noInline(assert);
+
+class Foo extends Array {
+    constructor(...args) {
+        super(...args);
+    }
+};
+function shallowEq(a, b) {
+    assert(a.length === b.length, a, b);
+    for (let i = 0; i &lt; a.length; i++)
+        assert(a[i] === b[i], a, b);
+}
+noInline(shallowEq);
+
+let tests = [
+    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
+    [[1,2,3,4,5], [1,2,3,4,5], 0],
+    [[1,2,3,4,5], [4], -2, -1],
+    [[1,2,3,4,5], [5], -1],
+    [[1,2,3,4,5], [5], -1, 5],
+    [[1,2,3,4,5], [], -10, -20],
+    [[1,2,3,4,5], [], -20, -10],
+    [[1,2,3,4,5], [], 6, 4],
+    [[1,2,3,4,5], [], 3, 2],
+    [[1,2,3,4,5], [4,5], 3, 10],
+    [[1,2,3,4,5], [3,4,5], 2, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
+    [[1,2,3,4,5], [2,3,4,5], -4, 10],
+];
+
+function runTest1(a, b) {
+    let result = a.slice(b);
+    assert(a instanceof Foo === result instanceof Foo);
+    return result;
+}
+noInline(runTest1);
+
+function runTest2(a, b, c) {
+    let result = a.slice(b, c);
+    assert(a instanceof Foo === result instanceof Foo);
+    return result;
+}
+noInline(runTest2);
+
+function addRandomProperties(input) {
+    for (let i = 0; i &lt; 4; i++) {
+        input[&quot;prop&quot; + i + ((Math.random() * 100000) | 0)] = i;
+    }
+}
+noInline(addRandomProperties);
+
+function runTests() {
+    for (let i = 0; i &lt; 10000; i++) {
+        for (let [input, output, ...args] of tests) {
+            addRandomProperties(input);
+            assert(args.length === 1 || args.length === 2);
+            if (args.length === 1)
+                shallowEq(runTest1(input, args[0]), output);
+            else
+                shallowEq(runTest2(input, args[0], args[1]), output);
+        }
+    }
+}
+
+runTests();
+
+tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -10, 10]);
+tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -5, 10]);
+tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4, 10]);
+tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4]);
+runTests();
</ins></span></pre></div>
<a id="branchessafari603branchJSTestsstressarraysliceosrexitjs"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/JSTests/stress/array-slice-osr-exit.js (0 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/JSTests/stress/array-slice-osr-exit.js                                (rev 0)
+++ branches/safari-603-branch/JSTests/stress/array-slice-osr-exit.js        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -0,0 +1,74 @@
</span><ins>+function assert(b, ...m) {
+    if (!b)
+        throw new Error(&quot;Bad: &quot;, ...m)
+}
+noInline(assert);
+
+class Foo extends Array {
+    constructor(...args) {
+        super(...args);
+    }
+};
+function shallowEq(a, b) {
+    assert(a.length === b.length, a, b);
+    for (let i = 0; i &lt; a.length; i++)
+        assert(a[i] === b[i], a, b);
+}
+noInline(shallowEq);
+
+let tests = [
+    [[1,2,3,4,5], [1,2,3,4,5], 0, 5],
+    [[1,2,3,4,5], [1,2,3,4,5], 0],
+    [[1,2,3,4,5], [4], -2, -1],
+    [[1,2,3,4,5], [5], -1],
+    [[1,2,3,4,5], [5], -1, 5],
+    [[1,2,3,4,5], [], -10, -20],
+    [[1,2,3,4,5], [], -20, -10],
+    [[1,2,3,4,5], [], 6, 4],
+    [[1,2,3,4,5], [], 3, 2],
+    [[1,2,3,4,5], [4,5], 3, 10],
+    [[1,2,3,4,5], [3,4,5], 2, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -10, 10],
+    [[1,2,3,4,5], [1,2,3,4,5], -5, 10],
+    [[1,2,3,4,5], [2,3,4,5], -4, 10],
+];
+tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -10, 10]);
+tests.push([new Foo(1,2,3,4,5), [1,2,3,4,5], -5, 10]);
+tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4, 10]);
+tests.push([new Foo(1,2,3,4,5), [2,3,4,5], -4]);
+
+function runTest1(a, b) {
+    let result = a.slice(b);
+    assert(a instanceof Foo === result instanceof Foo);
+    return result;
+}
+noInline(runTest1);
+
+function runTest2(a, b, c) {
+    let result = a.slice(b, c);
+    assert(a instanceof Foo === result instanceof Foo);
+    return result;
+}
+noInline(runTest2);
+
+function addRandomProperties(input) {
+    for (let i = 0; i &lt; 4; i++) {
+        input[&quot;prop&quot; + i + ((Math.random() * 100000) | 0)] = i;
+    }
+}
+noInline(addRandomProperties);
+
+function runTests() {
+    for (let i = 0; i &lt; 10000; i++) {
+        for (let [input, output, ...args] of tests) {
+            addRandomProperties(input);
+            assert(args.length === 1 || args.length === 2);
+            if (args.length === 1)
+                shallowEq(runTest1(input, args[0]), output);
+            else
+                shallowEq(runTest2(input, args[0], args[1]), output);
+        }
+    }
+}
+
+runTests();
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ChangeLog (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -1,5 +1,111 @@
</span><span class="cx"> 2017-01-18  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r210695. rdar://problem/29913445
+
+    2017-01-12  Saam Barati  &lt;sbarati@apple.com&gt;
+
+            Add a slice intrinsic to the DFG/FTL
+            https://bugs.webkit.org/show_bug.cgi?id=166707
+            &lt;rdar://problem/29913445&gt;
+
+            Reviewed by Filip Pizlo.
+
+            The gist of this patch is to inline Array.prototype.slice
+            into the DFG/FTL. The implementation in the DFG-backend
+            and FTLLowerDFGToB3 is just a straight forward implementation
+            of what the C function is doing. The more interesting bits
+            of this patch are setting up the proper watchpoints and conditions
+            in the executing code to prove that its safe to skip all of the
+            observable JS actions that Array.prototype.slice normally does.
+
+            We perform the following proofs:
+            1. Array.prototype.constructor has not changed (via a watchpoint).
+            2. That Array.prototype.constructor[Symbol.species] has not changed (via a watchpoint).
+            3. The global object is not having a bad time.
+            4. The array that is being sliced has an original array structure.
+            5. Array.prototype/Object.prototype have not transitioned.
+
+            Conditions 1, 2, and 3 are strictly required.
+
+            4 is ensuring a couple things:
+            1. That a &quot;constructor&quot; property hasn't been added to the array
+            we're slicing since we're supposed to perform a Get(array, &quot;constructor&quot;).
+            2. That we're not slicing an instance of a subclass of Array.
+
+            We could relax 4.1 in the future if we find other ways to test if
+            the incoming array hasn't changed the &quot;constructor&quot; property. We
+            would probably use TryGetById to do this.
+
+            I'm seeing a 5% speedup on crypto-pbkdf2 and often a 1% speedup on
+            the total benchmark (the results are sometimes noisy).
+
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+            * dfg/DFGCallArrayAllocatorSlowPathGenerator.h:
+            (JSC::DFG::CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator::CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator):
+            * dfg/DFGClobberize.h:
+            (JSC::DFG::clobberize):
+            * dfg/DFGDoesGC.cpp:
+            (JSC::DFG::doesGC):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGNodeType.h:
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::safeToExecute):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::compileArraySlice):
+            (JSC::DFG::SpeculativeJIT::emitAllocateButterfly):
+            * dfg/DFGSpeculativeJIT.h:
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            (JSC::DFG::SpeculativeJIT::emitInitializeButterfly):
+            (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            (JSC::DFG::SpeculativeJIT::emitInitializeButterfly):
+            (JSC::DFG::SpeculativeJIT::compileAllocateNewArrayWithSize):
+            * ftl/FTLAbstractHeapRepository.h:
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLowerDFGToB3.cpp:
+            (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+            (JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
+            (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
+            (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewObject):
+            (JSC::FTL::DFG::LowerDFGToB3::initializeArrayElements):
+            (JSC::FTL::DFG::LowerDFGToB3::storeStructure):
+            (JSC::FTL::DFG::LowerDFGToB3::allocateCell):
+            (JSC::FTL::DFG::LowerDFGToB3::allocateObject):
+            (JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
+            (JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArray):
+            * jit/AssemblyHelpers.cpp:
+            (JSC::AssemblyHelpers::emitLoadStructure):
+            * runtime/ArrayPrototype.cpp:
+            (JSC::ArrayPrototype::finishCreation):
+            (JSC::speciesWatchpointIsValid):
+            (JSC::speciesConstructArray):
+            (JSC::arrayProtoFuncSlice):
+            (JSC::arrayProtoPrivateFuncConcatMemcpy):
+            (JSC::ArrayPrototype::initializeSpeciesWatchpoint):
+            (JSC::ArrayPrototypeAdaptiveInferredPropertyWatchpoint::handleFire):
+            (JSC::speciesWatchpointsValid): Deleted.
+            (JSC::ArrayPrototype::attemptToInitializeSpeciesWatchpoint): Deleted.
+            * runtime/ArrayPrototype.h:
+            (JSC::ArrayPrototype::speciesWatchpointStatus): Deleted.
+            (): Deleted.
+            * runtime/Intrinsic.h:
+            * runtime/JSGlobalObject.cpp:
+            (JSC::JSGlobalObject::JSGlobalObject):
+            (JSC::JSGlobalObject::init):
+            * runtime/JSGlobalObject.h:
+            (JSC::JSGlobalObject::arraySpeciesWatchpoint):
+            * runtime/Structure.h:
+
+2017-01-18  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r210837. rdar://problem/29432371
</span><span class="cx"> 
</span><span class="cx">     2017-01-17  Michael Saboff  &lt;msaboff@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -1650,6 +1650,20 @@
</span><span class="cx">         clobberWorld(node-&gt;origin.semantic, clobberLimit);
</span><span class="cx">         forNode(node).setType(SpecBytecodeNumber);
</span><span class="cx">         break;
</span><ins>+
+    case ArraySlice: {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(node-&gt;origin.semantic);
+
+        // FIXME: We could do better here if we prove that the
+        // incoming value has only a single structure.
+        StructureSet structureSet;
+        structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithInt32));
+        structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithContiguous));
+        structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithDouble));
+
+        forNode(node).set(m_graph, structureSet);
+        break;
+    }
</ins><span class="cx">             
</span><span class="cx">     case ArrayPop:
</span><span class="cx">         clobberWorld(node-&gt;origin.semantic, clobberLimit);
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -2246,6 +2246,94 @@
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    case ArraySliceIntrinsic: {
+#if USE(JSVALUE32_64)
+        if (isX86()) {
+            // There aren't enough registers for this to be done easily.
+            return false;
+        }
+#endif
+        if (argumentCountIncludingThis &lt; 2)
+            return false;
+
+        if (m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
+            || m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCache))
+            return false;
+
+        ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
+        if (!arrayMode.isJSArray())
+            return false;
+
+        if (arrayMode.arrayClass() != Array::OriginalArray)
+            return false;
+
+        switch (arrayMode.type()) {
+        case Array::Double:
+        case Array::Int32:
+        case Array::Contiguous: {
+            JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
+
+            InlineWatchpointSet&amp; objectPrototypeTransition = globalObject-&gt;objectPrototype()-&gt;structure()-&gt;transitionWatchpointSet();
+            InlineWatchpointSet&amp; arrayPrototypeTransition = globalObject-&gt;arrayPrototype()-&gt;structure()-&gt;transitionWatchpointSet();
+
+            // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
+            if (globalObject-&gt;arraySpeciesWatchpoint().isStillValid()
+                &amp;&amp; globalObject-&gt;havingABadTimeWatchpoint()-&gt;isStillValid()
+                &amp;&amp; arrayPrototypeTransition.isStillValid()
+                &amp;&amp; objectPrototypeTransition.isStillValid()
+                &amp;&amp; globalObject-&gt;arrayPrototypeChainIsSane()) {
+
+                m_graph.watchpoints().addLazily(globalObject-&gt;arraySpeciesWatchpoint());
+                m_graph.watchpoints().addLazily(globalObject-&gt;havingABadTimeWatchpoint());
+                m_graph.watchpoints().addLazily(arrayPrototypeTransition);
+                m_graph.watchpoints().addLazily(objectPrototypeTransition);
+
+                insertChecks();
+
+                Node* array = get(virtualRegisterForArgument(0, registerOffset));
+                // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
+                // 1. We ensure that the &quot;constructor&quot; property hasn't been changed (because the observable
+                // effects of slice require that we perform a Get(array, &quot;constructor&quot;) and we can skip
+                // that if we're an original array structure. (We can relax this in the future by using
+                // TryGetById and CheckCell).
+                //
+                // 2. We check that the array we're calling slice on has the same global object as the lexical
+                // global object that this code is running in. This requirement is necessary because we setup the
+                // watchpoints above on the lexical global object. This means that code that calls slice on
+                // arrays produced by other global objects won't get this optimization. We could relax this
+                // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
+                // we generate instead of registering it as a watchpoint that would invalidate the compilation.
+                //
+                // 3. By proving we're an original array structure, we guarantee that the incoming array
+                // isn't a subclass of Array.
+
+                StructureSet structureSet;
+                structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithInt32));
+                structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithContiguous));
+                structureSet.add(globalObject-&gt;originalArrayStructureForIndexingType(ArrayWithDouble));
+                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
+
+                addVarArgChild(array);
+                addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
+                if (argumentCountIncludingThis &gt;= 3)
+                    addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
+                addVarArgChild(addToGraph(GetButterfly, array));
+
+                Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
+                set(VirtualRegister(resultOperand), arraySlice);
+                return true;
+            }
+
+            return false;
+        }
+        default:
+            return false;
+        }
+
+        RELEASE_ASSERT_NOT_REACHED();
+        return false;
+    }
</ins><span class="cx">         
</span><span class="cx">     case ArrayPopIntrinsic: {
</span><span class="cx">         if (argumentCountIncludingThis != 1)
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGCallArrayAllocatorSlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGCallArrayAllocatorSlowPathGenerator.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -124,6 +124,45 @@
</span><span class="cx">     Vector&lt;SilentRegisterSavePlan, 2&gt; m_plans;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator : public JumpingSlowPathGenerator&lt;MacroAssembler::JumpList&gt; {
+public:
+    CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator(
+        MacroAssembler::JumpList from, SpeculativeJIT* jit, P_JITOperation_EStZB function,
+        GPRReg resultGPR, GPRReg structureGPR, GPRReg sizeGPR, GPRReg storageGPR, GPRReg scratchGPR)
+        : JumpingSlowPathGenerator&lt;MacroAssembler::JumpList&gt;(from, jit)
+        , m_function(function)
+        , m_resultGPR(resultGPR)
+        , m_structureGPR(structureGPR)
+        , m_sizeGPR(sizeGPR)
+        , m_storageGPR(storageGPR)
+        , m_scratchGPR(scratchGPR)
+    {
+        jit-&gt;silentSpillAllRegistersImpl(false, m_plans, resultGPR, m_scratchGPR);
+    }
+
+protected:
+    void generateInternal(SpeculativeJIT* jit) override
+    {
+        linkFrom(jit);
+        for (unsigned i = 0; i &lt; m_plans.size(); ++i)
+            jit-&gt;silentSpill(m_plans[i]);
+        jit-&gt;callOperation(m_function, m_resultGPR, m_structureGPR, m_sizeGPR, m_storageGPR);
+        for (unsigned i = m_plans.size(); i--;)
+            jit-&gt;silentFill(m_plans[i], m_scratchGPR);
+        jit-&gt;m_jit.exceptionCheck();
+        jumpTo(jit);
+    }
+    
+private:
+    P_JITOperation_EStZB m_function;
+    GPRReg m_resultGPR;
+    GPRReg m_structureGPR;
+    GPRReg m_sizeGPR;
+    GPRReg m_storageGPR;
+    GPRReg m_scratchGPR;
+    Vector&lt;SilentRegisterSavePlan, 2&gt; m_plans;
+};
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGClobberize.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGClobberize.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGClobberize.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -503,6 +503,19 @@
</span><span class="cx">         read(MiscFields);
</span><span class="cx">         def(HeapLocation(IsFunctionLoc, MiscFields, node-&gt;child1()), LazyNode(node));
</span><span class="cx">         return;
</span><ins>+
+    case ArraySlice:
+        read(MiscFields);
+        read(JSCell_indexingType);
+        read(JSCell_structureID);
+        read(JSObject_butterfly);
+        read(Butterfly_publicLength);
+        read(IndexedDoubleProperties);
+        read(IndexedInt32Properties);
+        read(IndexedContiguousProperties);
+        read(HeapObjectCount);
+        write(HeapObjectCount);
+        return;
</ins><span class="cx">         
</span><span class="cx">     case GetById:
</span><span class="cx">     case GetByIdFlush:
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -309,6 +309,7 @@
</span><span class="cx">     case ToLowerCase:
</span><span class="cx">     case CallDOMGetter:
</span><span class="cx">     case CallDOM:
</span><ins>+    case ArraySlice:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -931,6 +931,14 @@
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+
+        case ArraySlice: {
+            fixEdge&lt;KnownCellUse&gt;(m_graph.varArgChild(node, 0));
+            fixEdge&lt;Int32Use&gt;(m_graph.varArgChild(node, 1));
+            if (node-&gt;numChildren() == 4)
+                fixEdge&lt;Int32Use&gt;(m_graph.varArgChild(node, 2));
+            break;
+        }
</ins><span class="cx">             
</span><span class="cx">         case RegExpExec:
</span><span class="cx">         case RegExpTest: {
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGNodeType.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGNodeType.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGNodeType.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -248,6 +248,7 @@
</span><span class="cx">     /* Optimizations for array mutation. */\
</span><span class="cx">     macro(ArrayPush, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(ArrayPop, NodeResultJS | NodeMustGenerate) \
</span><ins>+    macro(ArraySlice, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \
</ins><span class="cx">     \
</span><span class="cx">     /* Optimizations for regular expression matching. */\
</span><span class="cx">     macro(RegExpExec, NodeResultJS | NodeMustGenerate) \
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -860,6 +860,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><ins>+        case ArraySlice:
</ins><span class="cx">         case NewArrayWithSpread:
</span><span class="cx">         case NewArray:
</span><span class="cx">         case NewArrayWithSize:
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -382,6 +382,13 @@
</span><span class="cx">     case IsNonEmptyMapBucket:
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><ins>+    case ArraySlice: {
+        // You could plausibly move this code around as long as you proved the
+        // incoming array base structure is an original array at the hoisted location.
+        // Instead of doing that extra work, we just conservatively return false.
+        return false;
+    }
+
</ins><span class="cx">     case BottomValue:
</span><span class="cx">         // If in doubt, assume that this isn't safe to execute, just because we have no way of
</span><span class="cx">         // compiling this node.
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -7169,6 +7169,182 @@
</span><span class="cx">     int32Result(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileArraySlice(Node* node)
+{
+    ASSERT(node-&gt;op() == ArraySlice);
+
+    JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node-&gt;origin.semantic);
+
+    GPRTemporary temp(this);
+    StorageOperand storage(this, node-&gt;numChildren() == 3 ? m_jit.graph().varArgChild(node, 2) : m_jit.graph().varArgChild(node, 3));
+    GPRTemporary result(this);
+    
+    GPRReg storageGPR = storage.gpr();
+    GPRReg resultGPR = result.gpr();
+    GPRReg tempGPR = temp.gpr();
+
+    auto populateIndex = [&amp;] (unsigned childIndex, GPRReg length, GPRReg result) {
+        SpeculateInt32Operand index(this, m_jit.graph().varArgChild(node, childIndex));
+        GPRReg indexGPR = index.gpr();
+        MacroAssembler::JumpList done;
+        auto isPositive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, indexGPR, TrustedImm32(0));
+        m_jit.move(length, result);
+        done.append(m_jit.branchAdd32(MacroAssembler::PositiveOrZero, indexGPR, result));
+        m_jit.move(TrustedImm32(0), result);
+        done.append(m_jit.jump());
+
+        isPositive.link(&amp;m_jit);
+        m_jit.move(indexGPR, result);
+        done.append(m_jit.branch32(MacroAssembler::BelowOrEqual, result, length));
+        m_jit.move(length, result);
+
+        done.link(&amp;m_jit);
+    };
+
+    {
+        GPRTemporary tempLength(this);
+        GPRReg lengthGPR = tempLength.gpr();
+        m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), lengthGPR);
+
+        if (node-&gt;numChildren() == 4)
+            populateIndex(2, lengthGPR, tempGPR);
+        else
+            m_jit.move(lengthGPR, tempGPR);
+
+        GPRTemporary tempStartIndex(this);
+        GPRReg startGPR = tempStartIndex.gpr();
+        populateIndex(1, lengthGPR, startGPR);
+
+        auto tooBig = m_jit.branch32(MacroAssembler::Above, startGPR, tempGPR);
+        m_jit.sub32(startGPR, tempGPR); // the size of the array we'll make.
+        auto done = m_jit.jump();
+
+        tooBig.link(&amp;m_jit);
+        m_jit.move(TrustedImm32(0), tempGPR);
+        done.link(&amp;m_jit);
+    }
+
+
+    GPRTemporary temp3(this);
+    GPRReg tempValue = temp3.gpr();
+    {
+        SpeculateCellOperand cell(this, m_jit.graph().varArgChild(node, 0));
+        m_jit.load8(MacroAssembler::Address(cell.gpr(), JSCell::indexingTypeAndMiscOffset()), tempValue);
+        m_jit.and32(TrustedImm32(AllArrayTypesAndHistory), tempValue);
+    }
+
+    {
+#if USE(JSVALUE64)
+        GPRTemporary emptyValue(this);
+        JSValueRegs emptyValueRegs = JSValueRegs(emptyValue.gpr());
+#else
+        GPRTemporary emptyValuePayload(this);
+        GPRTemporary emptyValueTag(this);
+        JSValueRegs emptyValueRegs(emptyValueTag.gpr(), emptyValuePayload.gpr());
+#endif
+
+        GPRTemporary storage(this);
+        GPRReg storageResultGPR = storage.gpr();
+
+        GPRReg sizeGPR = tempGPR; 
+
+        CCallHelpers::JumpList done;
+
+        auto emitMoveEmptyValue = [&amp;] (JSValue v) {
+#if USE(JSVALUE64)
+            m_jit.move(TrustedImm64(JSValue::encode(v)), emptyValueRegs.gpr());
+#else
+            m_jit.move(TrustedImm32(v.tag()), emptyValueRegs.tagGPR());
+            m_jit.move(TrustedImm32(v.payload()), emptyValueRegs.payloadGPR());
+#endif
+        };
+
+        auto isContiguous = m_jit.branch32(MacroAssembler::Equal, tempValue, TrustedImm32(ArrayWithContiguous));
+        auto isInt32 = m_jit.branch32(MacroAssembler::Equal, tempValue, TrustedImm32(ArrayWithInt32));
+        // When we emit an ArraySlice, we dominate the use of the array by a CheckStructure
+        // to ensure the incoming array is one to be one of the original array structures
+        // with one of the following indexing shapes: Int32, Contiguous, Double. Therefore,
+        // we're a double array here.
+        m_jit.move(TrustedImmPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)), tempValue);
+        emitMoveEmptyValue(jsNaN());
+        done.append(m_jit.jump());
+
+        isContiguous.link(&amp;m_jit);
+        m_jit.move(TrustedImmPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)), tempValue);
+        emitMoveEmptyValue(JSValue());
+        done.append(m_jit.jump());
+
+        isInt32.link(&amp;m_jit);
+        m_jit.move(TrustedImmPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32)), tempValue);
+        emitMoveEmptyValue(JSValue());
+
+        done.link(&amp;m_jit);
+
+        {
+            GPRTemporary scratch(this);
+            GPRTemporary scratch2(this);
+            GPRReg scratchGPR = scratch.gpr();
+            GPRReg scratch2GPR = scratch2.gpr();
+
+            MacroAssembler::JumpList slowCases;
+            m_jit.move(TrustedImmPtr(0), storageResultGPR);
+
+            emitAllocateButterfly(storageResultGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases);
+            emitInitializeButterfly(storageResultGPR, sizeGPR, emptyValueRegs, scratchGPR);
+            emitAllocateJSObject&lt;JSArray&gt;(resultGPR, tempValue, storageResultGPR, scratchGPR, scratch2GPR, slowCases);
+            m_jit.mutatorFence();
+
+            addSlowPathGenerator(std::make_unique&lt;CallArrayAllocatorWithVariableStructureVariableSizeSlowPathGenerator&gt;(
+                slowCases, this, operationNewArrayWithSize, resultGPR, tempValue, sizeGPR, storageResultGPR, scratchGPR));
+        }
+    }
+
+    GPRTemporary temp4(this);
+    GPRReg loadIndex = temp4.gpr();
+
+    m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), tempValue);
+    if (node-&gt;numChildren() == 4)
+        populateIndex(2, tempValue, tempGPR);
+    else
+        m_jit.move(tempValue, tempGPR);
+    populateIndex(1, tempValue, loadIndex);
+
+    GPRTemporary temp5(this);
+    GPRReg storeIndex = temp5.gpr();
+    m_jit.move(TrustedImmPtr(0), storeIndex);
+
+    GPRTemporary temp2(this);
+    GPRReg resultButterfly = temp2.gpr();
+
+    m_jit.loadPtr(MacroAssembler::Address(resultGPR, JSObject::butterflyOffset()), resultButterfly);
+    m_jit.zeroExtend32ToPtr(tempGPR, tempGPR);
+    m_jit.zeroExtend32ToPtr(loadIndex, loadIndex);
+    auto done = m_jit.branchPtr(MacroAssembler::AboveOrEqual, loadIndex, tempGPR);
+
+    auto loop = m_jit.label();
+#if USE(JSVALUE64)
+    m_jit.load64(
+        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight), tempValue);
+    m_jit.store64(
+        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight));
+#else
+    m_jit.load32(
+        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight, PayloadOffset), tempValue);
+    m_jit.store32(
+        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight, PayloadOffset));
+    m_jit.load32(
+        MacroAssembler::BaseIndex(storageGPR, loadIndex, MacroAssembler::TimesEight, TagOffset), tempValue);
+    m_jit.store32(
+        tempValue, MacroAssembler::BaseIndex(resultButterfly, storeIndex, MacroAssembler::TimesEight, TagOffset));
+#endif // USE(JSVALUE64)
+    m_jit.addPtr(TrustedImm32(1), loadIndex);
+    m_jit.addPtr(TrustedImm32(1), storeIndex);
+    m_jit.branchPtr(MacroAssembler::Below, loadIndex, tempGPR).linkTo(loop, &amp;m_jit);
+
+    done.link(&amp;m_jit);
+    cellResult(resultGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileNotifyWrite(Node* node)
</span><span class="cx"> {
</span><span class="cx">     WatchpointSet* set = node-&gt;watchpointSet();
</span><span class="lines">@@ -9381,6 +9557,21 @@
</span><span class="cx">     noResult(node, UseChildrenCalledExplicitly);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::emitAllocateButterfly(GPRReg storageResultGPR, GPRReg sizeGPR, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, MacroAssembler::JumpList&amp; slowCases)
+{
+    RELEASE_ASSERT(RegisterSet(storageResultGPR, sizeGPR, scratch1, scratch2, scratch3).numberOfSetGPRs() == 5);
+    ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
+    m_jit.zeroExtend32ToPtr(sizeGPR, scratch1);
+    m_jit.lshift32(TrustedImm32(3), scratch1);
+    m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratch1, scratch2);
+    m_jit.emitAllocateVariableSized(
+        storageResultGPR, m_jit.vm()-&gt;heap.subspaceForAuxiliaryData(), scratch2, scratch1, scratch3, slowCases);
+    m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageResultGPR);
+
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageResultGPR, Butterfly::offsetOfPublicLength()));
+    m_jit.store32(sizeGPR, MacroAssembler::Address(storageResultGPR, Butterfly::offsetOfVectorLength()));
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -743,6 +743,8 @@
</span><span class="cx"> 
</span><span class="cx">     void emitCall(Node*);
</span><span class="cx"> 
</span><ins>+    void emitAllocateButterfly(GPRReg storageGPR, GPRReg sizeGPR, GPRReg scratch1, GPRReg scratch2, GPRReg scratch3, MacroAssembler::JumpList&amp; slowCases);
+    void emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR);
</ins><span class="cx">     void compileAllocateNewArrayWithSize(JSGlobalObject*, GPRReg resultGPR, GPRReg sizeGPR, IndexingType, bool shouldConvertLargeSizeToArrayStorage = true);
</span><span class="cx">     
</span><span class="cx">     // Called once a node has completed code generation but prior to setting
</span><span class="lines">@@ -2680,6 +2682,7 @@
</span><span class="cx">     void compileSpread(Node*);
</span><span class="cx">     void compileNewArrayWithSpread(Node*);
</span><span class="cx">     void compileGetRestLength(Node*);
</span><ins>+    void compileArraySlice(Node*);
</ins><span class="cx">     void compileNotifyWrite(Node*);
</span><span class="cx">     bool compileRegExpExec(Node*);
</span><span class="cx">     void compileIsObjectOrNull(Node*);
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -3550,6 +3550,11 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case ArraySlice: {
+        compileArraySlice(node);
+        break;
+    }
+
</ins><span class="cx">     case DFG::Jump: {
</span><span class="cx">         jump(node-&gt;targetBlock());
</span><span class="cx">         noResult(node);
</span><span class="lines">@@ -5666,6 +5671,18 @@
</span><span class="cx">     doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)
+{
+    m_jit.move(sizeGPR, scratchGPR);
+    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
+    MacroAssembler::Label loop = m_jit.label();
+    m_jit.sub32(TrustedImm32(1), scratchGPR);
+    m_jit.store32(emptyValueRegs.tagGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+    m_jit.store32(emptyValueRegs.payloadGPR(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+    m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &amp;m_jit);
+    done.link(&amp;m_jit);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
</span><span class="cx"> {
</span><span class="cx">     GPRTemporary storage(this);
</span><span class="lines">@@ -5681,34 +5698,21 @@
</span><span class="cx">     MacroAssembler::JumpList slowCases;
</span><span class="cx">     if (shouldConvertLargeSizeToArrayStorage)
</span><span class="cx">         slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
</span><del>-            
-    ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
-    m_jit.move(sizeGPR, scratchGPR);
-    m_jit.lshift32(TrustedImm32(3), scratchGPR);
-    m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
-    m_jit.emitAllocateVariableSized(
-        storageGPR, m_jit.vm()-&gt;heap.subspaceForAuxiliaryData(), resultGPR, scratchGPR,
-        scratch2GPR, slowCases);
-    m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageGPR);
</del><span class="cx"> 
</span><del>-    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
-    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-            
</del><ins>+    // We can use result as a scratch for this.
+    emitAllocateButterfly(storageGPR, sizeGPR, scratchGPR, scratch2GPR, resultGPR, slowCases);
+
</ins><span class="cx">     JSValue hole;
</span><span class="cx">     if (hasDouble(indexingType))
</span><span class="cx">         hole = JSValue(JSValue::EncodeAsDouble, PNaN);
</span><span class="cx">     else
</span><span class="cx">         hole = JSValue();
</span><ins>+    JSValueRegs emptyValueRegs(scratchGPR, scratch2GPR);
+    m_jit.move(TrustedImm32(hole.tag()), emptyValueRegs.tagGPR());
+    m_jit.move(TrustedImm32(hole.payload()), emptyValueRegs.payloadGPR());
+    // We can use result as a scratch for this.
+    emitInitializeButterfly(storageGPR, sizeGPR, emptyValueRegs, resultGPR);
</ins><span class="cx">             
</span><del>-    m_jit.move(sizeGPR, scratchGPR);
-    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
-    MacroAssembler::Label loop = m_jit.label();
-    m_jit.sub32(TrustedImm32(1), scratchGPR);
-    m_jit.store32(TrustedImm32(hole.u.asBits.tag), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
-    m_jit.store32(TrustedImm32(hole.u.asBits.payload), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
-    m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &amp;m_jit);
-    done.link(&amp;m_jit);
-    
</del><span class="cx">     Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
</span><span class="cx">     emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
</span><span class="cx">             
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -3462,6 +3462,11 @@
</span><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><ins>+
+    case ArraySlice: {
+        compileArraySlice(node);
+        break;
+    }
</ins><span class="cx">         
</span><span class="cx">     case ArrayPop: {
</span><span class="cx">         ASSERT(node-&gt;arrayMode().isJSArray());
</span><span class="lines">@@ -5939,6 +5944,17 @@
</span><span class="cx">     doubleResult(result.fpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::emitInitializeButterfly(GPRReg storageGPR, GPRReg sizeGPR, JSValueRegs emptyValueRegs, GPRReg scratchGPR)
+{
+    m_jit.zeroExtend32ToPtr(sizeGPR, scratchGPR);
+    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratchGPR);
+    MacroAssembler::Label loop = m_jit.label();
+    m_jit.sub32(TrustedImm32(1), scratchGPR);
+    m_jit.store64(emptyValueRegs.gpr(), MacroAssembler::BaseIndex(storageGPR, scratchGPR, MacroAssembler::TimesEight));
+    m_jit.branchTest32(MacroAssembler::NonZero, scratchGPR).linkTo(loop, &amp;m_jit);
+    done.link(&amp;m_jit);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileAllocateNewArrayWithSize(JSGlobalObject* globalObject, GPRReg resultGPR, GPRReg sizeGPR, IndexingType indexingType, bool shouldConvertLargeSizeToArrayStorage)
</span><span class="cx"> {
</span><span class="cx">     GPRTemporary storage(this);
</span><span class="lines">@@ -5955,30 +5971,15 @@
</span><span class="cx">     if (shouldConvertLargeSizeToArrayStorage)
</span><span class="cx">         slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_ARRAY_STORAGE_CONSTRUCTION_LENGTH)));
</span><span class="cx">             
</span><del>-    ASSERT((1 &lt;&lt; 3) == sizeof(JSValue));
-    m_jit.move(sizeGPR, scratchGPR);
-    m_jit.lshift32(TrustedImm32(3), scratchGPR);
-    m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
-    m_jit.emitAllocateVariableSized(
-        storageGPR, m_jit.vm()-&gt;heap.subspaceForAuxiliaryData(), resultGPR, scratchGPR,
-        scratch2GPR, slowCases);
-    m_jit.addPtr(TrustedImm32(sizeof(IndexingHeader)), storageGPR);
</del><ins>+    // We can use resultGPR as a scratch right now.
+    emitAllocateButterfly(storageGPR, sizeGPR, resultGPR, scratchGPR, scratch2GPR, slowCases);
</ins><span class="cx"> 
</span><del>-    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
-    m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
-            
</del><span class="cx">     if (hasDouble(indexingType))
</span><span class="cx">         m_jit.move(TrustedImm64(bitwise_cast&lt;int64_t&gt;(PNaN)), scratchGPR);
</span><span class="cx">     else
</span><span class="cx">         m_jit.move(TrustedImm64(JSValue::encode(JSValue())), scratchGPR);
</span><del>-    m_jit.move(sizeGPR, scratch2GPR);
-    MacroAssembler::Jump done = m_jit.branchTest32(MacroAssembler::Zero, scratch2GPR);
-    MacroAssembler::Label loop = m_jit.label();
-    m_jit.sub32(TrustedImm32(1), scratch2GPR);
-    m_jit.store64(scratchGPR, MacroAssembler::BaseIndex(storageGPR, scratch2GPR, MacroAssembler::TimesEight));
-    m_jit.branchTest32(MacroAssembler::NonZero, scratch2GPR).linkTo(loop, &amp;m_jit);
-    done.link(&amp;m_jit);
-    
</del><ins>+    emitInitializeButterfly(storageGPR, sizeGPR, JSValueRegs(scratchGPR), scratch2GPR);
+
</ins><span class="cx">     Structure* structure = globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType);
</span><span class="cx">     
</span><span class="cx">     emitAllocateJSObject&lt;JSArray&gt;(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -107,6 +107,8 @@
</span><span class="cx">     macro(Structure_globalObject, Structure::globalObjectOffset()) \
</span><span class="cx">     macro(Structure_prototype, Structure::prototypeOffset()) \
</span><span class="cx">     macro(Structure_structureID, Structure::structureIDOffset()) \
</span><ins>+    macro(Structure_inlineCapacity, Structure::inlineCapacityOffset()) \
+    macro(Structure_indexingTypeIncludingHistory, Structure::indexingTypeIncludingHistoryOffset()) \
</ins><span class="cx">     macro(JSMap_hashMapImpl, JSMap::offsetOfHashMapImpl()) \
</span><span class="cx">     macro(JSSet_hashMapImpl, JSSet::offsetOfHashMapImpl()) \
</span><span class="cx">     macro(HashMapImpl_capacity, HashMapImpl&lt;HashMapBucket&lt;HashMapBucketDataKey&gt;&gt;::offsetOfCapacity()) \
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -282,6 +282,7 @@
</span><span class="cx">     case CheckDOM:
</span><span class="cx">     case CallDOM:
</span><span class="cx">     case CallDOMGetter:
</span><ins>+    case ArraySlice:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -706,6 +706,9 @@
</span><span class="cx">         case ArrayPop:
</span><span class="cx">             compileArrayPop();
</span><span class="cx">             break;
</span><ins>+        case ArraySlice:
+            compileArraySlice();
+            break;
</ins><span class="cx">         case CreateActivation:
</span><span class="cx">             compileCreateActivation();
</span><span class="cx">             break;
</span><span class="lines">@@ -3860,6 +3863,75 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+
+    void compileArraySlice()
+    {
+        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
+
+        LValue sourceStorage = lowStorage(m_node-&gt;numChildren() == 3 ? m_graph.varArgChild(m_node, 2) : m_graph.varArgChild(m_node, 3));
+        LValue inputLength = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
+
+        LValue endBoundary;
+        if (m_node-&gt;numChildren() == 3)
+            endBoundary = m_out.load32(sourceStorage, m_heaps.Butterfly_publicLength);
+        else {
+            endBoundary = lowInt32(m_graph.varArgChild(m_node, 2));
+            endBoundary = m_out.select(m_out.greaterThanOrEqual(endBoundary, m_out.constInt32(0)),
+                m_out.select(m_out.above(endBoundary, inputLength), inputLength, endBoundary),
+                m_out.select(m_out.lessThan(m_out.add(inputLength, endBoundary), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, endBoundary)));
+        }
+
+        LValue startIndex = lowInt32(m_graph.varArgChild(m_node, 1));
+        startIndex = m_out.select(m_out.greaterThanOrEqual(startIndex, m_out.constInt32(0)),
+            m_out.select(m_out.above(startIndex, inputLength), inputLength, startIndex),
+            m_out.select(m_out.lessThan(m_out.add(inputLength, startIndex), m_out.constInt32(0)), m_out.constInt32(0), m_out.add(inputLength, startIndex)));
+
+        LValue resultLength = m_out.select(m_out.below(startIndex, endBoundary),
+            m_out.sub(endBoundary, startIndex),
+            m_out.constInt32(0));
+
+        ArrayValues arrayResult;
+        {
+            LValue indexingType = m_out.load8ZeroExt32(lowCell(m_graph.varArgChild(m_node, 0)), m_heaps.JSCell_indexingTypeAndMisc);
+            indexingType = m_out.bitAnd(indexingType, m_out.constInt32(AllArrayTypesAndHistory));
+            // When we emit an ArraySlice, we dominate the use of the array by a CheckStructure
+            // to ensure the incoming array is one to be one of the original array structures
+            // with one of the following indexing shapes: Int32, Contiguous, Double.
+            LValue structure = m_out.select(
+                m_out.equal(indexingType, m_out.constInt32(ArrayWithInt32)),
+                m_out.constIntPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithInt32)),
+                m_out.select(m_out.equal(indexingType, m_out.constInt32(ArrayWithContiguous)),
+                    m_out.constIntPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous)),
+                    m_out.constIntPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble))));
+            arrayResult = allocateJSArray(resultLength, structure, indexingType, false, false);
+        }
+
+        LBasicBlock loop = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        resultLength = m_out.zeroExtPtr(resultLength);
+        ValueFromBlock startLoadIndex = m_out.anchor(m_out.zeroExtPtr(startIndex));
+        ValueFromBlock startStoreIndex = m_out.anchor(m_out.constIntPtr(0));
+
+        m_out.branch(
+            m_out.below(m_out.constIntPtr(0), resultLength), unsure(loop), unsure(continuation));
+
+        LBasicBlock lastNext = m_out.appendTo(loop, continuation);
+        LValue storeIndex = m_out.phi(pointerType(), startStoreIndex);
+        LValue loadIndex = m_out.phi(pointerType(), startLoadIndex);
+        LValue value = m_out.load64(m_out.baseIndex(m_heaps.root, sourceStorage, loadIndex, ScaleEight));
+        m_out.store64(value, m_out.baseIndex(m_heaps.root, arrayResult.butterfly, storeIndex, ScaleEight));
+        LValue nextStoreIndex = m_out.add(storeIndex, m_out.constIntPtr(1));
+        m_out.addIncomingToPhi(storeIndex, m_out.anchor(nextStoreIndex));
+        m_out.addIncomingToPhi(loadIndex, m_out.anchor(m_out.add(loadIndex, m_out.constIntPtr(1))));
+        m_out.branch(
+            m_out.below(nextStoreIndex, resultLength), unsure(loop), unsure(continuation));
+
+        m_out.appendTo(continuation, lastNext);
+
+        mutatorFence();
+        setJSValue(arrayResult.array);
+    }
</ins><span class="cx">     
</span><span class="cx">     void compileArrayPop()
</span><span class="cx">     {
</span><span class="lines">@@ -4626,11 +4698,10 @@
</span><span class="cx">             m_node-&gt;indexingType());
</span><span class="cx">         
</span><span class="cx">         if (!globalObject-&gt;isHavingABadTime() &amp;&amp; !hasAnyArrayStorage(m_node-&gt;indexingType())) {
</span><ins>+            IndexingType indexingType = m_node-&gt;indexingType();
</ins><span class="cx">             setJSValue(
</span><span class="cx">                 allocateJSArray(
</span><del>-                    publicLength,
-                    globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(
-                        m_node-&gt;indexingType())).array);
</del><ins>+                    publicLength, m_out.constIntPtr(globalObject-&gt;arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
</ins><span class="cx">             mutatorFence();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -8665,7 +8736,7 @@
</span><span class="cx"> 
</span><span class="cx">                 m_out.store32(publicLength, butterfly, m_heaps.Butterfly_publicLength);
</span><span class="cx"> 
</span><del>-                initializeArrayElements(structure-&gt;indexingType(), m_out.int32Zero, vectorLength, butterfly);
</del><ins>+                initializeArrayElements(m_out.constInt32(structure-&gt;indexingType()), m_out.int32Zero, vectorLength, butterfly);
</ins><span class="cx"> 
</span><span class="cx">                 HashMap&lt;int32_t, LValue, DefaultHash&lt;int32_t&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;int32_t&gt;&gt; indexMap;
</span><span class="cx">                 Vector&lt;int32_t&gt; indices;
</span><span class="lines">@@ -9421,26 +9492,35 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void initializeArrayElements(IndexingType indexingType, LValue begin, LValue end, LValue butterfly)
</del><ins>+    void initializeArrayElements(LValue indexingType, LValue begin, LValue end, LValue butterfly)
</ins><span class="cx">     {
</span><del>-        if (hasUndecided(indexingType))
-            return;
</del><span class="cx">         
</span><span class="cx">         if (begin == end)
</span><span class="cx">             return;
</span><span class="cx">         
</span><del>-        IndexedAbstractHeap* heap = m_heaps.forIndexingType(indexingType);
-        DFG_ASSERT(m_graph, m_node, heap);
-        
-        LValue hole;
-        if (hasDouble(indexingType))
-            hole = m_out.constInt64(bitwise_cast&lt;int64_t&gt;(PNaN));
-        else
-            hole = m_out.constInt64(JSValue::encode(JSValue()));
-        
-        splatWords(butterfly, begin, end, hole, heap-&gt;atAnyIndex());
</del><ins>+        if (indexingType-&gt;hasInt32()) {
+            IndexingType rawIndexingType = static_cast&lt;IndexingType&gt;(indexingType-&gt;asInt32());
+            if (hasUndecided(rawIndexingType))
+                return;
+            IndexedAbstractHeap* heap = m_heaps.forIndexingType(rawIndexingType);
+            DFG_ASSERT(m_graph, m_node, heap);
+            
+            LValue hole;
+            if (hasDouble(rawIndexingType))
+                hole = m_out.constInt64(bitwise_cast&lt;int64_t&gt;(PNaN));
+            else
+                hole = m_out.constInt64(JSValue::encode(JSValue()));
+            
+            splatWords(butterfly, begin, end, hole, heap-&gt;atAnyIndex());
+        } else {
+            LValue hole = m_out.select(
+                m_out.equal(m_out.bitAnd(indexingType, m_out.constInt32(IndexingShapeMask)), m_out.constInt32(DoubleShape)),
+                m_out.constInt64(bitwise_cast&lt;int64_t&gt;(PNaN)),
+                m_out.constInt64(JSValue::encode(JSValue())));
+            splatWords(butterfly, begin, end, hole, m_heaps.root);
+        }
</ins><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     void splatWords(LValue base, LValue begin, LValue end, LValue value, const AbstractHeap&amp; heap)
</span><span class="cx">     {
</span><span class="cx">         const uint64_t unrollingLimit = 10;
</span><span class="lines">@@ -10392,37 +10472,69 @@
</span><span class="cx">             object, m_heaps.JSCell_usefulBytes);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    LValue allocateCell(LValue allocator, Structure* structure, LBasicBlock slowPath)
</del><ins>+    void storeStructure(LValue object, LValue structure)
</ins><span class="cx">     {
</span><ins>+        if (structure-&gt;hasIntPtr()) {
+            storeStructure(object, bitwise_cast&lt;Structure*&gt;(structure-&gt;asIntPtr()));
+            return;
+        }
+
+        LValue id = m_out.load32(structure, m_heaps.Structure_structureID);
+        m_out.store32(id, object, m_heaps.JSCell_structureID);
+
+        LValue blob = m_out.load32(structure, m_heaps.Structure_indexingTypeIncludingHistory);
+        m_out.store32(blob, object, m_heaps.JSCell_usefulBytes);
+    }
+
+    template &lt;typename StructureType&gt;
+    LValue allocateCell(LValue allocator, StructureType structure, LBasicBlock slowPath)
+    {
</ins><span class="cx">         LValue result = allocateHeapCell(allocator, slowPath);
</span><span class="cx">         storeStructure(result, structure);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    LValue allocateObject(
-        LValue allocator, Structure* structure, LValue butterfly, LBasicBlock slowPath)
</del><ins>+    LValue allocateObject(LValue allocator, Structure* structure, LValue butterfly, LBasicBlock slowPath)
</ins><span class="cx">     {
</span><ins>+        return allocateObject(allocator, m_out.constIntPtr(structure), butterfly, slowPath);
+    }
+
+    LValue allocateObject(LValue allocator, LValue structure, LValue butterfly, LBasicBlock slowPath)
+    {
</ins><span class="cx">         LValue result = allocateCell(allocator, structure, slowPath);
</span><del>-        splatWords(
-            result,
-            m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
-            m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8 + structure-&gt;inlineCapacity()),
-            m_out.int64Zero,
-            m_heaps.properties.atAnyNumber());
</del><ins>+        if (structure-&gt;hasIntPtr()) {
+            splatWords(
+                result,
+                m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
+                m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8 + bitwise_cast&lt;Structure*&gt;(structure-&gt;asIntPtr())-&gt;inlineCapacity()),
+                m_out.int64Zero,
+                m_heaps.properties.atAnyNumber());
+        } else {
+            LValue end = m_out.add(
+                m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
+                m_out.load8ZeroExt32(structure, m_heaps.Structure_inlineCapacity));
+            splatWords(
+                result,
+                m_out.constInt32(JSFinalObject::offsetOfInlineStorage() / 8),
+                end,
+                m_out.int64Zero,
+                m_heaps.properties.atAnyNumber());
+        }
+        
</ins><span class="cx">         m_out.storePtr(butterfly, result, m_heaps.JSObject_butterfly);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    template&lt;typename ClassType&gt;
</del><ins>+    template&lt;typename ClassType, typename StructureType&gt;
</ins><span class="cx">     LValue allocateObject(
</span><del>-        size_t size, Structure* structure, LValue butterfly, LBasicBlock slowPath)
</del><ins>+        size_t size, StructureType structure, LValue butterfly, LBasicBlock slowPath)
</ins><span class="cx">     {
</span><span class="cx">         MarkedAllocator* allocator = vm().heap.allocatorForObjectOfType&lt;ClassType&gt;(size);
</span><span class="cx">         return allocateObject(m_out.constIntPtr(allocator), structure, butterfly, slowPath);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    template&lt;typename ClassType&gt;
-    LValue allocateObject(Structure* structure, LValue butterfly, LBasicBlock slowPath)
</del><ins>+    template&lt;typename ClassType, typename StructureType&gt;
+    LValue allocateObject(StructureType structure, LValue butterfly, LBasicBlock slowPath)
</ins><span class="cx">     {
</span><span class="cx">         return allocateObject&lt;ClassType&gt;(
</span><span class="cx">             ClassType::allocationSize(0), structure, butterfly, slowPath);
</span><span class="lines">@@ -10545,15 +10657,17 @@
</span><span class="cx">         LValue butterfly;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    ArrayValues allocateJSArray(LValue publicLength, Structure* structure, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
</del><ins>+    ArrayValues allocateJSArray(LValue publicLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
</ins><span class="cx">     {
</span><span class="cx">         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node-&gt;origin.semantic);
</span><del>-        IndexingType indexingType = structure-&gt;indexingType();
-        ASSERT(
-            hasUndecided(indexingType)
-            || hasInt32(indexingType)
-            || hasDouble(indexingType)
-            || hasContiguous(indexingType));
</del><ins>+        if (indexingType-&gt;hasInt32()) {
+            IndexingType type = static_cast&lt;IndexingType&gt;(indexingType-&gt;asInt32());
+            ASSERT_UNUSED(type,
+                hasUndecided(type)
+                || hasInt32(type)
+                || hasDouble(type)
+                || hasContiguous(type));
+        }
</ins><span class="cx"> 
</span><span class="cx">         LBasicBlock fastCase = m_out.newBlock();
</span><span class="cx">         LBasicBlock largeCase = m_out.newBlock();
</span><span class="lines">@@ -10576,12 +10690,12 @@
</span><span class="cx">         m_out.appendTo(fastCase, largeCase);
</span><span class="cx"> 
</span><span class="cx">         LValue vectorLength = nullptr;
</span><del>-        if (publicLength-&gt;hasInt32()) {
</del><ins>+        if (publicLength-&gt;hasInt32() &amp;&amp; structure-&gt;hasIntPtr()) {
</ins><span class="cx">             unsigned publicLengthConst = static_cast&lt;unsigned&gt;(publicLength-&gt;asInt32());
</span><span class="cx">             if (publicLengthConst &lt;= MAX_STORAGE_VECTOR_LENGTH) {
</span><span class="cx">                 vectorLength = m_out.constInt32(
</span><span class="cx">                     Butterfly::optimalContiguousVectorLength(
</span><del>-                        structure-&gt;outOfLineCapacity(), publicLengthConst));
</del><ins>+                        bitwise_cast&lt;Structure*&gt;(structure-&gt;asIntPtr())-&gt;outOfLineCapacity(), publicLengthConst));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -10614,7 +10728,7 @@
</span><span class="cx">         ValueFromBlock haveButterfly = m_out.anchor(butterfly);
</span><span class="cx">         
</span><span class="cx">         LValue object = allocateObject&lt;JSArray&gt;(structure, butterfly, failCase);
</span><del>-            
</del><ins>+
</ins><span class="cx">         ValueFromBlock fastResult = m_out.anchor(object);
</span><span class="cx">         ValueFromBlock fastButterfly = m_out.anchor(butterfly);
</span><span class="cx">         m_out.jump(continuation);
</span><span class="lines">@@ -10626,7 +10740,7 @@
</span><span class="cx">         m_out.jump(slowCase);
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(failCase, slowCase);
</span><del>-        ValueFromBlock failStructure = m_out.anchor(m_out.constIntPtr(structure));
</del><ins>+        ValueFromBlock failStructure = m_out.anchor(structure);
</ins><span class="cx">         m_out.jump(slowCase);
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(slowCase, continuation);
</span><span class="lines">@@ -10656,7 +10770,7 @@
</span><span class="cx">         bool shouldInitializeElements = false;
</span><span class="cx">         bool shouldLargeArraySizeCreateArrayStorage = false;
</span><span class="cx">         return allocateJSArray(
</span><del>-            publicLength, structure, shouldInitializeElements,
</del><ins>+            publicLength, m_out.constIntPtr(structure), m_out.constInt32(structure-&gt;indexingType()), shouldInitializeElements,
</ins><span class="cx">             shouldLargeArraySizeCreateArrayStorage);
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -447,6 +447,7 @@
</span><span class="cx"> void AssemblyHelpers::emitLoadStructure(RegisterID source, RegisterID dest, RegisterID scratch)
</span><span class="cx"> {
</span><span class="cx"> #if USE(JSVALUE64)
</span><ins>+    ASSERT(dest != scratch);
</ins><span class="cx">     load32(MacroAssembler::Address(source, JSCell::structureIDOffset()), dest);
</span><span class="cx">     loadPtr(vm()-&gt;heap.structureIDTable().base(), scratch);
</span><span class="cx">     loadPtr(MacroAssembler::BaseIndex(scratch, dest, MacroAssembler::TimesEight), dest);
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeArrayPrototypecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -98,7 +98,7 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;reverse&quot;, arrayProtoFuncReverse, DontEnum, 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().shiftPublicName(), arrayProtoFuncShift, DontEnum, 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;builtinNames().shiftPrivateName(), arrayProtoFuncShift, DontEnum | DontDelete | ReadOnly, 0);
</span><del>-    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;slice, arrayProtoFuncSlice, DontEnum, 2);
</del><ins>+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames-&gt;slice, arrayProtoFuncSlice, DontEnum, 2, ArraySliceIntrinsic);
</ins><span class="cx">     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(&quot;sort&quot;, arrayPrototypeSortCodeGenerator, DontEnum);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;splice&quot;, arrayProtoFuncSplice, DontEnum, 2);
</span><span class="cx">     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(&quot;unshift&quot;, arrayProtoFuncUnShift, DontEnum, 1);
</span><span class="lines">@@ -191,21 +191,12 @@
</span><span class="cx">         throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool speciesWatchpointsValid(ExecState* exec, JSObject* thisObject)
</del><ins>+inline bool speciesWatchpointIsValid(JSObject* thisObject)
</ins><span class="cx"> {
</span><del>-    VM&amp; vm = exec-&gt;vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
</del><span class="cx">     ArrayPrototype* arrayPrototype = thisObject-&gt;globalObject()-&gt;arrayPrototype();
</span><del>-    ArrayPrototype::SpeciesWatchpointStatus status = arrayPrototype-&gt;speciesWatchpointStatus();
-    if (UNLIKELY(status == ArrayPrototype::SpeciesWatchpointStatus::Uninitialized)) {
-        status = arrayPrototype-&gt;attemptToInitializeSpeciesWatchpoint(exec);
-        RETURN_IF_EXCEPTION(scope, false);
-    }
-    ASSERT(status != ArrayPrototype::SpeciesWatchpointStatus::Uninitialized);
</del><span class="cx">     return !thisObject-&gt;hasCustomProperties()
</span><span class="cx">         &amp;&amp; arrayPrototype == thisObject-&gt;getPrototypeDirect()
</span><del>-        &amp;&amp; status == ArrayPrototype::SpeciesWatchpointStatus::Initialized;
</del><ins>+        &amp;&amp; arrayPrototype-&gt;globalObject()-&gt;arraySpeciesWatchpoint().isStillValid();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> enum class SpeciesConstructResult {
</span><span class="lines">@@ -230,8 +221,7 @@
</span><span class="cx">     if (LIKELY(thisIsArray)) {
</span><span class="cx">         // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal.
</span><span class="cx">         // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default.
</span><del>-        bool isValid = speciesWatchpointsValid(exec, thisObject);
-        RETURN_IF_EXCEPTION(scope, exceptionResult());
</del><ins>+        bool isValid = speciesWatchpointIsValid(thisObject);
</ins><span class="cx">         if (LIKELY(isValid))
</span><span class="cx">             return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
</span><span class="cx"> 
</span><span class="lines">@@ -920,29 +910,29 @@
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
</span><span class="cx"> {
</span><del>-    // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10
</del><ins>+    // https://tc39.github.io/ecma262/#sec-array.prototype.slice
</ins><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><span class="cx">     JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);
</span><span class="cx">     ASSERT(!!scope.exception() == !thisObj);
</span><span class="cx">     if (UNLIKELY(!thisObj))
</span><del>-        return encodedJSValue();
</del><ins>+        return { };
</ins><span class="cx">     unsigned length = getLength(exec, thisObj);
</span><del>-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><span class="cx">     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, length);
</span><del>-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, length, length);
</span><del>-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx"> 
</span><span class="cx">     std::pair&lt;SpeciesConstructResult, JSObject*&gt; speciesResult = speciesConstructArray(exec, thisObj, end - begin);
</span><span class="cx">     // We can only get an exception if we call some user function.
</span><span class="cx">     ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
</span><span class="cx">     if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
</span><del>-        return encodedJSValue();
</del><ins>+        return { };
</ins><span class="cx"> 
</span><span class="cx">     bool okToDoFastPath = speciesResult.first == SpeciesConstructResult::FastPath &amp;&amp; isJSArray(thisObj) &amp;&amp; length == getLength(exec, thisObj);
</span><del>-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+    RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">     if (LIKELY(okToDoFastPath)) {
</span><span class="cx">         if (JSArray* result = asArray(thisObj)-&gt;fastSlice(*exec, begin, end - begin))
</span><span class="cx">             return JSValue::encode(result);
</span><span class="lines">@@ -953,16 +943,16 @@
</span><span class="cx">         result = speciesResult.second;
</span><span class="cx">     else {
</span><span class="cx">         result = constructEmptyArray(exec, nullptr, end - begin);
</span><del>-        RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+        RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned n = 0;
</span><span class="cx">     for (unsigned k = begin; k &lt; end; k++, n++) {
</span><span class="cx">         JSValue v = getProperty(exec, thisObj, k);
</span><del>-        RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+        RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">         if (v) {
</span><span class="cx">             result-&gt;putDirectIndex(exec, n, v, 0, PutDirectIndexShouldThrow);
</span><del>-            RETURN_IF_EXCEPTION(scope, encodedJSValue());
</del><ins>+            RETURN_IF_EXCEPTION(scope, { });
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     scope.release();
</span><span class="lines">@@ -1249,8 +1239,7 @@
</span><span class="cx">         return JSValue::encode(jsNull());
</span><span class="cx"> 
</span><span class="cx">     // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers.
</span><del>-    bool isValid = speciesWatchpointsValid(exec, firstArray);
-    ASSERT(!scope.exception() || !isValid);
</del><ins>+    bool isValid = speciesWatchpointIsValid(firstArray);
</ins><span class="cx">     if (UNLIKELY(!isValid))
</span><span class="cx">         return JSValue::encode(jsNull());
</span><span class="cx"> 
</span><span class="lines">@@ -1342,15 +1331,18 @@
</span><span class="cx">     ArrayPrototype* m_arrayPrototype;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-ArrayPrototype::SpeciesWatchpointStatus ArrayPrototype::attemptToInitializeSpeciesWatchpoint(ExecState* exec)
</del><ins>+void ArrayPrototype::initializeSpeciesWatchpoint(ExecState* exec)
</ins><span class="cx"> {
</span><del>-    ASSERT(m_speciesWatchpointStatus == SpeciesWatchpointStatus::Uninitialized);
</del><ins>+    VM&amp; vm = exec-&gt;vm();
</ins><span class="cx"> 
</span><del>-    VM&amp; vm = exec-&gt;vm();
</del><ins>+    RELEASE_ASSERT(!m_constructorWatchpoint);
+    RELEASE_ASSERT(!m_constructorSpeciesWatchpoint);
+
</ins><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><ins>+    UNUSED_PARAM(scope);
</ins><span class="cx"> 
</span><span class="cx">     if (verbose)
</span><del>-        dataLog(&quot;Attempting to initialize Array species watchpoints for Array.prototype: &quot;, pointerDump(this), &quot; with structure: &quot;, pointerDump(this-&gt;structure()), &quot;\nand Array: &quot;, pointerDump(this-&gt;globalObject()-&gt;arrayConstructor()), &quot; with structure: &quot;, pointerDump(this-&gt;globalObject()-&gt;arrayConstructor()-&gt;structure()), &quot;\n&quot;);
</del><ins>+        dataLog(&quot;Initializing Array species watchpoints for Array.prototype: &quot;, pointerDump(this), &quot; with structure: &quot;, pointerDump(this-&gt;structure()), &quot;\nand Array: &quot;, pointerDump(this-&gt;globalObject()-&gt;arrayConstructor()), &quot; with structure: &quot;, pointerDump(this-&gt;globalObject()-&gt;arrayConstructor()-&gt;structure()), &quot;\n&quot;);
</ins><span class="cx">     // First we need to make sure that the Array.prototype.constructor property points to Array
</span><span class="cx">     // and that Array[Symbol.species] is the primordial GetterSetter.
</span><span class="cx"> 
</span><span class="lines">@@ -1364,12 +1356,11 @@
</span><span class="cx">     ArrayConstructor* arrayConstructor = globalObject-&gt;arrayConstructor();
</span><span class="cx"> 
</span><span class="cx">     PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry);
</span><del>-    JSValue(this).get(exec, vm.propertyNames-&gt;constructor, constructorSlot);
-    if (UNLIKELY(scope.exception())
-        || constructorSlot.slotBase() != this
-        || !constructorSlot.isCacheableValue()
-        || constructorSlot.getValue(exec, vm.propertyNames-&gt;constructor) != arrayConstructor)
-        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
</del><ins>+    this-&gt;getOwnPropertySlot(this, exec, vm.propertyNames-&gt;constructor, constructorSlot);
+    ASSERT(!scope.exception());
+    ASSERT(constructorSlot.slotBase() == this);
+    ASSERT(constructorSlot.isCacheableValue());
+    RELEASE_ASSERT(constructorSlot.getValue(exec, vm.propertyNames-&gt;constructor) == arrayConstructor);
</ins><span class="cx"> 
</span><span class="cx">     Structure* constructorStructure = arrayConstructor-&gt;structure(vm);
</span><span class="cx">     if (constructorStructure-&gt;isDictionary())
</span><span class="lines">@@ -1376,12 +1367,11 @@
</span><span class="cx">         constructorStructure = constructorStructure-&gt;flattenDictionaryStructure(vm, arrayConstructor);
</span><span class="cx"> 
</span><span class="cx">     PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry);
</span><del>-    JSValue(arrayConstructor).get(exec, vm.propertyNames-&gt;speciesSymbol, speciesSlot);
-    if (UNLIKELY(scope.exception())
-        || speciesSlot.slotBase() != arrayConstructor
-        || !speciesSlot.isCacheableGetter()
-        || speciesSlot.getterSetter() != globalObject-&gt;speciesGetterSetter())
-        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
</del><ins>+    arrayConstructor-&gt;getOwnPropertySlot(arrayConstructor, exec, vm.propertyNames-&gt;speciesSymbol, speciesSlot);
+    ASSERT(!scope.exception());
+    ASSERT(speciesSlot.slotBase() == arrayConstructor);
+    ASSERT(speciesSlot.isCacheableGetter());
+    RELEASE_ASSERT(speciesSlot.getterSetter() == globalObject-&gt;speciesGetterSetter());
</ins><span class="cx"> 
</span><span class="cx">     // Now we need to setup the watchpoints to make sure these conditions remain valid.
</span><span class="cx">     prototypeStructure-&gt;startWatchingPropertyForReplacements(vm, constructorSlot.cachedOffset());
</span><span class="lines">@@ -1390,8 +1380,8 @@
</span><span class="cx">     ObjectPropertyCondition constructorCondition = ObjectPropertyCondition::equivalence(vm, this, this, vm.propertyNames-&gt;constructor.impl(), arrayConstructor);
</span><span class="cx">     ObjectPropertyCondition speciesCondition = ObjectPropertyCondition::equivalence(vm, this, arrayConstructor, vm.propertyNames-&gt;speciesSymbol.impl(), globalObject-&gt;speciesGetterSetter());
</span><span class="cx"> 
</span><del>-    if (!constructorCondition.isWatchable() || !speciesCondition.isWatchable())
-        return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Fired;
</del><ins>+    RELEASE_ASSERT(constructorCondition.isWatchable());
+    RELEASE_ASSERT(speciesCondition.isWatchable());
</ins><span class="cx"> 
</span><span class="cx">     m_constructorWatchpoint = std::make_unique&lt;ArrayPrototypeAdaptiveInferredPropertyWatchpoint&gt;(constructorCondition, this);
</span><span class="cx">     m_constructorWatchpoint-&gt;install();
</span><span class="lines">@@ -1398,8 +1388,6 @@
</span><span class="cx"> 
</span><span class="cx">     m_constructorSpeciesWatchpoint = std::make_unique&lt;ArrayPrototypeAdaptiveInferredPropertyWatchpoint&gt;(speciesCondition, this);
</span><span class="cx">     m_constructorSpeciesWatchpoint-&gt;install();
</span><del>-
-    return m_speciesWatchpointStatus = SpeciesWatchpointStatus::Initialized;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ArrayPrototypeAdaptiveInferredPropertyWatchpoint::ArrayPrototypeAdaptiveInferredPropertyWatchpoint(const ObjectPropertyCondition&amp; key, ArrayPrototype* prototype)
</span><span class="lines">@@ -1418,7 +1406,8 @@
</span><span class="cx">     if (verbose)
</span><span class="cx">         WTF::dataLog(stringDetail, &quot;\n&quot;);
</span><span class="cx"> 
</span><del>-    m_arrayPrototype-&gt;m_speciesWatchpointStatus = ArrayPrototype::SpeciesWatchpointStatus::Fired;
</del><ins>+    JSGlobalObject* globalObject = m_arrayPrototype-&gt;globalObject();
+    globalObject-&gt;arraySpeciesWatchpoint().fireAll(globalObject-&gt;vm(), stringDetail);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeArrayPrototypeh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/ArrayPrototype.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -49,8 +49,7 @@
</span><span class="cx">         return Structure::create(vm, globalObject, prototype, TypeInfo(DerivedArrayType, StructureFlags), info(), ArrayClass);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    SpeciesWatchpointStatus speciesWatchpointStatus() const { return m_speciesWatchpointStatus; }
-    SpeciesWatchpointStatus attemptToInitializeSpeciesWatchpoint(ExecState*);
</del><ins>+    void initializeSpeciesWatchpoint(ExecState*);
</ins><span class="cx"> 
</span><span class="cx">     static const bool needsDestruction = false;
</span><span class="cx">     // We don't need destruction since we use a finalizer.
</span><span class="lines">@@ -64,7 +63,6 @@
</span><span class="cx">     friend ArrayPrototypeAdaptiveInferredPropertyWatchpoint;
</span><span class="cx">     std::unique_ptr&lt;ArrayPrototypeAdaptiveInferredPropertyWatchpoint&gt; m_constructorWatchpoint;
</span><span class="cx">     std::unique_ptr&lt;ArrayPrototypeAdaptiveInferredPropertyWatchpoint&gt; m_constructorSpeciesWatchpoint;
</span><del>-    SpeciesWatchpointStatus m_speciesWatchpointStatus { SpeciesWatchpointStatus::Uninitialized };
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState*);
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeIntrinsich"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/Intrinsic.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/Intrinsic.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/Intrinsic.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">     TanIntrinsic,
</span><span class="cx">     ArrayPushIntrinsic,
</span><span class="cx">     ArrayPopIntrinsic,
</span><ins>+    ArraySliceIntrinsic,
</ins><span class="cx">     CharCodeAtIntrinsic,
</span><span class="cx">     CharAtIntrinsic,
</span><span class="cx">     FromCharCodeIntrinsic,
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -331,6 +331,7 @@
</span><span class="cx">     , m_varInjectionWatchpoint(adoptRef(new WatchpointSet(IsWatched)))
</span><span class="cx">     , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast&lt;unsigned&gt;(randomNumber() * (std::numeric_limits&lt;unsigned&gt;::max() + 1.0)))
</span><span class="cx">     , m_arrayIteratorProtocolWatchpoint(IsWatched)
</span><ins>+    , m_arraySpeciesWatchpoint(IsWatched)
</ins><span class="cx">     , m_templateRegistry(vm)
</span><span class="cx">     , m_evalEnabled(true)
</span><span class="cx">     , m_runtimeFlags()
</span><span class="lines">@@ -943,6 +944,8 @@
</span><span class="cx">             m_arrayPrototypeSymbolIteratorWatchpoint = std::make_unique&lt;ArrayIteratorAdaptiveWatchpoint&gt;(condition, this);
</span><span class="cx">             m_arrayPrototypeSymbolIteratorWatchpoint-&gt;install();
</span><span class="cx">         }
</span><ins>+
+        this-&gt;arrayPrototype()-&gt;initializeSpeciesWatchpoint(exec);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     resetPrototype(vm, getPrototypeDirect());
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/JSGlobalObject.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -398,9 +398,11 @@
</span><span class="cx">     WeakRandom m_weakRandom;
</span><span class="cx"> 
</span><span class="cx">     InlineWatchpointSet&amp; arrayIteratorProtocolWatchpoint() { return m_arrayIteratorProtocolWatchpoint; }
</span><ins>+    InlineWatchpointSet&amp; arraySpeciesWatchpoint() { return m_arraySpeciesWatchpoint; }
</ins><span class="cx">     // If this hasn't been invalidated, it means the array iterator protocol
</span><span class="cx">     // is not observable to user code yet.
</span><span class="cx">     InlineWatchpointSet m_arrayIteratorProtocolWatchpoint;
</span><ins>+    InlineWatchpointSet m_arraySpeciesWatchpoint;
</ins><span class="cx">     std::unique_ptr&lt;ArrayIteratorAdaptiveWatchpoint&gt; m_arrayPrototypeSymbolIteratorWatchpoint;
</span><span class="cx">     std::unique_ptr&lt;ArrayIteratorAdaptiveWatchpoint&gt; m_arrayIteratorPrototypeNext;
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/Structure.h (210864 => 210865)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/Structure.h        2017-01-18 20:29:26 UTC (rev 210864)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/Structure.h        2017-01-18 20:42:19 UTC (rev 210865)
</span><span class="lines">@@ -464,6 +464,11 @@
</span><span class="cx">         return OBJECT_OFFSETOF(Structure, m_propertyTableUnsafe);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static ptrdiff_t inlineCapacityOffset()
+    {
+        return OBJECT_OFFSETOF(Structure, m_inlineCapacity);
+    }
+
</ins><span class="cx">     static Structure* createStructure(VM&amp;);
</span><span class="cx">         
</span><span class="cx">     bool transitionWatchpointSetHasBeenInvalidated() const
</span></span></pre>
</div>
</div>

</body>
</html>