<!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>[194834] 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/194834">194834</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-01-10 16:58:34 -0800 (Sun, 10 Jan 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>It should be possible to run liveness over registers without also tracking Tmps
https://bugs.webkit.org/show_bug.cgi?id=152963

Reviewed by Saam Barati.

Source/JavaScriptCore:

This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
code like that for handling cold function calls. It also makes code like that somewhat more
scalable, since we're no longer using HashSets.

Currently, the way we track sets of registers is with a BitVector. Normally, we use the
RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
the liveness analysis, everything gets turned into an index. So, we want to use BitVector
directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
think that this is good, because the lack of set methods (add/remove/contains) has caused
bugs in the past. This makes BitVector have methods both for set operations on bits and array
operations on bits. I think that's good, since BitVector gets used in both contexts.

* b3/B3IndexSet.h:
(JSC::B3::IndexSet::Iterable::iterator::iterator):
(JSC::B3::IndexSet::Iterable::begin):
(JSC::B3::IndexSet::dump):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::ForEach&lt;Tmp&gt;::forEach):
(JSC::B3::Air::ForEach&lt;Arg&gt;::forEach):
(JSC::B3::Air::ForEach&lt;Reg&gt;::forEach):
(JSC::B3::Air::Inst::forEach):
* b3/air/AirLiveness.h:
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
(JSC::B3::Air::RegLivenessAdapter::maxIndex):
(JSC::B3::Air::RegLivenessAdapter::acceptsType):
(JSC::B3::Air::RegLivenessAdapter::valueToIndex):
(JSC::B3::Air::RegLivenessAdapter::indexToValue):
* b3/air/AirReportUsedRegisters.cpp:
(JSC::B3::Air::reportUsedRegisters):
* jit/Reg.h:
(JSC::Reg::next):
(JSC::Reg::index):
(JSC::Reg::maxIndex):
(JSC::Reg::isSet):
(JSC::Reg::operator bool):
* jit/RegisterSet.h:
(JSC::RegisterSet::forEach):

Source/WTF:

Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
places. This also makes BitVector a drop-in replacement for HashSet&lt;unsigned&gt; in a lot of
places.

Also made the iterator methods of BitVector live on BitVector directly rather than behind the
thing returned from setBits(). This makes sense since that makes BitVector even more of a
drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
BitVector other than this, so it doesn't make sense to make it harder to access.

