<!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>[173072] trunk/Source</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/173072">173072</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-08-28 12:23:02 -0700 (Thu, 28 Aug 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>DFG should compute immediate dominators using the O(n log n) form of Lengauer and Tarjan's &quot;A Fast Algorithm for Finding Dominators in a Flowgraph&quot;
https://bugs.webkit.org/show_bug.cgi?id=93361

Reviewed by Mark Hahnenberg.
        
Source/JavaScriptCore:

This patch also adds some new utilities for reasoning about block-keyed maps, block sets,
and block worklists. It changes preexisting code to use these abstractions.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAnalysis.h:
(JSC::DFG::Analysis::computeIfNecessary):
(JSC::DFG::Analysis::computeDependencies):
* dfg/DFGBlockMap.h: Added.
(JSC::DFG::BlockMap::BlockMap):
(JSC::DFG::BlockMap::size):
(JSC::DFG::BlockMap::atIndex):
(JSC::DFG::BlockMap::operator[]):
* dfg/DFGBlockMapInlines.h: Added.
(JSC::DFG::BlockMap&lt;T&gt;::BlockMap):
* dfg/DFGBlockSet.h: Added.
(JSC::DFG::BlockSet::BlockSet):
(JSC::DFG::BlockSet::add):
(JSC::DFG::BlockSet::contains):
* dfg/DFGBlockWorklist.cpp: Added.
(JSC::DFG::BlockWorklist::BlockWorklist):
(JSC::DFG::BlockWorklist::~BlockWorklist):
(JSC::DFG::BlockWorklist::push):
(JSC::DFG::BlockWorklist::pop):
(JSC::DFG::PostOrderBlockWorklist::PostOrderBlockWorklist):
(JSC::DFG::PostOrderBlockWorklist::~PostOrderBlockWorklist):
(JSC::DFG::PostOrderBlockWorklist::pushPre):
(JSC::DFG::PostOrderBlockWorklist::pushPost):
(JSC::DFG::PostOrderBlockWorklist::pop):
* dfg/DFGBlockWorklist.h: Added.
(JSC::DFG::BlockWorklist::notEmpty):
(JSC::DFG::BlockWith::BlockWith):
(JSC::DFG::BlockWith::operator UnspecifiedBoolType*):
(JSC::DFG::ExtendedBlockWorklist::ExtendedBlockWorklist):
(JSC::DFG::ExtendedBlockWorklist::forcePush):
(JSC::DFG::ExtendedBlockWorklist::push):
(JSC::DFG::ExtendedBlockWorklist::notEmpty):
(JSC::DFG::ExtendedBlockWorklist::pop):
(JSC::DFG::BlockWithOrder::BlockWithOrder):
(JSC::DFG::BlockWithOrder::operator UnspecifiedBoolType*):
(JSC::DFG::PostOrderBlockWorklist::push):
(JSC::DFG::PostOrderBlockWorklist::notEmpty):
* dfg/DFGCSEPhase.cpp:
* dfg/DFGDominators.cpp:
(JSC::DFG::Dominators::compute):
(JSC::DFG::Dominators::naiveDominates):
(JSC::DFG::Dominators::dump):
(JSC::DFG::Dominators::pruneDominators): Deleted.
* dfg/DFGDominators.h:
(JSC::DFG::Dominators::strictlyDominates):
(JSC::DFG::Dominators::dominates):
(JSC::DFG::Dominators::BlockData::BlockData):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dumpBlockHeader):
(JSC::DFG::Graph::getBlocksInPreOrder):
(JSC::DFG::Graph::getBlocksInPostOrder):
* dfg/DFGInvalidationPointInjectionPhase.cpp:
(JSC::DFG::InvalidationPointInjectionPhase::run):
* dfg/DFGNaiveDominators.cpp: Added.
(JSC::DFG::NaiveDominators::NaiveDominators):
(JSC::DFG::NaiveDominators::~NaiveDominators):
(JSC::DFG::NaiveDominators::compute):
(JSC::DFG::NaiveDominators::pruneDominators):
(JSC::DFG::NaiveDominators::dump):
* dfg/DFGNaiveDominators.h: Added.
(JSC::DFG::NaiveDominators::dominates):
* dfg/DFGNaturalLoops.cpp:
(JSC::DFG::NaturalLoops::computeDependencies):
(JSC::DFG::NaturalLoops::compute):
* dfg/DFGNaturalLoops.h:

Source/WTF:

Make BitVector operations return the previous value of the bit you're changing. This is
useful for the kinds of set operations that are commonplace in compiler graph searches.

