<!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>[190310] 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/190310">190310</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-09-29 09:39:24 -0700 (Tue, 29 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>GC copy phase spans too many files
https://bugs.webkit.org/show_bug.cgi?id=149586

Reviewed by Andreas Kling.

Source/JavaScriptCore:

This puts the core logic of the copy phase into Heap::copyBackingStores(). Now, instead of
using many helpers in many places, the actual algorithm is all in one place.

This lets me do a lot of simplification.

- CopyVisitor no longer requires that you call startCopying() before, and doneCopying() and
  WTF::releaseFastMallocFreeMemoryForThisThread() after. The constructor and destructor now
  do this for you.

- CopyVisitor no longer contains the algorithm that drives copying. That's all in
  Heap::copyBackingStores() now. Basically, copyBackingStores() glues together the new
  WTF::ParallelVectorIterator with the copying algorithm that we used to have in
  CopyVisitor::copyFromShared().

- Lots of stuff that was in headers is now in .cpp files. That includes all non-hot-path
  code in CopyVisitor. Also, the code for copying in HeapInlines.h is now in
  ParallelVectorVisotor, and it's only included by Heap.cpp.

Overall, I like this direction for the GC. I don't think it's useful for Heap.cpp to have
calls to algorithms in some other file, unless those algorithms are either reusable or just
very dense. That's not actually true for the copy phase, and it's probably not true for
some other stuff like marking. I'll probably do the same refactoring for marking in another
bug.

This should have no effect on performance.

* heap/CopyVisitor.cpp:
(JSC::CopyVisitor::CopyVisitor):
(JSC::CopyVisitor::~CopyVisitor):
(JSC::CopyVisitor::copyFromShared): Deleted.
* heap/CopyVisitor.h:
* heap/CopyVisitorInlines.h:
(JSC::CopyVisitor::checkIfShouldCopy):
(JSC::CopyVisitor::allocateNewSpaceSlow):
(JSC::CopyVisitor::didCopy):
(JSC::CopyVisitor::visitItem): Deleted.
(JSC::CopyVisitor::startCopying): Deleted.
(JSC::CopyVisitor::doneCopying): Deleted.
* heap/Heap.cpp:
(JSC::Heap::copyBackingStores):
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::unregisterWeakGCMap):
(JSC::Heap::getNextBlocksToCopy): Deleted.

Source/WTF:

Extract the load balancing algorithm used by the GC's copy phase into a reusable template.
The GC copy phase now uses this.

