<!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>[214408] 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/214408">214408</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2017-03-26 14:39:27 -0700 (Sun, 26 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Air should use RegisterSet for RegLiveness
https://bugs.webkit.org/show_bug.cgi?id=170108

Reviewed by Yusuke Suzuki.
Source/JavaScriptCore:

        
The biggest change here is the introduction of the new RegLiveness class. This is a
drop-in replacement for the old RegLiveness, which was a specialization of
AbstractLiveness&lt;&gt;, but it's about 30% faster. It gets its speed boost from just using
sets everywhere, which is efficient for registers since RegisterSet is just two (on
x86-64) or three 32-bit (on ARM64) statically allocated words. This looks like a 1%
compile time progression on WasmBench.

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3TimingScope.cpp: Records phase timing totals.
(JSC::B3::TimingScope::TimingScope):
(JSC::B3::TimingScope::~TimingScope):
* b3/B3TimingScope.h:
* b3/air/AirAllocateRegistersByGraphColoring.cpp:
(JSC::B3::Air::allocateRegistersByGraphColoring):
* b3/air/AirLiveness.h: Move code around and rename a bit to make it more like RegLiveness; in particular we want the `iterator` to be called `iterator` not `Iterator`, and we want it to be internal to its iterable. Also rename this template to Liveness, to match the header filename.
(JSC::B3::Air::Liveness::Liveness):
(JSC::B3::Air::Liveness::LocalCalc::LocalCalc):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::Iterable):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::iterator):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator++):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator*):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator==):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator!=):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::begin):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::end):
(JSC::B3::Air::Liveness::Iterable::Iterable):
(JSC::B3::Air::Liveness::Iterable::iterator::iterator):
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter): Deleted.
(JSC::B3::Air::RegLivenessAdapter::numIndices): Deleted.
(JSC::B3::Air::RegLivenessAdapter::acceptsBank): Deleted.
(JSC::B3::Air::RegLivenessAdapter::acceptsRole): Deleted.
(JSC::B3::Air::RegLivenessAdapter::valueToIndex): Deleted.
(JSC::B3::Air::RegLivenessAdapter::indexToValue): Deleted.
(JSC::B3::Air::AbstractLiveness::AbstractLiveness): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::LocalCalc): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::Iterator): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator++): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator*): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator==): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator!=): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::Iterable): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::live): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::isLive): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::execute): Deleted.
(JSC::B3::Air::AbstractLiveness::rawLiveAtHead): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::Iterable): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::iterator): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator*): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator++): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator==): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator!=): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::begin): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::end): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::contains): Deleted.
(JSC::B3::Air::AbstractLiveness::liveAtHead): Deleted.
(JSC::B3::Air::AbstractLiveness::liveAtTail): Deleted.
(JSC::B3::Air::AbstractLiveness::workset): Deleted.
* b3/air/AirLogRegisterPressure.cpp:
* b3/air/AirLowerAfterRegAlloc.cpp:
* b3/air/AirRegLiveness.cpp: Added.
(JSC::B3::Air::RegLiveness::RegLiveness):
(JSC::B3::Air::RegLiveness::~RegLiveness):
(JSC::B3::Air::RegLiveness::LocalCalc::execute):
* b3/air/AirRegLiveness.h: Added.
(JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
(JSC::B3::Air::RegLiveness::LocalCalc::live):
(JSC::B3::Air::RegLiveness::LocalCalc::isLive):
(JSC::B3::Air::RegLiveness::liveAtHead):
(JSC::B3::Air::RegLiveness::liveAtTail):
* b3/air/AirReportUsedRegisters.cpp:
* jit/RegisterSet.h:
(JSC::RegisterSet::add):
(JSC::RegisterSet::remove):
(JSC::RegisterSet::contains):
(JSC::RegisterSet::subsumes):
(JSC::RegisterSet::iterator::iterator):
(JSC::RegisterSet::iterator::operator*):
(JSC::RegisterSet::iterator::operator++):
(JSC::RegisterSet::iterator::operator==):
(JSC::RegisterSet::iterator::operator!=):
(JSC::RegisterSet::begin):
(JSC::RegisterSet::end):

Source/WTF:


* wtf/Atomics.h:
(WTF::ensurePointer): This is a useful replacement for std::once, which requires less fencing.
* wtf/Bitmap.h: Add more utilities.
(WTF::Bitmap::iterator::iterator): An iterator for set bits.
(WTF::Bitmap::iterator::operator*):
(WTF::Bitmap::iterator::operator++):
(WTF::Bitmap::iterator::operator==):
(WTF::Bitmap::iterator::operator!=):
(WTF::Bitmap::begin):
(WTF::Bitmap::end):
(WTF::WordType&gt;::subsumes): a.subsumes(b) if all of b's set bits are set in a.
(WTF::WordType&gt;::findBit): find next set or clear bit.</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="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3TimingScopecpp">trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3TimingScopeh">trunk/Source/JavaScriptCore/b3/B3TimingScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirAllocateRegistersByGraphColoringcpp">trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLivenessh">trunk/Source/JavaScriptCore/b3/air/AirLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLogRegisterPressurecpp">trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp">trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp">trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegisterSeth">trunk/Source/JavaScriptCore/jit/RegisterSet.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfAtomicsh">trunk/Source/WTF/wtf/Atomics.h</a></li>
<li><a href="#trunkSourceWTFwtfBitmaph">trunk/Source/WTF/wtf/Bitmap.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreb3airAirRegLivenesscpp">trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirRegLivenessh">trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.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 (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -101,6 +101,7 @@
</span><span class="cx">     b3/air/AirOptimizeBlockOrder.cpp
</span><span class="cx">     b3/air/AirPadInterference.cpp
</span><span class="cx">     b3/air/AirPhaseScope.cpp
</span><ins>+    b3/air/AirRegLiveness.cpp
</ins><span class="cx">     b3/air/AirReportUsedRegisters.cpp
</span><span class="cx">     b3/air/AirSimplifyCFG.cpp
</span><span class="cx">     b3/air/AirSpecial.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,3 +1,97 @@
</span><ins>+2017-03-26  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should use RegisterSet for RegLiveness
+        https://bugs.webkit.org/show_bug.cgi?id=170108
+
+        Reviewed by Yusuke Suzuki.
+        
+        The biggest change here is the introduction of the new RegLiveness class. This is a
+        drop-in replacement for the old RegLiveness, which was a specialization of
+        AbstractLiveness&lt;&gt;, but it's about 30% faster. It gets its speed boost from just using
+        sets everywhere, which is efficient for registers since RegisterSet is just two (on
+        x86-64) or three 32-bit (on ARM64) statically allocated words. This looks like a 1%
+        compile time progression on WasmBench.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3TimingScope.cpp: Records phase timing totals.
+        (JSC::B3::TimingScope::TimingScope):
+        (JSC::B3::TimingScope::~TimingScope):
+        * b3/B3TimingScope.h:
+        * b3/air/AirAllocateRegistersByGraphColoring.cpp:
+        (JSC::B3::Air::allocateRegistersByGraphColoring):
+        * b3/air/AirLiveness.h: Move code around and rename a bit to make it more like RegLiveness; in particular we want the `iterator` to be called `iterator` not `Iterator`, and we want it to be internal to its iterable. Also rename this template to Liveness, to match the header filename.
+        (JSC::B3::Air::Liveness::Liveness):
+        (JSC::B3::Air::Liveness::LocalCalc::LocalCalc):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::Iterable):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::iterator):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator++):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator*):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator==):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator!=):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::begin):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::end):
+        (JSC::B3::Air::Liveness::Iterable::Iterable):
+        (JSC::B3::Air::Liveness::Iterable::iterator::iterator):
+        (JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::numIndices): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::acceptsBank): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::acceptsRole): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::valueToIndex): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::indexToValue): Deleted.
+        (JSC::B3::Air::AbstractLiveness::AbstractLiveness): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::LocalCalc): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::Iterator): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator++): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator*): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator==): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator!=): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::Iterable): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::live): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::isLive): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::execute): Deleted.
+        (JSC::B3::Air::AbstractLiveness::rawLiveAtHead): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::Iterable): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::iterator): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator*): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator++): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator==): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator!=): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::begin): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::end): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::contains): Deleted.
+        (JSC::B3::Air::AbstractLiveness::liveAtHead): Deleted.
+        (JSC::B3::Air::AbstractLiveness::liveAtTail): Deleted.
+        (JSC::B3::Air::AbstractLiveness::workset): Deleted.
+        * b3/air/AirLogRegisterPressure.cpp:
+        * b3/air/AirLowerAfterRegAlloc.cpp:
+        * b3/air/AirRegLiveness.cpp: Added.
+        (JSC::B3::Air::RegLiveness::RegLiveness):
+        (JSC::B3::Air::RegLiveness::~RegLiveness):
+        (JSC::B3::Air::RegLiveness::LocalCalc::execute):
+        * b3/air/AirRegLiveness.h: Added.
+        (JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
+        (JSC::B3::Air::RegLiveness::LocalCalc::live):
+        (JSC::B3::Air::RegLiveness::LocalCalc::isLive):
+        (JSC::B3::Air::RegLiveness::liveAtHead):
+        (JSC::B3::Air::RegLiveness::liveAtTail):
+        * b3/air/AirReportUsedRegisters.cpp:
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::add):
+        (JSC::RegisterSet::remove):
+        (JSC::RegisterSet::contains):
+        (JSC::RegisterSet::subsumes):
+        (JSC::RegisterSet::iterator::iterator):
+        (JSC::RegisterSet::iterator::operator*):
+        (JSC::RegisterSet::iterator::operator++):
+        (JSC::RegisterSet::iterator::operator==):
+        (JSC::RegisterSet::iterator::operator!=):
+        (JSC::RegisterSet::begin):
+        (JSC::RegisterSet::end):
+
</ins><span class="cx"> 2017-03-25  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix wasm by returning after we do TLS.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1005,6 +1005,8 @@
</span><span class="cx">                 0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
</span><span class="cx">                 0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */; };
</span><span class="cx">                 0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */; };
</span><ins>+                0FF4B4BC1E88449700DBBE86 /* AirRegLiveness.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */; };
+                0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */; };
</ins><span class="cx">                 0FF60AC216740F8300029779 /* ReduceWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF60AC016740F8100029779 /* ReduceWhitespace.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */; };
</span><span class="cx">                 0FF7168C15A3B235008F5DAA /* PropertyOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF7168A15A3B231008F5DAA /* PropertyOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -3520,6 +3522,8 @@
</span><span class="cx">                 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDisassembler.cpp; path = dfg/DFGDisassembler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDisassembler.h; path = dfg/DFGDisassembler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirRegLiveness.cpp; path = b3/air/AirRegLiveness.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirRegLiveness.h; path = b3/air/AirRegLiveness.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReduceWhitespace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF60AC016740F8100029779 /* ReduceWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReduceWhitespace.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FF7168A15A3B231008F5DAA /* PropertyOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyOffset.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5578,6 +5582,8 @@
</span><span class="cx">                                 0F9CABC71DB54A760008E83B /* AirPadInterference.h */,
</span><span class="cx">                                 0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */,
</span><span class="cx">                                 0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */,
</span><ins>+                                0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */,
+                                0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */,
</ins><span class="cx">                                 0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */,
</span><span class="cx">                                 0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */,
</span><span class="cx">                                 0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */,
</span><span class="lines">@@ -8236,6 +8242,7 @@
</span><span class="cx">                                 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */,
</span><span class="cx">                                 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
</span><span class="cx">                                 62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */,
</span><ins>+                                0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */,
</ins><span class="cx">                                 62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
</span><span class="cx">                                 0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
</span><span class="cx">                                 0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
</span><span class="lines">@@ -10625,6 +10632,7 @@
</span><span class="cx">                                 A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
</span><span class="cx">                                 14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
</span><span class="cx">                                 ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
</span><ins>+                                0FF4B4BC1E88449700DBBE86 /* AirRegLiveness.cpp in Sources */,
</ins><span class="cx">                                 65FB5117184EEE7000C12B70 /* ProtoCallFrame.cpp in Sources */,
</span><span class="cx">                                 1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
</span><span class="cx">                                 79B00CBC1C6AB07E0088C65D /* ProxyConstructor.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3TimingScopecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/B3TimingScope.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 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">@@ -29,23 +29,53 @@
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3Common.h&quot;
</span><del>-#include &lt;wtf/CurrentTime.h&gt;
</del><span class="cx"> #include &lt;wtf/DataLog.h&gt;
</span><ins>+#include &lt;wtf/HashMap.h&gt;
+#include &lt;wtf/Lock.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><ins>+namespace {
+
+class State {
+    WTF_MAKE_NONCOPYABLE(State);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    State() { }
+    
+    Seconds addToTotal(const char* name, Seconds duration)
+    {
+        auto locker = holdLock(lock);
+        return totals.add(name, Seconds(0)).iterator-&gt;value += duration;
+    }
+    
+private:
+    HashMap&lt;const char*, Seconds&gt; totals;
+    Lock lock;
+};
+
+State&amp; state()
+{
+    static Atomic&lt;State*&gt; s_state;
+    return ensurePointer(s_state, [] { return new State(); });
+}
+
+} // anonymous namespace
+
</ins><span class="cx"> TimingScope::TimingScope(const char* name)
</span><span class="cx">     : m_name(name)
</span><span class="cx"> {
</span><span class="cx">     if (shouldMeasurePhaseTiming())
</span><del>-        m_before = monotonicallyIncreasingTimeMS();
</del><ins>+        m_before = MonotonicTime::now();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> TimingScope::~TimingScope()
</span><span class="cx"> {
</span><span class="cx">     if (shouldMeasurePhaseTiming()) {
</span><del>-        double after = monotonicallyIncreasingTimeMS();
-        dataLog(&quot;[B3] &quot;, m_name, &quot; took: &quot;, after - m_before, &quot; ms.\n&quot;);
</del><ins>+        Seconds duration = MonotonicTime::now() - m_before;
+        dataLog(
+            &quot;[B3] &quot;, m_name, &quot; took: &quot;, duration.milliseconds(), &quot; ms &quot;,
+            &quot;(total: &quot;, state().addToTotal(m_name, duration).milliseconds(), &quot; ms).\n&quot;);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3TimingScopeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3TimingScope.h (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3TimingScope.h        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/B3TimingScope.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2017 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">@@ -27,6 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/MonotonicTime.h&gt;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="lines">@@ -39,7 +40,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     const char* m_name;
</span><del>-    double m_before;
</del><ins>+    MonotonicTime m_before;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirAllocateRegistersByGraphColoringcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/air/AirAllocateRegistersByGraphColoring.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -2257,7 +2257,7 @@
</span><span class="cx"> 
</span><span class="cx"> void allocateRegistersByGraphColoring(Code&amp; code)
</span><span class="cx"> {
</span><del>-    PhaseScope phaseScope(code, &quot;Air::allocateRegistersByGraphColoring&quot;);
</del><ins>+    PhaseScope phaseScope(code, &quot;allocateRegistersByGraphColoring&quot;);
</ins><span class="cx">     
</span><span class="cx">     if (false)
</span><span class="cx">         dataLog(&quot;Code before graph coloring:\n&quot;, code);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -79,30 +79,14 @@
</span><span class="cx">     Code&amp; m_code;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-struct RegLivenessAdapter {
-    typedef Reg Thing;
-    typedef BitVector IndexSet;
-
-    RegLivenessAdapter(Code&amp;) { }
-
-    static unsigned numIndices(Code&amp;)
-    {
-        return Reg::maxIndex() + 1;
-    }
-
-    static bool acceptsBank(Bank) { return true; }
-    static bool acceptsRole(Arg::Role) { return true; }
-    static unsigned valueToIndex(Reg reg) { return reg.index(); }
-    Reg indexToValue(unsigned index) { return Reg::fromIndex(index); }
-};
-
</del><ins>+// HEADS UP: The algorithm here is duplicated in AirRegLiveness.h.
</ins><span class="cx"> template&lt;typename Adapter&gt;
</span><del>-class AbstractLiveness : public Adapter {
</del><ins>+class Liveness : public Adapter {
</ins><span class="cx">     struct Workset;
</span><span class="cx"> public:
</span><span class="cx">     typedef typename Adapter::Thing Thing;
</span><span class="cx">     
</span><del>-    AbstractLiveness(Code&amp; code)
</del><ins>+    Liveness(Code&amp; code)
</ins><span class="cx">         : Adapter(code)
</span><span class="cx">         , m_workset(Adapter::numIndices(code))
</span><span class="cx">         , m_liveAtHead(code.size())
</span><span class="lines">@@ -131,7 +115,7 @@
</span><span class="cx">             changed = false;
</span><span class="cx"> 
</span><span class="cx">             for (size_t blockIndex = code.size(); blockIndex--;) {
</span><del>-                BasicBlock* block = code.at(blockIndex);
</del><ins>+                BasicBlock* block = code[blockIndex];
</ins><span class="cx">                 if (!block)
</span><span class="cx">                     continue;
</span><span class="cx"> 
</span><span class="lines">@@ -187,7 +171,7 @@
</span><span class="cx">     // This calculator has to be run in reverse.
</span><span class="cx">     class LocalCalc {
</span><span class="cx">     public:
</span><del>-        LocalCalc(AbstractLiveness&amp; liveness, BasicBlock* block)
</del><ins>+        LocalCalc(Liveness&amp; liveness, BasicBlock* block)
</ins><span class="cx">             : m_liveness(liveness)
</span><span class="cx">             , m_block(block)
</span><span class="cx">         {
</span><span class="lines">@@ -198,40 +182,42 @@
</span><span class="cx">                 workset.add(index);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        struct Iterator {
-            Iterator(Adapter&amp; adapter, IndexSparseSet&lt;UnsafeVectorOverflow&gt;::const_iterator sparceSetIterator)
-                : m_adapter(adapter)
-                , m_sparceSetIterator(sparceSetIterator)
</del><ins>+        class Iterable {
+        public:
+            Iterable(Liveness&amp; liveness)
+                : m_liveness(liveness)
</ins><span class="cx">             {
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            Iterator&amp; operator++()
-            {
-                ++m_sparceSetIterator;
-                return *this;
-            }
</del><ins>+            class iterator {
+            public:
+                iterator(Adapter&amp; adapter, IndexSparseSet&lt;UnsafeVectorOverflow&gt;::const_iterator sparceSetIterator)
+                    : m_adapter(adapter)
+                    , m_sparceSetIterator(sparceSetIterator)
+                {
+                }
</ins><span class="cx"> 
</span><del>-            typename Adapter::Thing operator*() const
-            {
-                return m_adapter.indexToValue(*m_sparceSetIterator);
-            }
</del><ins>+                iterator&amp; operator++()
+                {
+                    ++m_sparceSetIterator;
+                    return *this;
+                }
</ins><span class="cx"> 
</span><del>-            bool operator==(const Iterator&amp; other) { return m_sparceSetIterator == other.m_sparceSetIterator; }
-            bool operator!=(const Iterator&amp; other) { return m_sparceSetIterator != other.m_sparceSetIterator; }
</del><ins>+                typename Adapter::Thing operator*() const
+                {
+                    return m_adapter.indexToValue(*m_sparceSetIterator);
+                }
</ins><span class="cx"> 
</span><del>-        private:
-            Adapter&amp; m_adapter;
-            IndexSparseSet&lt;UnsafeVectorOverflow&gt;::const_iterator m_sparceSetIterator;
-        };
</del><ins>+                bool operator==(const iterator&amp; other) { return m_sparceSetIterator == other.m_sparceSetIterator; }
+                bool operator!=(const iterator&amp; other) { return m_sparceSetIterator != other.m_sparceSetIterator; }
</ins><span class="cx"> 
</span><del>-        struct Iterable {
-            Iterable(AbstractLiveness&amp; liveness)
-                : m_liveness(liveness)
-            {
-            }
</del><ins>+            private:
+                Adapter&amp; m_adapter;
+                IndexSparseSet&lt;UnsafeVectorOverflow&gt;::const_iterator m_sparceSetIterator;
+            };
</ins><span class="cx"> 
</span><del>-            Iterator begin() const { return Iterator(m_liveness, m_liveness.m_workset.begin()); }
-            Iterator end() const { return Iterator(m_liveness, m_liveness.m_workset.end()); }
</del><ins>+            iterator begin() const { return iterator(m_liveness, m_liveness.m_workset.begin()); }
+            iterator end() const { return iterator(m_liveness, m_liveness.m_workset.end()); }
</ins><span class="cx">             
</span><span class="cx">             bool contains(const typename Adapter::Thing&amp; thing) const
</span><span class="cx">             {
</span><span class="lines">@@ -239,7 +225,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">         private:
</span><del>-            AbstractLiveness&amp; m_liveness;
</del><ins>+            Liveness&amp; m_liveness;
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         Iterable live() const
</span><span class="lines">@@ -301,7 +287,7 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">     private:
</span><del>-        AbstractLiveness&amp; m_liveness;
</del><ins>+        Liveness&amp; m_liveness;
</ins><span class="cx">         BasicBlock* m_block;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -313,7 +299,7 @@
</span><span class="cx">     template&lt;typename UnderlyingIterable&gt;
</span><span class="cx">     class Iterable {
</span><span class="cx">     public:
</span><del>-        Iterable(AbstractLiveness&amp; liveness, const UnderlyingIterable&amp; iterable)
</del><ins>+        Iterable(Liveness&amp; liveness, const UnderlyingIterable&amp; iterable)
</ins><span class="cx">             : m_liveness(liveness)
</span><span class="cx">             , m_iterable(iterable)
</span><span class="cx">         {
</span><span class="lines">@@ -327,7 +313,7 @@
</span><span class="cx">             {
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            iterator(AbstractLiveness&amp; liveness, typename UnderlyingIterable::const_iterator iter)
</del><ins>+            iterator(Liveness&amp; liveness, typename UnderlyingIterable::const_iterator iter)
</ins><span class="cx">                 : m_liveness(&amp;liveness)
</span><span class="cx">                 , m_iter(iter)
</span><span class="cx">             {
</span><span class="lines">@@ -356,7 +342,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">         private:
</span><del>-            AbstractLiveness* m_liveness;
</del><ins>+            Liveness* m_liveness;
</ins><span class="cx">             typename UnderlyingIterable::const_iterator m_iter;
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="lines">@@ -369,7 +355,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">     private:
</span><del>-        AbstractLiveness&amp; m_liveness;
</del><ins>+        Liveness&amp; m_liveness;
</ins><span class="cx">         const UnderlyingIterable&amp; m_iterable;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -387,7 +373,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class LocalCalc;
</span><del>-    friend struct LocalCalc::Iterable;
</del><ins>+    friend class LocalCalc::Iterable;
</ins><span class="cx"> 
</span><span class="cx">     IndexSparseSet&lt;UnsafeVectorOverflow&gt; m_workset;
</span><span class="cx">     IndexMap&lt;BasicBlock, Vector&lt;unsigned&gt;&gt; m_liveAtHead;
</span><span class="lines">@@ -395,12 +381,11 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;Bank bank, Arg::Temperature minimumTemperature = Arg::Cold&gt;
</span><del>-using TmpLiveness = AbstractLiveness&lt;TmpLivenessAdapter&lt;bank, minimumTemperature&gt;&gt;;
</del><ins>+using TmpLiveness = Liveness&lt;TmpLivenessAdapter&lt;bank, minimumTemperature&gt;&gt;;
</ins><span class="cx"> 
</span><del>-typedef AbstractLiveness&lt;TmpLivenessAdapter&lt;GP&gt;&gt; GPLiveness;
-typedef AbstractLiveness&lt;TmpLivenessAdapter&lt;FP&gt;&gt; FPLiveness;
-typedef AbstractLiveness&lt;StackSlotLivenessAdapter&gt; StackSlotLiveness;
-typedef AbstractLiveness&lt;RegLivenessAdapter&gt; RegLiveness;
</del><ins>+typedef Liveness&lt;TmpLivenessAdapter&lt;GP&gt;&gt; GPLiveness;
+typedef Liveness&lt;TmpLivenessAdapter&lt;FP&gt;&gt; FPLiveness;
+typedef Liveness&lt;StackSlotLivenessAdapter&gt; StackSlotLiveness;
</ins><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLogRegisterPressurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/air/AirLogRegisterPressure.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> #include &quot;AirArgInlines.h&quot;
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><del>-#include &quot;AirLiveness.h&quot;
</del><ins>+#include &quot;AirRegLiveness.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLowerAfterRegAlloccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/air/AirLowerAfterRegAlloc.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> #include &quot;AirEmitShuffle.h&quot;
</span><span class="cx"> #include &quot;AirInsertionSet.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><del>-#include &quot;AirLiveness.h&quot;
</del><ins>+#include &quot;AirRegLiveness.h&quot;
</ins><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><span class="cx"> #include &quot;B3CCallValue.h&quot;
</span><span class="cx"> #include &quot;B3ValueInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirRegLivenesscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.cpp (0 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -0,0 +1,143 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;AirRegLiveness.h&quot;
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirArgInlines.h&quot;
+#include &quot;AirInstInlines.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+RegLiveness::RegLiveness(Code&amp; code)
+    : m_liveAtHead(code.size())
+    , m_liveAtTail(code.size())
+{
+    // The liveAtTail of each block automatically contains the LateUse's of the terminal.
+    for (BasicBlock* block : code) {
+        RegisterSet&amp; liveAtTail = m_liveAtTail[block];
+            
+        block-&gt;last().forEach&lt;Reg&gt;(
+            [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                if (Arg::isLateUse(role))
+                    liveAtTail.add(reg);
+            });
+    }
+        
+    BitVector dirtyBlocks;
+    for (size_t blockIndex = code.size(); blockIndex--;)
+        dirtyBlocks.set(blockIndex);
+        
+    bool changed;
+    do {
+        changed = false;
+            
+        for (size_t blockIndex = code.size(); blockIndex--;) {
+            BasicBlock* block = code[blockIndex];
+            if (!block)
+                continue;
+                
+            if (!dirtyBlocks.quickClear(blockIndex))
+                continue;
+                
+            LocalCalc localCalc(*this, block);
+            for (size_t instIndex = block-&gt;size(); instIndex--;)
+                localCalc.execute(instIndex);
+                
+            // Handle the early def's of the first instruction.
+            block-&gt;at(0).forEach&lt;Reg&gt;(
+                [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                    if (Arg::isEarlyDef(role))
+                        localCalc.m_workset.remove(reg);
+                });
+                
+            RegisterSet&amp; liveAtHead = m_liveAtHead[block];
+            if (liveAtHead.subsumes(localCalc.m_workset))
+                continue;
+                
+            liveAtHead.merge(localCalc.m_workset);
+                
+            for (BasicBlock* predecessor : block-&gt;predecessors()) {
+                RegisterSet&amp; liveAtTail = m_liveAtTail[predecessor];
+                if (liveAtTail.subsumes(localCalc.m_workset))
+                    continue;
+                    
+                liveAtTail.merge(localCalc.m_workset);
+                dirtyBlocks.quickSet(predecessor-&gt;index());
+                changed = true;
+            }
+        }
+    } while (changed);
+}
+
+RegLiveness::~RegLiveness()
+{
+}
+
+void RegLiveness::LocalCalc::execute(unsigned instIndex)
+{
+    Inst&amp; inst = m_block-&gt;at(instIndex);
+            
+    // First handle the early def's of the next instruction.
+    if (instIndex + 1 &lt; m_block-&gt;size()) {
+        Inst&amp; nextInst = m_block-&gt;at(instIndex + 1);
+        nextInst.forEach&lt;Reg&gt;(
+            [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                if (Arg::isEarlyDef(role))
+                    m_workset.remove(reg);
+            });
+    }
+            
+    // Then handle def's.
+    inst.forEach&lt;Reg&gt;(
+        [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+            if (Arg::isLateDef(role))
+                m_workset.remove(reg);
+        });
+            
+    // Then handle use's.
+    inst.forEach&lt;Reg&gt;(
+        [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+            if (Arg::isEarlyUse(role))
+                m_workset.add(reg);
+        });
+            
+    // And finally, handle the late use's of the previous instruction.
+    if (instIndex) {
+        Inst&amp; prevInst = m_block-&gt;at(instIndex - 1);
+        prevInst.forEach&lt;Reg&gt;(
+            [&amp;] (Reg&amp; reg, Arg::Role role, Bank, Width) {
+                if (Arg::isLateUse(role))
+                    m_workset.add(reg);
+            });
+    }
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirRegLivenessh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h (0 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/b3/air/AirRegLiveness.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -0,0 +1,94 @@
</span><ins>+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+#include &quot;AirBasicBlock.h&quot;
+#include &quot;AirCode.h&quot;
+#include &quot;AirInst.h&quot;
+#include &quot;RegisterSet.h&quot;
+
+namespace JSC { namespace B3 { namespace Air {
+
+// Although we could trivially adapt Air::Liveness&lt;&gt; to work with Reg, this would not be so
+// efficient. There is a small number of registers, so it's much better to use bitvectors for
+// register liveness. This is a specialization of Liveness&lt;&gt; that uses bitvectors directly.
+// This makes the code sufficiently different that it didn't make sense to try to share code.
+class RegLiveness {
+public:
+    typedef Reg Thing;
+    
+    RegLiveness(Code&amp; code);
+    ~RegLiveness();
+    
+    // This calculator has to be run in reverse.
+    class LocalCalc {
+    public:
+        LocalCalc(RegLiveness&amp; liveness, BasicBlock* block)
+            : m_block(block)
+            , m_workset(liveness.m_liveAtTail[block])
+        {
+        }
+        
+        const RegisterSet&amp; live() const
+        {
+            return m_workset;
+        }
+        
+        bool isLive(Reg reg) const
+        {
+            return m_workset.contains(reg);
+        }
+        
+        void execute(unsigned instIndex);
+        
+    private:
+        friend class RegLiveness;
+        
+        BasicBlock* m_block;
+        RegisterSet m_workset;
+    };
+    
+    const RegisterSet&amp; liveAtHead(BasicBlock* block) const
+    {
+        return m_liveAtHead[block];
+    }
+    
+    const RegisterSet&amp; liveAtTail(BasicBlock* block) const
+    {
+        return m_liveAtTail[block];
+    }
+    
+private:
+    IndexMap&lt;BasicBlock, RegisterSet&gt; m_liveAtHead;
+    IndexMap&lt;BasicBlock, RegisterSet&gt; m_liveAtTail;
+};
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> #include &quot;AirArgInlines.h&quot;
</span><span class="cx"> #include &quot;AirCode.h&quot;
</span><span class="cx"> #include &quot;AirInstInlines.h&quot;
</span><del>-#include &quot;AirLiveness.h&quot;
</del><ins>+#include &quot;AirRegLiveness.h&quot;
</ins><span class="cx"> #include &quot;AirPhaseScope.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 { namespace Air {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -36,6 +36,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+typedef Bitmap&lt;MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1&gt; RegisterBitmap;
+
</ins><span class="cx"> class RegisterSet {
</span><span class="cx"> public:
</span><span class="cx">     template&lt;typename... Regs&gt;
</span><span class="lines">@@ -99,10 +101,17 @@
</span><span class="cx">             set(reg);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Also allow add/remove/contains terminology, which means the same thing as set/clear/get.
+    void add(Reg reg) { set(reg); }
+    void remove(Reg reg) { clear(reg); }
+    bool contains(Reg reg) const { return get(reg); }
+    
</ins><span class="cx">     void merge(const RegisterSet&amp; other) { m_bits.merge(other.m_bits); }
</span><span class="cx">     void filter(const RegisterSet&amp; other) { m_bits.filter(other.m_bits); }
</span><span class="cx">     void exclude(const RegisterSet&amp; other) { m_bits.exclude(other.m_bits); }
</span><span class="cx">     
</span><ins>+    bool subsumes(const RegisterSet&amp; other) const { return m_bits.subsumes(other.m_bits); }
+    
</ins><span class="cx">     size_t numberOfSetGPRs() const;
</span><span class="cx">     size_t numberOfSetFPRs() const;
</span><span class="cx">     size_t numberOfSetRegisters() const { return m_bits.count(); }
</span><span class="lines">@@ -149,6 +158,42 @@
</span><span class="cx">             });
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    class iterator {
+    public:
+        iterator()
+        {
+        }
+        
+        iterator(const RegisterBitmap::iterator&amp; iter)
+            : m_iter(iter)
+        {
+        }
+        
+        Reg operator*() const { return Reg::fromIndex(*m_iter); }
+        
+        iterator&amp; operator++()
+        {
+            ++m_iter;
+            return *this;
+        }
+        
+        bool operator==(const iterator&amp; other)
+        {
+            return m_iter == other.m_iter;
+        }
+        
+        bool operator!=(const iterator&amp; other)
+        {
+            return !(*this == other);
+        }
+        
+    private:
+        RegisterBitmap::iterator m_iter;
+    };
+    
+    iterator begin() const { return iterator(m_bits.begin()); }
+    iterator end() const { return iterator(m_bits.end()); }
+    
</ins><span class="cx"> private:
</span><span class="cx">     void setAny(Reg reg) { set(reg); }
</span><span class="cx">     void setAny(const RegisterSet&amp; set) { merge(set); }
</span><span class="lines">@@ -166,7 +211,7 @@
</span><span class="cx">     static const unsigned hashSpecialBitIndex = fprOffset + MacroAssembler::numFPRs;
</span><span class="cx">     static const unsigned deletedBitIndex = 0;
</span><span class="cx">     
</span><del>-    Bitmap&lt;MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1&gt; m_bits;
</del><ins>+    RegisterBitmap m_bits;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct RegisterSetHash {
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/ChangeLog        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2017-03-26  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Air should use RegisterSet for RegLiveness
+        https://bugs.webkit.org/show_bug.cgi?id=170108
+
+        Reviewed by Yusuke Suzuki.
+
+        * wtf/Atomics.h:
+        (WTF::ensurePointer): This is a useful replacement for std::once, which requires less fencing.
+        * wtf/Bitmap.h: Add more utilities.
+        (WTF::Bitmap::iterator::iterator): An iterator for set bits.
+        (WTF::Bitmap::iterator::operator*):
+        (WTF::Bitmap::iterator::operator++):
+        (WTF::Bitmap::iterator::operator==):
+        (WTF::Bitmap::iterator::operator!=):
+        (WTF::Bitmap::begin):
+        (WTF::Bitmap::end):
+        (WTF::WordType&gt;::subsumes): a.subsumes(b) if all of b's set bits are set in a.
+        (WTF::WordType&gt;::findBit): find next set or clear bit.
+
</ins><span class="cx"> 2017-03-24  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         WebAssembly: store state in TLS instead of on VM
</span></span></pre></div>
<a id="trunkSourceWTFwtfAtomicsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Atomics.h (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Atomics.h        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/wtf/Atomics.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -519,6 +519,23 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T, typename Func&gt;
+ALWAYS_INLINE T&amp; ensurePointer(Atomic&lt;T*&gt;&amp; pointer, const Func&amp; func)
+{
+    for (;;) {
+        T* oldValue = pointer.load(std::memory_order_relaxed);
+        if (oldValue) {
+            // On all sensible CPUs, we get an implicit dependency-based load-load barrier when
+            // loading this.
+            return *oldValue;
+        }
+        T* newValue = func();
+        if (pointer.compareExchangeWeak(oldValue, newValue))
+            return *newValue;
+        delete newValue;
+    }
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::Atomic;
</span><span class="lines">@@ -528,6 +545,7 @@
</span><span class="cx"> using WTF::consume;
</span><span class="cx"> using WTF::dependency;
</span><span class="cx"> using WTF::dependencyWith;
</span><ins>+using WTF::ensurePointer;
</ins><span class="cx"> using WTF::nullDependency;
</span><span class="cx"> 
</span><span class="cx"> #endif // Atomics_h
</span></span></pre></div>
<a id="trunkSourceWTFwtfBitmaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Bitmap.h (214407 => 214408)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Bitmap.h        2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/wtf/Bitmap.h        2017-03-26 21:39:27 UTC (rev 214408)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2010, 2016 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2010-2017 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -59,9 +59,54 @@
</span><span class="cx">     void filter(const Bitmap&amp;);
</span><span class="cx">     void exclude(const Bitmap&amp;);
</span><span class="cx">     
</span><ins>+    bool subsumes(const Bitmap&amp;) const;
+    
</ins><span class="cx">     template&lt;typename Func&gt;
</span><span class="cx">     void forEachSetBit(const Func&amp;) const;
</span><span class="cx">     
</span><ins>+    size_t findBit(size_t startIndex, bool value) const;
+    
+    class iterator {
+    public:
+        iterator()
+            : m_bitmap(nullptr)
+            , m_index(0)
+        {
+        }
+        
+        iterator(const Bitmap&amp; bitmap, size_t index)
+            : m_bitmap(&amp;bitmap)
+            , m_index(index)
+        {
+        }
+        
+        size_t operator*() const { return m_index; }
+        
+        iterator&amp; operator++()
+        {
+            m_index = m_bitmap-&gt;findBit(m_index + 1, true);
+            return *this;
+        }
+        
+        bool operator==(const iterator&amp; other) const
+        {
+            return m_index == other.m_index;
+        }
+        
+        bool operator!=(const iterator&amp; other) const
+        {
+            return !(*this == other);
+        }
+
+    private:
+        const Bitmap* m_bitmap;
+        size_t m_index;
+    };
+    
+    // Use this to iterate over set bits.
+    iterator begin() const { return iterator(*this, findBit(0, true)); }
+    iterator end() const { return iterator(*this, bitmapSize); }
+    
</ins><span class="cx">     void mergeAndClear(Bitmap&amp;);
</span><span class="cx">     void setAndClear(Bitmap&amp;);
</span><span class="cx">     
</span><span class="lines">@@ -258,6 +303,18 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;size_t bitmapSize, typename WordType&gt;
</span><ins>+inline bool Bitmap&lt;bitmapSize, WordType&gt;::subsumes(const Bitmap&amp; other) const
+{
+    for (size_t i = 0; i &lt; words; ++i) {
+        WordType myBits = bits[i];
+        WordType otherBits = other.bits[i];
+        if ((myBits | otherBits) != myBits)
+            return false;
+    }
+    return true;
+}
+
+template&lt;size_t bitmapSize, typename WordType&gt;
</ins><span class="cx"> template&lt;typename Func&gt;
</span><span class="cx"> inline void Bitmap&lt;bitmapSize, WordType&gt;::forEachSetBit(const Func&amp; func) const
</span><span class="cx"> {
</span><span class="lines">@@ -275,6 +332,28 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;size_t bitmapSize, typename WordType&gt;
</span><ins>+inline size_t Bitmap&lt;bitmapSize, WordType&gt;::findBit(size_t startIndex, bool value) const
+{
+    WordType skipValue = -(static_cast&lt;WordType&gt;(value) ^ 1);
+    size_t wordIndex = startIndex / wordSize;
+    size_t startIndexInWord = startIndex - wordIndex * wordSize;
+    
+    while (wordIndex &lt; words) {
+        WordType word = bits[wordIndex];
+        if (word != skipValue) {
+            size_t index = startIndexInWord;
+            if (findBitInWord(word, index, wordSize, value))
+                return wordIndex * wordSize + index;
+        }
+        
+        wordIndex++;
+        startIndexInWord = 0;
+    }
+    
+    return bitmapSize;
+}
+
+template&lt;size_t bitmapSize, typename WordType&gt;
</ins><span class="cx"> inline void Bitmap&lt;bitmapSize, WordType&gt;::mergeAndClear(Bitmap&amp; other)
</span><span class="cx"> {
</span><span class="cx">     for (size_t i = 0; i &lt; words; ++i) {
</span></span></pre>
</div>
</div>

</body>
</html>