* wtf/BitVector.h:
(WTF::BitVector::quickSet):
(WTF::BitVector::quickClear):
(WTF::BitVector::set):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAnalysish">trunk/Source/JavaScriptCore/dfg/DFGAnalysis.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDominatorscpp">trunk/Source/JavaScriptCore/dfg/DFGDominators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDominatorsh">trunk/Source/JavaScriptCore/dfg/DFGDominators.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInvalidationPointInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGInvalidationPointInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNaturalLoopscpp">trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNaturalLoopsh">trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfBitVectorh">trunk/Source/WTF/wtf/BitVector.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockMaph">trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockMapInlinesh">trunk/Source/JavaScriptCore/dfg/DFGBlockMapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockSeth">trunk/Source/JavaScriptCore/dfg/DFGBlockSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockWorklistcpp">trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockWorklisth">trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNaiveDominatorscpp">trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNaiveDominatorsh">trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -126,6 +126,7 @@
</span><span class="cx">     dfg/DFGBasicBlock.cpp
</span><span class="cx">     dfg/DFGBinarySwitch.cpp
</span><span class="cx">     dfg/DFGBlockInsertionSet.cpp
</span><ins>+    dfg/DFGBlockWorklist.cpp
</ins><span class="cx">     dfg/DFGByteCodeParser.cpp
</span><span class="cx">     dfg/DFGCFAPhase.cpp
</span><span class="cx">     dfg/DFGCFGSimplificationPhase.cpp
</span><span class="lines">@@ -175,6 +176,7 @@
</span><span class="cx">     dfg/DFGLoopPreHeaderCreationPhase.cpp
</span><span class="cx">     dfg/DFGMayExit.cpp
</span><span class="cx">     dfg/DFGMinifiedNode.cpp
</span><ins>+    dfg/DFGNaiveDominators.cpp
</ins><span class="cx">     dfg/DFGNaturalLoops.cpp
</span><span class="cx">     dfg/DFGNode.cpp
</span><span class="cx">     dfg/DFGNodeFlags.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -1,5 +1,88 @@
</span><span class="cx"> 2014-08-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        DFG should compute immediate dominators using the O(n log n) form of Lengauer and Tarjan's &quot;A Fast Algorithm for Finding Dominators in a Flowgraph&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=93361
+
+        Reviewed by Mark Hahnenberg.
+        
+        This patch also adds some new utilities for reasoning about block-keyed maps, block sets,
+        and block worklists. It changes preexisting code to use these abstractions.
+        
+        The main effect of this code is that all current clients of dominators end up using the
+        results of the new idom calculation. We convert the dom tree to a dominance test using
+        Dietz's pre/post number range check trick.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAnalysis.h:
+        (JSC::DFG::Analysis::computeIfNecessary):
+        (JSC::DFG::Analysis::computeDependencies):
+        * dfg/DFGBlockMap.h: Added.
+        (JSC::DFG::BlockMap::BlockMap):
+        (JSC::DFG::BlockMap::size):
+        (JSC::DFG::BlockMap::atIndex):
+        (JSC::DFG::BlockMap::operator[]):
+        * dfg/DFGBlockMapInlines.h: Added.
+        (JSC::DFG::BlockMap&lt;T&gt;::BlockMap):
+        * dfg/DFGBlockSet.h: Added.
+        (JSC::DFG::BlockSet::BlockSet):
+        (JSC::DFG::BlockSet::add):
+        (JSC::DFG::BlockSet::contains):
+        * dfg/DFGBlockWorklist.cpp: Added.
+        (JSC::DFG::BlockWorklist::BlockWorklist):
+        (JSC::DFG::BlockWorklist::~BlockWorklist):
+        (JSC::DFG::BlockWorklist::push):
+        (JSC::DFG::BlockWorklist::pop):
+        (JSC::DFG::PostOrderBlockWorklist::PostOrderBlockWorklist):
+        (JSC::DFG::PostOrderBlockWorklist::~PostOrderBlockWorklist):
+        (JSC::DFG::PostOrderBlockWorklist::pushPre):
+        (JSC::DFG::PostOrderBlockWorklist::pushPost):
+        (JSC::DFG::PostOrderBlockWorklist::pop):
+        * dfg/DFGBlockWorklist.h: Added.
+        (JSC::DFG::BlockWorklist::notEmpty):
+        (JSC::DFG::BlockWith::BlockWith):
+        (JSC::DFG::BlockWith::operator UnspecifiedBoolType*):
+        (JSC::DFG::ExtendedBlockWorklist::ExtendedBlockWorklist):
+        (JSC::DFG::ExtendedBlockWorklist::forcePush):
+        (JSC::DFG::ExtendedBlockWorklist::push):
+        (JSC::DFG::ExtendedBlockWorklist::notEmpty):
+        (JSC::DFG::ExtendedBlockWorklist::pop):
+        (JSC::DFG::BlockWithOrder::BlockWithOrder):
+        (JSC::DFG::BlockWithOrder::operator UnspecifiedBoolType*):
+        (JSC::DFG::PostOrderBlockWorklist::push):
+        (JSC::DFG::PostOrderBlockWorklist::notEmpty):
+        * dfg/DFGCSEPhase.cpp:
+        * dfg/DFGDominators.cpp:
+        (JSC::DFG::Dominators::compute):
+        (JSC::DFG::Dominators::naiveDominates):
+        (JSC::DFG::Dominators::dump):
+        (JSC::DFG::Dominators::pruneDominators): Deleted.
+        * dfg/DFGDominators.h:
+        (JSC::DFG::Dominators::strictlyDominates):
+        (JSC::DFG::Dominators::dominates):
+        (JSC::DFG::Dominators::BlockData::BlockData):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dumpBlockHeader):
+        (JSC::DFG::Graph::getBlocksInPreOrder):
+        (JSC::DFG::Graph::getBlocksInPostOrder):
+        * dfg/DFGInvalidationPointInjectionPhase.cpp:
+        (JSC::DFG::InvalidationPointInjectionPhase::run):
+        * dfg/DFGNaiveDominators.cpp: Added.
+        (JSC::DFG::NaiveDominators::NaiveDominators):
+        (JSC::DFG::NaiveDominators::~NaiveDominators):
+        (JSC::DFG::NaiveDominators::compute):
+        (JSC::DFG::NaiveDominators::pruneDominators):
+        (JSC::DFG::NaiveDominators::dump):
+        * dfg/DFGNaiveDominators.h: Added.
+        (JSC::DFG::NaiveDominators::dominates):
+        * dfg/DFGNaturalLoops.cpp:
+        (JSC::DFG::NaturalLoops::computeDependencies):
+        (JSC::DFG::NaturalLoops::compute):
+        * dfg/DFGNaturalLoops.h:
+
+2014-08-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         FTL should be able to do polymorphic call inlining
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=135145
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -372,6 +372,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGBasicBlock.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGBinarySwitch.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGBlockInsertionSet.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGBlockWorklist.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGByteCodeParser.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGCapabilities.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGCFAPhase.cpp&quot; /&gt;
</span><span class="lines">@@ -421,6 +422,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGLoopPreHeaderCreationPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGMayExit.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGMinifiedNode.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGNaiveDominators.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGNaturalLoops.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGNode.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGNodeFlags.cpp&quot; /&gt;
</span><span class="lines">@@ -993,6 +995,10 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGBasicBlockInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGBinarySwitch.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGBlockInsertionSet.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGBlockMap.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\dfg\DFGBlockMapInlines.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\dfg\DFGBlockWorklist.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\dfg\DFGBlockSet.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGBranchDirection.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGByteCodeParser.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGCallArrayAllocatorSlowPathGenerator.h&quot; /&gt;
</span><span class="lines">@@ -1056,6 +1062,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGMinifiedGraph.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGMinifiedID.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGMinifiedNode.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGNaiveDominators.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGNaturalLoops.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGNode.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGNodeAllocator.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -498,6 +498,13 @@
</span><span class="cx">                 0FC314121814559100033232 /* RegisterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC314101814559100033232 /* RegisterSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FC314131814559100033232 /* TempRegisterSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC314111814559100033232 /* TempRegisterSet.cpp */; };
</span><span class="cx">                 0FC3141518146D7000033232 /* RegisterSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC3141418146D7000033232 /* RegisterSet.cpp */; };
</span><ins>+                0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC3CCF519ADA410006AC72A /* DFGBlockMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC3CCF619ADA410006AC72A /* DFGBlockMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC3CCF719ADA410006AC72A /* DFGBlockSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FC3CCFF19ADA410006AC72A /* DFGBlockWorklist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC3CCF819ADA410006AC72A /* DFGBlockWorklist.cpp */; };
+                0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC3CCF919ADA410006AC72A /* DFGBlockWorklist.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FC3CD0119ADA411006AC72A /* DFGNaiveDominators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC3CCFA19ADA410006AC72A /* DFGNaiveDominators.cpp */; };
+                0FC3CD0219ADA411006AC72A /* DFGNaiveDominators.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC3CCFB19ADA410006AC72A /* DFGNaiveDominators.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */; };
</span><span class="cx">                 0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FC712E217CD8791008CC93C /* JITToDFGDeferredCompilationCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */; };
</span><span class="lines">@@ -2421,6 +2428,13 @@
</span><span class="cx">                 0FC314101814559100033232 /* RegisterSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC314111814559100033232 /* TempRegisterSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TempRegisterSet.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC3141418146D7000033232 /* RegisterSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterSet.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FC3CCF519ADA410006AC72A /* DFGBlockMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockMap.h; path = dfg/DFGBlockMap.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCF619ADA410006AC72A /* DFGBlockMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockMapInlines.h; path = dfg/DFGBlockMapInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCF719ADA410006AC72A /* DFGBlockSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockSet.h; path = dfg/DFGBlockSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCF819ADA410006AC72A /* DFGBlockWorklist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBlockWorklist.cpp; path = dfg/DFGBlockWorklist.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCF919ADA410006AC72A /* DFGBlockWorklist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBlockWorklist.h; path = dfg/DFGBlockWorklist.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCFA19ADA410006AC72A /* DFGNaiveDominators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNaiveDominators.cpp; path = dfg/DFGNaiveDominators.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC3CCFB19ADA410006AC72A /* DFGNaiveDominators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNaiveDominators.h; path = dfg/DFGNaiveDominators.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DeferredCompilationCallback.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeferredCompilationCallback.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JITToDFGDeferredCompilationCallback.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4819,6 +4833,11 @@
</span><span class="cx">                                 A70B083117A0B79B00DAF14B /* DFGBinarySwitch.h */,
</span><span class="cx">                                 A7D89CE417A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp */,
</span><span class="cx">                                 A7D89CE517A0B8CC00773AD8 /* DFGBlockInsertionSet.h */,
</span><ins>+                                0FC3CCF519ADA410006AC72A /* DFGBlockMap.h */,
+                                0FC3CCF619ADA410006AC72A /* DFGBlockMapInlines.h */,
+                                0FC3CCF719ADA410006AC72A /* DFGBlockSet.h */,
+                                0FC3CCF819ADA410006AC72A /* DFGBlockWorklist.cpp */,
+                                0FC3CCF919ADA410006AC72A /* DFGBlockWorklist.h */,
</ins><span class="cx">                                 0F8364B5164B0C0E0053329A /* DFGBranchDirection.h */,
</span><span class="cx">                                 86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */,
</span><span class="cx">                                 86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */,
</span><span class="lines">@@ -4930,6 +4949,8 @@
</span><span class="cx">                                 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
</span><span class="cx">                                 0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */,
</span><span class="cx">                                 0F2BDC3E1522801700CD8910 /* DFGMinifiedNode.h */,
</span><ins>+                                0FC3CCFA19ADA410006AC72A /* DFGNaiveDominators.cpp */,
+                                0FC3CCFB19ADA410006AC72A /* DFGNaiveDominators.h */,
</ins><span class="cx">                                 A737810A1799EA2E00817533 /* DFGNaturalLoops.cpp */,
</span><span class="cx">                                 A737810B1799EA2E00817533 /* DFGNaturalLoops.h */,
</span><span class="cx">                                 0FB4B51E16B62772003F696B /* DFGNode.cpp */,
</span><span class="lines">@@ -5842,6 +5863,7 @@
</span><span class="cx">                                 C2FC9BD316644DFB00810D33 /* CopiedBlockInlines.h in Headers */,
</span><span class="cx">                                 C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */,
</span><span class="cx">                                 C2C8D02D14A3C6E000578E65 /* CopiedSpaceInlines.h in Headers */,
</span><ins>+                                0FC3CCFD19ADA410006AC72A /* DFGBlockMapInlines.h in Headers */,
</ins><span class="cx">                                 0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */,
</span><span class="cx">                                 C2239D1816262BDD005AC5FD /* CopyVisitor.h in Headers */,
</span><span class="cx">                                 C2239D1916262BDD005AC5FD /* CopyVisitorInlines.h in Headers */,
</span><span class="lines">@@ -5917,6 +5939,7 @@
</span><span class="cx">                                 A7BFF3C0179868940002F462 /* DFGFiltrationResult.h in Headers */,
</span><span class="cx">                                 A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
</span><span class="cx">                                 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
</span><ins>+                                0FC3CCFC19ADA410006AC72A /* DFGBlockMap.h in Headers */,
</ins><span class="cx">                                 0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
</span><span class="cx">                                 A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
</span><span class="cx">                                 86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */,
</span><span class="lines">@@ -6317,6 +6340,7 @@
</span><span class="cx">                                 0F431738146BAC69007E3890 /* ListableHandler.h in Headers */,
</span><span class="cx">                                 A7E2EA6B0FB460CF00601F06 /* LiteralParser.h in Headers */,
</span><span class="cx">                                 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */,
</span><ins>+                                0FC3CD0019ADA410006AC72A /* DFGBlockWorklist.h in Headers */,
</ins><span class="cx">                                 FE20CE9E15F04A9500DF3430 /* LLIntCLoop.h in Headers */,
</span><span class="cx">                                 0F4680CA14BBB16C00BFE272 /* LLIntCommon.h in Headers */,
</span><span class="cx">                                 0F4680D314BBD16700BFE272 /* LLIntData.h in Headers */,
</span><span class="lines">@@ -6329,6 +6353,7 @@
</span><span class="cx">                                 0F0123331944EA1B00843A0C /* DFGValueStrength.h in Headers */,
</span><span class="cx">                                 0FCEFACE1805E75500472CE4 /* LLVMAPI.h in Headers */,
</span><span class="cx">                                 0FCEFACF1805E75500472CE4 /* LLVMAPIFunctions.h in Headers */,
</span><ins>+                                0FC3CCFE19ADA410006AC72A /* DFGBlockSet.h in Headers */,
</ins><span class="cx">                                 A7E5AB381799E4B200D2833D /* LLVMDisassembler.h in Headers */,
</span><span class="cx">                                 0FCEFAD31805EDCC00472CE4 /* LLVMHeaders.h in Headers */,
</span><span class="cx">                                 142E3139134FF0A600AFADB5 /* Local.h in Headers */,
</span><span class="lines">@@ -6374,6 +6399,7 @@
</span><span class="cx">                                 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */,
</span><span class="cx">                                 BC18C43F0E16F5CD00B34460 /* Nodes.h in Headers */,
</span><span class="cx">                                 99E45A2818A1B2590026D88F /* NondeterministicInput.h in Headers */,
</span><ins>+                                0FC3CD0219ADA411006AC72A /* DFGNaiveDominators.h in Headers */,
</ins><span class="cx">                                 BC18C4410E16F5CD00B34460 /* NumberConstructor.h in Headers */,
</span><span class="cx">                                 0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */,
</span><span class="cx">                                 BC18C4420E16F5CD00B34460 /* NumberConstructor.lut.h in Headers */,
</span><span class="lines">@@ -7297,6 +7323,7 @@
</span><span class="cx">                                 A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */,
</span><span class="cx">                                 2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
</span><span class="cx">                                 0FC20CB918556A3500C9E954 /* DFGSSALoweringPhase.cpp in Sources */,
</span><ins>+                                0FC3CD0119ADA411006AC72A /* DFGNaiveDominators.cpp in Sources */,
</ins><span class="cx">                                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
</span><span class="cx">                                 0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */,
</span><span class="cx">                                 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */,
</span><span class="lines">@@ -7357,6 +7384,7 @@
</span><span class="cx">                                 0FD8A31917D51F2200CA2C40 /* FTLForOSREntryJITCode.cpp in Sources */,
</span><span class="cx">                                 0F25F1AF181635F300522F39 /* FTLInlineCacheSize.cpp in Sources */,
</span><span class="cx">                                 0FEA0A281709623B00BB722C /* FTLIntrinsicRepository.cpp in Sources */,
</span><ins>+                                0FC3CCFF19ADA410006AC72A /* DFGBlockWorklist.cpp in Sources */,
</ins><span class="cx">                                 0FEA0A0D170513DB00BB722C /* FTLJITCode.cpp in Sources */,
</span><span class="cx">                                 A78A9780179738D5009DF744 /* FTLJITFinalizer.cpp in Sources */,
</span><span class="cx">                                 0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAnalysish"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAnalysis.h (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAnalysis.h        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGAnalysis.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">     {
</span><span class="cx">         if (m_valid)
</span><span class="cx">             return;
</span><ins>+        // It's best to run dependent analyses from this method.
+        static_cast&lt;T*&gt;(this)-&gt;computeDependencies(graph);
</ins><span class="cx">         // Set to true early, since the analysis may choose to call its own methods in
</span><span class="cx">         // compute() and it may want to ASSERT() validity in those methods.
</span><span class="cx">         m_valid = true;
</span><span class="lines">@@ -61,6 +63,12 @@
</span><span class="cx">     
</span><span class="cx">     bool isValid() const { return m_valid; }
</span><span class="cx"> 
</span><ins>+    // Override this to compute any dependent analyses. See
+    // NaturalLoops::computeDependencies(Graph&amp;) for an example. This isn't strictly necessary but
+    // it makes debug dumps in cases of error work a bit better because this analysis wouldn't yet
+    // be pretending to be valid.
+    void computeDependencies(Graph&amp;) { }
+
</ins><span class="cx"> private:
</span><span class="cx">     bool m_valid;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockMaph"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+/*
+ * Copyright (C) 2014 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. 
+ */
+
+#ifndef DFGBlockMap_h
+#define DFGBlockMap_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlock.h&quot;
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+template&lt;typename T&gt;
+class BlockMap {
+public:
+    BlockMap()
+    {
+    }
+    
+    BlockMap(Graph&amp;);
+    
+    BlockIndex size() const
+    {
+        return m_vector.size();
+    }
+    
+    T&amp; atIndex(BlockIndex blockIndex)
+    {
+        return m_vector[blockIndex];
+    }
+    
+    const T&amp; atIndex(BlockIndex blockIndex) const
+    {
+        return m_vector[blockIndex];
+    }
+    
+    T&amp; operator[](BlockIndex blockIndex)
+    {
+        return m_vector[blockIndex];
+    }
+    
+    const T&amp; operator[](BlockIndex blockIndex) const
+    {
+        return m_vector[blockIndex];
+    }
+    
+    T&amp; operator[](BasicBlock* block)
+    {
+        return m_vector[block-&gt;index];
+    }
+    
+    const T&amp; operator[](BasicBlock* block) const
+    {
+        return m_vector[block-&gt;index];
+    }
+
+private:
+    Vector&lt;T&gt; m_vector;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGBlockMap_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockMapInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGBlockMapInlines.h (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockMapInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockMapInlines.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright (C) 2014 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. 
+ */
+
+#ifndef DFGBlockMapInlines_h
+#define DFGBlockMapInlines_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBlockMap.h&quot;
+#include &quot;DFGGraph.h&quot;
+
+namespace JSC { namespace DFG {
+
+template&lt;typename T&gt;
+BlockMap&lt;T&gt;::BlockMap(Graph&amp; graph)
+{
+    m_vector.resize(graph.numBlocks());
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGBlockMapInlines_h
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockSeth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGBlockSet.h (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockSet.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockSet.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,61 @@
</span><ins>+/*
+ * Copyright (C) 2014 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. 
+ */
+
+#ifndef DFGBlockSet_h
+#define DFGBlockSet_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlock.h&quot;
+
+namespace JSC { namespace DFG {
+
+class BlockSet {
+public:
+    BlockSet() { }
+    
+    // Return true if the block was added, false if it was already present.
+    bool add(BasicBlock* block)
+    {
+        return !m_set.set(block-&gt;index);
+    }
+    
+    bool contains(BasicBlock* block) const
+    {
+        if (!block)
+            return false;
+        return m_set.get(block-&gt;index);
+    }
+    
+private:
+    BitVector m_set;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGBlockSet_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockWorklistcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.cpp (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,86 @@
</span><ins>+/*
+ * Copyright (C) 2014 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;DFGBlockWorklist.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlock.h&quot;
+
+namespace JSC { namespace DFG {
+
+BlockWorklist::BlockWorklist()
+{
+}
+
+BlockWorklist::~BlockWorklist()
+{
+}
+
+bool BlockWorklist::push(BasicBlock* block)
+{
+    if (!m_seen.add(block))
+        return false;
+    
+    m_stack.append(block);
+    return true;
+}
+
+BasicBlock* BlockWorklist::pop()
+{
+    if (m_stack.isEmpty())
+        return nullptr;
+    
+    return m_stack.takeLast();
+}
+
+PostOrderBlockWorklist::PostOrderBlockWorklist()
+{
+}
+
+PostOrderBlockWorklist::~PostOrderBlockWorklist()
+{
+}
+
+bool PostOrderBlockWorklist::pushPre(BasicBlock* block)
+{
+    return m_worklist.push(block, PreOrder);
+}
+
+void PostOrderBlockWorklist::pushPost(BasicBlock* block)
+{
+    m_worklist.forcePush(block, PostOrder);
+}
+
+BlockWithOrder PostOrderBlockWorklist::pop()
+{
+    BlockWith&lt;VisitOrder&gt; result = m_worklist.pop();
+    return BlockWithOrder(result.block, result.data);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockWorklisth"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.h (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockWorklist.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+/*
+ * Copyright (C) 2014 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. 
+ */
+
+#ifndef DFGBlockWorklist_h
+#define DFGBlockWorklist_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlock.h&quot;
+#include &quot;DFGBlockSet.h&quot;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC { namespace DFG {
+
+struct BasicBlock;
+
+class BlockWorklist {
+public:
+    BlockWorklist();
+    ~BlockWorklist();
+    
+    bool push(BasicBlock*); // Returns true if we didn't know about the block before.
+    
+    bool notEmpty() const { return !m_stack.isEmpty(); }
+    BasicBlock* pop();
+    
+private:
+    BlockSet m_seen;
+    Vector&lt;BasicBlock*, 16&gt; m_stack;
+};
+
+// When you say BlockWith&lt;int&gt; you should read it as &quot;block with an int&quot;.
+template&lt;typename T&gt;
+struct BlockWith {
+    BlockWith()
+        : block(nullptr)
+    {
+    }
+    
+    BlockWith(BasicBlock* block, const T&amp; data)
+        : block(block)
+        , data(data)
+    {
+    }
+    
+    typedef void* (BlockWith&lt;T&gt;::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
+    {
+        return block ? reinterpret_cast&lt;UnspecifiedBoolType*&gt;(1) : nullptr;
+    }
+
+    BasicBlock* block;
+    T data;
+};
+
+// Extended block worklist is useful for enqueueing some meta-data along with the block. It also
+// permits forcibly enqueueing things even if the block has already been seen. It's useful for
+// things like building a spanning tree, in which case T (the auxiliary payload) would be the
+// successor index.
+template&lt;typename T&gt;
+class ExtendedBlockWorklist {
+public:
+    ExtendedBlockWorklist() { }
+    
+    void forcePush(const BlockWith&lt;T&gt;&amp; entry)
+    {
+        m_stack.append(entry);
+    }
+    
+    void forcePush(BasicBlock* block, const T&amp; data)
+    {
+        forcePush(BlockWith&lt;T&gt;(block, data));
+    }
+    
+    bool push(const BlockWith&lt;T&gt;&amp; entry)
+    {
+        if (!m_seen.add(entry.block))
+            return false;
+        
+        forcePush(entry);
+        return true;
+    }
+    
+    bool push(BasicBlock* block, const T&amp; data)
+    {
+        return push(BlockWith&lt;T&gt;(block, data));
+    }
+    
+    bool notEmpty() const { return !m_stack.isEmpty(); }
+    
+    BlockWith&lt;T&gt; pop()
+    {
+        if (m_stack.isEmpty())
+            return BlockWith&lt;T&gt;();
+        
+        return m_stack.takeLast();
+    }
+
+private:
+    BlockSet m_seen;
+    Vector&lt;BlockWith&lt;T&gt;&gt; m_stack;
+};
+
+enum VisitOrder {
+    PreOrder,
+    PostOrder
+};
+
+struct BlockWithOrder {
+    BlockWithOrder()
+        : block(nullptr)
+        , order(PreOrder)
+    {
+    }
+    
+    BlockWithOrder(BasicBlock* block, VisitOrder order)
+        : block(block)
+        , order(order)
+    {
+    }
+    
+    typedef void* (BlockWithOrder::*UnspecifiedBoolType);
+    operator UnspecifiedBoolType*() const
+    {
+        return block ? reinterpret_cast&lt;UnspecifiedBoolType*&gt;(1) : nullptr;
+    }
+
+    BasicBlock* block;
+    VisitOrder order;
+};
+
+// Block worklist suitable for post-order traversal.
+class PostOrderBlockWorklist {
+public:
+    PostOrderBlockWorklist();
+    ~PostOrderBlockWorklist();
+    
+    bool pushPre(BasicBlock*);
+    void pushPost(BasicBlock*);
+    
+    bool push(BasicBlock* block, VisitOrder order = PreOrder)
+    {
+        switch (order) {
+        case PreOrder:
+            return pushPre(block);
+        case PostOrder:
+            pushPost(block);
+            return true;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return false;
+    }
+    bool push(const BlockWithOrder&amp; data)
+    {
+        return push(data.block, data.order);
+    }
+    
+    bool notEmpty() const { return m_worklist.notEmpty(); }
+    BlockWithOrder pop();
+
+private:
+    ExtendedBlockWorklist&lt;VisitOrder&gt; m_worklist;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGBlockWorklist_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DFGAbstractHeap.h&quot;
</span><ins>+#include &quot;DFGBlockMapInlines.h&quot;
</ins><span class="cx"> #include &quot;DFGClobberSet.h&quot;
</span><span class="cx"> #include &quot;DFGClobberize.h&quot;
</span><span class="cx"> #include &quot;DFGEdgeUsesStructure.h&quot;
</span><span class="lines">@@ -364,6 +365,7 @@
</span><span class="cx"> public:
</span><span class="cx">     GlobalCSEPhase(Graph&amp; graph)
</span><span class="cx">         : Phase(graph, &quot;global common subexpression elimination&quot;)
</span><ins>+        , m_impureDataMap(graph)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -377,13 +379,11 @@
</span><span class="cx">         
</span><span class="cx">         m_graph.getBlocksInPreOrder(m_preOrder);
</span><span class="cx">         
</span><del>-        m_impureDataMap.resize(m_graph.numBlocks());
-        
</del><span class="cx">         // First figure out what gets clobbered by blocks. Node that this uses the preOrder list
</span><span class="cx">         // for convenience only.
</span><span class="cx">         for (unsigned i = m_preOrder.size(); i--;) {
</span><span class="cx">             m_block = m_preOrder[i];
</span><del>-            m_impureData = &amp;m_impureDataMap[m_block-&gt;index];
</del><ins>+            m_impureData = &amp;m_impureDataMap[m_block];
</ins><span class="cx">             for (unsigned nodeIndex = m_block-&gt;size(); nodeIndex--;)
</span><span class="cx">                 addWrites(m_graph, m_block-&gt;at(nodeIndex), m_impureData-&gt;writes);
</span><span class="cx">         }
</span><span class="lines">@@ -407,7 +407,7 @@
</span><span class="cx">     {
</span><span class="cx">         m_pureValues.clear();
</span><span class="cx">         
</span><del>-        for (unsigned i = m_impureDataMap.size(); i--;) {
</del><ins>+        for (BlockIndex i = m_impureDataMap.size(); i--;) {
</ins><span class="cx">             m_impureDataMap[i].availableAtTail.clear();
</span><span class="cx">             m_impureDataMap[i].didVisit = false;
</span><span class="cx">         }
</span><span class="lines">@@ -423,7 +423,7 @@
</span><span class="cx">         
</span><span class="cx">         for (unsigned i = 0; i &lt; m_preOrder.size(); ++i) {
</span><span class="cx">             m_block = m_preOrder[i];
</span><del>-            m_impureData = &amp;m_impureDataMap[m_block-&gt;index];
</del><ins>+            m_impureData = &amp;m_impureDataMap[m_block];
</ins><span class="cx">             m_writesSoFar.clear();
</span><span class="cx">             
</span><span class="cx">             if (verbose)
</span><span class="lines">@@ -562,12 +562,12 @@
</span><span class="cx">             
</span><span class="cx">             if (verbose)
</span><span class="cx">                 dataLog(&quot;      Searching in block &quot;, *block, &quot;\n&quot;);
</span><del>-            ImpureBlockData&amp; data = m_impureDataMap[block-&gt;index];
</del><ins>+            ImpureBlockData&amp; data = m_impureDataMap[block];
</ins><span class="cx">             
</span><span class="cx">             // We require strict domination because this would only see things in our own block if
</span><span class="cx">             // they came *after* our position in the block. Clearly, while our block dominates
</span><span class="cx">             // itself, the things in the block after us don't dominate us.
</span><del>-            if (m_graph.m_dominators.dominates(block, m_block) &amp;&amp; block != m_block) {
</del><ins>+            if (m_graph.m_dominators.strictlyDominates(block, m_block)) {
</ins><span class="cx">                 if (verbose)
</span><span class="cx">                     dataLog(&quot;        It strictly dominates.\n&quot;);
</span><span class="cx">                 DFG_ASSERT(m_graph, m_node, data.didVisit);
</span><span class="lines">@@ -612,7 +612,7 @@
</span><span class="cx">         // the reduction in compile time would warrant the increase in complexity, though.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=134876
</span><span class="cx">         for (BasicBlock* block : seenList)
</span><del>-            m_impureDataMap[block-&gt;index].availableAtTail.add(location, match);
</del><ins>+            m_impureDataMap[block].availableAtTail.add(location, match);
</ins><span class="cx">         m_impureData-&gt;availableAtTail.add(location, match);
</span><span class="cx">         
</span><span class="cx">         return match;
</span><span class="lines">@@ -654,7 +654,7 @@
</span><span class="cx">     Vector&lt;BasicBlock*&gt; m_preOrder;
</span><span class="cx"> 
</span><span class="cx">     PureMultiMap m_pureValues;
</span><del>-    Vector&lt;ImpureBlockData&gt; m_impureDataMap;
</del><ins>+    BlockMap&lt;ImpureBlockData&gt; m_impureDataMap;
</ins><span class="cx">     
</span><span class="cx">     BasicBlock* m_block;
</span><span class="cx">     Node* m_node;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDominatorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDominators.cpp (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDominators.cpp        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGDominators.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 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">@@ -28,7 +28,10 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGBlockMapInlines.h&quot;
+#include &quot;DFGBlockWorklist.h&quot;
</ins><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><ins>+#include &quot;DFGNaiveDominators.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="lines">@@ -41,94 +44,390 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Dominators::compute(Graph&amp; graph)
-{
-    // This implements a naive dominator solver.
</del><ins>+namespace {
+
+// This implements Lengauer and Tarjan's &quot;A Fast Algorithm for Finding Dominators in a Flowgraph&quot;
+// (TOPLAS 1979). It uses the &quot;simple&quot; implementation of LINK and EVAL, which yields an O(n log n)
+// solution. The full paper is linked below; this code attempts to closely follow the algorithm as
+// it is presented in the paper; in particular sections 3 and 4 as well as appendix B.
+// https://www.cs.princeton.edu/courses/archive/fall03/cs528/handouts/a%20fast%20algorithm%20for%20finding.pdf
+//
+// This code is very subtle. The Lengauer-Tarjan algorithm is incredibly deep to begin with. The
+// goal of this code is to follow the code in the paper, however our implementation must deviate
+// from the paper when it comes to recursion. The authors had used recursion to implement DFS, and
+// also to implement the &quot;simple&quot; EVAL. We convert both of those into worklist-based solutions.
+// Finally, once the algorithm gives us immediate dominators, we implement dominance tests by
+// walking the dominator tree and computing pre and post numbers. We then use the range inclusion
+// check trick that was first discovered by Paul F. Dietz in 1982 in &quot;Maintaining order in a linked
+// list&quot; (see http://dl.acm.org/citation.cfm?id=802184).
+
+class LengauerTarjan {
+public:
+    LengauerTarjan(Graph&amp; graph)
+        : m_graph(graph)
+        , m_data(graph)
+    {
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            m_data[block].label = block;
+        }
+    }
</ins><span class="cx">     
</span><del>-    ASSERT(graph.block(0)-&gt;predecessors.isEmpty());
</del><ins>+    void compute()
+    {
+        computeDepthFirstPreNumbering(); // Step 1.
+        computeSemiDominatorsAndImplicitImmediateDominators(); // Steps 2 and 3.
+        computeExplicitImmediateDominators(); // Step 4.
+    }
</ins><span class="cx">     
</span><del>-    unsigned numBlocks = graph.numBlocks();
-    
-    // Allocate storage for the dense dominance matrix. 
-    if (numBlocks &gt; m_results.size()) {
-        m_results.grow(numBlocks);
-        for (unsigned i = numBlocks; i--;)
-            m_results[i].resize(numBlocks);
-        m_scratch.resize(numBlocks);
</del><ins>+    BasicBlock* immediateDominator(BasicBlock* block)
+    {
+        return m_data[block].dom;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // We know that the entry block is only dominated by itself.
-    m_results[0].clearAll();
-    m_results[0].set(0);
</del><ins>+private:
+    void computeDepthFirstPreNumbering()
+    {
+        // Use a block worklist that also tracks the index inside the successor list. This is
+        // necessary for ensuring that we don't attempt to visit a successor until the previous
+        // successors that we had visited are fully processed. This ends up being revealed in the
+        // output of this method because the first time we see an edge to a block, we set the
+        // block's parent. So, if we have:
+        //
+        // A -&gt; B
+        // A -&gt; C
+        // B -&gt; C
+        //
+        // And we're processing A, then we want to ensure that if we see A-&gt;B first (and hence set
+        // B's prenumber before we set C's) then we also end up setting C's parent to B by virtue
+        // of not noticing A-&gt;C until we're done processing B.
+        
+        ExtendedBlockWorklist&lt;unsigned&gt; worklist;
+        worklist.push(m_graph.block(0), 0);
+        
+        while (BlockWith&lt;unsigned&gt; item = worklist.pop()) {
+            BasicBlock* block = item.block;
+            unsigned successorIndex = item.data;
+            
+            // We initially push with successorIndex = 0 regardless of whether or not we have any
+            // successors. This is so that we can assign our prenumber. Subsequently we get pushed
+            // with higher successorIndex values, but only if they are in range.
+            ASSERT(!successorIndex || successorIndex &lt; block-&gt;numSuccessors());
</ins><span class="cx"> 
</span><del>-    // Find all of the valid blocks.
-    m_scratch.clearAll();
-    for (unsigned i = numBlocks; i--;) {
-        if (!graph.block(i))
-            continue;
-        m_scratch.set(i);
</del><ins>+            if (!successorIndex) {
+                m_data[block].semiNumber = m_blockByPreNumber.size();
+                m_blockByPreNumber.append(block);
+            }
+            
+            if (successorIndex &lt; block-&gt;numSuccessors()) {
+                unsigned nextSuccessorIndex = successorIndex + 1;
+                if (nextSuccessorIndex &lt; block-&gt;numSuccessors())
+                    worklist.forcePush(block, nextSuccessorIndex);
+
+                BasicBlock* successorBlock = block-&gt;successor(successorIndex);
+                if (worklist.push(successorBlock, 0))
+                    m_data[successorBlock].parent = block;
+            }
+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    // Mark all nodes as dominated by everything.
-    for (unsigned i = numBlocks; i-- &gt; 1;) {
-        if (!graph.block(i) || graph.block(i)-&gt;predecessors.isEmpty())
-            m_results[i].clearAll();
-        else
-            m_results[i].set(m_scratch);
</del><ins>+    void computeSemiDominatorsAndImplicitImmediateDominators()
+    {
+        for (unsigned currentPreNumber = m_blockByPreNumber.size(); currentPreNumber-- &gt; 1;) {
+            BasicBlock* block = m_blockByPreNumber[currentPreNumber];
+            BlockData&amp; blockData = m_data[block];
+            
+            // Step 2:
+            for (BasicBlock* predecessorBlock : block-&gt;predecessors) {
+                BasicBlock* intermediateBlock = eval(predecessorBlock);
+                blockData.semiNumber = std::min(
+                    m_data[intermediateBlock].semiNumber, blockData.semiNumber);
+            }
+            unsigned bucketPreNumber = blockData.semiNumber;
+            ASSERT(bucketPreNumber &lt;= currentPreNumber);
+            m_data[m_blockByPreNumber[bucketPreNumber]].bucket.append(block);
+            link(blockData.parent, block);
+            
+            // Step 3:
+            for (BasicBlock* semiDominee : m_data[blockData.parent].bucket) {
+                BasicBlock* possibleDominator = eval(semiDominee);
+                BlockData&amp; semiDomineeData = m_data[semiDominee];
+                ASSERT(m_blockByPreNumber[semiDomineeData.semiNumber] == blockData.parent);
+                BlockData&amp; possibleDominatorData = m_data[possibleDominator];
+                if (possibleDominatorData.semiNumber &lt; semiDomineeData.semiNumber)
+                    semiDomineeData.dom = possibleDominator;
+                else
+                    semiDomineeData.dom = blockData.parent;
+            }
+            m_data[blockData.parent].bucket.clear();
+        }
</ins><span class="cx">     }
</span><ins>+    
+    void computeExplicitImmediateDominators()
+    {
+        for (unsigned currentPreNumber = 1; currentPreNumber &lt; m_blockByPreNumber.size(); ++currentPreNumber) {
+            BasicBlock* block = m_blockByPreNumber[currentPreNumber];
+            BlockData&amp; blockData = m_data[block];
+            
+            if (blockData.dom != m_blockByPreNumber[blockData.semiNumber])
+                blockData.dom = m_data[blockData.dom].dom;
+        }
+    }
+    
+    void link(BasicBlock* from, BasicBlock* to)
+    {
+        m_data[to].ancestor = from;
+    }
+    
+    BasicBlock* eval(BasicBlock* block)
+    {
+        if (!m_data[block].ancestor)
+            return block;
+        
+        compress(block);
+        return m_data[block].label;
+    }
+    
+    void compress(BasicBlock* initialBlock)
+    {
+        // This was meant to be a recursive function, but we don't like recursion because we don't
+        // want to blow the stack. The original function will call compress() recursively on the
+        // ancestor of anything that has an ancestor. So, we populate our worklist with the
+        // recursive ancestors of initialBlock. Then we process the list starting from the block
+        // that is furthest up the ancestor chain.
+        
+        BasicBlock* ancestor = m_data[initialBlock].ancestor;
+        ASSERT(ancestor);
+        if (!m_data[ancestor].ancestor)
+            return;
+        
+        Vector&lt;BasicBlock*, 16&gt; stack;
+        for (BasicBlock* block = initialBlock; block; block = m_data[block].ancestor)
+            stack.append(block);
+        
+        // We only care about blocks that have an ancestor that has an ancestor. The last two
+        // elements in the stack won't satisfy this property.
+        ASSERT(stack.size() &gt;= 2);
+        ASSERT(!m_data[stack[stack.size() - 1]].ancestor);
+        ASSERT(!m_data[m_data[stack[stack.size() - 2]].ancestor].ancestor);
+        
+        for (unsigned i = stack.size() - 2; i--;) {
+            BasicBlock* block = stack[i];
+            BasicBlock*&amp; labelOfBlock = m_data[block].label;
+            BasicBlock*&amp; ancestorOfBlock = m_data[block].ancestor;
+            ASSERT(ancestorOfBlock);
+            ASSERT(m_data[ancestorOfBlock].ancestor);
+            
+            BasicBlock* labelOfAncestorOfBlock = m_data[ancestorOfBlock].label;
+            
+            if (m_data[labelOfAncestorOfBlock].semiNumber &lt; m_data[labelOfBlock].semiNumber)
+                labelOfBlock = labelOfAncestorOfBlock;
+            ancestorOfBlock = m_data[ancestorOfBlock].ancestor;
+        }
+    }
</ins><span class="cx"> 
</span><del>-    // Iteratively eliminate nodes that are not dominator.
-    bool changed;
-    do {
-        changed = false;
-        // Prune dominators in all non entry blocks: forward scan.
-        for (unsigned i = 1; i &lt; numBlocks; ++i)
-            changed |= pruneDominators(graph, i);
</del><ins>+    struct BlockData {
+        BlockData()
+            : parent(nullptr)
+            , preNumber(UINT_MAX)
+            , semiNumber(UINT_MAX)
+            , ancestor(nullptr)
+            , label(nullptr)
+            , dom(nullptr)
+        {
+        }
+        
+        BasicBlock* parent;
+        unsigned preNumber;
+        unsigned semiNumber;
+        BasicBlock* ancestor;
+        BasicBlock* label;
+        Vector&lt;BasicBlock*&gt; bucket;
+        BasicBlock* dom;
+    };
+    
+    Graph&amp; m_graph;
+    BlockMap&lt;BlockData&gt; m_data;
+    Vector&lt;BasicBlock*&gt; m_blockByPreNumber;
+};
</ins><span class="cx"> 
</span><del>-        if (!changed)
-            break;
</del><ins>+struct ValidationContext {
+    ValidationContext(Graph&amp; graph, Dominators&amp; dominators)
+        : graph(graph)
+        , dominators(dominators)
+    {
+    }
+    
+    void reportError(BasicBlock* from, BasicBlock* to, const char* message)
+    {
+        Error error;
+        error.from = from;
+        error.to = to;
+        error.message = message;
+        errors.append(error);
+    }
+    
+    void handleErrors()
+    {
+        if (errors.isEmpty())
+            return;
+        
+        startCrashing();
+        dataLog(&quot;DFG DOMINATOR VALIDATION FAILED:\n&quot;);
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;For block domination relationships:\n&quot;);
+        for (unsigned i = 0; i &lt; errors.size(); ++i) {
+            dataLog(
+                &quot;    &quot;, pointerDump(errors[i].from), &quot; -&gt; &quot;, pointerDump(errors[i].to),
+                &quot; (&quot;, errors[i].message, &quot;)\n&quot;);
+        }
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;Control flow graph:\n&quot;);
+        for (BlockIndex blockIndex = 0; blockIndex &lt; graph.numBlocks(); ++blockIndex) {
+            BasicBlock* block = graph.block(blockIndex);
+            if (!block)
+                continue;
+            dataLog(&quot;    Block #&quot;, blockIndex, &quot;: successors = [&quot;);
+            CommaPrinter comma;
+            for (unsigned i = 0; i &lt; block-&gt;numSuccessors(); ++i)
+                dataLog(comma, *block-&gt;successor(i));
+            dataLog(&quot;], predecessors = [&quot;);
+            comma = CommaPrinter();
+            for (unsigned i = 0; i &lt; block-&gt;predecessors.size(); ++i)
+                dataLog(comma, *block-&gt;predecessors[i]);
+            dataLog(&quot;]\n&quot;);
+        }
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;Lengauer-Tarjan Dominators:\n&quot;);
+        dataLog(dominators);
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;Naive Dominators:\n&quot;);
+        naiveDominators.dump(graph, WTF::dataFile());
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;Graph at time of failure:\n&quot;);
+        graph.dump();
+        dataLog(&quot;\n&quot;);
+        dataLog(&quot;DFG DOMINATOR VALIDATION FAILIED!\n&quot;);
+        CRASH();
+    }
+    
+    Graph&amp; graph;
+    Dominators&amp; dominators;
+    NaiveDominators naiveDominators;
+    
+    struct Error {
+        BasicBlock* from;
+        BasicBlock* to;
+        const char* message;
+    };
+    
+    Vector&lt;Error&gt; errors;
+};
</ins><span class="cx"> 
</span><del>-        // Prune dominators in all non entry blocks: backward scan.
-        changed = false;
-        for (unsigned i = numBlocks; i-- &gt; 1;)
-            changed |= pruneDominators(graph, i);
-    } while (changed);
-}
</del><ins>+} // anonymous namespace
</ins><span class="cx"> 
</span><del>-bool Dominators::pruneDominators(Graph&amp; graph, BlockIndex idx)
</del><ins>+void Dominators::compute(Graph&amp; graph)
</ins><span class="cx"> {
</span><del>-    BasicBlock* block = graph.block(idx);
</del><ins>+    LengauerTarjan lengauerTarjan(graph);
+    lengauerTarjan.compute();
</ins><span class="cx"> 
</span><del>-    if (!block || block-&gt;predecessors.isEmpty())
-        return false;
-
-    // Find the intersection of dom(preds).
-    m_scratch.set(m_results[block-&gt;predecessors[0]-&gt;index]);
-    for (unsigned j = block-&gt;predecessors.size(); j-- &gt; 1;)
-        m_scratch.filter(m_results[block-&gt;predecessors[j]-&gt;index]);
-
-    // The block is also dominated by itself.
-    m_scratch.set(idx);
-
-    return m_results[idx].setAndCheck(m_scratch);
-}
-
-void Dominators::dump(Graph&amp; graph, PrintStream&amp; out) const
-{
-    for (BlockIndex blockIndex = 0; blockIndex &lt; graph.numBlocks(); ++blockIndex) {
</del><ins>+    m_data = BlockMap&lt;BlockData&gt;(graph);
+    
+    // From here we want to build a spanning tree with both upward and downward links and we want
+    // to do a search over this tree to compute pre and post numbers that can be used for dominance
+    // tests.
+    
+    for (BlockIndex blockIndex = graph.numBlocks(); blockIndex--;) {
</ins><span class="cx">         BasicBlock* block = graph.block(blockIndex);
</span><span class="cx">         if (!block)
</span><span class="cx">             continue;
</span><del>-        out.print(&quot;    Block &quot;, *block, &quot;:&quot;);
-        for (BlockIndex otherIndex = 0; otherIndex &lt; graph.numBlocks(); ++otherIndex) {
-            if (!dominates(block-&gt;index, otherIndex))
</del><ins>+        
+        BasicBlock* idomBlock = lengauerTarjan.immediateDominator(block);
+        m_data[block].idomParent = idomBlock;
+        if (idomBlock)
+            m_data[idomBlock].idomKids.append(block);
+    }
+    
+    unsigned nextPreNumber = 0;
+    unsigned nextPostNumber = 0;
+    
+    // Plain stack-based worklist because we are guaranteed to see each block exactly once anyway.
+    Vector&lt;BlockWithOrder&gt; worklist;
+    worklist.append(BlockWithOrder(graph.block(0), PreOrder));
+    while (!worklist.isEmpty()) {
+        BlockWithOrder item = worklist.takeLast();
+        switch (item.order) {
+        case PreOrder:
+            m_data[item.block].preNumber = nextPreNumber++;
+            worklist.append(BlockWithOrder(item.block, PostOrder));
+            for (BasicBlock* kid : m_data[item.block].idomKids)
+                worklist.append(BlockWithOrder(kid, PreOrder));
+            break;
+        case PostOrder:
+            m_data[item.block].postNumber = nextPostNumber++;
+            break;
+        }
+    }
+    
+    if (validationEnabled()) {
+        // Check our dominator calculation:
+        // 1) Check that our range-based ancestry test is the same as a naive ancestry test.
+        // 2) Check that our notion of who dominates whom is identical to a naive (not
+        //    Lengauer-Tarjan) dominator calculation.
+        
+        ValidationContext context(graph, *this);
+        context.naiveDominators.compute(graph);
+        
+        for (BlockIndex fromBlockIndex = graph.numBlocks(); fromBlockIndex--;) {
+            BasicBlock* fromBlock = graph.block(fromBlockIndex);
+            if (!fromBlock || m_data[fromBlock].preNumber == UINT_MAX)
</ins><span class="cx">                 continue;
</span><del>-            out.print(&quot; #&quot;, otherIndex);
</del><ins>+            for (BlockIndex toBlockIndex = graph.numBlocks(); toBlockIndex--;) {
+                BasicBlock* toBlock = graph.block(toBlockIndex);
+                if (!toBlock || m_data[toBlock].preNumber == UINT_MAX)
+                    continue;
+                
+                if (dominates(fromBlock, toBlock) != naiveDominates(fromBlock, toBlock))
+                    context.reportError(fromBlock, toBlock, &quot;Range-based domination check is broken&quot;);
+                if (dominates(fromBlock, toBlock) != context.naiveDominators.dominates(fromBlock, toBlock))
+                    context.reportError(fromBlock, toBlock, &quot;Lengauer-Tarjan domination is broken&quot;);
+            }
</ins><span class="cx">         }
</span><del>-        out.print(&quot;\n&quot;);
</del><ins>+        
+        context.handleErrors();
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Dominators::naiveDominates(BasicBlock* from, BasicBlock* to) const
+{
+    for (BasicBlock* block = to; block; block = m_data[block].idomParent) {
+        if (block == from)
+            return true;
+    }
+    return false;
+}
+
+void Dominators::dump(PrintStream&amp; out) const
+{
+    if (!isValid()) {
+        out.print(&quot;    Not Valid.\n&quot;);
+        return;
+    }
+    
+    for (BlockIndex blockIndex = 0; blockIndex &lt; m_data.size(); ++blockIndex) {
+        if (m_data[blockIndex].preNumber == UINT_MAX)
+            continue;
+        
+        out.print(&quot;    Block #&quot;, blockIndex, &quot;: idom = &quot;, pointerDump(m_data[blockIndex].idomParent), &quot;, idomKids = [&quot;);
+        CommaPrinter comma;
+        for (unsigned i = 0; i &lt; m_data[blockIndex].idomKids.size(); ++i)
+            out.print(comma, *m_data[blockIndex].idomKids[i]);
+        out.print(&quot;], pre/post = &quot;, m_data[blockIndex].preNumber, &quot;/&quot;, m_data[blockIndex].postNumber, &quot;\n&quot;);
+    }
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDominatorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDominators.h (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDominators.h        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGDominators.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014 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">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DFGAnalysis.h&quot;
</span><span class="cx"> #include &quot;DFGBasicBlock.h&quot;
</span><ins>+#include &quot;DFGBlockMap.h&quot;
</ins><span class="cx"> #include &quot;DFGCommon.h&quot;
</span><span class="cx"> #include &lt;wtf/FastBitVector.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -44,24 +45,39 @@
</span><span class="cx">     
</span><span class="cx">     void compute(Graph&amp;);
</span><span class="cx">     
</span><del>-    bool dominates(BlockIndex from, BlockIndex to) const
</del><ins>+    bool strictlyDominates(BasicBlock* from, BasicBlock* to) const
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(isValid());
</span><del>-        return m_results[to].get(from);
</del><ins>+        return m_data[to].preNumber &gt; m_data[from].preNumber
+            &amp;&amp; m_data[to].postNumber &lt; m_data[from].postNumber;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool dominates(BasicBlock* from, BasicBlock* to) const
</span><span class="cx">     {
</span><del>-        return dominates(from-&gt;index, to-&gt;index);
</del><ins>+        return from == to || strictlyDominates(from, to);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void dump(Graph&amp;, PrintStream&amp;) const;
</del><ins>+    void dump(PrintStream&amp;) const;
</ins><span class="cx">     
</span><span class="cx"> private:
</span><del>-    bool pruneDominators(Graph&amp;, BlockIndex);
</del><ins>+    bool naiveDominates(BasicBlock* from, BasicBlock* to) const;
</ins><span class="cx">     
</span><del>-    Vector&lt;FastBitVector&gt; m_results; // For each block, the bitvector of blocks that dominate it.
-    FastBitVector m_scratch; // A temporary bitvector with bit for each block. We recycle this to save new/deletes.
</del><ins>+    struct BlockData {
+        BlockData()
+            : idomParent(nullptr)
+            , preNumber(UINT_MAX)
+            , postNumber(UINT_MAX)
+        {
+        }
+        
+        Vector&lt;BasicBlock*&gt; idomKids;
+        BasicBlock* idomParent;
+        
+        unsigned preNumber;
+        unsigned postNumber;
+    };
+    
+    BlockMap&lt;BlockData&gt; m_data;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;BytecodeLivenessAnalysisInlines.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;CodeBlockWithJITType.h&quot;
</span><ins>+#include &quot;DFGBlockWorklist.h&quot;
</ins><span class="cx"> #include &quot;DFGClobberSet.h&quot;
</span><span class="cx"> #include &quot;DFGJITCode.h&quot;
</span><span class="cx"> #include &quot;DFGVariableAccessDataDump.h&quot;
</span><span class="lines">@@ -370,15 +371,19 @@
</span><span class="cx">     if (m_dominators.isValid()) {
</span><span class="cx">         out.print(prefix, &quot;  Dominated by:&quot;);
</span><span class="cx">         for (size_t i = 0; i &lt; m_blocks.size(); ++i) {
</span><del>-            if (!m_dominators.dominates(i, block-&gt;index))
</del><ins>+            if (!this-&gt;block(i))
</ins><span class="cx">                 continue;
</span><ins>+            if (!m_dominators.dominates(this-&gt;block(i), block))
+                continue;
</ins><span class="cx">             out.print(&quot; #&quot;, i);
</span><span class="cx">         }
</span><span class="cx">         out.print(&quot;\n&quot;);
</span><span class="cx">         out.print(prefix, &quot;  Dominates:&quot;);
</span><span class="cx">         for (size_t i = 0; i &lt; m_blocks.size(); ++i) {
</span><del>-            if (!m_dominators.dominates(block-&gt;index, i))
</del><ins>+            if (!this-&gt;block(i))
</ins><span class="cx">                 continue;
</span><ins>+            if (!m_dominators.dominates(block, this-&gt;block(i)))
+                continue;
</ins><span class="cx">             out.print(&quot; #&quot;, i);
</span><span class="cx">         }
</span><span class="cx">         out.print(&quot;\n&quot;);
</span><span class="lines">@@ -635,73 +640,30 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Utilities for pre- and post-order traversals.
-namespace {
-
-inline void addForPreOrder(Vector&lt;BasicBlock*&gt;&amp; result, Vector&lt;BasicBlock*, 16&gt;&amp; worklist, BitVector&amp; seen, BasicBlock* block)
-{
-    if (seen.get(block-&gt;index))
-        return;
-    
-    result.append(block);
-    worklist.append(block);
-    seen.set(block-&gt;index);
-}
-
-enum PostOrderTaskKind {
-    PostOrderFirstVisit,
-    PostOrderAddToResult
-};
-
-struct PostOrderTask {
-    PostOrderTask(BasicBlock* block = nullptr, PostOrderTaskKind kind = PostOrderFirstVisit)
-        : m_block(block)
-        , m_kind(kind)
-    {
-    }
-    
-    BasicBlock* m_block;
-    PostOrderTaskKind m_kind;
-};
-
-inline void addForPostOrder(Vector&lt;PostOrderTask, 16&gt;&amp; worklist, BitVector&amp; seen, BasicBlock* block)
-{
-    if (seen.get(block-&gt;index))
-        return;
-    
-    worklist.append(PostOrderTask(block, PostOrderFirstVisit));
-    seen.set(block-&gt;index);
-}
-
-} // anonymous namespace
-
</del><span class="cx"> void Graph::getBlocksInPreOrder(Vector&lt;BasicBlock*&gt;&amp; result)
</span><span class="cx"> {
</span><del>-    Vector&lt;BasicBlock*, 16&gt; worklist;
-    BitVector seen;
-    addForPreOrder(result, worklist, seen, block(0));
-    while (!worklist.isEmpty()) {
-        BasicBlock* block = worklist.takeLast();
</del><ins>+    BlockWorklist worklist;
+    worklist.push(block(0));
+    while (BasicBlock* block = worklist.pop()) {
+        result.append(block);
</ins><span class="cx">         for (unsigned i = block-&gt;numSuccessors(); i--;)
</span><del>-            addForPreOrder(result, worklist, seen, block-&gt;successor(i));
</del><ins>+            worklist.push(block-&gt;successor(i));
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Graph::getBlocksInPostOrder(Vector&lt;BasicBlock*&gt;&amp; result)
</span><span class="cx"> {
</span><del>-    Vector&lt;PostOrderTask, 16&gt; worklist;
-    BitVector seen;
-    addForPostOrder(worklist, seen, block(0));
-    while (!worklist.isEmpty()) {
-        PostOrderTask task = worklist.takeLast();
-        switch (task.m_kind) {
-        case PostOrderFirstVisit:
-            worklist.append(PostOrderTask(task.m_block, PostOrderAddToResult));
-            for (unsigned i = task.m_block-&gt;numSuccessors(); i--;)
-                addForPostOrder(worklist, seen, task.m_block-&gt;successor(i));
</del><ins>+    PostOrderBlockWorklist worklist;
+    worklist.push(block(0));
+    while (BlockWithOrder item = worklist.pop()) {
+        switch (item.order) {
+        case PreOrder:
+            worklist.pushPost(item.block);
+            for (unsigned i = item.block-&gt;numSuccessors(); i--;)
+                worklist.push(item.block-&gt;successor(i));
</ins><span class="cx">             break;
</span><del>-        case PostOrderAddToResult:
-            result.append(task.m_block);
</del><ins>+        case PostOrder:
+            result.append(item.block);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInvalidationPointInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGInvalidationPointInjectionPhase.cpp (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInvalidationPointInjectionPhase.cpp        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGInvalidationPointInjectionPhase.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><ins>+#include &quot;DFGBlockSet.h&quot;
</ins><span class="cx"> #include &quot;DFGClobberize.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGInsertionSet.h&quot;
</span><span class="lines">@@ -50,7 +51,7 @@
</span><span class="cx">     {
</span><span class="cx">         ASSERT(m_graph.m_form != SSA);
</span><span class="cx">         
</span><del>-        BitVector blocksThatNeedInvalidationPoints;
</del><ins>+        BlockSet blocksThatNeedInvalidationPoints;
</ins><span class="cx">         
</span><span class="cx">         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
</span><span class="cx">             BasicBlock* block = m_graph.block(blockIndex);
</span><span class="lines">@@ -63,17 +64,18 @@
</span><span class="cx">             // Note: this assumes that control flow occurs at bytecode instruction boundaries.
</span><span class="cx">             if (m_originThatHadFire.isSet()) {
</span><span class="cx">                 for (unsigned i = block-&gt;numSuccessors(); i--;)
</span><del>-                    blocksThatNeedInvalidationPoints.set(block-&gt;successor(i)-&gt;index);
</del><ins>+                    blocksThatNeedInvalidationPoints.add(block-&gt;successor(i));
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             m_insertionSet.execute(block);
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
</span><del>-            if (!blocksThatNeedInvalidationPoints.get(blockIndex))
</del><ins>+            BasicBlock* block = m_graph.block(blockIndex);
+
+            if (!blocksThatNeedInvalidationPoints.contains(block))
</ins><span class="cx">                 continue;
</span><span class="cx">             
</span><del>-            BasicBlock* block = m_graph.block(blockIndex);
</del><span class="cx">             insertInvalidationCheck(0, block-&gt;at(0));
</span><span class="cx">             m_insertionSet.execute(block);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNaiveDominatorscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.cpp (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,135 @@
</span><ins>+/*
+ * Copyright (C) 2011, 2014 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;DFGNaiveDominators.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGGraph.h&quot;
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC { namespace DFG {
+
+NaiveDominators::NaiveDominators()
+{
+}
+
+NaiveDominators::~NaiveDominators()
+{
+}
+
+void NaiveDominators::compute(Graph&amp; graph)
+{
+    // This implements a naive dominator solver.
+    
+    ASSERT(graph.block(0)-&gt;predecessors.isEmpty());
+    
+    unsigned numBlocks = graph.numBlocks();
+    
+    // Allocate storage for the dense dominance matrix. 
+    if (numBlocks &gt; m_results.size()) {
+        m_results.grow(numBlocks);
+        for (unsigned i = numBlocks; i--;)
+            m_results[i].resize(numBlocks);
+        m_scratch.resize(numBlocks);
+    }
+
+    // We know that the entry block is only dominated by itself.
+    m_results[0].clearAll();
+    m_results[0].set(0);
+
+    // Find all of the valid blocks.
+    m_scratch.clearAll();
+    for (unsigned i = numBlocks; i--;) {
+        if (!graph.block(i))
+            continue;
+        m_scratch.set(i);
+    }
+    
+    // Mark all nodes as dominated by everything.
+    for (unsigned i = numBlocks; i-- &gt; 1;) {
+        if (!graph.block(i) || graph.block(i)-&gt;predecessors.isEmpty())
+            m_results[i].clearAll();
+        else
+            m_results[i].set(m_scratch);
+    }
+
+    // Iteratively eliminate nodes that are not dominator.
+    bool changed;
+    do {
+        changed = false;
+        // Prune dominators in all non entry blocks: forward scan.
+        for (unsigned i = 1; i &lt; numBlocks; ++i)
+            changed |= pruneDominators(graph, i);
+
+        if (!changed)
+            break;
+
+        // Prune dominators in all non entry blocks: backward scan.
+        changed = false;
+        for (unsigned i = numBlocks; i-- &gt; 1;)
+            changed |= pruneDominators(graph, i);
+    } while (changed);
+}
+
+bool NaiveDominators::pruneDominators(Graph&amp; graph, BlockIndex idx)
+{
+    BasicBlock* block = graph.block(idx);
+
+    if (!block || block-&gt;predecessors.isEmpty())
+        return false;
+
+    // Find the intersection of dom(preds).
+    m_scratch.set(m_results[block-&gt;predecessors[0]-&gt;index]);
+    for (unsigned j = block-&gt;predecessors.size(); j-- &gt; 1;)
+        m_scratch.filter(m_results[block-&gt;predecessors[j]-&gt;index]);
+
+    // The block is also dominated by itself.
+    m_scratch.set(idx);
+
+    return m_results[idx].setAndCheck(m_scratch);
+}
+
+void NaiveDominators::dump(Graph&amp; graph, PrintStream&amp; out) const
+{
+    for (BlockIndex blockIndex = 0; blockIndex &lt; graph.numBlocks(); ++blockIndex) {
+        BasicBlock* block = graph.block(blockIndex);
+        if (!block)
+            continue;
+        out.print(&quot;    Block &quot;, *block, &quot;:&quot;);
+        for (BlockIndex otherIndex = 0; otherIndex &lt; graph.numBlocks(); ++otherIndex) {
+            if (!dominates(block-&gt;index, otherIndex))
+                continue;
+            out.print(&quot; #&quot;, otherIndex);
+        }
+        out.print(&quot;\n&quot;);
+    }
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNaiveDominatorsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.h (0 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGNaiveDominators.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+/*
+ * Copyright (C) 2011, 2014 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. 
+ */
+
+#ifndef DFGNaiveDominators_h
+#define DFGNaiveDominators_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlock.h&quot;
+#include &quot;DFGCommon.h&quot;
+#include &lt;wtf/FastBitVector.h&gt;
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// This class is only used for validating the real dominators implementation.
+
+class NaiveDominators {
+public:
+    NaiveDominators();
+    ~NaiveDominators();
+    
+    void compute(Graph&amp;);
+    
+    bool dominates(BlockIndex from, BlockIndex to) const
+    {
+        return m_results[to].get(from);
+    }
+    
+    bool dominates(BasicBlock* from, BasicBlock* to) const
+    {
+        return dominates(from-&gt;index, to-&gt;index);
+    }
+    
+    void dump(Graph&amp;, PrintStream&amp;) const;
+    
+private:
+    bool pruneDominators(Graph&amp;, BlockIndex);
+    
+    Vector&lt;FastBitVector&gt; m_results; // For each block, the bitvector of blocks that dominate it.
+    FastBitVector m_scratch; // A temporary bitvector with bit for each block. We recycle this to save new/deletes.
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGNaiveDominators_h
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNaturalLoopscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.cpp (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.cpp        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.cpp        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -45,6 +45,11 @@
</span><span class="cx"> NaturalLoops::NaturalLoops() { }
</span><span class="cx"> NaturalLoops::~NaturalLoops() { }
</span><span class="cx"> 
</span><ins>+void NaturalLoops::computeDependencies(Graph&amp; graph)
+{
+    graph.m_dominators.computeIfNecessary(graph);
+}
+
</ins><span class="cx"> void NaturalLoops::compute(Graph&amp; graph)
</span><span class="cx"> {
</span><span class="cx">     // Implement the classic dominator-based natural loop finder. The first
</span><span class="lines">@@ -57,11 +62,9 @@
</span><span class="cx">     
</span><span class="cx">     static const bool verbose = false;
</span><span class="cx">     
</span><del>-    graph.m_dominators.computeIfNecessary(graph);
-    
</del><span class="cx">     if (verbose) {
</span><span class="cx">         dataLog(&quot;Dominators:\n&quot;);
</span><del>-        graph.m_dominators.dump(graph, WTF::dataFile());
</del><ins>+        graph.m_dominators.dump(WTF::dataFile());
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     m_loops.resize(0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNaturalLoopsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.h (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.h        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/JavaScriptCore/dfg/DFGNaturalLoops.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -93,6 +93,7 @@
</span><span class="cx">     NaturalLoops();
</span><span class="cx">     ~NaturalLoops();
</span><span class="cx">     
</span><ins>+    void computeDependencies(Graph&amp;);
</ins><span class="cx">     void compute(Graph&amp;);
</span><span class="cx">     
</span><span class="cx">     unsigned numLoops() const
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/WTF/ChangeLog        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -1,5 +1,22 @@
</span><span class="cx"> 2014-08-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        DFG should compute immediate dominators using the O(n log n) form of Lengauer and Tarjan's &quot;A Fast Algorithm for Finding Dominators in a Flowgraph&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=93361
+
+        Reviewed by Mark Hahnenberg.
+        
+        Make BitVector operations return the previous value of the bit you're changing. This is
+        useful for the kinds of set operations that are commonplace in compiler graph searches.
+
+        * wtf/BitVector.h:
+        (WTF::BitVector::quickSet):
+        (WTF::BitVector::quickClear):
+        (WTF::BitVector::set):
+        (WTF::BitVector::ensureSizeAndSet):
+        (WTF::BitVector::clear):
+
+2014-08-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         FTL should be able to do polymorphic call inlining
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=135145
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfBitVectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/BitVector.h (173071 => 173072)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/BitVector.h        2014-08-28 19:21:24 UTC (rev 173071)
+++ trunk/Source/WTF/wtf/BitVector.h        2014-08-28 19:23:02 UTC (rev 173072)
</span><span class="lines">@@ -117,24 +117,31 @@
</span><span class="cx">         return !!(bits()[bit / bitsInPointer()] &amp; (static_cast&lt;uintptr_t&gt;(1) &lt;&lt; (bit &amp; (bitsInPointer() - 1))));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void quickSet(size_t bit)
</del><ins>+    bool quickSet(size_t bit)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(bit &lt; size());
</span><del>-        bits()[bit / bitsInPointer()] |= (static_cast&lt;uintptr_t&gt;(1) &lt;&lt; (bit &amp; (bitsInPointer() - 1)));
</del><ins>+        uintptr_t&amp; word = bits()[bit / bitsInPointer()];
+        uintptr_t mask = static_cast&lt;uintptr_t&gt;(1) &lt;&lt; (bit &amp; (bitsInPointer() - 1));
+        bool result = !!(word &amp; mask);
+        word |= mask;
+        return result;
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void quickClear(size_t bit)
</del><ins>+    bool quickClear(size_t bit)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT_WITH_SECURITY_IMPLICATION(bit &lt; size());
</span><del>-        bits()[bit / bitsInPointer()] &amp;= ~(static_cast&lt;uintptr_t&gt;(1) &lt;&lt; (bit &amp; (bitsInPointer() - 1)));
</del><ins>+        uintptr_t&amp; word = bits()[bit / bitsInPointer()];
+        uintptr_t mask = static_cast&lt;uintptr_t&gt;(1) &lt;&lt; (bit &amp; (bitsInPointer() - 1));
+        bool result = !!(word &amp; mask);
+        word &amp;= ~mask;
+        return result;
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void quickSet(size_t bit, bool value)
</del><ins>+    bool quickSet(size_t bit, bool value)
</ins><span class="cx">     {
</span><span class="cx">         if (value)
</span><del>-            quickSet(bit);
-        else
-            quickClear(bit);
</del><ins>+            return quickSet(bit);
+        return quickClear(bit);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool get(size_t bit) const
</span><span class="lines">@@ -144,31 +151,30 @@
</span><span class="cx">         return quickGet(bit);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void set(size_t bit)
</del><ins>+    bool set(size_t bit)
</ins><span class="cx">     {
</span><span class="cx">         ensureSize(bit + 1);
</span><del>-        quickSet(bit);
</del><ins>+        return quickSet(bit);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void ensureSizeAndSet(size_t bit, size_t size)
</del><ins>+    bool ensureSizeAndSet(size_t bit, size_t size)
</ins><span class="cx">     {
</span><span class="cx">         ensureSize(size);
</span><del>-        quickSet(bit);
</del><ins>+        return quickSet(bit);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void clear(size_t bit)
</del><ins>+    bool clear(size_t bit)
</ins><span class="cx">     {
</span><span class="cx">         if (bit &gt;= size())
</span><del>-            return;
-        quickClear(bit);
</del><ins>+            return false;
+        return quickClear(bit);
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void set(size_t bit, bool value)
</del><ins>+    bool set(size_t bit, bool value)
</ins><span class="cx">     {
</span><span class="cx">         if (value)
</span><del>-            set(bit);
-        else
-            clear(bit);
</del><ins>+            return set(bit);
+        return clear(bit);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void merge(const BitVector&amp; other)
</span></span></pre>
</div>
</div>

</body>
</html>