<!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>[181467] 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/181467">181467</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-03-12 18:57:59 -0700 (Thu, 12 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Bytecode liveness analysis should have more lambdas and fewer sets
https://bugs.webkit.org/show_bug.cgi?id=142647

Reviewed by Mark Lam.
        
Source/JavaScriptCore:

In bug 141174 I'll need to identify all of the bytecode kill sites. This requires hooking into
the bytecode analysis' stepOverFunction method, except in such a way that we observe uses that
are not in outs. This refactors stepOverFunction so that you can pass it use/def functors that
can either be used to propagate outs (as we do right now) or to additionally detect kills or
whatever else.
        
In order to achieve this, the liveness analysis was moved off of maintaining uses/defs
bitvectors. This wasn't helping the abstraction and was probably inefficient. The new code
should be a bit faster since we don't have to clear uses/defs bitvectors on each instruction. On
the other hand, being able to intercept each use means that our code for exception handlers is
no longer a bitwise-merge; it requires finding set bits. Fortunately, this code only kicks in
for instructions inside a try, and its performance is O(live at catch), so that's probably not
bad.

* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::indexForOperand):
(JSC::stepOverInstruction):
(JSC::computeLocalLivenessForBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::computeFullLiveness):
(JSC::setForOperand): Deleted.
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:

Source/WTF:

Add a method for iterating each set bit in a FastBitVector. Uses a functor as a callback since
this allows for a more efficient algorithm.

