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

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

<h3>Log Message</h3>
<pre>DFG plays fast and loose with the shadow values of a Phi
https://bugs.webkit.org/show_bug.cgi?id=164309

Reviewed by Saam Barati.
        
JSTests:

This test demonstrates why the DFG needs to recognize the shadow value of a Phi.

* stress/dfg-ssa-swap.js: Added.
(foo):

Source/JavaScriptCore:

Oh boy, what an embarrassing mistake! The style of SSA I like to use avoids block/value
tuples as parameters of a Phi, thereby simplifying CFG transformations and making Phi largely
not a special case for most compiler transforms. It does this by introducing another value
called Upsilon, which stores a value into some Phi.
        
B3 uses this also. The easiest way to understand what Upsilon/Phi behave like is to look at
the B3-&gt;Air lowering. Air is not SSA - it has Tmps that you can assign to and use as many
times as you like. B3 allocates one Tmp per Value, and an extra &quot;phiTmp&quot; for Phis, so that
Phis get two Tmps total. Upsilon stores the value into the phiTmp of the Phi, while Phi moves
the value from its phiTmp to its tmp.
        
This is necessary to support scenarios like this:
        
    a: Phi()
    b: Upsilon(@x, ^a)
    c: Use(@a)
        
Here, we want @c to see @a's value before @b. That's a very basic requirement of SSA: that
the a value (like @a) doesn't change during its lifetime.
        
Unfortunately, DFG's liveness analysis, abstract interpreter, and integer range optimization
all failed to correctly model Upsilon/Phi this way. They would assume that it's accurate to
model the Upsilon as storing into the Phi directly.
        
Because DFG does flow analysis over SSA, making it correct means enabling it to speak of the
shadow value. This change addresses this problem by introducing the concept of a
NodeFlowProjection. This is a key that lets us speak of both a Node's primary value and its
optional &quot;shadow&quot; value. Liveness, AI, and integer range are now keyed by NodeFlowProjection
rather than Node*. Conceptually this turns out to be a very simple change, but it does touch
a good amount of code.
        
This looks to be perf-neutral.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/air/AirLiveness.h:
(JSC::B3::Air::TmpLivenessAdapter::numIndices):
(JSC::B3::Air::StackSlotLivenessAdapter::numIndices):
(JSC::B3::Air::RegLivenessAdapter::numIndices):
(JSC::B3::Air::AbstractLiveness::AbstractLiveness):
(JSC::B3::Air::TmpLivenessAdapter::maxIndex): Deleted.
(JSC::B3::Air::StackSlotLivenessAdapter::maxIndex): Deleted.
(JSC::B3::Air::RegLivenessAdapter::maxIndex): Deleted.
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::forNode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::forAllValues):
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::dump):
* dfg/DFGAtTailAbstractState.cpp:
(JSC::DFG::AtTailAbstractState::createValueForNode):
(JSC::DFG::AtTailAbstractState::forNode):
* dfg/DFGAtTailAbstractState.h:
* dfg/DFGBasicBlock.h:
* dfg/DFGCombinedLiveness.cpp:
(JSC::DFG::liveNodesAtHead):
* dfg/DFGCombinedLiveness.h:
* dfg/DFGFlowIndexing.cpp: Added.
(JSC::DFG::FlowIndexing::FlowIndexing):
(JSC::DFG::FlowIndexing::~FlowIndexing):
(JSC::DFG::FlowIndexing::recompute):
* dfg/DFGFlowIndexing.h: Added.
(JSC::DFG::FlowIndexing::graph):
(JSC::DFG::FlowIndexing::numIndices):
(JSC::DFG::FlowIndexing::index):
(JSC::DFG::FlowIndexing::shadowIndex):
(JSC::DFG::FlowIndexing::nodeProjection):
* dfg/DFGFlowMap.h: Added.
(JSC::DFG::FlowMap::FlowMap):
(JSC::DFG::FlowMap::resize):
(JSC::DFG::FlowMap::graph):
(JSC::DFG::FlowMap::at):
(JSC::DFG::FlowMap::atShadow):
(WTF::printInternal):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::abstractValuesCache): Deleted.
* dfg/DFGInPlaceAbstractState.cpp:
(JSC::DFG::InPlaceAbstractState::InPlaceAbstractState):
(JSC::DFG::InPlaceAbstractState::beginBasicBlock):
(JSC::DFG::setLiveValues):
(JSC::DFG::InPlaceAbstractState::endBasicBlock):
(JSC::DFG::InPlaceAbstractState::merge):
* dfg/DFGInPlaceAbstractState.h:
(JSC::DFG::InPlaceAbstractState::createValueForNode):
(JSC::DFG::InPlaceAbstractState::forNode):
* dfg/DFGIntegerRangeOptimizationPhase.cpp:
* dfg/DFGLivenessAnalysisPhase.cpp:
(JSC::DFG::LivenessAnalysisPhase::LivenessAnalysisPhase):
(JSC::DFG::LivenessAnalysisPhase::run):
(JSC::DFG::LivenessAnalysisPhase::processBlock):
(JSC::DFG::LivenessAnalysisPhase::addChildUse): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::NodeComparator::operator()):
(JSC::DFG::nodeListDump):
(JSC::DFG::nodeMapDump):
(JSC::DFG::nodeValuePairListDump):
(JSC::DFG::nodeComparator): Deleted.
* dfg/DFGNodeAbstractValuePair.cpp: Added.
(JSC::DFG::NodeAbstractValuePair::dump):
* dfg/DFGNodeAbstractValuePair.h: Added.
(JSC::DFG::NodeAbstractValuePair::NodeAbstractValuePair):
* dfg/DFGNodeFlowProjection.cpp: Added.
(JSC::DFG::NodeFlowProjection::dump):
* dfg/DFGNodeFlowProjection.h: Added.
(JSC::DFG::NodeFlowProjection::NodeFlowProjection):
(JSC::DFG::NodeFlowProjection::operator bool):
(JSC::DFG::NodeFlowProjection::kind):
(JSC::DFG::NodeFlowProjection::node):
(JSC::DFG::NodeFlowProjection::operator*):
(JSC::DFG::NodeFlowProjection::operator-&gt;):
(JSC::DFG::NodeFlowProjection::hash):
(JSC::DFG::NodeFlowProjection::operator==):
(JSC::DFG::NodeFlowProjection::operator!=):
(JSC::DFG::NodeFlowProjection::operator&lt;):
(JSC::DFG::NodeFlowProjection::operator&gt;):
(JSC::DFG::NodeFlowProjection::operator&lt;=):
(JSC::DFG::NodeFlowProjection::operator&gt;=):
(JSC::DFG::NodeFlowProjection::isHashTableDeletedValue):
(JSC::DFG::NodeFlowProjection::isStillValid):
(JSC::DFG::NodeFlowProjection::forEach):
(JSC::DFG::NodeFlowProjectionHash::hash):
(JSC::DFG::NodeFlowProjectionHash::equal):
* dfg/DFGStoreBarrierInsertionPhase.cpp:

Source/WTF:

Made this API use size rather than maxIndex as its initialization parameter, because that's
less confusing.

