<!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>[181350] trunk/Source/JavaScriptCore</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/181350">181350</a></dd>
<dt>Author</dt> <dd>akling@apple.com</dd>
<dt>Date</dt> <dd>2015-03-10 15:59:10 -0700 (Tue, 10 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Eden collections should trigger sweep of MarkedBlocks containing new objects.
&lt;https://webkit.org/b/142538&gt;

Reviewed by Geoffrey Garen.

Take a snapshot of all MarkedBlocks with new objects as part of Eden collections,
and append that to the IncrementalSweeper's working set.

This ensures that we run destructors for objects that were discovered to be garbage during
Eden collections, instead of delaying their teardown until the next full collection,
or the next allocation cycle for their block.

* heap/Heap.cpp:
(JSC::Heap::snapshotMarkedSpace): For Eden collections, snapshot the list of MarkedBlocks
that contain new objects, since those are the only ones we're interested in.
Also use Vector::resizeToFit() to allocate the snapshot for full collections, since we know
the final size we need up front.

(JSC::Heap::notifyIncrementalSweeper): For Eden collections, tell the IncrementalSweeper
to add the block snapshot (taken earlier) to its existing set of blocks instead of replacing
it entirely. This allows Eden collections and incremental sweeping to occur interleaved with
each other without missing destruction opportunities.

* heap/IncrementalSweeper.h:
* heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::doSweep):
(JSC::IncrementalSweeper::sweepNextBlock): Change the way we iterate over the sweeper's
work list: instead of keeping an index for the next block, just pop from the end of the list.
This allows us to add new blocks and deduplicate the list without disturbing iteration.

(JSC::IncrementalSweeper::startSweeping): Make this take a Vector&lt;MarkedBlock&gt;&amp;&amp; so we can
pass ownership of this Vector efficiently from Heap to IncrementalSweeper.

(JSC::IncrementalSweeper::addBlocksAndContinueSweeping): Added. This is used by Eden
collections to add a set of MarkedBlocks with new objects to the sweeper's existing
working set and kick the timer.