* wtf/FastBitVector.h:
(WTF::FastBitVector::forEachSetBit):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysiscpp">trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfFastBitVectorh">trunk/Source/WTF/wtf/FastBitVector.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -1,3 +1,35 @@
</span><ins>+2015-03-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Bytecode liveness analysis should have more lambdas and fewer sets
+        https://bugs.webkit.org/show_bug.cgi?id=142647
+
+        Reviewed by Mark Lam.
+        
+        In bug 141174 I'll need to identify all of the bytecode kill sites. This requires hooking into
+        the bytecode analysis' stepOverFunction method, except in such a way that we observe uses that
+        are not in outs. This refactors stepOverFunction so that you can pass it use/def functors that
+        can either be used to propagate outs (as we do right now) or to additionally detect kills or
+        whatever else.
+        
+        In order to achieve this, the liveness analysis was moved off of maintaining uses/defs
+        bitvectors. This wasn't helping the abstraction and was probably inefficient. The new code
+        should be a bit faster since we don't have to clear uses/defs bitvectors on each instruction. On
+        the other hand, being able to intercept each use means that our code for exception handlers is
+        no longer a bitwise-merge; it requires finding set bits. Fortunately, this code only kicks in
+        for instructions inside a try, and its performance is O(live at catch), so that's probably not
+        bad.
+
+        * bytecode/BytecodeLivenessAnalysis.cpp:
+        (JSC::indexForOperand):
+        (JSC::stepOverInstruction):
+        (JSC::computeLocalLivenessForBytecodeOffset):
+        (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
+        (JSC::setForOperand): Deleted.
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+
</ins><span class="cx"> 2015-03-12  Ryosuke Niwa  &lt;rniwa@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         &quot;this&quot; should be in TDZ until super is called in the constructor of a derived class
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysiscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 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">@@ -58,37 +58,15 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void setForOperand(CodeBlock* codeBlock, FastBitVector&amp; bits, int operand)
</del><ins>+static unsigned indexForOperand(CodeBlock* codeBlock, int operand)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isValidRegisterForLiveness(codeBlock, operand));
</span><span class="cx">     VirtualRegister virtualReg(operand);
</span><span class="cx">     if (virtualReg.offset() &gt; codeBlock-&gt;captureStart())
</span><del>-        bits.set(virtualReg.toLocal());
-    else
-        bits.set(virtualReg.toLocal() - codeBlock-&gt;captureCount());
</del><ins>+        return virtualReg.toLocal();
+    return virtualReg.toLocal() - codeBlock-&gt;captureCount();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-namespace {
-
-class SetBit {
-public:
-    SetBit(FastBitVector&amp; bits)
-        : m_bits(bits)
-    {
-    }
-    
-    void operator()(CodeBlock* codeBlock, Instruction*, OpcodeID, int operand)
-    {
-        if (isValidRegisterForLiveness(codeBlock, operand))
-            setForOperand(codeBlock, m_bits, operand);
-    }
-    
-private:
-    FastBitVector&amp; m_bits;
-};
-
-} // anonymous namespace
-
</del><span class="cx"> static unsigned getLeaderOffsetForBasicBlock(RefPtr&lt;BytecodeBasicBlock&gt;* basicBlock)
</span><span class="cx"> {
</span><span class="cx">     return (*basicBlock)-&gt;leaderBytecodeOffset();
</span><span class="lines">@@ -133,28 +111,63 @@
</span><span class="cx">     return basicBlock[1].get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void stepOverInstruction(CodeBlock* codeBlock, Vector&lt;RefPtr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset, FastBitVector&amp; uses, FastBitVector&amp; defs, FastBitVector&amp; out)
</del><ins>+// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes
+// exception handlers in the uses.
+template&lt;typename UseFunctor, typename DefFunctor&gt;
+static void stepOverInstruction(CodeBlock* codeBlock, Vector&lt;RefPtr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset, const UseFunctor&amp; use, const DefFunctor&amp; def)
</ins><span class="cx"> {
</span><del>-    uses.clearAll();
-    defs.clearAll();
</del><ins>+    // This abstractly execute the instruction in reverse. Instructions logically first use operands and
+    // then define operands. This logical ordering is necessary for operations that use and def the same
+    // operand, like:
+    //
+    //     op_add loc1, loc1, loc2
+    //
+    // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add
+    // operation cannot travel forward in time to read the value that it will produce after reading that
+    // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of
+    // uses before defs).
+    //
+    // Since this is a liveness analysis, this ordering ends up being particularly important: if we did
+    // uses before defs, then the add operation above would appear to not have loc1 live, since we'd
+    // first add it to the out set (the use), and then we'd remove it (the def).
</ins><span class="cx">     
</span><del>-    SetBit setUses(uses);
-    SetBit setDefs(defs);
-    computeUsesForBytecodeOffset(codeBlock, bytecodeOffset, setUses);
-    computeDefsForBytecodeOffset(codeBlock, bytecodeOffset, setDefs);
</del><ins>+    computeDefsForBytecodeOffset(
+        codeBlock, bytecodeOffset,
+        [&amp;] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) {
+            if (isValidRegisterForLiveness(codeBlock, operand))
+                def(indexForOperand(codeBlock, operand));
+        });
</ins><span class="cx">     
</span><del>-    out.exclude(defs);
-    out.merge(uses);
-    
</del><ins>+    computeUsesForBytecodeOffset(
+        codeBlock, bytecodeOffset,
+        [&amp;] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) {
+            if (isValidRegisterForLiveness(codeBlock, operand))
+                use(indexForOperand(codeBlock, operand));
+        });
+        
</ins><span class="cx">     // If we have an exception handler, we want the live-in variables of the 
</span><span class="cx">     // exception handler block to be included in the live-in of this particular bytecode.
</span><span class="cx">     if (HandlerInfo* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset)) {
</span><span class="cx">         BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler-&gt;target);
</span><span class="cx">         ASSERT(handlerBlock);
</span><del>-        out.merge(handlerBlock-&gt;in());
</del><ins>+        handlerBlock-&gt;in().forEachSetBit(use);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void stepOverInstruction(CodeBlock* codeBlock, Vector&lt;RefPtr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset, FastBitVector&amp; out)
+{
+    stepOverInstruction(
+        codeBlock, basicBlocks, bytecodeOffset,
+        [&amp;] (unsigned bitIndex) {
+            // This is the use functor, so we set the bit.
+            out.set(bitIndex);
+        },
+        [&amp;] (unsigned bitIndex) {
+            // This is the def functor, so we clear the bit.
+            out.clear(bitIndex);
+        });
+}
+
</ins><span class="cx"> static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector&lt;RefPtr&lt;BytecodeBasicBlock&gt; &gt;&amp; basicBlocks, unsigned targetOffset, FastBitVector&amp; result)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!block-&gt;isExitBlock());
</span><span class="lines">@@ -162,17 +175,12 @@
</span><span class="cx"> 
</span><span class="cx">     FastBitVector out = block-&gt;out();
</span><span class="cx"> 
</span><del>-    FastBitVector uses;
-    FastBitVector defs;
-    uses.resize(out.numBits());
-    defs.resize(out.numBits());
-
</del><span class="cx">     for (int i = block-&gt;bytecodeOffsets().size() - 1; i &gt;= 0; i--) {
</span><span class="cx">         unsigned bytecodeOffset = block-&gt;bytecodeOffsets()[i];
</span><span class="cx">         if (targetOffset &gt; bytecodeOffset)
</span><span class="cx">             break;
</span><span class="cx">         
</span><del>-        stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, uses, defs, out);
</del><ins>+        stepOverInstruction(codeBlock, basicBlocks, bytecodeOffset, out);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     result.set(out);
</span><span class="lines">@@ -277,8 +285,6 @@
</span><span class="cx"> void BytecodeLivenessAnalysis::computeFullLiveness(FullBytecodeLiveness&amp; result)
</span><span class="cx"> {
</span><span class="cx">     FastBitVector out;
</span><del>-    FastBitVector uses;
-    FastBitVector defs;
</del><span class="cx">     
</span><span class="cx">     result.m_codeBlock = m_codeBlock;
</span><span class="cx">     result.m_map.clear();
</span><span class="lines">@@ -289,12 +295,10 @@
</span><span class="cx">             continue;
</span><span class="cx">         
</span><span class="cx">         out = block-&gt;out();
</span><del>-        uses.resize(out.numBits());
-        defs.resize(out.numBits());
</del><span class="cx">         
</span><span class="cx">         for (unsigned i = block-&gt;bytecodeOffsets().size(); i--;) {
</span><span class="cx">             unsigned bytecodeOffset = block-&gt;bytecodeOffsets()[i];
</span><del>-            stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, uses, defs, out);
</del><ins>+            stepOverInstruction(m_codeBlock, m_basicBlocks, bytecodeOffset, out);
</ins><span class="cx">             result.m_map.add(bytecodeOffset, out);
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2015 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">@@ -32,7 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Functor&gt;
</span><span class="cx"> void computeUsesForBytecodeOffset(
</span><del>-    CodeBlock* codeBlock, unsigned bytecodeOffset, Functor&amp; functor)
</del><ins>+    CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor&amp; functor)
</ins><span class="cx"> {
</span><span class="cx">     Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
</span><span class="cx">     Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
</span><span class="lines">@@ -235,7 +235,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Functor&gt;
</span><del>-void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Functor&amp; functor)
</del><ins>+void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, const Functor&amp; functor)
</ins><span class="cx"> {
</span><span class="cx">     Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
</span><span class="cx">     Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -3881,7 +3881,7 @@
</span><span class="cx"> namespace {
</span><span class="cx"> 
</span><span class="cx"> struct VerifyCapturedDef {
</span><del>-    void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand)
</del><ins>+    void operator()(CodeBlock* codeBlock, Instruction* instruction, OpcodeID opcodeID, int operand) const
</ins><span class="cx">     {
</span><span class="cx">         unsigned bytecodeOffset = instruction - codeBlock-&gt;instructions().begin();
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/WTF/ChangeLog        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2015-03-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Bytecode liveness analysis should have more lambdas and fewer sets
+        https://bugs.webkit.org/show_bug.cgi?id=142647
+
+        Reviewed by Mark Lam.
+        
+        Add a method for iterating each set bit in a FastBitVector. Uses a functor as a callback since
+        this allows for a more efficient algorithm.
+
+        * wtf/FastBitVector.h:
+        (WTF::FastBitVector::forEachSetBit):
+
</ins><span class="cx"> 2015-03-12  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Disable Yarr JIT for ARMv7k
</span></span></pre></div>
<a id="trunkSourceWTFwtfFastBitVectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/FastBitVector.h (181466 => 181467)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/FastBitVector.h        2015-03-13 01:11:15 UTC (rev 181466)
+++ trunk/Source/WTF/wtf/FastBitVector.h        2015-03-13 01:57:59 UTC (rev 181467)
</span><span class="lines">@@ -177,6 +177,22 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    template&lt;typename Functor&gt;
+    void forEachSetBit(const Functor&amp; functor)
+    {
+        unsigned n = arrayLength();
+        for (unsigned i = 0; i &lt; n; ++i) {
+            uint32_t word = m_array[i];
+            unsigned j = i &lt;&lt; 5;
+            while (word) {
+                if (word &amp; 1)
+                    functor(j);
+                word &gt;&gt;= 1;
+                j++;
+            }
+        }
+    }
+    
</ins><span class="cx">     WTF_EXPORT_PRIVATE void dump(PrintStream&amp;) const;
</span><span class="cx">     
</span><span class="cx"> private:
</span></span></pre>
</div>
</div>

</body>
</html>