* wtf/BitVector.h:
(WTF::BitVector::get):
(WTF::BitVector::contains):
(WTF::BitVector::set):
(WTF::BitVector::add):
(WTF::BitVector::ensureSizeAndSet):
(WTF::BitVector::clear):
(WTF::BitVector::remove):
(WTF::BitVector::hash):
(WTF::BitVector::iterator::iterator):
(WTF::BitVector::iterator::operator*):
(WTF::BitVector::iterator::operator++):
(WTF::BitVector::iterator::operator==):
(WTF::BitVector::iterator::operator!=):
(WTF::BitVector::begin):
(WTF::BitVector::end):
(WTF::BitVector::bitsInPointer):
(WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
(WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
(WTF::BitVector::SetBitsIterable::begin): Deleted.
(WTF::BitVector::SetBitsIterable::end): Deleted.
(WTF::BitVector::setBits): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3IndexSeth">trunk/Source/JavaScriptCore/b3/B3IndexSet.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirInstInlinesh">trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirLivenessh">trunk/Source/JavaScriptCore/b3/air/AirLiveness.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp">trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRegh">trunk/Source/JavaScriptCore/jit/Reg.h</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="#trunkSourceWTFwtfBitVectorh">trunk/Source/WTF/wtf/BitVector.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,3 +1,49 @@
</span><ins>+2016-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        It should be possible to run liveness over registers without also tracking Tmps
+        https://bugs.webkit.org/show_bug.cgi?id=152963
+
+        Reviewed by Saam Barati.
+
+        This adds a RegLivenessAdapter so that we can run Liveness over registers. This makes it
+        easier to write certain kinds of phases, like ReportUsedRegisters. I anticipate writing more
+        code like that for handling cold function calls. It also makes code like that somewhat more
+        scalable, since we're no longer using HashSets.
+
+        Currently, the way we track sets of registers is with a BitVector. Normally, we use the
+        RegisterSet class, which wraps BitVector, so that we can add()/contains() on Reg's. But in
+        the liveness analysis, everything gets turned into an index. So, we want to use BitVector
+        directly. To do that, I needed to make the BitVector API look a bit more like a set API. I
+        think that this is good, because the lack of set methods (add/remove/contains) has caused
+        bugs in the past. This makes BitVector have methods both for set operations on bits and array
+        operations on bits. I think that's good, since BitVector gets used in both contexts.
+
+        * b3/B3IndexSet.h:
+        (JSC::B3::IndexSet::Iterable::iterator::iterator):
+        (JSC::B3::IndexSet::Iterable::begin):
+        (JSC::B3::IndexSet::dump):
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::ForEach&lt;Tmp&gt;::forEach):
+        (JSC::B3::Air::ForEach&lt;Arg&gt;::forEach):
+        (JSC::B3::Air::ForEach&lt;Reg&gt;::forEach):
+        (JSC::B3::Air::Inst::forEach):
+        * b3/air/AirLiveness.h:
+        (JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter):
+        (JSC::B3::Air::RegLivenessAdapter::maxIndex):
+        (JSC::B3::Air::RegLivenessAdapter::acceptsType):
+        (JSC::B3::Air::RegLivenessAdapter::valueToIndex):
+        (JSC::B3::Air::RegLivenessAdapter::indexToValue):
+        * b3/air/AirReportUsedRegisters.cpp:
+        (JSC::B3::Air::reportUsedRegisters):
+        * jit/Reg.h:
+        (JSC::Reg::next):
+        (JSC::Reg::index):
+        (JSC::Reg::maxIndex):
+        (JSC::Reg::isSet):
+        (JSC::Reg::operator bool):
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::forEach):
+
</ins><span class="cx"> 2016-01-10  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Make branchMul functional in ARM B3 and minor fixes
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3IndexSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3IndexSet.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3IndexSet.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/b3/B3IndexSet.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -85,7 +85,7 @@
</span><span class="cx">             {
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            iterator(const CollectionType&amp; collection, BitVector::SetBitsIterable::iterator iter)
</del><ins>+            iterator(const CollectionType&amp; collection, BitVector::iterator iter)
</ins><span class="cx">                 : m_collection(&amp;collection)
</span><span class="cx">                 , m_iter(iter)
</span><span class="cx">             {
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx"> 
</span><span class="cx">         private:
</span><span class="cx">             const CollectionType* m_collection;
</span><del>-            BitVector::SetBitsIterable::iterator m_iter;
</del><ins>+            BitVector::iterator m_iter;
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         iterator begin() const { return iterator(m_collection, m_set.begin()); }
</span><span class="lines">@@ -141,7 +141,7 @@
</span><span class="cx">     void dump(PrintStream&amp; out) const
</span><span class="cx">     {
</span><span class="cx">         CommaPrinter comma;
</span><del>-        for (size_t index : indices().setBits())
</del><ins>+        for (size_t index : indices())
</ins><span class="cx">             out.print(comma, T::dumpPrefix, index);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirInstInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/b3/air/AirInstInlines.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx">         inst.forEachTmp(functor);
</span><span class="cx">     }
</span><span class="cx"> };
</span><ins>+
</ins><span class="cx"> template&lt;&gt; struct ForEach&lt;Arg&gt; {
</span><span class="cx">     template&lt;typename Functor&gt;
</span><span class="cx">     static void forEach(Inst&amp; inst, const Functor&amp; functor)
</span><span class="lines">@@ -50,6 +51,7 @@
</span><span class="cx">         inst.forEachArg(functor);
</span><span class="cx">     }
</span><span class="cx"> };
</span><ins>+
</ins><span class="cx"> template&lt;&gt; struct ForEach&lt;StackSlot*&gt; {
</span><span class="cx">     template&lt;typename Functor&gt;
</span><span class="cx">     static void forEach(Inst&amp; inst, const Functor&amp; functor)
</span><span class="lines">@@ -72,6 +74,22 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+template&lt;&gt; struct ForEach&lt;Reg&gt; {
+    template&lt;typename Functor&gt;
+    static void forEach(Inst&amp; inst, const Functor&amp; functor)
+    {
+        inst.forEachTmp(
+            [&amp;] (Tmp&amp; tmp, Arg::Role role, Arg::Type type, Arg::Width width) {
+                if (!tmp.isReg())
+                    return;
+
+                Reg reg = tmp.reg();
+                functor(reg, role, type, width);
+                tmp = Tmp(reg);
+            });
+    }
+};
+
</ins><span class="cx"> template&lt;typename Thing, typename Functor&gt;
</span><span class="cx"> void Inst::forEach(const Functor&amp; functor)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirLivenessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirLiveness.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/b3/air/AirLiveness.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -76,6 +76,22 @@
</span><span class="cx">     Code&amp; m_code;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct RegLivenessAdapter {
+    typedef Reg Thing;
+    typedef BitVector IndexSet;
+
+    RegLivenessAdapter(Code&amp;) { }
+
+    static unsigned maxIndex(Code&amp;)
+    {
+        return Reg::maxIndex();
+    }
+
+    static bool acceptsType(Arg::Type) { return true; }
+    static unsigned valueToIndex(Reg reg) { return reg.index(); }
+    Reg indexToValue(unsigned index) { return Reg::fromIndex(index); }
+};
+
</ins><span class="cx"> template&lt;typename Adapter&gt;
</span><span class="cx"> class AbstractLiveness : private Adapter {
</span><span class="cx">     struct Workset;
</span><span class="lines">@@ -344,6 +360,7 @@
</span><span class="cx"> typedef AbstractLiveness&lt;TmpLivenessAdapter&lt;Arg::GP&gt;&gt; GPLiveness;
</span><span class="cx"> typedef AbstractLiveness&lt;TmpLivenessAdapter&lt;Arg::FP&gt;&gt; FPLiveness;
</span><span class="cx"> typedef AbstractLiveness&lt;StackSlotLivenessAdapter&gt; StackSlotLiveness;
</span><ins>+typedef AbstractLiveness&lt;RegLivenessAdapter&gt; RegLiveness;
</ins><span class="cx"> 
</span><span class="cx"> } } } // namespace JSC::B3::Air
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3airAirReportUsedRegisterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/b3/air/AirReportUsedRegisters.cpp        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -39,31 +39,20 @@
</span><span class="cx"> {
</span><span class="cx">     PhaseScope phaseScope(code, &quot;reportUsedRegisters&quot;);
</span><span class="cx"> 
</span><del>-    // FIXME: We should tell liveness to only track Regs.
-    // https://bugs.webkit.org/show_bug.cgi?id=150751
-    GPLiveness gpLiveness(code);
-    FPLiveness fpLiveness(code);
</del><ins>+    RegLiveness liveness(code);
</ins><span class="cx"> 
</span><span class="cx">     for (BasicBlock* block : code) {
</span><del>-        GPLiveness::LocalCalc gpLocalCalc(gpLiveness, block);
-        FPLiveness::LocalCalc fpLocalCalc(fpLiveness, block);
</del><ins>+        RegLiveness::LocalCalc localCalc(liveness, block);
</ins><span class="cx"> 
</span><span class="cx">         for (unsigned instIndex = block-&gt;size(); instIndex--;) {
</span><span class="cx">             Inst&amp; inst = block-&gt;at(instIndex);
</span><span class="cx">             if (inst.hasSpecial()) {
</span><span class="cx">                 RegisterSet registerSet;
</span><del>-                for (Tmp tmp : gpLocalCalc.live()) {
-                    ASSERT(tmp.isGP());
-                    registerSet.set(tmp.reg());
-                }
-                for (Tmp tmp : fpLocalCalc.live()) {
-                    ASSERT(tmp.isFP());
-                    registerSet.set(tmp.reg());
-                }
</del><ins>+                for (Reg reg : localCalc.live())
+                    registerSet.set(reg);
</ins><span class="cx">                 inst.reportUsedRegisters(registerSet);
</span><span class="cx">             }
</span><del>-            gpLocalCalc.execute(instIndex);
-            fpLocalCalc.execute(instIndex);
</del><ins>+            localCalc.execute(instIndex);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Reg.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Reg.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/jit/Reg.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -103,6 +103,11 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unsigned index() const { return m_index; }
</span><ins>+
+    static unsigned maxIndex()
+    {
+        return last().index();
+    }
</ins><span class="cx">     
</span><span class="cx">     bool isSet() const { return m_index != invalid(); }
</span><span class="cx">     explicit operator bool() const { return isSet(); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRegisterSeth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/RegisterSet.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/JavaScriptCore/jit/RegisterSet.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -124,7 +124,7 @@
</span><span class="cx">     template&lt;typename Functor&gt;
</span><span class="cx">     void forEach(const Functor&amp; functor) const
</span><span class="cx">     {
</span><del>-        for (size_t index : m_vector.setBits())
</del><ins>+        for (size_t index : m_vector)
</ins><span class="cx">             functor(Reg::fromIndex(index));
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/WTF/ChangeLog        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,3 +1,46 @@
</span><ins>+2016-01-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        It should be possible to run liveness over registers without also tracking Tmps
+        https://bugs.webkit.org/show_bug.cgi?id=152963
+
+        Reviewed by Saam Barati.
+
+        Add set methods (add/contains/remove) to BitVector, since it gets used as a set in a lot of
+        places. This also makes BitVector a drop-in replacement for HashSet&lt;unsigned&gt; in a lot of
+        places.
+
+        Also made the iterator methods of BitVector live on BitVector directly rather than behind the
+        thing returned from setBits(). This makes sense since that makes BitVector even more of a
+        drop-in for HashSet. It's not harmful since we've never added any other mode of iterating a
+        BitVector other than this, so it doesn't make sense to make it harder to access.
+
+        * wtf/BitVector.h:
+        (WTF::BitVector::get):
+        (WTF::BitVector::contains):
+        (WTF::BitVector::set):
+        (WTF::BitVector::add):
+        (WTF::BitVector::ensureSizeAndSet):
+        (WTF::BitVector::clear):
+        (WTF::BitVector::remove):
+        (WTF::BitVector::hash):
+        (WTF::BitVector::iterator::iterator):
+        (WTF::BitVector::iterator::operator*):
+        (WTF::BitVector::iterator::operator++):
+        (WTF::BitVector::iterator::operator==):
+        (WTF::BitVector::iterator::operator!=):
+        (WTF::BitVector::begin):
+        (WTF::BitVector::end):
+        (WTF::BitVector::bitsInPointer):
+        (WTF::BitVector::SetBitsIterable::SetBitsIterable): Deleted.
+        (WTF::BitVector::SetBitsIterable::iterator::iterator): Deleted.
+        (WTF::BitVector::SetBitsIterable::iterator::operator*): Deleted.
+        (WTF::BitVector::SetBitsIterable::iterator::operator++): Deleted.
+        (WTF::BitVector::SetBitsIterable::iterator::operator==): Deleted.
+        (WTF::BitVector::SetBitsIterable::iterator::operator!=): Deleted.
+        (WTF::BitVector::SetBitsIterable::begin): Deleted.
+        (WTF::BitVector::SetBitsIterable::end): Deleted.
+        (WTF::BitVector::setBits): Deleted.
+
</ins><span class="cx"> 2016-01-09  Andreas Kling  &lt;akling@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Use NeverDestroyed instead of DEPRECATED_DEFINE_STATIC_LOCAL
</span></span></pre></div>
<a id="trunkSourceWTFwtfBitVectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/BitVector.h (194833 => 194834)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/BitVector.h        2016-01-10 22:33:01 UTC (rev 194833)
+++ trunk/Source/WTF/wtf/BitVector.h        2016-01-11 00:58:34 UTC (rev 194834)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -151,6 +151,11 @@
</span><span class="cx">             return false;
</span><span class="cx">         return quickGet(bit);
</span><span class="cx">     }
</span><ins>+
+    bool contains(size_t bit) const
+    {
+        return get(bit);
+    }
</ins><span class="cx">     
</span><span class="cx">     bool set(size_t bit)
</span><span class="cx">     {
</span><span class="lines">@@ -158,6 +163,13 @@
</span><span class="cx">         return quickSet(bit);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // This works like the add methods of sets. Instead of returning the previous value, like set(),
+    // it returns whether the bit transitioned from false to true.
+    bool add(size_t bit)
+    {
+        return !set(bit);
+    }
+
</ins><span class="cx">     bool ensureSizeAndSet(size_t bit, size_t size)
</span><span class="cx">     {
</span><span class="cx">         ensureSize(size);
</span><span class="lines">@@ -170,6 +182,11 @@
</span><span class="cx">             return false;
</span><span class="cx">         return quickClear(bit);
</span><span class="cx">     }
</span><ins>+
+    bool remove(size_t bit)
+    {
+        return clear(bit);
+    }
</ins><span class="cx">     
</span><span class="cx">     bool set(size_t bit, bool value)
</span><span class="cx">     {
</span><span class="lines">@@ -269,58 +286,46 @@
</span><span class="cx">         return IntHash&lt;uintptr_t&gt;::hash(value);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    class SetBitsIterable {
</del><ins>+    class iterator {
</ins><span class="cx">     public:
</span><del>-        SetBitsIterable(const BitVector&amp; bitVector)
-            : m_bitVector(bitVector)
</del><ins>+        iterator()
+            : m_bitVector(nullptr)
+            , m_index(0)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        class iterator {
-        public:
-            iterator()
-                : m_bitVector(nullptr)
-                , m_index(0)
-            {
-            }
-            
-            iterator(const BitVector&amp; bitVector, size_t index)
-                : m_bitVector(&amp;bitVector)
-                , m_index(index)
-            {
-            }
-            
-            size_t operator*() const { return m_index; }
-            
-            iterator&amp; operator++()
-            {
-                m_index = m_bitVector-&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 BitVector* m_bitVector;
-            size_t m_index;
-        };
</del><ins>+        iterator(const BitVector&amp; bitVector, size_t index)
+            : m_bitVector(&amp;bitVector)
+            , m_index(index)
+        {
+        }
</ins><span class="cx">         
</span><del>-        iterator begin() const { return iterator(m_bitVector, m_bitVector.findBit(0, true)); }
-        iterator end() const { return iterator(m_bitVector, m_bitVector.size()); }
</del><ins>+        size_t operator*() const { return m_index; }
</ins><span class="cx">         
</span><ins>+        iterator&amp; operator++()
+        {
+            m_index = m_bitVector-&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);
+        }
</ins><span class="cx">     private:
</span><del>-        const BitVector&amp; m_bitVector;
</del><ins>+        const BitVector* m_bitVector;
+        size_t m_index;
</ins><span class="cx">     };
</span><del>-    
-    SetBitsIterable setBits() const { return SetBitsIterable(*this); }
-    
</del><ins>+
+    // Use this to iterate over set bits.
+    iterator begin() const { return iterator(*this, findBit(0, true)); }
+    iterator end() const { return iterator(*this, size()); }
+        
</ins><span class="cx"> private:
</span><span class="cx">     static unsigned bitsInPointer()
</span><span class="cx">     {
</span></span></pre>
</div>
</div>

</body>
</html>