* WTF.vcxproj/WTF.vcxproj:
* WTF.vcxproj/WTF.vcxproj.filters:
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/ParallelVectorIterator.h: Added.
(WTF::ParallelVectorIterator::ParallelVectorIterator):
(WTF::ParallelVectorIterator::iterate):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopyVisitorcpp">trunk/Source/JavaScriptCore/heap/CopyVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopyVisitorh">trunk/Source/JavaScriptCore/heap/CopyVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopyVisitorInlinesh">trunk/Source/JavaScriptCore/heap/CopyVisitorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFWTFvcxprojWTFvcxproj">trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj</a></li>
<li><a href="#trunkSourceWTFWTFvcxprojWTFvcxprojfilters">trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters</a></li>
<li><a href="#trunkSourceWTFWTFxcodeprojprojectpbxproj">trunk/Source/WTF/WTF.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWTFwtfCMakeListstxt">trunk/Source/WTF/wtf/CMakeLists.txt</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWTFwtfParallelVectorIteratorh">trunk/Source/WTF/wtf/ParallelVectorIterator.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2015-09-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        GC copy phase spans too many files
+        https://bugs.webkit.org/show_bug.cgi?id=149586
+
+        Reviewed by Andreas Kling.
+
+        This puts the core logic of the copy phase into Heap::copyBackingStores(). Now, instead of
+        using many helpers in many places, the actual algorithm is all in one place.
+
+        This lets me do a lot of simplification.
+
+        - CopyVisitor no longer requires that you call startCopying() before, and doneCopying() and
+          WTF::releaseFastMallocFreeMemoryForThisThread() after. The constructor and destructor now
+          do this for you.
+
+        - CopyVisitor no longer contains the algorithm that drives copying. That's all in
+          Heap::copyBackingStores() now. Basically, copyBackingStores() glues together the new
+          WTF::ParallelVectorIterator with the copying algorithm that we used to have in
+          CopyVisitor::copyFromShared().
+
+        - Lots of stuff that was in headers is now in .cpp files. That includes all non-hot-path
+          code in CopyVisitor. Also, the code for copying in HeapInlines.h is now in
+          ParallelVectorVisotor, and it's only included by Heap.cpp.
+
+        Overall, I like this direction for the GC. I don't think it's useful for Heap.cpp to have
+        calls to algorithms in some other file, unless those algorithms are either reusable or just
+        very dense. That's not actually true for the copy phase, and it's probably not true for
+        some other stuff like marking. I'll probably do the same refactoring for marking in another
+        bug.
+
+        This should have no effect on performance.
+
+        * heap/CopyVisitor.cpp:
+        (JSC::CopyVisitor::CopyVisitor):
+        (JSC::CopyVisitor::~CopyVisitor):
+        (JSC::CopyVisitor::copyFromShared): Deleted.
+        * heap/CopyVisitor.h:
+        * heap/CopyVisitorInlines.h:
+        (JSC::CopyVisitor::checkIfShouldCopy):
+        (JSC::CopyVisitor::allocateNewSpaceSlow):
+        (JSC::CopyVisitor::didCopy):
+        (JSC::CopyVisitor::visitItem): Deleted.
+        (JSC::CopyVisitor::startCopying): Deleted.
+        (JSC::CopyVisitor::doneCopying): Deleted.
+        * heap/Heap.cpp:
+        (JSC::Heap::copyBackingStores):
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::unregisterWeakGCMap):
+        (JSC::Heap::getNextBlocksToCopy): Deleted.
+
</ins><span class="cx"> 2015-09-29  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
</span><span class="cx"> 
</span><span class="cx">         Add support for WebIDL JSBuiltin attributes
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyVisitor.cpp (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyVisitor.cpp        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/CopyVisitor.cpp        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 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">@@ -39,28 +39,18 @@
</span><span class="cx"> CopyVisitor::CopyVisitor(Heap&amp; heap)
</span><span class="cx">     : m_heap(heap)
</span><span class="cx"> {
</span><ins>+    ASSERT(!m_copiedAllocator.isValid());
+    CopiedBlock* block = nullptr;
+    m_heap.m_storageSpace.doneFillingBlock(nullptr, &amp;block);
+    m_copiedAllocator.setCurrentBlock(block);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CopyVisitor::copyFromShared()
</del><ins>+CopyVisitor::~CopyVisitor()
</ins><span class="cx"> {
</span><del>-    size_t next, end;
-    m_heap.getNextBlocksToCopy(next, end);
-    while (next &lt; end) {
-        for (; next &lt; end; ++next) {
-            CopiedBlock* block = m_heap.m_blocksToCopy[next];
-            if (!block-&gt;hasWorkList())
-                continue;
-
-            CopyWorkList&amp; workList = block-&gt;workList();
-            for (CopyWorkList::iterator it = workList.begin(); it != workList.end(); ++it)
-                visitItem(*it);
-
-            ASSERT(!block-&gt;liveBytes());
-            m_heap.m_storageSpace.recycleEvacuatedBlock(block, m_heap.operationInProgress());
-        }
-        m_heap.getNextBlocksToCopy(next, end);
-    }
-    ASSERT(next == end);
</del><ins>+    if (m_copiedAllocator.isValid())
+        m_heap.m_storageSpace.doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), nullptr);
+    
+    WTF::releaseFastMallocFreeMemoryForThisThread();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyVisitor.h (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyVisitor.h        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/CopyVisitor.h        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 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">@@ -27,6 +27,7 @@
</span><span class="cx"> #define CopyVisitor_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CopiedSpace.h&quot;
</span><ins>+#include &lt;wtf/Noncopyable.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -34,14 +35,13 @@
</span><span class="cx"> class JSCell;
</span><span class="cx"> 
</span><span class="cx"> class CopyVisitor {
</span><ins>+    WTF_MAKE_NONCOPYABLE(CopyVisitor);
</ins><span class="cx"> public:
</span><span class="cx">     CopyVisitor(Heap&amp;);
</span><ins>+    ~CopyVisitor();
</ins><span class="cx"> 
</span><span class="cx">     void copyFromShared();
</span><span class="cx"> 
</span><del>-    void startCopying();
-    void doneCopying();
-
</del><span class="cx">     // Low-level API for copying, appropriate for cases where the object's heap references
</span><span class="cx">     // are discontiguous or if the object occurs frequently enough that you need to focus on
</span><span class="cx">     // performance. Use this with care as it is easy to shoot yourself in the foot.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyVisitorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyVisitorInlines.h (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyVisitorInlines.h        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/CopyVisitorInlines.h        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -34,16 +34,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-inline void CopyVisitor::visitItem(CopyWorklistItem item)
-{
-    if (item.token() == ButterflyCopyToken) {
-        JSObject::copyBackingStore(item.cell(), *this, ButterflyCopyToken);
-        return;
-    }
-    
-    item.cell()-&gt;methodTable()-&gt;copyBackingStore(item.cell(), *this, item.token());
-}
-
</del><span class="cx"> inline bool CopyVisitor::checkIfShouldCopy(void* oldPtr)
</span><span class="cx"> {
</span><span class="cx">     CopiedBlock* block = CopiedSpace::blockFor(oldPtr);
</span><span class="lines">@@ -75,22 +65,6 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void CopyVisitor::startCopying()
-{
-    ASSERT(!m_copiedAllocator.isValid());
-    CopiedBlock* block = 0;
-    m_heap.m_storageSpace.doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), &amp;block);
-    m_copiedAllocator.setCurrentBlock(block);
-}
-
-inline void CopyVisitor::doneCopying()
-{
-    if (!m_copiedAllocator.isValid())
-        return;
-
-    m_heap.m_storageSpace.doneFillingBlock(m_copiedAllocator.resetCurrentBlock(), 0);
-}
-
</del><span class="cx"> inline void CopyVisitor::didCopy(void* ptr, size_t bytes)
</span><span class="cx"> {
</span><span class="cx">     CopiedBlock* block = CopiedSpace::blockFor(ptr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx"> #include &lt;algorithm&gt;
</span><span class="cx"> #include &lt;wtf/RAMSize.h&gt;
</span><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><ins>+#include &lt;wtf/ParallelVectorIterator.h&gt;
</ins><span class="cx"> #include &lt;wtf/ProcessID.h&gt;
</span><span class="cx"> 
</span><span class="cx"> using namespace std;
</span><span class="lines">@@ -60,7 +61,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-namespace { 
</del><ins>+namespace {
</ins><span class="cx"> 
</span><span class="cx"> static const size_t largeHeapSize = 32 * MB; // About 1.5X the average webpage.
</span><span class="cx"> static const size_t smallHeapSize = 1 * MB; // Matches the FastMalloc per-thread cache.
</span><span class="lines">@@ -619,27 +620,47 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_storageSpace.shouldDoCopyPhase()) {
</span><del>-        {
-            LockHolder locker(m_copyLock);
-            if (m_operationInProgress == EdenCollection) {
-                // Reset the vector to be empty, but don't throw away the backing store.
-                m_blocksToCopy.shrink(0);
-                for (CopiedBlock* block = m_storageSpace.m_newGen.fromSpace-&gt;head(); block; block = block-&gt;next())
-                    m_blocksToCopy.append(block);
-            } else {
-                ASSERT(m_operationInProgress == FullCollection);
-                WTF::copyToVector(m_storageSpace.m_blockSet, m_blocksToCopy);
-            }
-            m_copyIndex = 0;
</del><ins>+        if (m_operationInProgress == EdenCollection) {
+            // Reset the vector to be empty, but don't throw away the backing store.
+            m_blocksToCopy.shrink(0);
+            for (CopiedBlock* block = m_storageSpace.m_newGen.fromSpace-&gt;head(); block; block = block-&gt;next())
+                m_blocksToCopy.append(block);
+        } else {
+            ASSERT(m_operationInProgress == FullCollection);
+            WTF::copyToVector(m_storageSpace.m_blockSet, m_blocksToCopy);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        ParallelVectorIterator&lt;Vector&lt;CopiedBlock*&gt;&gt; iterator(
+            m_blocksToCopy, s_blockFragmentLength);
+
+        // Note that it's safe to use the [&amp;] capture list here, even though we're creating a task
+        // that other threads run. That's because after runFunctionInParallel() returns, the task
+        // we have created is not going to be running anymore. Hence, everything on the stack here
+        // outlives the task.
</ins><span class="cx">         m_helperClient.runFunctionInParallel(
</span><del>-            [this] () {
</del><ins>+            [&amp;] () {
</ins><span class="cx">                 CopyVisitor copyVisitor(*this);
</span><del>-                copyVisitor.startCopying();
-                copyVisitor.copyFromShared();
-                copyVisitor.doneCopying();
-                WTF::releaseFastMallocFreeMemoryForThisThread();
</del><ins>+                
+                iterator.iterate(
+                    [&amp;] (CopiedBlock* block) {
+                        if (!block-&gt;hasWorkList())
+                            return;
+                        
+                        CopyWorkList&amp; workList = block-&gt;workList();
+                        for (CopyWorklistItem item : workList) {
+                            if (item.token() == ButterflyCopyToken) {
+                                JSObject::copyBackingStore(
+                                    item.cell(), copyVisitor, ButterflyCopyToken);
+                                continue;
+                            }
+                            
+                            item.cell()-&gt;methodTable()-&gt;copyBackingStore(
+                                item.cell(), copyVisitor, item.token());
+                        }
+                        
+                        ASSERT(!block-&gt;liveBytes());
+                        m_storageSpace.recycleEvacuatedBlock(block, m_operationInProgress);
+                    });
</ins><span class="cx">             });
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -346,8 +346,6 @@
</span><span class="cx">     size_t threadBytesCopied();
</span><span class="cx">     size_t threadDupStrings();
</span><span class="cx"> 
</span><del>-    void getNextBlocksToCopy(size_t&amp;, size_t&amp;);
-
</del><span class="cx">     const HeapType m_heapType;
</span><span class="cx">     const size_t m_ramSize;
</span><span class="cx">     const size_t m_minBytesPerCycle;
</span><span class="lines">@@ -437,9 +435,7 @@
</span><span class="cx">     Lock m_opaqueRootsMutex;
</span><span class="cx">     HashSet&lt;void*&gt; m_opaqueRoots;
</span><span class="cx"> 
</span><del>-    Lock m_copyLock;
</del><span class="cx">     Vector&lt;CopiedBlock*&gt; m_blocksToCopy;
</span><del>-    size_t m_copyIndex { 0 };
</del><span class="cx">     static const size_t s_blockFragmentLength = 32;
</span><span class="cx"> 
</span><span class="cx">     ListableHandler&lt;WeakReferenceHarvester&gt;::List m_weakReferenceHarvesters;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -326,14 +326,6 @@
</span><span class="cx">     m_weakGCMaps.remove(weakGCMap);
</span><span class="cx"> }
</span><span class="cx">     
</span><del>-inline void Heap::getNextBlocksToCopy(size_t&amp; start, size_t&amp; end)
-{
-    LockHolder locker(m_copyLock);
-    start = m_copyIndex;
-    end = std::min(m_blocksToCopy.size(), m_copyIndex + s_blockFragmentLength);
-    m_copyIndex = end;
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // HeapInlines_h
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/WTF/ChangeLog        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-09-29  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        GC copy phase spans too many files
+        https://bugs.webkit.org/show_bug.cgi?id=149586
+
+        Reviewed by Andreas Kling.
+
+        Extract the load balancing algorithm used by the GC's copy phase into a reusable template.
+        The GC copy phase now uses this.
+
+        * WTF.vcxproj/WTF.vcxproj:
+        * WTF.vcxproj/WTF.vcxproj.filters:
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/ParallelVectorIterator.h: Added.
+        (WTF::ParallelVectorIterator::ParallelVectorIterator):
+        (WTF::ParallelVectorIterator::iterate):
+
</ins><span class="cx"> 2015-09-26  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, fix Windows build by adding WTF_EXPORT_PRIVATE in various places.
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -252,6 +252,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobsGeneric.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobsLibdispatch.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobsOpenMP.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\ParallelVectorIterator.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParkingLot.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PassRefPtr.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\Platform.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -565,6 +565,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobsOpenMP.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;wtf&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\ParallelVectorIterator.h&quot;&gt;
+      &lt;Filter&gt;wtf&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PassRefPtr.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;wtf&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceWTFWTFxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx">                 0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE4479A1B7AAA03009498EB /* WordLock.cpp */; };
</span><span class="cx">                 0FE4479D1B7AAA03009498EB /* WordLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE4479B1B7AAA03009498EB /* WordLock.h */; };
</span><span class="cx">                 0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */; };
</span><ins>+                0FEB3DD11BB7366B009D7AAD /* ParallelVectorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEB3DD01BB7366B009D7AAD /* ParallelVectorIterator.h */; };
</ins><span class="cx">                 0FED67B61B22D4D80066CE15 /* TinyPtrSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */; };
</span><span class="cx">                 0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */; };
</span><span class="cx">                 0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */; };
</span><span class="lines">@@ -341,6 +342,7 @@
</span><span class="cx">                 0FE4479A1B7AAA03009498EB /* WordLock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WordLock.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FE4479B1B7AAA03009498EB /* WordLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WordLock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTask.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FEB3DD01BB7366B009D7AAD /* ParallelVectorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelVectorIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyPtrSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParallelHelperPool.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelHelperPool.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -830,6 +832,7 @@
</span><span class="cx">                                 0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */,
</span><span class="cx">                                 A8A472E6151A825B004123FF /* ParallelJobs.h */,
</span><span class="cx">                                 A8A472E9151A825B004123FF /* ParallelJobsLibdispatch.h */,
</span><ins>+                                0FEB3DD01BB7366B009D7AAD /* ParallelVectorIterator.h */,
</ins><span class="cx">                                 0F824A641B7443A0002E345D /* ParkingLot.cpp */,
</span><span class="cx">                                 0F824A651B7443A0002E345D /* ParkingLot.h */,
</span><span class="cx">                                 A8A472ED151A825B004123FF /* PassRefPtr.h */,
</span><span class="lines">@@ -1085,6 +1088,7 @@
</span><span class="cx">                                 0FB14E19180FA218009B6B4D /* Bag.h in Headers */,
</span><span class="cx">                                 0FB14E1B1810E1DC009B6B4D /* BagToHashMap.h in Headers */,
</span><span class="cx">                                 8134013915B092FD001FF0B8 /* Base64.h in Headers */,
</span><ins>+                                0FEB3DD11BB7366B009D7AAD /* ParallelVectorIterator.h in Headers */,
</ins><span class="cx">                                 A8A473A9151A825B004123FF /* bignum-dtoa.h in Headers */,
</span><span class="cx">                                 A8A473AB151A825B004123FF /* bignum.h in Headers */,
</span><span class="cx">                                 0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (190309 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2015-09-29 14:05:14 UTC (rev 190309)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -60,10 +60,12 @@
</span><span class="cx">     PageAllocation.h
</span><span class="cx">     PageBlock.h
</span><span class="cx">     PageReservation.h
</span><ins>+    ParallelHelperPool.h
</ins><span class="cx">     ParallelJobs.h
</span><span class="cx">     ParallelJobsGeneric.h
</span><span class="cx">     ParallelJobsLibdispatch.h
</span><span class="cx">     ParallelJobsOpenMP.h
</span><ins>+    ParallelVectorIterator.h
</ins><span class="cx">     ParkingLot.h
</span><span class="cx">     PassRefPtr.h
</span><span class="cx">     Platform.h
</span></span></pre></div>
<a id="trunkSourceWTFwtfParallelVectorIteratorh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/ParallelVectorIterator.h (0 => 190310)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParallelVectorIterator.h                                (rev 0)
+++ trunk/Source/WTF/wtf/ParallelVectorIterator.h        2015-09-29 16:39:24 UTC (rev 190310)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ParallelVectorIterator_h
+#define ParallelVectorIterator_h
+
+#include &lt;wtf/FastMalloc.h&gt;
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+
+namespace WTF {
+
+template&lt;typename VectorType&gt;
+class ParallelVectorIterator {
+    WTF_MAKE_NONCOPYABLE(ParallelVectorIterator);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ParallelVectorIterator(VectorType&amp; vector, size_t shardSize)
+        : m_vector(vector)
+        , m_shardSize(shardSize)
+    {
+    }
+
+    template&lt;typename Functor&gt;
+    ALWAYS_INLINE void iterate(const Functor&amp; functor)
+    {
+        for (;;) {
+            size_t begin;
+            size_t end;
+            {
+                LockHolder locker(m_lock);
+                begin = m_next;
+                if (begin == m_vector.size())
+                    return;
+                if (m_vector.size() - begin &lt; m_shardSize)
+                    end = m_vector.size();
+                else
+                    end = begin + m_shardSize;
+                RELEASE_ASSERT(end &lt;= m_vector.size());
+                RELEASE_ASSERT(begin &lt; end);
+                m_next = end;
+            }
+
+            for (size_t i = begin; i &lt; end; ++i)
+                functor(m_vector[i]);
+        }
+    }
+private:
+    VectorType&amp; m_vector;
+    Lock m_lock;
+    size_t m_shardSize;
+    size_t m_next { 0 };
+};
+
+} // namespace WTF
+
+using WTF::ParallelVectorIterator;
+
+#endif // ParallelVectorIterator_h
+
</ins></span></pre>
</div>
</div>

</body>
</html>