* wtf/IndexSparseSet.h:
(WTF::IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLivenessh">trunk/Source/JavaScriptCore/b3/air/AirLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAtTailAbstractStatecpp">trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAtTailAbstractStateh">trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBasicBlockh">trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCombinedLivenesscpp">trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCombinedLivenessh">trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp">trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStateh">trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLivenessAnalysisPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfIndexSparseSeth">trunk/Source/WTF/wtf/IndexSparseSet.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressdfgssaswapjs">trunk/JSTests/stress/dfg-ssa-swap.js</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFlowIndexingcpp">trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFlowIndexingh">trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFlowMaph">trunk/Source/JavaScriptCore/dfg/DFGFlowMap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeAbstractValuePaircpp">trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeAbstractValuePairh">trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeFlowProjectioncpp">trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeFlowProjectionh">trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/JSTests/ChangeLog        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-11-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG plays fast and loose with the shadow values of a Phi
+        https://bugs.webkit.org/show_bug.cgi?id=164309
+
+        Reviewed by Saam Barati.
+        
+        This test demonstrates why the DFG needs to recognize the shadow value of a Phi.
+
+        * stress/dfg-ssa-swap.js: Added.
+        (foo):
+
</ins><span class="cx"> 2016-11-03  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Asking for a value profile prediction should be defensive against not finding a value profile
</span></span></pre></div>
<a id="trunkJSTestsstressdfgssaswapjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/dfg-ssa-swap.js (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/dfg-ssa-swap.js                                (rev 0)
+++ trunk/JSTests/stress/dfg-ssa-swap.js        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+var i,c=0;
+function foo()
+{
+    var a=1,b;for(i=0;i&lt;2;++i){[a,b]=[b,a];c++}if(!a^b)throw c
+}
+noInline(foo);
+for(var k = 0; k &lt; 10000; ++k)
+    foo()
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -312,6 +312,7 @@
</span><span class="cx">     dfg/DFGFailedFinalizer.cpp
</span><span class="cx">     dfg/DFGFinalizer.cpp
</span><span class="cx">     dfg/DFGFixupPhase.cpp
</span><ins>+    dfg/DFGFlowIndexing.cpp
</ins><span class="cx">     dfg/DFGFlushFormat.cpp
</span><span class="cx">     dfg/DFGFlushedAt.cpp
</span><span class="cx">     dfg/DFGLiveCatchVariablePreservationPhase.cpp
</span><span class="lines">@@ -343,7 +344,9 @@
</span><span class="cx">     dfg/DFGMultiGetByOffsetData.cpp
</span><span class="cx">     dfg/DFGNaturalLoops.cpp
</span><span class="cx">     dfg/DFGNode.cpp
</span><ins>+    dfg/DFGNodeAbstractValuePair.cpp
</ins><span class="cx">     dfg/DFGNodeFlags.cpp
</span><ins>+    dfg/DFGNodeFlowProjection.cpp
</ins><span class="cx">     dfg/DFGNodeOrigin.cpp
</span><span class="cx">     dfg/DFGOSRAvailabilityAnalysisPhase.cpp
</span><span class="cx">     dfg/DFGOSREntry.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -1,3 +1,136 @@
</span><ins>+2016-11-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG plays fast and loose with the shadow values of a Phi
+        https://bugs.webkit.org/show_bug.cgi?id=164309
+
+        Reviewed by Saam Barati.
+        
+        Oh boy, what an embarrassing mistake! The style of SSA I like to use avoids block/value
+        tuples as parameters of a Phi, thereby simplifying CFG transformations and making Phi largely
+        not a special case for most compiler transforms. It does this by introducing another value
+        called Upsilon, which stores a value into some Phi.
+        
+        B3 uses this also. The easiest way to understand what Upsilon/Phi behave like is to look at
+        the B3-&gt;Air lowering. Air is not SSA - it has Tmps that you can assign to and use as many
+        times as you like. B3 allocates one Tmp per Value, and an extra &quot;phiTmp&quot; for Phis, so that
+        Phis get two Tmps total. Upsilon stores the value into the phiTmp of the Phi, while Phi moves
+        the value from its phiTmp to its tmp.
+        
+        This is necessary to support scenarios like this:
+        
+            a: Phi()
+            b: Upsilon(@x, ^a)
+            c: Use(@a)
+        
+        Here, we want @c to see @a's value before @b. That's a very basic requirement of SSA: that
+        the a value (like @a) doesn't change during its lifetime.
+        
+        Unfortunately, DFG's liveness analysis, abstract interpreter, and integer range optimization
+        all failed to correctly model Upsilon/Phi this way. They would assume that it's accurate to
+        model the Upsilon as storing into the Phi directly.
+        
+        Because DFG does flow analysis over SSA, making it correct means enabling it to speak of the
+        shadow value. This change addresses this problem by introducing the concept of a
+        NodeFlowProjection. This is a key that lets us speak of both a Node's primary value and its
+        optional &quot;shadow&quot; value. Liveness, AI, and integer range are now keyed by NodeFlowProjection
+        rather than Node*. Conceptually this turns out to be a very simple change, but it does touch
+        a good amount of code.
+        
+        This looks to be perf-neutral.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/air/AirLiveness.h:
+        (JSC::B3::Air::TmpLivenessAdapter::numIndices):
+        (JSC::B3::Air::StackSlotLivenessAdapter::numIndices):
+        (JSC::B3::Air::RegLivenessAdapter::numIndices):
+        (JSC::B3::Air::AbstractLiveness::AbstractLiveness):
+        (JSC::B3::Air::TmpLivenessAdapter::maxIndex): Deleted.
+        (JSC::B3::Air::StackSlotLivenessAdapter::maxIndex): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::maxIndex): Deleted.
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::forNode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::forAllValues):
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::dump):
+        * dfg/DFGAtTailAbstractState.cpp:
+        (JSC::DFG::AtTailAbstractState::createValueForNode):
+        (JSC::DFG::AtTailAbstractState::forNode):
+        * dfg/DFGAtTailAbstractState.h:
+        * dfg/DFGBasicBlock.h:
+        * dfg/DFGCombinedLiveness.cpp:
+        (JSC::DFG::liveNodesAtHead):
+        * dfg/DFGCombinedLiveness.h:
+        * dfg/DFGFlowIndexing.cpp: Added.
+        (JSC::DFG::FlowIndexing::FlowIndexing):
+        (JSC::DFG::FlowIndexing::~FlowIndexing):
+        (JSC::DFG::FlowIndexing::recompute):
+        * dfg/DFGFlowIndexing.h: Added.
+        (JSC::DFG::FlowIndexing::graph):
+        (JSC::DFG::FlowIndexing::numIndices):
+        (JSC::DFG::FlowIndexing::index):
+        (JSC::DFG::FlowIndexing::shadowIndex):
+        (JSC::DFG::FlowIndexing::nodeProjection):
+        * dfg/DFGFlowMap.h: Added.
+        (JSC::DFG::FlowMap::FlowMap):
+        (JSC::DFG::FlowMap::resize):
+        (JSC::DFG::FlowMap::graph):
+        (JSC::DFG::FlowMap::at):
+        (JSC::DFG::FlowMap::atShadow):
+        (WTF::printInternal):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::Graph):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::abstractValuesCache): Deleted.
+        * dfg/DFGInPlaceAbstractState.cpp:
+        (JSC::DFG::InPlaceAbstractState::InPlaceAbstractState):
+        (JSC::DFG::InPlaceAbstractState::beginBasicBlock):
+        (JSC::DFG::setLiveValues):
+        (JSC::DFG::InPlaceAbstractState::endBasicBlock):
+        (JSC::DFG::InPlaceAbstractState::merge):
+        * dfg/DFGInPlaceAbstractState.h:
+        (JSC::DFG::InPlaceAbstractState::createValueForNode):
+        (JSC::DFG::InPlaceAbstractState::forNode):
+        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
+        * dfg/DFGLivenessAnalysisPhase.cpp:
+        (JSC::DFG::LivenessAnalysisPhase::LivenessAnalysisPhase):
+        (JSC::DFG::LivenessAnalysisPhase::run):
+        (JSC::DFG::LivenessAnalysisPhase::processBlock):
+        (JSC::DFG::LivenessAnalysisPhase::addChildUse): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::NodeComparator::operator()):
+        (JSC::DFG::nodeListDump):
+        (JSC::DFG::nodeMapDump):
+        (JSC::DFG::nodeValuePairListDump):
+        (JSC::DFG::nodeComparator): Deleted.
+        * dfg/DFGNodeAbstractValuePair.cpp: Added.
+        (JSC::DFG::NodeAbstractValuePair::dump):
+        * dfg/DFGNodeAbstractValuePair.h: Added.
+        (JSC::DFG::NodeAbstractValuePair::NodeAbstractValuePair):
+        * dfg/DFGNodeFlowProjection.cpp: Added.
+        (JSC::DFG::NodeFlowProjection::dump):
+        * dfg/DFGNodeFlowProjection.h: Added.
+        (JSC::DFG::NodeFlowProjection::NodeFlowProjection):
+        (JSC::DFG::NodeFlowProjection::operator bool):
+        (JSC::DFG::NodeFlowProjection::kind):
+        (JSC::DFG::NodeFlowProjection::node):
+        (JSC::DFG::NodeFlowProjection::operator*):
+        (JSC::DFG::NodeFlowProjection::operator-&gt;):
+        (JSC::DFG::NodeFlowProjection::hash):
+        (JSC::DFG::NodeFlowProjection::operator==):
+        (JSC::DFG::NodeFlowProjection::operator!=):
+        (JSC::DFG::NodeFlowProjection::operator&lt;):
+        (JSC::DFG::NodeFlowProjection::operator&gt;):
+        (JSC::DFG::NodeFlowProjection::operator&lt;=):
+        (JSC::DFG::NodeFlowProjection::operator&gt;=):
+        (JSC::DFG::NodeFlowProjection::isHashTableDeletedValue):
+        (JSC::DFG::NodeFlowProjection::isStillValid):
+        (JSC::DFG::NodeFlowProjection::forEach):
+        (JSC::DFG::NodeFlowProjectionHash::hash):
+        (JSC::DFG::NodeFlowProjectionHash::equal):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+
</ins><span class="cx"> 2016-11-03  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, changelog fix due to failed git rebase..
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -129,6 +129,13 @@
</span><span class="cx">                 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */; };
</span><span class="cx">                 0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */; };
</span><span class="cx">                 0F1FE51C1922A3BC006987C5 /* AbortReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FE51B1922A3BC006987C5 /* AbortReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F20177F1DCADC3300EA5950 /* DFGFlowIndexing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */; };
+                0F2017801DCADC3500EA5950 /* DFGFlowIndexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */; };
+                0F2017821DCADD4200EA5950 /* DFGFlowMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2017811DCADD4000EA5950 /* DFGFlowMap.h */; };
+                0F2017851DCAE14900EA5950 /* DFGNodeFlowProjection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2017841DCAE14700EA5950 /* DFGNodeFlowProjection.h */; };
+                0F2017861DCAE14C00EA5950 /* DFGNodeFlowProjection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2017831DCAE14700EA5950 /* DFGNodeFlowProjection.cpp */; };
+                0F2017891DCB942400EA5950 /* DFGNodeAbstractValuePair.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2017881DCB942200EA5950 /* DFGNodeAbstractValuePair.h */; };
+                0F20178A1DCB942600EA5950 /* DFGNodeAbstractValuePair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2017871DCB942200EA5950 /* DFGNodeAbstractValuePair.cpp */; };
</ins><span class="cx">                 0F20C2591A8013AB00DA3229 /* VirtualRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */; };
</span><span class="cx">                 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -2517,6 +2524,13 @@
</span><span class="cx">                 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSlowPathGenerator.h; path = dfg/DFGSlowPathGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSilentRegisterSavePlan.h; path = dfg/DFGSilentRegisterSavePlan.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1FE51B1922A3BC006987C5 /* AbortReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbortReason.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFlowIndexing.cpp; path = dfg/DFGFlowIndexing.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlowIndexing.h; path = dfg/DFGFlowIndexing.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2017811DCADD4000EA5950 /* DFGFlowMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlowMap.h; path = dfg/DFGFlowMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2017831DCAE14700EA5950 /* DFGNodeFlowProjection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeFlowProjection.cpp; path = dfg/DFGNodeFlowProjection.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2017841DCAE14700EA5950 /* DFGNodeFlowProjection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeFlowProjection.h; path = dfg/DFGNodeFlowProjection.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2017871DCB942200EA5950 /* DFGNodeAbstractValuePair.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeAbstractValuePair.cpp; path = dfg/DFGNodeAbstractValuePair.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F2017881DCB942200EA5950 /* DFGNodeAbstractValuePair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeAbstractValuePair.h; path = dfg/DFGNodeAbstractValuePair.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F20C2581A8013AB00DA3229 /* VirtualRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VirtualRegister.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -6729,8 +6743,6 @@
</span><span class="cx">                                 0FFFC94E14EF909500C72532 /* DFGCSEPhase.h */,
</span><span class="cx">                                 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */,
</span><span class="cx">                                 0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
</span><del>-                                E322E5A01DA64435006E7709 /* DFGDOMJITPatchpointParams.cpp */,
-                                E322E5A11DA64435006E7709 /* DFGDOMJITPatchpointParams.h */,
</del><span class="cx">                                 0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
</span><span class="cx">                                 0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
</span><span class="cx">                                 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
</span><span class="lines">@@ -6745,6 +6757,8 @@
</span><span class="cx">                                 0F5A1271192D9FDF008764A3 /* DFGDoesGC.cpp */,
</span><span class="cx">                                 0F5A1272192D9FDF008764A3 /* DFGDoesGC.h */,
</span><span class="cx">                                 0FD81AD0154FB4EB00983E72 /* DFGDominators.h */,
</span><ins>+                                E322E5A01DA64435006E7709 /* DFGDOMJITPatchpointParams.cpp */,
+                                E322E5A11DA64435006E7709 /* DFGDOMJITPatchpointParams.h */,
</ins><span class="cx">                                 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */,
</span><span class="cx">                                 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */,
</span><span class="cx">                                 0FD3C82214115D0E00FD81CB /* DFGDriver.h */,
</span><span class="lines">@@ -6761,6 +6775,9 @@
</span><span class="cx">                                 A78A976F179738B8009DF744 /* DFGFinalizer.h */,
</span><span class="cx">                                 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */,
</span><span class="cx">                                 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */,
</span><ins>+                                0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */,
+                                0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */,
+                                0F2017811DCADD4000EA5950 /* DFGFlowMap.h */,
</ins><span class="cx">                                 0F9D339417FFC4E60073C2BC /* DFGFlushedAt.cpp */,
</span><span class="cx">                                 0F9D339517FFC4E60073C2BC /* DFGFlushedAt.h */,
</span><span class="cx">                                 A7D89CE817A0B8CC00773AD8 /* DFGFlushFormat.cpp */,
</span><span class="lines">@@ -6828,9 +6845,13 @@
</span><span class="cx">                                 A737810B1799EA2E00817533 /* DFGNaturalLoops.h */,
</span><span class="cx">                                 0FB4B51E16B62772003F696B /* DFGNode.cpp */,
</span><span class="cx">                                 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */,
</span><ins>+                                0F2017871DCB942200EA5950 /* DFGNodeAbstractValuePair.cpp */,
+                                0F2017881DCB942200EA5950 /* DFGNodeAbstractValuePair.h */,
</ins><span class="cx">                                 0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */,
</span><span class="cx">                                 0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */,
</span><span class="cx">                                 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */,
</span><ins>+                                0F2017831DCAE14700EA5950 /* DFGNodeFlowProjection.cpp */,
+                                0F2017841DCAE14700EA5950 /* DFGNodeFlowProjection.h */,
</ins><span class="cx">                                 0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */,
</span><span class="cx">                                 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */,
</span><span class="cx">                                 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */,
</span><span class="lines">@@ -7612,6 +7633,7 @@
</span><span class="cx">                                 0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
</span><span class="cx">                                 0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */,
</span><span class="cx">                                 0F338E161BF0276C0013C88F /* B3ValueKeyInlines.h in Headers */,
</span><ins>+                                0F2017821DCADD4200EA5950 /* DFGFlowMap.h in Headers */,
</ins><span class="cx">                                 0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
</span><span class="cx">                                 0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
</span><span class="cx">                                 0F3730931C0D67EE00052BFA /* AirUseCounts.h in Headers */,
</span><span class="lines">@@ -8498,6 +8520,7 @@
</span><span class="cx">                                 A7C1EAF017987AB600299DB2 /* CLoopStackInlines.h in Headers */,
</span><span class="cx">                                 BC18C4270E16F5CD00B34460 /* JSString.h in Headers */,
</span><span class="cx">                                 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */,
</span><ins>+                                0F2017851DCAE14900EA5950 /* DFGNodeFlowProjection.h in Headers */,
</ins><span class="cx">                                 E3555B8A1DAE03A500F36921 /* DOMJITCallDOMGetterPatchpoint.h in Headers */,
</span><span class="cx">                                 70EC0EC31AA0D7DA00B6AAFA /* JSStringIterator.h in Headers */,
</span><span class="cx">                                 0F070A471D543A8B006E7232 /* CellContainer.h in Headers */,
</span><span class="lines">@@ -8595,6 +8618,7 @@
</span><span class="cx">                                 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */,
</span><span class="cx">                                 14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */,
</span><span class="cx">                                 142D6F1213539A4100B02E86 /* MarkStack.h in Headers */,
</span><ins>+                                0F2017891DCB942400EA5950 /* DFGNodeAbstractValuePair.h in Headers */,
</ins><span class="cx">                                 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */,
</span><span class="cx">                                 4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */,
</span><span class="cx">                                 BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */,
</span><span class="lines">@@ -8663,6 +8687,7 @@
</span><span class="cx">                                 0FB387901BFBC44D00E3AB1E /* AirOptimizeBlockOrder.h in Headers */,
</span><span class="cx">                                 DCEE220D1CEBAF75000C2396 /* DFGNullAbstractState.h in Headers */,
</span><span class="cx">                                 0FF729BA166AD360000F5BA3 /* ProfilerCompilation.h in Headers */,
</span><ins>+                                0F2017801DCADC3500EA5950 /* DFGFlowIndexing.h in Headers */,
</ins><span class="cx">                                 0FF729BB166AD360000F5BA3 /* ProfilerCompilationKind.h in Headers */,
</span><span class="cx">                                 0F4A38FA1C8E13DF00190318 /* SuperSampler.h in Headers */,
</span><span class="cx">                                 0FF729BC166AD360000F5BA3 /* ProfilerCompiledBytecode.h in Headers */,
</span><span class="lines">@@ -9858,6 +9883,7 @@
</span><span class="cx">                                 A5840E20187B7B8600843B10 /* InjectedScriptModule.cpp in Sources */,
</span><span class="cx">                                 0FA762041DB9242600B7A2FD /* CollectionScope.cpp in Sources */,
</span><span class="cx">                                 148A7BEF1B82975A002D9157 /* InlineCallFrame.cpp in Sources */,
</span><ins>+                                0F20178A1DCB942600EA5950 /* DFGNodeAbstractValuePair.cpp in Sources */,
</ins><span class="cx">                                 0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */,
</span><span class="cx">                                 A5CEEE14187F3BAD00E55C99 /* InspectorAgent.cpp in Sources */,
</span><span class="cx">                                 A593CF86184038CA00BFCE27 /* InspectorAgentRegistry.cpp in Sources */,
</span><span class="lines">@@ -10087,6 +10113,7 @@
</span><span class="cx">                                 0F37308C1C0BD29100052BFA /* B3PhiChildren.cpp in Sources */,
</span><span class="cx">                                 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */,
</span><span class="cx">                                 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */,
</span><ins>+                                0F20177F1DCADC3300EA5950 /* DFGFlowIndexing.cpp in Sources */,
</ins><span class="cx">                                 0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */,
</span><span class="cx">                                 E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */,
</span><span class="cx">                                 E355F3521B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp in Sources */,
</span><span class="lines">@@ -10184,6 +10211,7 @@
</span><span class="cx">                                 A5FD0067189AFE9C00633231 /* ScriptArguments.cpp in Sources */,
</span><span class="cx">                                 A5FD006D189B00AA00633231 /* ScriptCallFrame.cpp in Sources */,
</span><span class="cx">                                 A5FD006F189B00AA00633231 /* ScriptCallStack.cpp in Sources */,
</span><ins>+                                0F2017861DCAE14C00EA5950 /* DFGNodeFlowProjection.cpp in Sources */,
</ins><span class="cx">                                 A5FD007D189B0B4C00633231 /* ScriptCallStackFactory.cpp in Sources */,
</span><span class="cx">                                 A503FA25188EFFFD00110F14 /* ScriptDebugServer.cpp in Sources */,
</span><span class="cx">                                 A55D93A5185012A800400DED /* ScriptFunctionCall.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> 
</span><span class="cx">     TmpLivenessAdapter(Code&amp;) { }
</span><span class="cx"> 
</span><del>-    static unsigned maxIndex(Code&amp; code)
</del><ins>+    static unsigned numIndices(Code&amp; code)
</ins><span class="cx">     {
</span><span class="cx">         unsigned numTmps = code.numTmps(adapterType);
</span><span class="cx">         return AbsoluteTmpMapper&lt;adapterType&gt;::absoluteIndex(numTmps);
</span><span class="lines">@@ -65,9 +65,9 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static unsigned maxIndex(Code&amp; code)
</del><ins>+    static unsigned numIndices(Code&amp; code)
</ins><span class="cx">     {
</span><del>-        return code.stackSlots().size() - 1;
</del><ins>+        return code.stackSlots().size();
</ins><span class="cx">     }
</span><span class="cx">     static bool acceptsType(Arg::Type) { return true; }
</span><span class="cx">     static unsigned valueToIndex(StackSlot* stackSlot) { return stackSlot-&gt;index(); }
</span><span class="lines">@@ -83,9 +83,9 @@
</span><span class="cx"> 
</span><span class="cx">     RegLivenessAdapter(Code&amp;) { }
</span><span class="cx"> 
</span><del>-    static unsigned maxIndex(Code&amp;)
</del><ins>+    static unsigned numIndices(Code&amp;)
</ins><span class="cx">     {
</span><del>-        return Reg::maxIndex();
</del><ins>+        return Reg::maxIndex() + 1;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     static bool acceptsType(Arg::Type) { return true; }
</span><span class="lines">@@ -101,7 +101,7 @@
</span><span class="cx">     
</span><span class="cx">     AbstractLiveness(Code&amp; code)
</span><span class="cx">         : Adapter(code)
</span><del>-        , m_workset(Adapter::maxIndex(code))
</del><ins>+        , m_workset(Adapter::numIndices(code))
</ins><span class="cx">         , m_liveAtHead(code.size())
</span><span class="cx">         , m_liveAtTail(code.size())
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;DFGBranchDirection.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGNode.h&quot;
</span><ins>+#include &quot;DFGNodeFlowProjection.h&quot;
</ins><span class="cx"> #include &quot;DFGPhiChildren.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="lines">@@ -41,7 +42,7 @@
</span><span class="cx">     AbstractInterpreter(Graph&amp;, AbstractStateType&amp;);
</span><span class="cx">     ~AbstractInterpreter();
</span><span class="cx">     
</span><del>-    AbstractValue&amp; forNode(Node* node)
</del><ins>+    AbstractValue&amp; forNode(NodeFlowProjection node)
</ins><span class="cx">     {
</span><span class="cx">         return m_state.forNode(node);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -2817,6 +2817,7 @@
</span><span class="cx">             
</span><span class="cx">     case Phi:
</span><span class="cx">         RELEASE_ASSERT(m_graph.m_form == SSA);
</span><ins>+        forNode(node) = forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow));
</ins><span class="cx">         // The state of this node would have already been decided, but it may have become a
</span><span class="cx">         // constant, in which case we'd like to know.
</span><span class="cx">         if (forNode(node).m_value)
</span><span class="lines">@@ -2824,8 +2825,11 @@
</span><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     case Upsilon: {
</span><del>-        m_state.createValueForNode(node-&gt;phi());
-        forNode(node-&gt;phi()) = forNode(node-&gt;child1());
</del><ins>+        NodeFlowProjection shadow(node-&gt;phi(), NodeFlowProjection::Shadow);
+        if (shadow.isStillValid()) {
+            m_state.createValueForNode(shadow);
+            forNode(shadow) = forNode(node-&gt;child1());
+        }
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -2977,11 +2981,18 @@
</span><span class="cx">     else
</span><span class="cx">         clobberLimit++;
</span><span class="cx">     ASSERT(clobberLimit &lt;= m_state.block()-&gt;size());
</span><del>-    for (size_t i = clobberLimit; i--;)
-        functor(forNode(m_state.block()-&gt;at(i)));
</del><ins>+    for (size_t i = clobberLimit; i--;) {
+        NodeFlowProjection::forEach(
+            m_state.block()-&gt;at(i),
+            [&amp;] (NodeFlowProjection nodeProjection) {
+                functor(forNode(nodeProjection));
+            });
+    }
</ins><span class="cx">     if (m_graph.m_form == SSA) {
</span><del>-        for (Node* node : m_state.block()-&gt;ssa-&gt;liveAtHead)
-            functor(forNode(node));
</del><ins>+        for (NodeFlowProjection node : m_state.block()-&gt;ssa-&gt;liveAtHead) {
+            if (node.isStillValid())
+                functor(forNode(node));
+        }
</ins><span class="cx">     }
</span><span class="cx">     for (size_t i = m_state.variables().numberOfArguments(); i--;)
</span><span class="cx">         functor(m_state.variables().argument(i));
</span><span class="lines">@@ -3037,9 +3048,9 @@
</span><span class="cx"> void AbstractInterpreter&lt;AbstractStateType&gt;::dump(PrintStream&amp; out)
</span><span class="cx"> {
</span><span class="cx">     CommaPrinter comma(&quot; &quot;);
</span><del>-    HashSet&lt;Node*&gt; seen;
</del><ins>+    HashSet&lt;NodeFlowProjection&gt; seen;
</ins><span class="cx">     if (m_graph.m_form == SSA) {
</span><del>-        for (Node* node : m_state.block()-&gt;ssa-&gt;liveAtHead) {
</del><ins>+        for (NodeFlowProjection node : m_state.block()-&gt;ssa-&gt;liveAtHead) {
</ins><span class="cx">             seen.add(node);
</span><span class="cx">             AbstractValue&amp; value = forNode(node);
</span><span class="cx">             if (value.isClear())
</span><span class="lines">@@ -3048,15 +3059,17 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     for (size_t i = 0; i &lt; m_state.block()-&gt;size(); ++i) {
</span><del>-        Node* node = m_state.block()-&gt;at(i);
-        seen.add(node);
-        AbstractValue&amp; value = forNode(node);
-        if (value.isClear())
-            continue;
-        out.print(comma, node, &quot;:&quot;, value);
</del><ins>+        NodeFlowProjection::forEach(
+            m_state.block()-&gt;at(i), [&amp;] (NodeFlowProjection nodeProjection) {
+                seen.add(nodeProjection);
+                AbstractValue&amp; value = forNode(nodeProjection);
+                if (value.isClear())
+                    return;
+                out.print(comma, nodeProjection, &quot;:&quot;, value);
+            });
</ins><span class="cx">     }
</span><span class="cx">     if (m_graph.m_form == SSA) {
</span><del>-        for (Node* node : m_state.block()-&gt;ssa-&gt;liveAtTail) {
</del><ins>+        for (NodeFlowProjection node : m_state.block()-&gt;ssa-&gt;liveAtTail) {
</ins><span class="cx">             if (seen.contains(node))
</span><span class="cx">                 continue;
</span><span class="cx">             AbstractValue&amp; value = forNode(node);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAtTailAbstractStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -47,16 +47,16 @@
</span><span class="cx"> 
</span><span class="cx"> AtTailAbstractState::~AtTailAbstractState() { }
</span><span class="cx"> 
</span><del>-void AtTailAbstractState::createValueForNode(Node* node)
</del><ins>+void AtTailAbstractState::createValueForNode(NodeFlowProjection node)
</ins><span class="cx"> {
</span><span class="cx">     m_valuesAtTailMap.at(m_block).add(node, AbstractValue());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-AbstractValue&amp; AtTailAbstractState::forNode(Node* node)
</del><ins>+AbstractValue&amp; AtTailAbstractState::forNode(NodeFlowProjection node)
</ins><span class="cx"> {
</span><span class="cx">     auto&amp; valuesAtTail = m_valuesAtTailMap.at(m_block);
</span><del>-    HashMap&lt;Node*, AbstractValue&gt;::iterator iter = valuesAtTail.find(node);
-    DFG_ASSERT(m_graph, node, iter != valuesAtTail.end());
</del><ins>+    HashMap&lt;NodeFlowProjection, AbstractValue&gt;::iterator iter = valuesAtTail.find(node);
+    DFG_ASSERT(m_graph, node.node(), iter != valuesAtTail.end());
</ins><span class="cx">     return iter-&gt;value;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAtTailAbstractStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;DFGBasicBlock.h&quot;
</span><span class="cx"> #include &quot;DFGBlockMap.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><ins>+#include &quot;DFGNodeFlowProjection.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG { 
</span><span class="cx"> 
</span><span class="lines">@@ -47,8 +48,8 @@
</span><span class="cx">         m_block = block;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void createValueForNode(Node*);
-    AbstractValue&amp; forNode(Node*);
</del><ins>+    void createValueForNode(NodeFlowProjection);
+    AbstractValue&amp; forNode(NodeFlowProjection);
</ins><span class="cx">     AbstractValue&amp; forNode(Edge edge) { return forNode(edge.node()); }
</span><span class="cx">     Operands&lt;AbstractValue&gt;&amp; variables() { return m_block-&gt;valuesAtTail; }
</span><span class="cx">     
</span><span class="lines">@@ -66,7 +67,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Graph&amp; m_graph;
</span><del>-    BlockMap&lt;HashMap&lt;Node*, AbstractValue&gt;&gt; m_valuesAtTailMap;
</del><ins>+    BlockMap&lt;HashMap&lt;NodeFlowProjection, AbstractValue&gt;&gt; m_valuesAtTailMap;
</ins><span class="cx">     BasicBlock* m_block { nullptr };
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;DFGBranchDirection.h&quot;
</span><span class="cx"> #include &quot;DFGFlushedAt.h&quot;
</span><span class="cx"> #include &quot;DFGNode.h&quot;
</span><ins>+#include &quot;DFGNodeAbstractValuePair.h&quot;
</ins><span class="cx"> #include &quot;DFGNodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGStructureClobberState.h&quot;
</span><span class="cx"> #include &quot;Operands.h&quot;
</span><span class="lines">@@ -248,12 +249,8 @@
</span><span class="cx">         AvailabilityMap availabilityAtHead;
</span><span class="cx">         AvailabilityMap availabilityAtTail;
</span><span class="cx"> 
</span><del>-        Vector&lt;Node*&gt; liveAtHead;
-        Vector&lt;Node*&gt; liveAtTail;
-        struct NodeAbstractValuePair {
-            Node* node;
-            AbstractValue value;
-        };
</del><ins>+        Vector&lt;NodeFlowProjection&gt; liveAtHead;
+        Vector&lt;NodeFlowProjection&gt; liveAtTail;
</ins><span class="cx">         Vector&lt;NodeAbstractValuePair&gt; valuesAtHead;
</span><span class="cx">         Vector&lt;NodeAbstractValuePair&gt; valuesAtTail;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCombinedLivenesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -38,8 +38,10 @@
</span><span class="cx"> HashSet&lt;Node*&gt; liveNodesAtHead(Graph&amp; graph, BasicBlock* block)
</span><span class="cx"> {
</span><span class="cx">     HashSet&lt;Node*&gt; seen;
</span><del>-    for (Node* node : block-&gt;ssa-&gt;liveAtHead)
-        seen.add(node);
</del><ins>+    for (NodeFlowProjection node : block-&gt;ssa-&gt;liveAtHead) {
+        if (node.kind() == NodeFlowProjection::Primary)
+            seen.add(node.node());
+    }
</ins><span class="cx">     
</span><span class="cx">     AvailabilityMap&amp; availabilityMap = block-&gt;ssa-&gt;availabilityAtHead;
</span><span class="cx">     graph.forAllLocalsLiveInBytecode(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCombinedLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGCombinedLiveness.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -35,6 +35,11 @@
</span><span class="cx"> // Returns the set of nodes live at tail, both due to due DFG and due to bytecode (i.e. OSR exit).
</span><span class="cx"> HashSet&lt;Node*&gt; liveNodesAtHead(Graph&amp;, BasicBlock*);
</span><span class="cx"> 
</span><ins>+// WARNING: This currently does not reason about the liveness of shadow values. The execution
+// semantics of DFG SSA are that an Upsilon stores to the shadow value of a Phi, and the Phi loads
+// from that shadow value. Hence, the shadow values are like variables, and have liveness. The normal
+// liveness analysis will tell you about the liveness of shadow values. It's OK to ignore shadow
+// values if you treat Upsilon as an opaque escape, and all of the clients of CombinedLiveness do so.
</ins><span class="cx"> struct CombinedLiveness {
</span><span class="cx">     CombinedLiveness() { }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFlowIndexingcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.cpp (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGFlowIndexing.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+FlowIndexing::FlowIndexing(Graph&amp; graph)
+    : m_graph(graph)
+    , m_numIndices(0)
+{
+    recompute();
+}
+
+FlowIndexing::~FlowIndexing()
+{
+}
+
+void FlowIndexing::recompute()
+{
+    unsigned numNodeIndices = m_graph.maxNodeCount();
+    
+    m_nodeIndexToShadowIndex.resize(numNodeIndices);
+    m_nodeIndexToShadowIndex.fill(UINT_MAX);
+    
+    m_shadowIndexToNodeIndex.resize(0);
+
+    m_numIndices = numNodeIndices;
+
+    for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+        for (Node* node : *block) {
+            if (node-&gt;op() != Phi)
+                continue;
+            
+            unsigned nodeIndex = node-&gt;index();
+            unsigned shadowIndex = m_numIndices++;
+            m_nodeIndexToShadowIndex[nodeIndex] = shadowIndex;
+            m_shadowIndexToNodeIndex.append(nodeIndex);
+            DFG_ASSERT(m_graph, nullptr, m_shadowIndexToNodeIndex.size() + numNodeIndices == m_numIndices);
+            DFG_ASSERT(m_graph, nullptr, m_shadowIndexToNodeIndex[shadowIndex - numNodeIndices] == nodeIndex);
+        }
+    }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFlowIndexingh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.h (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGFlowIndexing.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,112 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGGraph.h&quot;
+#include &quot;DFGNodeFlowProjection.h&quot;
+
+namespace JSC { namespace DFG {
+
+// This is a mapping from nodes to unique, dense indices that can be used for creating fast
+// Node-keyed maps. The special part is that it also allocated indices for the shadow values of Phi
+// nodes, which is needed for any flow-sensitive analysis.
+class FlowIndexing {
+public:
+    FlowIndexing(Graph&amp;);
+    ~FlowIndexing();
+    
+    void recompute();
+    
+    Graph&amp; graph() const { return m_graph; }
+    
+    unsigned numIndices() const { return m_numIndices; }
+    
+    unsigned index(unsigned nodeIndex) const { return nodeIndex; }
+    
+    unsigned index(Node* node) const { return index(node-&gt;index()); }
+    
+    unsigned shadowIndex(unsigned nodeIndex) const
+    {
+        return m_nodeIndexToShadowIndex[nodeIndex];
+    }
+    
+    unsigned shadowIndex(Node* node) const
+    {
+        DFG_ASSERT(m_graph, node, node-&gt;op() == Phi);
+        return shadowIndex(node-&gt;index());
+    }
+    
+    unsigned index(unsigned nodeIndex, NodeFlowProjection::Kind kind) const
+    {
+        switch (kind) {
+        case NodeFlowProjection::Primary:
+            return index(nodeIndex);
+        case NodeFlowProjection::Shadow:
+            return shadowIndex(nodeIndex);
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    unsigned index(Node *node, NodeFlowProjection::Kind kind) const
+    {
+        switch (kind) {
+        case NodeFlowProjection::Primary:
+            return index(node);
+        case NodeFlowProjection::Shadow:
+            return shadowIndex(node);
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+    
+    unsigned index(NodeFlowProjection projection) const
+    {
+        return index(projection.node(), projection.kind());
+    }
+    
+    NodeFlowProjection nodeProjection(unsigned index) const
+    {
+        if (index &lt; m_nodeIndexToShadowIndex.size())
+            return NodeFlowProjection(m_graph.nodeAt(index));
+        return NodeFlowProjection(
+            m_graph.nodeAt(m_shadowIndexToNodeIndex[index - m_nodeIndexToShadowIndex.size()]),
+            NodeFlowProjection::Shadow);
+    }
+    
+private:
+    Graph&amp; m_graph;
+    unsigned m_numIndices;
+    Vector&lt;unsigned, 0, UnsafeVectorOverflow&gt; m_nodeIndexToShadowIndex;
+    Vector&lt;unsigned, 0, UnsafeVectorOverflow&gt; m_shadowIndexToNodeIndex;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFlowMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGFlowMap.h (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFlowMap.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGFlowMap.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,139 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGFlowIndexing.h&quot;
+#include &quot;DFGGraph.h&quot;
+#include &quot;DFGNode.h&quot;
+
+namespace JSC { namespace DFG {
+
+// This is a mapping from nodes to values that is useful for flow-sensitive analysis. In such an
+// analysis, at every point in the program we need to consider the values of nodes plus the shadow
+// values of Phis. This makes it easy to do both of those things.
+template&lt;typename T&gt;
+class FlowMap {
+public:
+    FlowMap(Graph&amp; graph)
+        : m_graph(graph)
+    {
+        resize();
+    }
+    
+    // Call this if the number of nodes in the graph has changed. Note that this does not reset any
+    // entries.
+    void resize()
+    {
+        m_map.resize(m_graph.maxNodeCount());
+        m_shadowMap.resize(m_graph.maxNodeCount());
+    }
+    
+    Graph&amp; graph() const { return m_graph; }
+    
+    T&amp; at(unsigned nodeIndex)
+    {
+        return m_map[nodeIndex];
+    }
+    
+    T&amp; at(Node* node)
+    {
+        return at(node-&gt;index());
+    }
+    
+    T&amp; atShadow(unsigned nodeIndex)
+    {
+        return m_shadowMap[nodeIndex];
+    }
+    
+    T&amp; atShadow(Node* node)
+    {
+        return atShadow(node-&gt;index());
+    }
+    
+    T&amp; at(unsigned nodeIndex, NodeFlowProjection::Kind kind)
+    {
+        switch (kind) {
+        case NodeFlowProjection::Primary:
+            return at(nodeIndex);
+        case NodeFlowProjection::Shadow:
+            return atShadow(nodeIndex);
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return *bitwise_cast&lt;T*&gt;(nullptr);
+    }
+    
+    T&amp; at(Node* node, NodeFlowProjection::Kind kind)
+    {
+        return at(node-&gt;index(), kind);
+    }
+    
+    T&amp; at(NodeFlowProjection projection)
+    {
+        return at(projection.node(), projection.kind());
+    }
+    
+    const T&amp; at(unsigned nodeIndex) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;at(nodeIndex); }
+    const T&amp; at(Node* node) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;at(node); }
+    const T&amp; atShadow(unsigned nodeIndex) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;atShadow(nodeIndex); }
+    const T&amp; atShadow(Node* node) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;atShadow(node); }
+    const T&amp; at(unsigned nodeIndex, NodeFlowProjection::Kind kind) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;at(nodeIndex, kind); }
+    const T&amp; at(Node* node, NodeFlowProjection::Kind kind) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;at(node, kind); }
+    const T&amp; at(NodeFlowProjection projection) const { return const_cast&lt;FlowMap*&gt;(this)-&gt;at(projection); }
+    
+private:
+    Graph&amp; m_graph;
+    Vector&lt;T, 0, UnsafeVectorOverflow&gt; m_map;
+    Vector&lt;T, 0, UnsafeVectorOverflow&gt; m_shadowMap;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template&lt;typename T&gt;
+void printInternal(PrintStream&amp; out, const JSC::DFG::FlowMap&lt;T&gt;&amp; map)
+{
+    CommaPrinter comma;
+    for (unsigned i = 0; i &lt; map.graph().maxNodeCount(); ++i) {
+        if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
+            if (const T&amp; value = map.at(node))
+                out.print(comma, node, &quot;=&gt;&quot;, value);
+        }
+    }
+    for (unsigned i = 0; i &lt; map.graph().maxNodeCount(); ++i) {
+        if (JSC::DFG::Node* node = map.graph().nodeAt(i)) {
+            if (const T&amp; value = map.atShadow(node))
+                out.print(comma, &quot;shadow(&quot;, node, &quot;)=&gt;&quot;, value);
+        }
+    }
+}
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> #include &quot;DFGClobbersExitState.h&quot;
</span><span class="cx"> #include &quot;DFGControlEquivalenceAnalysis.h&quot;
</span><span class="cx"> #include &quot;DFGDominators.h&quot;
</span><ins>+#include &quot;DFGFlowIndexing.h&quot;
+#include &quot;DFGFlowMap.h&quot;
</ins><span class="cx"> #include &quot;DFGJITCode.h&quot;
</span><span class="cx"> #include &quot;DFGMayExit.h&quot;
</span><span class="cx"> #include &quot;DFGNaturalLoops.h&quot;
</span><span class="lines">@@ -83,6 +85,9 @@
</span><span class="cx">     ASSERT(m_profiledBlock);
</span><span class="cx">     
</span><span class="cx">     m_hasDebuggerEnabled = m_profiledBlock-&gt;wasCompiledWithDebuggingOpcodes() || Options::forceDebuggerBytecodeGeneration();
</span><ins>+    
+    m_indexingCache = std::make_unique&lt;FlowIndexing&gt;(*this);
+    m_abstractValuesCache = std::make_unique&lt;FlowMap&lt;AbstractValue&gt;&gt;(*this);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Graph::~Graph()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -59,9 +59,12 @@
</span><span class="cx"> class CFG;
</span><span class="cx"> class ControlEquivalenceAnalysis;
</span><span class="cx"> class Dominators;
</span><ins>+class FlowIndexing;
</ins><span class="cx"> class NaturalLoops;
</span><span class="cx"> class PrePostNumbering;
</span><span class="cx"> 
</span><ins>+template&lt;typename&gt; class FlowMap;
+
</ins><span class="cx"> #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do {            \
</span><span class="cx">         Node* _node = (node);                                           \
</span><span class="cx">         if (_node-&gt;flags() &amp; NodeHasVarArgs) {                          \
</span><span class="lines">@@ -201,8 +204,6 @@
</span><span class="cx">     Node* nodeAt(unsigned index) const { return m_nodesByIndex[index]; }
</span><span class="cx">     void packNodeIndices();
</span><span class="cx"> 
</span><del>-    Vector&lt;AbstractValue, 0, UnsafeVectorOverflow&gt;&amp; abstractValuesCache() { return m_abstractValuesCache; }
-
</del><span class="cx">     void dethread();
</span><span class="cx">     
</span><span class="cx">     FrozenValue* freeze(JSValue); // We use weak freezing by default.
</span><span class="lines">@@ -935,6 +936,9 @@
</span><span class="cx">     RefCountState m_refCountState;
</span><span class="cx">     bool m_hasDebuggerEnabled;
</span><span class="cx">     bool m_hasExceptionHandlers { false };
</span><ins>+    std::unique_ptr&lt;FlowIndexing&gt; m_indexingCache;
+    std::unique_ptr&lt;FlowMap&lt;AbstractValue&gt;&gt; m_abstractValuesCache;
+
</ins><span class="cx"> private:
</span><span class="cx">     void addNodeToMapByIndex(Node*);
</span><span class="cx"> 
</span><span class="lines">@@ -972,7 +976,6 @@
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;Node*, 0, UnsafeVectorOverflow&gt; m_nodesByIndex;
</span><span class="cx">     Vector&lt;unsigned, 0, UnsafeVectorOverflow&gt; m_nodeIndexFreeList;
</span><del>-    Vector&lt;AbstractValue, 0, UnsafeVectorOverflow&gt; m_abstractValuesCache;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx"> 
</span><span class="cx"> InPlaceAbstractState::InPlaceAbstractState(Graph&amp; graph)
</span><span class="cx">     : m_graph(graph)
</span><del>-    , m_abstractValues(graph.abstractValuesCache())
</del><ins>+    , m_abstractValues(*graph.m_abstractValuesCache)
</ins><span class="cx">     , m_variables(m_graph.m_codeBlock-&gt;numParameters(), graph.m_localVars)
</span><span class="cx">     , m_block(0)
</span><span class="cx"> {
</span><span class="lines">@@ -57,19 +57,22 @@
</span><span class="cx">     ASSERT(basicBlock-&gt;variablesAtTail.numberOfLocals() == basicBlock-&gt;valuesAtTail.numberOfLocals());
</span><span class="cx">     ASSERT(basicBlock-&gt;variablesAtHead.numberOfLocals() == basicBlock-&gt;variablesAtTail.numberOfLocals());
</span><span class="cx"> 
</span><del>-    // Certain phases insert nodes in a block after running through it.
-    // We cannot reserve the space for AbstractValues when initializing AbstractState because the number of values
-    // can increase as we execute. Instead, we increase the size as needed before processing each block.
-    m_abstractValues.resize(m_graph.maxNodeCount());
</del><ins>+    m_abstractValues.resize();
</ins><span class="cx">     
</span><del>-    for (size_t i = 0; i &lt; basicBlock-&gt;size(); i++)
-        forNode(basicBlock-&gt;at(i)).clear();
</del><ins>+    for (size_t i = 0; i &lt; basicBlock-&gt;size(); i++) {
+        NodeFlowProjection::forEach(
+            basicBlock-&gt;at(i), [&amp;] (NodeFlowProjection nodeProjection) {
+                forNode(nodeProjection).clear();
+            });
+    }
</ins><span class="cx"> 
</span><span class="cx">     m_variables = basicBlock-&gt;valuesAtHead;
</span><span class="cx">     
</span><span class="cx">     if (m_graph.m_form == SSA) {
</span><del>-        for (auto&amp; entry : basicBlock-&gt;ssa-&gt;valuesAtHead)
-            forNode(entry.node) = entry.value;
</del><ins>+        for (NodeAbstractValuePair&amp; entry : basicBlock-&gt;ssa-&gt;valuesAtHead) {
+            if (entry.node.isStillValid())
+                forNode(entry.node) = entry.value;
+        }
</ins><span class="cx">     }
</span><span class="cx">     basicBlock-&gt;cfaShouldRevisit = false;
</span><span class="cx">     basicBlock-&gt;cfaHasVisited = true;
</span><span class="lines">@@ -80,12 +83,12 @@
</span><span class="cx">     m_structureClobberState = basicBlock-&gt;cfaStructureClobberStateAtHead;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setLiveValues(Vector&lt;BasicBlock::SSAData::NodeAbstractValuePair&gt;&amp; values, const Vector&lt;Node*&gt;&amp; live)
</del><ins>+static void setLiveValues(Vector&lt;NodeAbstractValuePair&gt;&amp; values, const Vector&lt;NodeFlowProjection&gt;&amp; live)
</ins><span class="cx"> {
</span><span class="cx">     values.resize(0);
</span><span class="cx">     values.reserveCapacity(live.size());
</span><del>-    for (Node* node : live)
-        values.uncheckedAppend(BasicBlock::SSAData::NodeAbstractValuePair { node, AbstractValue() });
</del><ins>+    for (NodeFlowProjection node : live)
+        values.uncheckedAppend(NodeAbstractValuePair { node, AbstractValue() });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void InPlaceAbstractState::initialize()
</span><span class="lines">@@ -199,7 +202,7 @@
</span><span class="cx">         for (size_t i = 0; i &lt; block-&gt;valuesAtTail.size(); ++i)
</span><span class="cx">             block-&gt;valuesAtTail[i].merge(m_variables[i]);
</span><span class="cx"> 
</span><del>-        for (auto&amp; valueAtTail : block-&gt;ssa-&gt;valuesAtTail) {
</del><ins>+        for (NodeAbstractValuePair&amp; valueAtTail : block-&gt;ssa-&gt;valuesAtTail) {
</ins><span class="cx">             AbstractValue&amp; valueAtNode = forNode(valueAtTail.node);
</span><span class="cx">             valueAtTail.value.merge(valueAtNode);
</span><span class="cx">             valueAtNode = valueAtTail.value;
</span><span class="lines">@@ -291,13 +294,13 @@
</span><span class="cx">         for (size_t i = from-&gt;valuesAtTail.size(); i--;)
</span><span class="cx">             changed |= to-&gt;valuesAtHead[i].merge(from-&gt;valuesAtTail[i]);
</span><span class="cx"> 
</span><del>-        for (auto&amp; entry : to-&gt;ssa-&gt;valuesAtHead) {
-            Node* node = entry.node;
</del><ins>+        for (NodeAbstractValuePair&amp; entry : to-&gt;ssa-&gt;valuesAtHead) {
+            NodeFlowProjection node = entry.node;
</ins><span class="cx">             if (verbose)
</span><span class="cx">                 dataLog(&quot;      Merging for &quot;, node, &quot;: from &quot;, forNode(node), &quot; to &quot;, entry.value, &quot;\n&quot;);
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">             unsigned valueCountInFromBlock = 0;
</span><del>-            for (auto&amp; fromBlockValueAtTail : from-&gt;ssa-&gt;valuesAtTail) {
</del><ins>+            for (NodeAbstractValuePair&amp; fromBlockValueAtTail : from-&gt;ssa-&gt;valuesAtTail) {
</ins><span class="cx">                 if (fromBlockValueAtTail.node == node) {
</span><span class="cx">                     ASSERT(fromBlockValueAtTail.value == forNode(node));
</span><span class="cx">                     ++valueCountInFromBlock;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInPlaceAbstractStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DFGAbstractValue.h&quot;
</span><span class="cx"> #include &quot;DFGBranchDirection.h&quot;
</span><ins>+#include &quot;DFGFlowMap.h&quot;
</ins><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGNode.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -43,11 +44,11 @@
</span><span class="cx">     
</span><span class="cx">     explicit operator bool() const { return true; }
</span><span class="cx">     
</span><del>-    void createValueForNode(Node*) { }
</del><ins>+    void createValueForNode(NodeFlowProjection) { }
</ins><span class="cx">     
</span><del>-    AbstractValue&amp; forNode(Node* node)
</del><ins>+    AbstractValue&amp; forNode(NodeFlowProjection node)
</ins><span class="cx">     {
</span><del>-        return m_abstractValues[node-&gt;index()];
</del><ins>+        return m_abstractValues.at(node);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     AbstractValue&amp; forNode(Edge edge)
</span><span class="lines">@@ -132,7 +133,7 @@
</span><span class="cx">     
</span><span class="cx">     Graph&amp; m_graph;
</span><span class="cx"> 
</span><del>-    Vector&lt;AbstractValue, 0, UnsafeVectorOverflow&gt;&amp; m_abstractValues;
</del><ins>+    FlowMap&lt;AbstractValue&gt;&amp; m_abstractValues;
</ins><span class="cx">     Operands&lt;AbstractValue&gt; m_variables;
</span><span class="cx">     BasicBlock* m_block;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGIntegerRangeOptimizationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;DFGBlockSet.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGInsertionSet.h&quot;
</span><ins>+#include &quot;DFGNodeFlowProjection.h&quot;
</ins><span class="cx"> #include &quot;DFGPhase.h&quot;
</span><span class="cx"> #include &quot;DFGPredictionPropagationPhase.h&quot;
</span><span class="cx"> #include &quot;DFGVariableAccessDataDump.h&quot;
</span><span class="lines">@@ -121,7 +122,7 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Relationship(Node* left, Node* right, Kind kind, int offset = 0)
</del><ins>+    Relationship(NodeFlowProjection left, NodeFlowProjection right, Kind kind, int offset = 0)
</ins><span class="cx">         : m_left(left)
</span><span class="cx">         , m_right(right)
</span><span class="cx">         , m_kind(kind)
</span><span class="lines">@@ -132,17 +133,17 @@
</span><span class="cx">         RELEASE_ASSERT(m_left != m_right);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static Relationship safeCreate(Node* left, Node* right, Kind kind, int offset = 0)
</del><ins>+    static Relationship safeCreate(NodeFlowProjection left, NodeFlowProjection right, Kind kind, int offset = 0)
</ins><span class="cx">     {
</span><del>-        if (!left || !right || left == right)
</del><ins>+        if (!left.isStillValid() || !right.isStillValid() || left == right)
</ins><span class="cx">             return Relationship();
</span><span class="cx">         return Relationship(left, right, kind, offset);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    explicit operator bool() const { return m_left; }
</del><ins>+    explicit operator bool() const { return !!m_left; }
</ins><span class="cx">     
</span><del>-    Node* left() const { return m_left; }
-    Node* right() const { return m_right; }
</del><ins>+    NodeFlowProjection left() const { return m_left; }
+    NodeFlowProjection right() const { return m_right; }
</ins><span class="cx">     Kind kind() const { return m_kind; }
</span><span class="cx">     int offset() const { return m_offset; }
</span><span class="cx"> 
</span><span class="lines">@@ -258,7 +259,7 @@
</span><span class="cx">     // If possible, returns a form of this relationship where the given node is the left
</span><span class="cx">     // side. Returns a null relationship if this relationship cannot say anything about this
</span><span class="cx">     // node.
</span><del>-    Relationship forNode(Node* node) const
</del><ins>+    Relationship forNode(NodeFlowProjection node) const
</ins><span class="cx">     {
</span><span class="cx">         if (m_left == node)
</span><span class="cx">             return *this;
</span><span class="lines">@@ -267,7 +268,7 @@
</span><span class="cx">         return Relationship();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void setLeft(Node* left)
</del><ins>+    void setLeft(NodeFlowProjection left)
</ins><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(left != m_right);
</span><span class="cx">         m_left = left;
</span><span class="lines">@@ -984,13 +985,13 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Node* m_left;
-    Node* m_right;
</del><ins>+    NodeFlowProjection m_left;
+    NodeFlowProjection m_right;
</ins><span class="cx">     Kind m_kind;
</span><span class="cx">     int m_offset; // This offset can be arbitrarily large.
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-typedef HashMap&lt;Node*, Vector&lt;Relationship&gt;&gt; RelationshipMap;
</del><ins>+typedef HashMap&lt;NodeFlowProjection, Vector&lt;Relationship&gt;&gt; RelationshipMap;
</ins><span class="cx"> 
</span><span class="cx"> class IntegerRangeOptimizationPhase : public Phase {
</span><span class="cx"> public:
</span><span class="lines">@@ -1314,7 +1315,7 @@
</span><span class="cx">                         if (relationship.minValueOfLeft() &gt;= 0)
</span><span class="cx">                             nonNegative = true;
</span><span class="cx">                         
</span><del>-                        if (relationship.right() == node-&gt;child2()) {
</del><ins>+                        if (relationship.right() == node-&gt;child2().node()) {
</ins><span class="cx">                             if (relationship.kind() == Relationship::Equal
</span><span class="cx">                                 &amp;&amp; relationship.offset() &lt; 0)
</span><span class="cx">                                 lessThanLength = true;
</span><span class="lines">@@ -1491,23 +1492,16 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case Upsilon: {
</span><del>-            setRelationship(
-                Relationship::safeCreate(
-                    node-&gt;child1().node(), node-&gt;phi(), Relationship::Equal, 0));
</del><ins>+            setEquivalence(
+                node-&gt;child1().node(),
+                NodeFlowProjection(node-&gt;phi(), NodeFlowProjection::Shadow));
+            break;
+        }
</ins><span class="cx">             
</span><del>-            auto iter = m_relationships.find(node-&gt;child1().node());
-            if (iter != m_relationships.end()) {
-                Vector&lt;Relationship&gt; toAdd;
-                for (Relationship relationship : iter-&gt;value) {
-                    Relationship newRelationship = relationship;
-                    if (node-&gt;phi() == newRelationship.right())
-                        continue;
-                    newRelationship.setLeft(node-&gt;phi());
-                    toAdd.append(newRelationship);
-                }
-                for (Relationship relationship : toAdd)
-                    setRelationship(relationship);
-            }
</del><ins>+        case Phi: {
+            setEquivalence(
+                NodeFlowProjection(node, NodeFlowProjection::Shadow),
+                node);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -1516,6 +1510,26 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void setEquivalence(NodeFlowProjection oldNode, NodeFlowProjection newNode)
+    {
+        setRelationship(Relationship::safeCreate(oldNode, newNode, Relationship::Equal, 0));
+        
+        auto iter = m_relationships.find(oldNode);
+        if (iter != m_relationships.end()) {
+            Vector&lt;Relationship&gt; toAdd;
+            for (Relationship relationship : iter-&gt;value) {
+                Relationship newRelationship = relationship;
+                // Avoid creating any kind of self-relationship.
+                if (newNode.node() == newRelationship.right().node())
+                    continue;
+                newRelationship.setLeft(newNode);
+                toAdd.append(newRelationship);
+            }
+            for (Relationship relationship : toAdd)
+                setRelationship(relationship);
+        }
+    }
+            
</ins><span class="cx">     void setRelationship(Relationship relationship, unsigned timeToLive = 1)
</span><span class="cx">     {
</span><span class="cx">         setRelationship(m_relationships, relationship, timeToLive);
</span><span class="lines">@@ -1669,7 +1683,7 @@
</span><span class="cx">         
</span><span class="cx">         if (m_seenBlocks.add(target)) {
</span><span class="cx">             // This is a new block. We copy subject to liveness pruning.
</span><del>-            auto isLive = [&amp;] (Node* node) {
</del><ins>+            auto isLive = [&amp;] (NodeFlowProjection node) {
</ins><span class="cx">                 if (node == m_zero)
</span><span class="cx">                     return true;
</span><span class="cx">                 return target-&gt;ssa-&gt;liveAtHead.contains(node);
</span><span class="lines">@@ -1701,7 +1715,7 @@
</span><span class="cx">         // assigned would only happen if we have not processed the node's predecessor. We
</span><span class="cx">         // shouldn't process blocks until we have processed the block's predecessor because we
</span><span class="cx">         // are using reverse postorder.
</span><del>-        Vector&lt;Node*&gt; toRemove;
</del><ins>+        Vector&lt;NodeFlowProjection&gt; toRemove;
</ins><span class="cx">         bool changed = false;
</span><span class="cx">         for (auto&amp; entry : m_relationshipsAtHead[target]) {
</span><span class="cx">             auto iter = relationshipMap.find(entry.key);
</span><span class="lines">@@ -1791,7 +1805,7 @@
</span><span class="cx">             entry.value = mergedRelationships;
</span><span class="cx">             changed = true;
</span><span class="cx">         }
</span><del>-        for (Node* node : toRemove)
</del><ins>+        for (NodeFlowProjection node : toRemove)
</ins><span class="cx">             m_relationshipsAtHead[target].remove(node);
</span><span class="cx">         
</span><span class="cx">         return changed;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLivenessAnalysisPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGLivenessAnalysisPhase.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DFGBasicBlockInlines.h&quot;
</span><span class="cx"> #include &quot;DFGBlockMapInlines.h&quot;
</span><ins>+#include &quot;DFGFlowIndexing.h&quot;
</ins><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGInsertionSet.h&quot;
</span><span class="cx"> #include &quot;DFGPhase.h&quot;
</span><span class="lines">@@ -44,10 +45,12 @@
</span><span class="cx">     LivenessAnalysisPhase(Graph&amp; graph)
</span><span class="cx">         : Phase(graph, &quot;liveness analysis&quot;)
</span><span class="cx">         , m_dirtyBlocks(m_graph.numBlocks())
</span><ins>+        , m_indexing(*m_graph.m_indexingCache)
</ins><span class="cx">         , m_liveAtHead(m_graph)
</span><span class="cx">         , m_liveAtTail(m_graph)
</span><del>-        , m_workset(graph.maxNodeCount() - 1)
</del><span class="cx">     {
</span><ins>+        m_graph.m_indexingCache-&gt;recompute();
+        m_workset = std::make_unique&lt;IndexSparseSet&lt;UnsafeVectorOverflow&gt;&gt;(m_graph.m_indexingCache-&gt;numIndices());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool run()
</span><span class="lines">@@ -80,20 +83,20 @@
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="cx">             {
</span><del>-                const auto&amp; liveAtHeadIndices = m_liveAtHead[blockIndex];
-                Vector&lt;Node*&gt;&amp; liveAtHead = block-&gt;ssa-&gt;liveAtHead;
</del><ins>+                const Vector&lt;unsigned, 0, UnsafeVectorOverflow, 1&gt;&amp; liveAtHeadIndices = m_liveAtHead[blockIndex];
+                Vector&lt;NodeFlowProjection&gt;&amp; liveAtHead = block-&gt;ssa-&gt;liveAtHead;
</ins><span class="cx">                 liveAtHead.resize(0);
</span><span class="cx">                 liveAtHead.reserveCapacity(liveAtHeadIndices.size());
</span><span class="cx">                 for (unsigned index : liveAtHeadIndices)
</span><del>-                    liveAtHead.uncheckedAppend(m_graph.nodeAt(index));
</del><ins>+                    liveAtHead.uncheckedAppend(m_indexing.nodeProjection(index));
</ins><span class="cx">             }
</span><span class="cx">             {
</span><del>-                const auto&amp; liveAtTailIndices = m_liveAtTail[blockIndex];
-                Vector&lt;Node*&gt;&amp; liveAtTail = block-&gt;ssa-&gt;liveAtTail;
</del><ins>+                const HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&amp; liveAtTailIndices = m_liveAtTail[blockIndex];
+                Vector&lt;NodeFlowProjection&gt;&amp; liveAtTail = block-&gt;ssa-&gt;liveAtTail;
</ins><span class="cx">                 liveAtTail.resize(0);
</span><span class="cx">                 liveAtTail.reserveCapacity(liveAtTailIndices.size());
</span><span class="cx">                 for (unsigned index : m_liveAtTail[blockIndex])
</span><del>-                    liveAtTail.uncheckedAppend(m_graph.nodeAt(index));
</del><ins>+                    liveAtTail.uncheckedAppend(m_indexing.nodeProjection(index));
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -106,67 +109,57 @@
</span><span class="cx">         BasicBlock* block = m_graph.block(blockIndex);
</span><span class="cx">         ASSERT_WITH_MESSAGE(block, &quot;Only dirty blocks needs updates. A null block should never be dirty.&quot;);
</span><span class="cx"> 
</span><del>-        m_workset.clear();
</del><ins>+        m_workset-&gt;clear();
</ins><span class="cx">         for (unsigned index : m_liveAtTail[blockIndex])
</span><del>-            m_workset.add(index);
</del><ins>+            m_workset-&gt;add(index);
</ins><span class="cx"> 
</span><span class="cx">         for (unsigned nodeIndex = block-&gt;size(); nodeIndex--;) {
</span><span class="cx">             Node* node = block-&gt;at(nodeIndex);
</span><span class="cx"> 
</span><del>-            // Given an Upsilon:
-            //
-            //    n: Upsilon(@x, ^p)
-            //
-            // We say that it def's @p and @n and uses @x.
-            //
-            // Given a Phi:
-            //
-            //    p: Phi()
-            //
-            // We say nothing. It's neither a use nor a def.
-            //
-            // Given a node:
-            //
-            //    n: Thingy(@a, @b, @c)
-            //
-            // We say that it def's @n and uses @a, @b, @c.
</del><ins>+            auto handleEdge = [&amp;] (Edge&amp; edge) {
+                bool newEntry = m_workset-&gt;add(m_indexing.index(edge.node()));
+                edge.setKillStatus(newEntry ? DoesKill : DoesNotKill);
+            };
</ins><span class="cx">             
</span><span class="cx">             switch (node-&gt;op()) {
</span><span class="cx">             case Upsilon: {
</span><del>-                ASSERT_WITH_MESSAGE(!m_workset.contains(node-&gt;index()), &quot;Upsilon should not be used as defs by other nodes.&quot;);
</del><ins>+                ASSERT_WITH_MESSAGE(!m_workset-&gt;contains(node-&gt;index()), &quot;Upsilon should not be used as defs by other nodes.&quot;);
</ins><span class="cx"> 
</span><span class="cx">                 Node* phi = node-&gt;phi();
</span><del>-                m_workset.remove(phi-&gt;index());
-                m_workset.add(node-&gt;child1()-&gt;index());
</del><ins>+                m_workset-&gt;remove(m_indexing.shadowIndex(phi));
+                handleEdge(node-&gt;child1());
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case Phi: {
</span><ins>+                m_workset-&gt;remove(m_indexing.index(node));
+                m_workset-&gt;add(m_indexing.shadowIndex(node));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             default:
</span><del>-                m_workset.remove(node-&gt;index());
-                DFG_NODE_DO_TO_CHILDREN(m_graph, node, addChildUse);
</del><ins>+                m_workset-&gt;remove(m_indexing.index(node));
+                m_graph.doToChildren(node, handleEdge);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Update live at head.
</span><del>-        auto&amp; liveAtHead = m_liveAtHead[blockIndex];
-        if (m_workset.size() == liveAtHead.size())
</del><ins>+        Vector&lt;unsigned, 0, UnsafeVectorOverflow, 1&gt;&amp; liveAtHead = m_liveAtHead[blockIndex];
+        if (m_workset-&gt;size() == liveAtHead.size())
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         for (unsigned liveIndexAtHead : liveAtHead)
</span><del>-            m_workset.remove(liveIndexAtHead);
-        ASSERT(!m_workset.isEmpty());
</del><ins>+            m_workset-&gt;remove(liveIndexAtHead);
+        ASSERT(!m_workset-&gt;isEmpty());
</ins><span class="cx"> 
</span><del>-        liveAtHead.reserveCapacity(liveAtHead.size() + m_workset.size());
-        for (unsigned newValue : m_workset)
</del><ins>+        liveAtHead.reserveCapacity(liveAtHead.size() + m_workset-&gt;size());
+        for (unsigned newValue : *m_workset)
</ins><span class="cx">             liveAtHead.uncheckedAppend(newValue);
</span><span class="cx"> 
</span><span class="cx">         bool changedPredecessor = false;
</span><span class="cx">         for (BasicBlock* predecessor : block-&gt;predecessors) {
</span><del>-            auto&amp; liveAtTail = m_liveAtTail[predecessor];
-            for (unsigned newValue : m_workset) {
</del><ins>+            HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&amp;
+                liveAtTail = m_liveAtTail[predecessor];
+            for (unsigned newValue : *m_workset) {
</ins><span class="cx">                 if (liveAtTail.add(newValue)) {
</span><span class="cx">                     if (!m_dirtyBlocks.quickSet(predecessor-&gt;index))
</span><span class="cx">                         changedPredecessor = true;
</span><span class="lines">@@ -176,14 +169,10 @@
</span><span class="cx">         return changedPredecessor;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    ALWAYS_INLINE void addChildUse(Node*, Edge&amp; edge)
-    {
-        bool newEntry = m_workset.add(edge-&gt;index());
-        edge.setKillStatus(newEntry ? DoesKill : DoesNotKill);
-    }
-
</del><span class="cx">     // Blocks with new live values at tail.
</span><span class="cx">     BitVector m_dirtyBlocks;
</span><ins>+    
+    FlowIndexing&amp; m_indexing;
</ins><span class="cx"> 
</span><span class="cx">     // Live values per block edge.
</span><span class="cx">     BlockMap&lt;Vector&lt;unsigned, 0, UnsafeVectorOverflow, 1&gt;&gt; m_liveAtHead;
</span><span class="lines">@@ -190,7 +179,7 @@
</span><span class="cx">     BlockMap&lt;HashSet&lt;unsigned, DefaultHash&lt;unsigned&gt;::Hash, WTF::UnsignedWithZeroKeyHashTraits&lt;unsigned&gt;&gt;&gt; m_liveAtTail;
</span><span class="cx"> 
</span><span class="cx">     // Single sparse set allocated once and used by every basic block.
</span><del>-    IndexSparseSet&lt;UnsafeVectorOverflow&gt; m_workset;
</del><ins>+    std::unique_ptr&lt;IndexSparseSet&lt;UnsafeVectorOverflow&gt;&gt; m_workset;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> bool performLivenessAnalysis(Graph&amp; graph)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -2560,15 +2560,18 @@
</span><span class="cx">     BasicBlock* owner;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline bool nodeComparator(Node* a, Node* b)
-{
-    return a-&gt;index() &lt; b-&gt;index();
-}
</del><ins>+struct NodeComparator {
+    template&lt;typename NodePtrType&gt;
+    bool operator()(NodePtrType a, NodePtrType b) const
+    {
+        return a-&gt;index() &lt; b-&gt;index();
+    }
+};
</ins><span class="cx"> 
</span><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> CString nodeListDump(const T&amp; nodeList)
</span><span class="cx"> {
</span><del>-    return sortedListDump(nodeList, nodeComparator);
</del><ins>+    return sortedListDump(nodeList, NodeComparator());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename T&gt;
</span><span class="lines">@@ -2579,7 +2582,7 @@
</span><span class="cx">         typename T::const_iterator iter = nodeMap.begin();
</span><span class="cx">         iter != nodeMap.end(); ++iter)
</span><span class="cx">         keys.append(iter-&gt;key);
</span><del>-    std::sort(keys.begin(), keys.end(), nodeComparator);
</del><ins>+    std::sort(keys.begin(), keys.end(), NodeComparator());
</ins><span class="cx">     StringPrintStream out;
</span><span class="cx">     CommaPrinter comma;
</span><span class="cx">     for(unsigned i = 0; i &lt; keys.size(); ++i)
</span><span class="lines">@@ -2593,7 +2596,7 @@
</span><span class="cx">     using V = typename T::ValueType;
</span><span class="cx">     T sortedList = nodeValuePairList;
</span><span class="cx">     std::sort(sortedList.begin(), sortedList.end(), [](const V&amp; a, const V&amp; b) {
</span><del>-        return nodeComparator(a.node, b.node);
</del><ins>+        return NodeComparator()(a.node, b.node);
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     StringPrintStream out;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeAbstractValuePaircpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.cpp (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGNodeAbstractValuePair.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+void NodeAbstractValuePair::dump(PrintStream&amp; out) const
+{
+    out.print(node, &quot;=&gt;&quot;, value);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeAbstractValuePairh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.h (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeAbstractValuePair.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGAbstractValue.h&quot;
+#include &quot;DFGNodeFlowProjection.h&quot;
+
+namespace JSC { namespace DFG {
+
+struct NodeAbstractValuePair {
+    NodeAbstractValuePair() { }
+    
+    NodeAbstractValuePair(NodeFlowProjection node, const AbstractValue&amp; value)
+        : node(node)
+        , value(value)
+    {
+    }
+    
+    void dump(PrintStream&amp; out) const;
+    
+    NodeFlowProjection node;
+    AbstractValue value;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlowProjectioncpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.cpp (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGNodeFlowProjection.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+void NodeFlowProjection::dump(PrintStream&amp; out) const
+{
+    if (!*this) {
+        out.print(&quot;-&quot;);
+        return;
+    }
+    if (kind() == Primary) {
+        out.print(node());
+        return;
+    }
+    out.print(&quot;shadow(&quot;, node(), &quot;)&quot;);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlowProjectionh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.h (0 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlowProjection.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -0,0 +1,155 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGNode.h&quot;
+#include &lt;wtf/HashTable.h&gt;
+
+namespace JSC { namespace DFG {
+
+class NodeFlowProjection {
+public:
+    enum Kind {
+        Primary,
+        Shadow
+    };
+    
+    NodeFlowProjection() { }
+    
+    NodeFlowProjection(Node* node)
+        : m_word(bitwise_cast&lt;uintptr_t&gt;(node))
+    {
+        ASSERT(kind() == Primary);
+    }
+    
+    NodeFlowProjection(Node* node, Kind kind)
+        : m_word(bitwise_cast&lt;uintptr_t&gt;(node) | (kind == Shadow ? shadowBit : 0))
+    {
+        ASSERT(kind() == kind);
+    }
+    
+    NodeFlowProjection(WTF::HashTableDeletedValueType)
+        : m_word(shadowBit)
+    {
+    }
+    
+    explicit operator bool() const { return !!m_word; }
+    
+    Kind kind() const { return (m_word &amp; shadowBit) ? Shadow : Primary; }
+    
+    Node* node() const { return bitwise_cast&lt;Node*&gt;(m_word &amp; ~shadowBit); }
+    
+    Node&amp; operator*() const { return *node(); }
+    Node* operator-&gt;() const { return node(); }
+    
+    unsigned hash() const
+    {
+        return m_word;
+    }
+    
+    bool operator==(NodeFlowProjection other) const
+    {
+        return m_word == other.m_word;
+    }
+    
+    bool operator!=(NodeFlowProjection other) const
+    {
+        return !(*this == other);
+    }
+    
+    bool operator&lt;(NodeFlowProjection other) const
+    {
+        if (kind() != other.kind())
+            return kind() &lt; other.kind();
+        return node() &lt; other.node();
+    }
+    
+    bool operator&gt;(NodeFlowProjection other) const
+    {
+        return other &lt; *this;
+    }
+    
+    bool operator&lt;=(NodeFlowProjection other) const
+    {
+        return !(*this &gt; other);
+    }
+    
+    bool operator&gt;=(NodeFlowProjection other) const
+    {
+        return !(*this &lt; other);
+    }
+    
+    bool isHashTableDeletedValue() const
+    {
+        return *this == NodeFlowProjection(WTF::HashTableDeletedValue);
+    }
+    
+    // Phi shadow projections can become invalid because the Phi might be folded to something else.
+    bool isStillValid() const
+    {
+        return *this &amp;&amp; (kind() == Primary || node()-&gt;op() == Phi);
+    }
+    
+    void dump(PrintStream&amp;) const;
+    
+    template&lt;typename Func&gt;
+    static void forEach(Node* node, const Func&amp; func)
+    {
+        func(NodeFlowProjection(node));
+        if (node-&gt;op() == Phi)
+            func(NodeFlowProjection(node, Shadow));
+    }
+    
+public:
+    static const uintptr_t shadowBit = 1;
+    
+    uintptr_t m_word { 0 };
+};
+
+struct NodeFlowProjectionHash {
+    static unsigned hash(NodeFlowProjection key) { return key.hash(); }
+    static bool equal(NodeFlowProjection a, NodeFlowProjection b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::DFG::NodeFlowProjection&gt; {
+    typedef JSC::DFG::NodeFlowProjectionHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::DFG::NodeFlowProjection&gt; : SimpleClassHashTraits&lt;JSC::DFG::NodeFlowProjection&gt; { };
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -126,11 +126,13 @@
</span><span class="cx">                     // Construct the state-at-tail based on the epochs of live nodes and the
</span><span class="cx">                     // current epoch. We grow state-at-tail monotonically to ensure convergence.
</span><span class="cx">                     bool thisBlockChanged = false;
</span><del>-                    for (Node* node : block-&gt;ssa-&gt;liveAtTail) {
</del><ins>+                    for (NodeFlowProjection node : block-&gt;ssa-&gt;liveAtTail) {
+                        if (node.kind() == NodeFlowProjection::Shadow)
+                            continue;
</ins><span class="cx">                         if (node-&gt;epoch() != m_currentEpoch) {
</span><span class="cx">                             // If the node is older than the current epoch, then we may need to
</span><span class="cx">                             // run a barrier on it in the future. So, add it to the state.
</span><del>-                            thisBlockChanged |= m_stateAtTail-&gt;at(block).add(node).isNewEntry;
</del><ins>+                            thisBlockChanged |= m_stateAtTail-&gt;at(block).add(node.node()).isNewEntry;
</ins><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                     
</span><span class="lines">@@ -178,8 +180,10 @@
</span><span class="cx">                 return false;
</span><span class="cx">             m_state-&gt;beginBasicBlock(block);
</span><span class="cx">             
</span><del>-            for (Node* node : block-&gt;ssa-&gt;liveAtHead) {
-                if (m_stateAtHead-&gt;at(block).contains(node)) {
</del><ins>+            for (NodeFlowProjection node : block-&gt;ssa-&gt;liveAtHead) {
+                if (node.kind() == NodeFlowProjection::Shadow)
+                    continue;
+                if (m_stateAtHead-&gt;at(block).contains(node.node())) {
</ins><span class="cx">                     // If previous blocks tell us that this node may need a barrier in the
</span><span class="cx">                     // future, then put it in the ancient primordial epoch. This forces us to
</span><span class="cx">                     // emit a barrier on any possibly-cell store, regardless of the epoch of the
</span><span class="lines">@@ -326,7 +330,8 @@
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="cx">             case Upsilon:
</span><del>-                m_node-&gt;phi()-&gt;setEpoch(m_node-&gt;epoch());
</del><ins>+                // Assume the worst for Phis so that we don't have to worry about Phi shadows.
+                m_node-&gt;phi()-&gt;setEpoch(Epoch());
</ins><span class="cx">                 m_node-&gt;setEpoch(Epoch());
</span><span class="cx">                 break;
</span><span class="cx">                 
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/WTF/ChangeLog        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-11-03  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        DFG plays fast and loose with the shadow values of a Phi
+        https://bugs.webkit.org/show_bug.cgi?id=164309
+
+        Reviewed by Saam Barati.
+        
+        Made this API use size rather than maxIndex as its initialization parameter, because that's
+        less confusing.
+
+        * wtf/IndexSparseSet.h:
+        (WTF::IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet):
+
</ins><span class="cx"> 2016-11-03  Konstantin Tokarev  &lt;annulen@yandex.ru&gt;
</span><span class="cx"> 
</span><span class="cx">         Fixes to build JSCOnly on macOS
</span></span></pre></div>
<a id="trunkSourceWTFwtfIndexSparseSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/IndexSparseSet.h (208363 => 208364)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/IndexSparseSet.h        2016-11-04 01:57:15 UTC (rev 208363)
+++ trunk/Source/WTF/wtf/IndexSparseSet.h        2016-11-04 02:37:45 UTC (rev 208364)
</span><span class="lines">@@ -45,7 +45,7 @@
</span><span class="cx"> class IndexSparseSet {
</span><span class="cx">     typedef Vector&lt;unsigned, 0, OverflowHandler&gt; ValueList;
</span><span class="cx"> public:
</span><del>-    explicit IndexSparseSet(unsigned maxValue);
</del><ins>+    explicit IndexSparseSet(unsigned size);
</ins><span class="cx"> 
</span><span class="cx">     bool add(unsigned);
</span><span class="cx">     bool remove(unsigned);
</span><span class="lines">@@ -65,9 +65,9 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename OverflowHandler&gt;
</span><del>-inline IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet(unsigned maxValue)
</del><ins>+inline IndexSparseSet&lt;OverflowHandler&gt;::IndexSparseSet(unsigned size)
</ins><span class="cx"> {
</span><del>-    m_map.resize(maxValue + 1);
</del><ins>+    m_map.resize(size);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename OverflowHandler&gt;
</span></span></pre>
</div>
</div>

</body>
</html>