* heap/MarkedSpace.h:
(JSC::MarkedSpace::blocksWithNewObjects): Expose the list of MarkedBlocks with new objects.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweepercpp">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweeperh">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpaceh">trunk/Source/JavaScriptCore/heap/MarkedSpace.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181349 => 181350)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-10 22:39:40 UTC (rev 181349)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-10 22:59:10 UTC (rev 181350)
</span><span class="lines">@@ -1,3 +1,45 @@
</span><ins>+2015-03-10  Andreas Kling  &lt;akling@apple.com&gt;
+
+        Eden collections should trigger sweep of MarkedBlocks containing new objects.
+        &lt;https://webkit.org/b/142538&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        Take a snapshot of all MarkedBlocks with new objects as part of Eden collections,
+        and append that to the IncrementalSweeper's working set.
+
+        This ensures that we run destructors for objects that were discovered to be garbage during
+        Eden collections, instead of delaying their teardown until the next full collection,
+        or the next allocation cycle for their block.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::snapshotMarkedSpace): For Eden collections, snapshot the list of MarkedBlocks
+        that contain new objects, since those are the only ones we're interested in.
+        Also use Vector::resizeToFit() to allocate the snapshot for full collections, since we know
+        the final size we need up front.
+
+        (JSC::Heap::notifyIncrementalSweeper): For Eden collections, tell the IncrementalSweeper
+        to add the block snapshot (taken earlier) to its existing set of blocks instead of replacing
+        it entirely. This allows Eden collections and incremental sweeping to occur interleaved with
+        each other without missing destruction opportunities.
+
+        * heap/IncrementalSweeper.h:
+        * heap/IncrementalSweeper.cpp:
+        (JSC::IncrementalSweeper::doSweep):
+        (JSC::IncrementalSweeper::sweepNextBlock): Change the way we iterate over the sweeper's
+        work list: instead of keeping an index for the next block, just pop from the end of the list.
+        This allows us to add new blocks and deduplicate the list without disturbing iteration.
+
+        (JSC::IncrementalSweeper::startSweeping): Make this take a Vector&lt;MarkedBlock&gt;&amp;&amp; so we can
+        pass ownership of this Vector efficiently from Heap to IncrementalSweeper.
+
+        (JSC::IncrementalSweeper::addBlocksAndContinueSweeping): Added. This is used by Eden
+        collections to add a set of MarkedBlocks with new objects to the sweeper's existing
+        working set and kick the timer.
+
+        * heap/MarkedSpace.h:
+        (JSC::MarkedSpace::blocksWithNewObjects): Expose the list of MarkedBlocks with new objects.
+
</ins><span class="cx"> 2015-03-10  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Use unsigned for HashSet size.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (181349 => 181350)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-03-10 22:39:40 UTC (rev 181349)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-03-10 22:59:10 UTC (rev 181350)
</span><span class="lines">@@ -1210,12 +1210,14 @@
</span><span class="cx"> void Heap::snapshotMarkedSpace()
</span><span class="cx"> {
</span><span class="cx">     GCPHASE(SnapshotMarkedSpace);
</span><del>-    if (m_operationInProgress != FullCollection)
-        return;
</del><span class="cx"> 
</span><del>-    m_blockSnapshot.resize(m_objectSpace.blocks().set().size());
-    MarkedBlockSnapshotFunctor functor(m_blockSnapshot);
-    m_objectSpace.forEachBlock(functor);
</del><ins>+    if (m_operationInProgress == EdenCollection)
+        m_blockSnapshot = m_objectSpace.blocksWithNewObjects();
+    else {
+        m_blockSnapshot.resizeToFit(m_objectSpace.blocks().set().size());
+        MarkedBlockSnapshotFunctor functor(m_blockSnapshot);
+        m_objectSpace.forEachBlock(functor);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::deleteSourceProviderCaches()
</span><span class="lines">@@ -1227,9 +1229,10 @@
</span><span class="cx"> void Heap::notifyIncrementalSweeper()
</span><span class="cx"> {
</span><span class="cx">     GCPHASE(NotifyIncrementalSweeper);
</span><del>-    if (m_operationInProgress != FullCollection)
-        return;
-    m_sweeper-&gt;startSweeping(m_blockSnapshot);
</del><ins>+    if (m_operationInProgress == EdenCollection)
+        m_sweeper-&gt;addBlocksAndContinueSweeping(WTF::move(m_blockSnapshot));
+    else
+        m_sweeper-&gt;startSweeping(WTF::move(m_blockSnapshot));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::rememberCurrentlyExecutingCodeBlocks()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweepercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp (181349 => 181350)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2015-03-10 22:39:40 UTC (rev 181349)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2015-03-10 22:59:10 UTC (rev 181350)
</span><span class="lines">@@ -45,7 +45,6 @@
</span><span class="cx"> 
</span><span class="cx"> IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
</span><span class="cx">     : HeapTimer(heap-&gt;vm(), runLoop)
</span><del>-    , m_currentBlockToSweepIndex(0)
</del><span class="cx">     , m_blocksToSweep(heap-&gt;m_blockSnapshot)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -73,7 +72,7 @@
</span><span class="cx"> 
</span><span class="cx"> void IncrementalSweeper::doSweep(double sweepBeginTime)
</span><span class="cx"> {
</span><del>-    while (m_currentBlockToSweepIndex &lt; m_blocksToSweep.size()) {
</del><ins>+    while (!m_blocksToSweep.isEmpty()) {
</ins><span class="cx">         sweepNextBlock();
</span><span class="cx"> 
</span><span class="cx">         double elapsedTime = WTF::monotonicallyIncreasingTime() - sweepBeginTime;
</span><span class="lines">@@ -90,8 +89,8 @@
</span><span class="cx"> 
</span><span class="cx"> void IncrementalSweeper::sweepNextBlock()
</span><span class="cx"> {
</span><del>-    while (m_currentBlockToSweepIndex &lt; m_blocksToSweep.size()) {
-        MarkedBlock* block = m_blocksToSweep[m_currentBlockToSweepIndex++];
</del><ins>+    while (!m_blocksToSweep.isEmpty()) {
+        MarkedBlock* block = m_blocksToSweep.takeLast();
</ins><span class="cx"> 
</span><span class="cx">         if (!block-&gt;needsSweeping())
</span><span class="cx">             continue;
</span><span class="lines">@@ -102,16 +101,23 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void IncrementalSweeper::startSweeping(Vector&lt;MarkedBlock*&gt;&amp; blockSnapshot)
</del><ins>+void IncrementalSweeper::startSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp; blockSnapshot)
</ins><span class="cx"> {
</span><del>-    m_blocksToSweep = blockSnapshot;
-    m_currentBlockToSweepIndex = 0;
</del><ins>+    m_blocksToSweep = WTF::move(blockSnapshot);
</ins><span class="cx">     scheduleTimer();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IncrementalSweeper::addBlocksAndContinueSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp; blockSnapshot)
+{
+    Vector&lt;MarkedBlock*&gt; blocks = WTF::move(blockSnapshot);
+    m_blocksToSweep.appendVector(blocks);
+    std::sort(m_blocksToSweep.begin(), m_blocksToSweep.end());
+    m_blocksToSweep.shrink(std::unique(m_blocksToSweep.begin(), m_blocksToSweep.end()) - m_blocksToSweep.begin());
+    scheduleTimer();
+}
+
</ins><span class="cx"> void IncrementalSweeper::willFinishSweeping()
</span><span class="cx"> {
</span><del>-    m_currentBlockToSweepIndex = 0;
</del><span class="cx">     m_blocksToSweep.clear();
</span><span class="cx">     if (m_vm)
</span><span class="cx">         cancelTimer();
</span><span class="lines">@@ -128,10 +134,14 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void IncrementalSweeper::startSweeping(Vector&lt;MarkedBlock*&gt;&amp;)
</del><ins>+void IncrementalSweeper::startSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp;)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void IncrementalSweeper::addBlocksAndContinueSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp;)
+{
+}
+
</ins><span class="cx"> void IncrementalSweeper::willFinishSweeping()
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweeperh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h (181349 => 181350)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2015-03-10 22:39:40 UTC (rev 181349)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2015-03-10 22:59:10 UTC (rev 181350)
</span><span class="lines">@@ -43,7 +43,9 @@
</span><span class="cx">     explicit IncrementalSweeper(VM*);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    void startSweeping(Vector&lt;MarkedBlock*&gt;&amp;);
</del><ins>+    void startSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp;);
+    void addBlocksAndContinueSweeping(Vector&lt;MarkedBlock*&gt;&amp;&amp;);
+
</ins><span class="cx">     JS_EXPORT_PRIVATE virtual void doWork() override;
</span><span class="cx">     void sweepNextBlock();
</span><span class="cx">     void willFinishSweeping();
</span><span class="lines">@@ -55,7 +57,6 @@
</span><span class="cx">     void cancelTimer();
</span><span class="cx">     bool hasWork() const { return !m_blocksToSweep.isEmpty(); }
</span><span class="cx">     
</span><del>-    unsigned m_currentBlockToSweepIndex;
</del><span class="cx">     Vector&lt;MarkedBlock*&gt;&amp; m_blocksToSweep;
</span><span class="cx"> #endif
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.h (181349 => 181350)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2015-03-10 22:39:40 UTC (rev 181349)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2015-03-10 22:59:10 UTC (rev 181350)
</span><span class="lines">@@ -160,6 +160,8 @@
</span><span class="cx">     template&lt;typename T&gt; void releaseSoon(RetainPtr&lt;T&gt;&amp;&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+    const Vector&lt;MarkedBlock*&gt;&amp; blocksWithNewObjects() const { return m_blocksWithNewObjects; }
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="cx">     friend class JIT;
</span></span></pre>
</div>
</div>

</body>
</html>