<!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>[190267] 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/190267">190267</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-09-26 11:07:09 -0700 (Sat, 26 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>VMs should share GC threads
https://bugs.webkit.org/show_bug.cgi?id=149433
rdar://problem/12859344

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This changes the GC to use a new WTF abstraction for parallelism called ParallelHelperPool.
This allows us to remove GCThread and all of the GCPhase machinery. This kills a lot of
code and also gives our GC magical thread sharing powers. If two GCs in two different VMs
fire at the same time, then they will both get a random subset of the available shared GC
threads. If one GC happens before the other, then it will probably get all of the available
threads. If a GC happens while another VM already started GCing, then it will probably not
get any helper threads. This is probably fine, since in multi-VM scenarios we have no
reason to optimize for anything other than total throughput.

The GC has one static helper pool. This pool is available via JSC::heapHelperPool(). It
would be OK for other parts of JSC to use it in the future for parallel tasks. Each Heap
instance has a helper client attached to the pool.

The marking phase tells the ParallelHelperClient to asynchronously run a function that
joins parallel marking and finishes once marking reaches termination. It uses the
client.setFunction() idiom where the threads share work with each other using a specialized
worklist. The ParallelHelperPool is not involved in deciding when threads should terminate.

The copying phase tells the ParallelHelperClient to run a copying function in parallel. It
uses the client.runFunctionInParallel() idiom. The copying function gets work from the
m_blocksToCopy worklist inside Heap.

To test that multiple VMs work properly, this adds a multi-VM test to testapi.mm. This test
creates five concurrent VMs and has each of them allocate about 30MB of memory before doing
a full GC. I've confirmed that this tests uses only 6 total GC threads on my 8-core
computer (this is correct since we are currently configured for 7-way parallelism).

This shouldn't affect performance on benchmarks, but it will sure help apps with a lot of
VM instances.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/AbstractMacroAssembler.h:
* heap/GCThread.cpp: Removed.
* heap/GCThread.h: Removed.
* heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::~Heap):
(JSC::Heap::isPagedOut):
(JSC::Heap::markRoots):
(JSC::Heap::copyBackingStores):
(JSC::Heap::resetVisitors):
(JSC::Heap::threadVisitCount):
(JSC::Heap::threadBytesVisited):
(JSC::Heap::threadBytesCopied):
(JSC::Heap::startNextPhase): Deleted.
(JSC::Heap::endCurrentPhase): Deleted.
* heap/Heap.h:
* heap/HeapHelperPool.cpp: Added.
(JSC::heapHelperPool):
* heap/HeapHelperPool.h: Added.
* heap/MarkStack.cpp:
(JSC::MarkStackArray::stealSomeCellsFrom):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::didStartMarking):
(JSC::SlotVisitor::reset):
(JSC::SlotVisitor::drainFromShared):
* jit/BinarySwitch.h:
* runtime/CodeCache.h:
* runtime/VM.h:
* runtime/WeakRandom.h: Removed.
* API/tests/testapi.mm:

Source/WTF:

This adds two major things to WTF: WeakRandom and ParallelHelperPool. WeakRandom was
already in JSC; we're just hoisting it into WTF. It's just a weak random number generator
that's suitable for places where you need just a tiny bit of randomness.

ParallelHelperPool is a new API that simplifies data-parallel algorithms like the JSC GC.
In a data-parallel algorithm, we want to run one task on as many cores as possible and let
the task worry about which subset of the input data to work on. In some cases, the
algorithm will not need to do any load balancing - and if load balancing is required, it's
up to the user. This is appropriate in contexts where the load balancing needs to be
custom-tuned for performance, like the GC's marking phase.

This new API has three concepts: task, client, and pool. A task is a reference counted
object with a run() method, which may be run in parallel. It is usually used to wrap a
functor. A pool is a pool of threads that can run things. A client is a placeholder for a
task. A client can have zero or one tasks. A client must be registered with a pool. When a
client has a task, the pool's threads may choose to run it. If a thread starts running a
task, it will run it to completion. When the task returns on any thread, the client takes
it to mean that the task should be removed. That means that any currently running instances
of the task will finish but no new threads will attempt to run the task. You can easily ask
a client to wait until a task finishes. You can also easily ask a client to run a task on
the current thread in addition to possibly some helper threads from the pool.

For some data-parallel algorithms, programming with ParallelHelperPool is as easy as:

client.runFunctionInParallel(
    [=] () {
        do things;
    });

Note that you cannot tell ahead of time how many threads will join to help the task.
Threads may become available after the task has already started running. Those threads may
join after the other threads have already started. It's not advisable to make algorithmic
decisions based on client.numberOfActiveThreads(), since that number may change. Usually
the best way to use ParallelHelperPool is with an algorithm that has its own custom
worklist. An example of a very simple custom worklist is the one in the JSC GC's copying
phase - it's just a Vector and an index that indicates the next set of elements to process.

This new API was initially designed to simplify how GCThread works, by replacing Phase with
a callback that contains the phase's workload. I then realized that with a few tweaks, I
could make this somewhat general enough that it might become interesting outside GC. I also
realized that I could use this to enable thread sharing. So, although the API is kinda
quirky, it's grounded in the reality of how the JSC GC does parallelism.

* WTF.vcxproj/WTF.vcxproj:
* WTF.vcxproj/WTF.vcxproj.filters:
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/ParallelHelperPool.cpp: Added.
(WTF::ParallelHelperClient::ParallelHelperClient):
(WTF::ParallelHelperClient::~ParallelHelperClient):
(WTF::ParallelHelperClient::setTask):
(WTF::ParallelHelperClient::finish):
(WTF::ParallelHelperClient::doSomeHelping):
(WTF::ParallelHelperClient::runTaskInParallel):
(WTF::ParallelHelperClient::claimTask):
(WTF::ParallelHelperClient::runTask):
(WTF::ParallelHelperPool::ParallelHelperPool):
(WTF::ParallelHelperPool::~ParallelHelperPool):
(WTF::ParallelHelperPool::addThreads):
(WTF::ParallelHelperPool::ensureThreads):
(WTF::ParallelHelperPool::doSomeHelping):
(WTF::ParallelHelperPool::didMakeWorkAvailable):
(WTF::ParallelHelperPool::helperThreadBody):
(WTF::ParallelHelperPool::hasClientWithTask):
(WTF::ParallelHelperPool::getClientWithTask):
(WTF::ParallelHelperPool::waitForClientWithTask):
* wtf/ParallelHelperPool.h: Added.
(WTF::ParallelHelperClient::setFunction):
(WTF::ParallelHelperClient::runFunctionInParallel):
(WTF::ParallelHelperClient::pool):
(WTF::ParallelHelperClient::numberOfActiveThreads):
(WTF::ParallelHelperPool::numberOfThreads):
* wtf/SharedTask.h: Added.
(WTF::SharedTask::SharedTask):
(WTF::SharedTask::~SharedTask):
(WTF::SharedTaskFunctor::SharedTaskFunctor):
(WTF::createSharedTask):
* wtf/WeakRandom.h: Copied from Source/JavaScriptCore/runtime/WeakRandom.h.
(WTF::WeakRandom::WeakRandom):
(WTF::WeakRandom::initializeSeed):
(WTF::WeakRandom::seedUnsafe):
(WTF::WeakRandom::getUint32):
(WTF::WeakRandom::advance):
(JSC::WeakRandom::WeakRandom): Deleted.
(JSC::WeakRandom::seedUnsafe): Deleted.
(JSC::WeakRandom::getUint32): Deleted.
(JSC::WeakRandom::advance): Deleted.
(JSC::WeakRandom::initializeSeed): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreAPIteststestapimm">trunk/Source/JavaScriptCore/API/tests/testapi.mm</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.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="#trunkSourceJavaScriptCoreheapMarkStackcpp">trunk/Source/JavaScriptCore/heap/MarkStack.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitBinarySwitchh">trunk/Source/JavaScriptCore/jit/BinarySwitch.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCodeCacheh">trunk/Source/JavaScriptCore/runtime/CodeCache.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.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="#trunkSourceJavaScriptCoreheapHeapHelperPoolcpp">trunk/Source/JavaScriptCore/heap/HeapHelperPool.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapHelperPoolh">trunk/Source/JavaScriptCore/heap/HeapHelperPool.h</a></li>
<li><a href="#trunkSourceWTFwtfParallelHelperPoolcpp">trunk/Source/WTF/wtf/ParallelHelperPool.cpp</a></li>
<li><a href="#trunkSourceWTFwtfParallelHelperPoolh">trunk/Source/WTF/wtf/ParallelHelperPool.h</a></li>
<li><a href="#trunkSourceWTFwtfSharedTaskh">trunk/Source/WTF/wtf/SharedTask.h</a></li>
<li><a href="#trunkSourceWTFwtfWeakRandomh">trunk/Source/WTF/wtf/WeakRandom.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapGCThreadcpp">trunk/Source/JavaScriptCore/heap/GCThread.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCThreadh">trunk/Source/JavaScriptCore/heap/GCThread.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeWeakRandomh">trunk/Source/JavaScriptCore/runtime/WeakRandom.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreAPIteststestapimm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/tests/testapi.mm (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/tests/testapi.mm        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/API/tests/testapi.mm        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #import &quot;Regress141809.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #import &lt;pthread.h&gt;
</span><ins>+#import &lt;vector&gt;
</ins><span class="cx"> 
</span><span class="cx"> extern &quot;C&quot; void JSSynchronousGarbageCollectForDebugging(JSContextRef);
</span><span class="cx"> extern &quot;C&quot; void JSSynchronousEdenCollectForDebugging(JSContextRef);
</span><span class="lines">@@ -481,9 +482,34 @@
</span><span class="cx">     // Do something to enter the VM.
</span><span class="cx">     TestObject *testObject = [TestObject testObject];
</span><span class="cx">     context[@&quot;testObject&quot;] = testObject;
</span><del>-    pthread_exit(nullptr);
</del><ins>+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void* multiVMThreadMain(void* okPtr)
+{
+    bool&amp; ok = *static_cast&lt;bool*&gt;(okPtr);
+    JSVirtualMachine *vm = [[JSVirtualMachine alloc] init];
+    JSContext* context = [[JSContext alloc] initWithVirtualMachine:vm];
+    [context evaluateScript:
+        @&quot;var array = [{}];\n&quot;
+         &quot;for (var i = 0; i &lt; 20; ++i) {\n&quot;
+         &quot;    var newArray = new Array(array.length * 2);\n&quot;
+         &quot;    for (var j = 0; j &lt; newArray.length; ++j)\n&quot;
+         &quot;        newArray[j] = {parent: array[j / 2]};\n&quot;
+         &quot;    array = newArray;\n&quot;
+         &quot;}\n&quot;];
+    if (context.exception) {
+        NSLog(@&quot;Uncaught exception.\n&quot;);
+        ok = false;
+    }
+    if (![context.globalObject valueForProperty:@&quot;array&quot;].toObject) {
+        NSLog(@&quot;Did not find \&quot;array\&quot; variable.\n&quot;);
+        ok = false;
+    }
+    JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
+    return nullptr;
+}
+
</ins><span class="cx"> // This test is flaky. Since GC marks C stack and registers as roots conservatively,
</span><span class="cx"> // objects not referenced logically can be accidentally marked and alive.
</span><span class="cx"> // To avoid this situation as possible as we can,
</span><span class="lines">@@ -1416,6 +1442,21 @@
</span><span class="cx">         checkResult(@&quot;Did not crash after entering the VM from another thread&quot;, true);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    @autoreleasepool {
+        std::vector&lt;pthread_t&gt; threads;
+        bool ok = true;
+        for (unsigned i = 0; i &lt; 5; ++i) {
+            pthread_t threadID;
+            pthread_create(&amp;threadID, nullptr, multiVMThreadMain, &amp;ok);
+            threads.push_back(threadID);
+        }
+
+        for (pthread_t thread : threads)
+            pthread_join(thread, nullptr);
+
+        checkResult(@&quot;Ran code in five concurrent VMs that GC'd&quot;, ok);
+    }
+    
</ins><span class="cx">     currentThisInsideBlockGetterTest();
</span><span class="cx">     runDateTests();
</span><span class="cx">     runJSExportTests();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -294,10 +294,10 @@
</span><span class="cx">     heap/FullGCActivityCallback.cpp
</span><span class="cx">     heap/GCActivityCallback.cpp
</span><span class="cx">     heap/GCLogging.cpp
</span><del>-    heap/GCThread.cpp
</del><span class="cx">     heap/HandleSet.cpp
</span><span class="cx">     heap/HandleStack.cpp
</span><span class="cx">     heap/Heap.cpp
</span><ins>+    heap/HeapHelperPool.cpp
</ins><span class="cx">     heap/HeapStatistics.cpp
</span><span class="cx">     heap/HeapTimer.cpp
</span><span class="cx">     heap/HeapVerifier.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,3 +1,76 @@
</span><ins>+2015-09-24  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        VMs should share GC threads
+        https://bugs.webkit.org/show_bug.cgi?id=149433
+        rdar://problem/12859344
+
+        Reviewed by Geoffrey Garen.
+
+        This changes the GC to use a new WTF abstraction for parallelism called ParallelHelperPool.
+        This allows us to remove GCThread and all of the GCPhase machinery. This kills a lot of
+        code and also gives our GC magical thread sharing powers. If two GCs in two different VMs
+        fire at the same time, then they will both get a random subset of the available shared GC
+        threads. If one GC happens before the other, then it will probably get all of the available
+        threads. If a GC happens while another VM already started GCing, then it will probably not
+        get any helper threads. This is probably fine, since in multi-VM scenarios we have no
+        reason to optimize for anything other than total throughput.
+
+        The GC has one static helper pool. This pool is available via JSC::heapHelperPool(). It
+        would be OK for other parts of JSC to use it in the future for parallel tasks. Each Heap
+        instance has a helper client attached to the pool.
+
+        The marking phase tells the ParallelHelperClient to asynchronously run a function that
+        joins parallel marking and finishes once marking reaches termination. It uses the
+        client.setFunction() idiom where the threads share work with each other using a specialized
+        worklist. The ParallelHelperPool is not involved in deciding when threads should terminate.
+
+        The copying phase tells the ParallelHelperClient to run a copying function in parallel. It
+        uses the client.runFunctionInParallel() idiom. The copying function gets work from the
+        m_blocksToCopy worklist inside Heap.
+
+        To test that multiple VMs work properly, this adds a multi-VM test to testapi.mm. This test
+        creates five concurrent VMs and has each of them allocate about 30MB of memory before doing
+        a full GC. I've confirmed that this tests uses only 6 total GC threads on my 8-core
+        computer (this is correct since we are currently configured for 7-way parallelism).
+
+        This shouldn't affect performance on benchmarks, but it will sure help apps with a lot of
+        VM instances.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/AbstractMacroAssembler.h:
+        * heap/GCThread.cpp: Removed.
+        * heap/GCThread.h: Removed.
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap):
+        (JSC::Heap::~Heap):
+        (JSC::Heap::isPagedOut):
+        (JSC::Heap::markRoots):
+        (JSC::Heap::copyBackingStores):
+        (JSC::Heap::resetVisitors):
+        (JSC::Heap::threadVisitCount):
+        (JSC::Heap::threadBytesVisited):
+        (JSC::Heap::threadBytesCopied):
+        (JSC::Heap::startNextPhase): Deleted.
+        (JSC::Heap::endCurrentPhase): Deleted.
+        * heap/Heap.h:
+        * heap/HeapHelperPool.cpp: Added.
+        (JSC::heapHelperPool):
+        * heap/HeapHelperPool.h: Added.
+        * heap/MarkStack.cpp:
+        (JSC::MarkStackArray::stealSomeCellsFrom):
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::didStartMarking):
+        (JSC::SlotVisitor::reset):
+        (JSC::SlotVisitor::drainFromShared):
+        * jit/BinarySwitch.h:
+        * runtime/CodeCache.h:
+        * runtime/VM.h:
+        * runtime/WeakRandom.h: Removed.
+        * API/tests/testapi.mm:
+
</ins><span class="cx"> 2015-09-25  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         DFG should use PhantomLocal instead of Flush as liveness preservation mechanism in LiveCatchVariablesPreservationPhase
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -569,6 +569,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HandleSet.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HandleStack.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\Heap.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\heap\HeapHelperPool.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HeapStatistics.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HeapTimer.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HeapVerifier.cpp&quot; /&gt;
</span><span class="lines">@@ -1350,6 +1351,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HandleStack.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HandleTypes.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\Heap.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\heap\HeapHelperPool.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HeapInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HeapOperation.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HeapRootVisitor.h&quot; /&gt;
</span><span class="lines">@@ -1809,7 +1811,6 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WeakMapPrototype.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WeakSetConstructor.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WeakSetPrototype.h&quot; /&gt;
</span><del>-    &lt;ClInclude Include=&quot;..\runtime\WeakRandom.h&quot; /&gt;
</del><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WriteBarrier.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WriteBarrierInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\tools\CodeProfile.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -291,6 +291,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\heap\Heap.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;heap&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\heap\HeapHelperPool.cpp&quot;&gt;
+      &lt;Filter&gt;heap&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\heap\HeapStatistics.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;heap&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -2288,6 +2291,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\heap\Heap.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;heap&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\heap\HeapHelperPool.h&quot;&gt;
+      &lt;Filter&gt;heap&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\heap\HeapInlines.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;heap&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><span class="lines">@@ -3167,9 +3173,6 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WeakGCMap.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><del>-    &lt;ClInclude Include=&quot;..\runtime\WeakRandom.h&quot;&gt;
-      &lt;Filter&gt;runtime&lt;/Filter&gt;
-    &lt;/ClInclude&gt;
</del><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\WriteBarrier.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;runtime&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -274,6 +274,8 @@
</span><span class="cx">                 0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; };
</span><span class="cx">                 0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */; };
</span><span class="cx">                 0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; };
</span><ins>+                0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */; };
+                0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */; };
</ins><span class="cx">                 0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
</span><span class="cx">                 0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; };
</span><span class="cx">                 0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */; };
</span><span class="lines">@@ -775,7 +777,6 @@
</span><span class="cx">                 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 141448CA13A176EC00F5BA1A /* MarkedBlockSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 141448CD13A1783700F5BA1A /* TinyBloomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 14150132154BB13F005D8C98 /* WeakSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1421359A0A677F4F00A8195E /* JSBase.cpp */; };
</span><span class="cx">                 14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8580255597D01FF60F7 /* Debugger.cpp */; };
</span><span class="cx">                 1428082D107EC0570013E7B2 /* CallData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA62DFE0E2826230004F30D /* CallData.cpp */; };
</span><span class="lines">@@ -1665,8 +1666,6 @@
</span><span class="cx">                 C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2239D1216262BDD005AC5FD /* CopyVisitor.cpp */; };
</span><span class="cx">                 C2239D1816262BDD005AC5FD /* CopyVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1316262BDD005AC5FD /* CopyVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 C2239D1916262BDD005AC5FD /* CopyVisitorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2239D1516262BDD005AC5FD /* GCThread.cpp */; };
-                C2239D1B16262BDD005AC5FD /* GCThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1616262BDD005AC5FD /* GCThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C225494215F7DBAA0065E898 /* SlotVisitor.cpp */; };
</span><span class="cx">                 C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* CopiedSpace.cpp */; };
</span><span class="lines">@@ -2119,6 +2118,8 @@
</span><span class="cx">                 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapHelperPool.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapHelperPool.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoint.cpp; path = llint/LLIntEntrypoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2616,7 +2617,6 @@
</span><span class="cx">                 141448CA13A176EC00F5BA1A /* MarkedBlockSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedBlockSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyBloomFilter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 14150132154BB13F005D8C98 /* WeakSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakSetInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 1421359A0A677F4F00A8195E /* JSBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 142711380A460BBB0080EEEA /* JSBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 1429D77B0ED20D7300B89619 /* Interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Interpreter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3537,8 +3537,6 @@
</span><span class="cx">                 C2239D1216262BDD005AC5FD /* CopyVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopyVisitor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2239D1316262BDD005AC5FD /* CopyVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyVisitor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyVisitorInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                C2239D1516262BDD005AC5FD /* GCThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCThread.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                C2239D1616262BDD005AC5FD /* GCThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCThread.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotVisitor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C240305314B404C90079EB64 /* CopiedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopiedSpace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C24D31E0161CD695002AA4DB /* HeapStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapStatistics.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4251,8 +4249,6 @@
</span><span class="cx">                                 2AABCDE618EF294200002096 /* GCLogging.h */,
</span><span class="cx">                                 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */,
</span><span class="cx">                                 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */,
</span><del>-                                C2239D1516262BDD005AC5FD /* GCThread.cpp */,
-                                C2239D1616262BDD005AC5FD /* GCThread.h */,
</del><span class="cx">                                 142E312B134FF0A600AFADB5 /* Handle.h */,
</span><span class="cx">                                 C28318FF16FE4B7D00157BFD /* HandleBlock.h */,
</span><span class="cx">                                 C283190116FE533E00157BFD /* HandleBlockInlines.h */,
</span><span class="lines">@@ -4263,6 +4259,8 @@
</span><span class="cx">                                 146FA5A81378F6B0003627A3 /* HandleTypes.h */,
</span><span class="cx">                                 14BA7A9513AADFF8005B7C2C /* Heap.cpp */,
</span><span class="cx">                                 14BA7A9613AADFF8005B7C2C /* Heap.h */,
</span><ins>+                                0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */,
+                                0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */,
</ins><span class="cx">                                 C2DA778218E259990066FCB6 /* HeapInlines.h */,
</span><span class="cx">                                 2AD8932917E3868F00668276 /* HeapIterationScope.h */,
</span><span class="cx">                                 2A6F462517E959CE00C45C98 /* HeapOperation.h */,
</span><span class="lines">@@ -5092,7 +5090,6 @@
</span><span class="cx">                                 A7CA3AEA17DA5168006538AF /* WeakMapData.h */,
</span><span class="cx">                                 A7CA3ADF17DA41AE006538AF /* WeakMapPrototype.cpp */,
</span><span class="cx">                                 A7CA3AE017DA41AE006538AF /* WeakMapPrototype.h */,
</span><del>-                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
</del><span class="cx">                                 709FB8631AE335C60039D069 /* WeakSetConstructor.cpp */,
</span><span class="cx">                                 709FB8641AE335C60039D069 /* WeakSetConstructor.h */,
</span><span class="cx">                                 709FB8651AE335C60039D069 /* WeakSetPrototype.cpp */,
</span><span class="lines">@@ -6155,6 +6152,7 @@
</span><span class="cx">                                 A78A9777179738B8009DF744 /* DFGFinalizer.h in Headers */,
</span><span class="cx">                                 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
</span><span class="cx">                                 0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
</span><ins>+                                0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */,
</ins><span class="cx">                                 A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
</span><span class="cx">                                 0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */,
</span><span class="cx">                                 0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */,
</span><span class="lines">@@ -6931,7 +6929,6 @@
</span><span class="cx">                                 A7CA3AE417DA41AE006538AF /* WeakMapConstructor.h in Headers */,
</span><span class="cx">                                 A7CA3AEC17DA5168006538AF /* WeakMapData.h in Headers */,
</span><span class="cx">                                 A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
</span><del>-                                1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */,
</del><span class="cx">                                 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */,
</span><span class="cx">                                 14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */,
</span><span class="cx">                                 709FB86A1AE335C60039D069 /* WeakSetConstructor.h in Headers */,
</span><span class="lines">@@ -8062,6 +8059,7 @@
</span><span class="cx">                                 0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
</span><span class="cx">                                 0FF42743158EBE91004CB9FF /* udis86_input.c in Sources */,
</span><span class="cx">                                 0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */,
</span><ins>+                                0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */,
</ins><span class="cx">                                 0FF42745158EBE91004CB9FF /* udis86_syn-att.c in Sources */,
</span><span class="cx">                                 0FF42746158EBE91004CB9FF /* udis86_syn-intel.c in Sources */,
</span><span class="cx">                                 0FF42747158EBE91004CB9FF /* udis86_syn.c in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -31,9 +31,9 @@
</span><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;Options.h&quot;
</span><del>-#include &quot;WeakRandom.h&quot;
</del><span class="cx"> #include &lt;wtf/CryptographicallyRandomNumber.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><ins>+#include &lt;wtf/WeakRandom.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(ASSEMBLER)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCThreadcpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCThread.cpp (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCThread.cpp        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/GCThread.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,130 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012, 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. AND ITS CONTRIBUTORS ``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 ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-#include &quot;GCThread.h&quot;
-
-#include &quot;CopyVisitor.h&quot;
-#include &quot;CopyVisitorInlines.h&quot;
-#include &quot;JSCInlines.h&quot;
-#include &quot;SlotVisitor.h&quot;
-#include &lt;wtf/MainThread.h&gt;
-
-namespace JSC {
-
-GCThread::GCThread(Heap&amp; heap, std::unique_ptr&lt;SlotVisitor&gt; slotVisitor)
-    : m_threadID(0)
-    , m_heap(heap)
-    , m_slotVisitor(WTF::move(slotVisitor))
-{
-}
-
-ThreadIdentifier GCThread::threadID()
-{
-    ASSERT(m_threadID);
-    return m_threadID;
-}
-
-void GCThread::initializeThreadID(ThreadIdentifier threadID)
-{
-    ASSERT(!m_threadID);
-    m_threadID = threadID;
-}
-
-SlotVisitor* GCThread::slotVisitor()
-{
-    ASSERT(m_slotVisitor);
-    return m_slotVisitor.get();
-}
-
-GCPhase GCThread::waitForNextPhase()
-{
-    std::unique_lock&lt;Lock&gt; lock(m_heap.m_phaseMutex);
-    m_heap.m_phaseConditionVariable.wait(lock, [this] { return !m_heap.m_gcThreadsShouldWait; });
-
-    m_heap.m_numberOfActiveGCThreads--;
-    if (!m_heap.m_numberOfActiveGCThreads)
-        m_heap.m_activityConditionVariable.notifyOne();
-
-    m_heap.m_phaseConditionVariable.wait(lock, [this] { return m_heap.m_currentPhase != NoPhase; });
-    m_heap.m_numberOfActiveGCThreads++;
-    return m_heap.m_currentPhase;
-}
-
-void GCThread::gcThreadMain()
-{
-    GCPhase currentPhase;
-    WTF::registerGCThread();
-    // Wait for the main thread to finish creating and initializing us. The main thread grabs this lock before 
-    // creating this thread. We aren't guaranteed to have a valid threadID until the main thread releases this lock.
-    {
-        std::lock_guard&lt;Lock&gt; lock(m_heap.m_phaseMutex);
-    }
-    {
-        ParallelModeEnabler enabler(*m_slotVisitor);
-        while ((currentPhase = waitForNextPhase()) != Exit) {
-            // Note: Each phase is responsible for its own termination conditions. The comments below describe 
-            // how each phase reaches termination.
-            switch (currentPhase) {
-            case Mark:
-                m_slotVisitor-&gt;drainFromShared(SlotVisitor::SlaveDrain);
-                // GCThreads only return from drainFromShared() if the main thread sets the m_parallelMarkersShouldExit 
-                // flag in the GCThreadSharedData. The only way the main thread sets that flag is if it realizes 
-                // that all of the various subphases in Heap::markRoots() have been fully finished and there is 
-                // no more marking work to do and all of the GCThreads are idle, meaning no more work can be generated.
-                break;
-            case Copy: {
-                CopyVisitor copyVisitor(m_heap);
-                copyVisitor.startCopying();
-                copyVisitor.copyFromShared();
-                // We know we're done copying when we return from copyFromShared() because we would 
-                // only do so if there were no more chunks of copying work left to do. When there is no 
-                // more copying work to do, the main thread will wait in CopiedSpace::doneCopying() until 
-                // all of the blocks that the GCThreads borrowed have been returned. doneCopying() 
-                // returns our borrowed CopiedBlock, allowing the copying phase to finish.
-                copyVisitor.doneCopying();
-
-                WTF::releaseFastMallocFreeMemoryForThisThread();
-
-                break;
-            }
-            case NoPhase:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            case Exit:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
-        }
-    }
-}
-
-void GCThread::gcThreadStartFunc(void* data)
-{
-    GCThread* thread = static_cast&lt;GCThread*&gt;(data);
-    thread-&gt;gcThreadMain();
-}
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCThreadh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/heap/GCThread.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCThread.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/GCThread.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,65 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``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 ITS 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 GCThread_h
-#define GCThread_h
-
-#include &lt;wtf/Deque.h&gt;
-#include &lt;wtf/Threading.h&gt;
-
-namespace JSC {
-
-class Heap;
-class SlotVisitor;
-
-enum GCPhase {
-    NoPhase,
-    Mark,
-    Copy,
-    Exit
-};
-
-class GCThread {
-public:
-    GCThread(Heap&amp;, std::unique_ptr&lt;SlotVisitor&gt;);
-
-    SlotVisitor* slotVisitor();
-    ThreadIdentifier threadID();
-    void initializeThreadID(ThreadIdentifier);
-
-    static void gcThreadStartFunc(void*);
-
-private:
-    void gcThreadMain();
-    GCPhase waitForNextPhase();
-
-    ThreadIdentifier m_threadID;
-    Heap&amp; m_heap;
-    std::unique_ptr&lt;SlotVisitor&gt; m_slotVisitor;
-};
-
-} // namespace JSC
-
-#endif
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2009, 2011, 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;FullGCActivityCallback.h&quot;
</span><span class="cx"> #include &quot;GCActivityCallback.h&quot;
</span><span class="cx"> #include &quot;GCIncomingRefCountedSetInlines.h&quot;
</span><ins>+#include &quot;HeapHelperPool.h&quot;
</ins><span class="cx"> #include &quot;HeapIterationScope.h&quot;
</span><span class="cx"> #include &quot;HeapRootVisitor.h&quot;
</span><span class="cx"> #include &quot;HeapStatistics.h&quot;
</span><span class="lines">@@ -336,7 +337,6 @@
</span><span class="cx">     , m_deprecatedExtraMemorySize(0)
</span><span class="cx">     , m_machineThreads(this)
</span><span class="cx">     , m_slotVisitor(*this)
</span><del>-    , m_copyVisitor(*this)
</del><span class="cx">     , m_handleSet(vm)
</span><span class="cx">     , m_isSafeToCollect(false)
</span><span class="cx">     , m_writeBarrierBuffer(256)
</span><span class="lines">@@ -356,22 +356,8 @@
</span><span class="cx"> #if USE(CF)
</span><span class="cx">     , m_delayedReleaseRecursionCount(0)
</span><span class="cx"> #endif
</span><ins>+    , m_helperClient(&amp;heapHelperPool())
</ins><span class="cx"> {
</span><del>-    {
-        // Grab the lock so the new GC threads can be properly initialized before they start running.
-        std::unique_lock&lt;Lock&gt; lock(m_phaseMutex);
-        for (unsigned i = 1; i &lt; Options::numberOfGCMarkers(); ++i) {
-            m_numberOfActiveGCThreads++;
-            GCThread* newThread = new GCThread(*this, std::make_unique&lt;SlotVisitor&gt;(*this));
-            ThreadIdentifier threadID = createThread(GCThread::gcThreadStartFunc, newThread, &quot;JavaScriptCore::Marking&quot;);
-            newThread-&gt;initializeThreadID(threadID);
-            m_gcThreads.append(newThread);
-        }
-        
-        // Wait for all the GCThreads to get to the right place.
-        m_activityConditionVariable.wait(lock, [this] { return !m_numberOfActiveGCThreads; });
-    }
-    
</del><span class="cx">     m_storageSpace.init();
</span><span class="cx">     if (Options::verifyHeap())
</span><span class="cx">         m_verifier = std::make_unique&lt;HeapVerifier&gt;(this, Options::numberOfGCCyclesToRecordForVerification());
</span><span class="lines">@@ -381,21 +367,6 @@
</span><span class="cx"> {
</span><span class="cx">     for (WeakBlock* block : m_logicallyEmptyWeakBlocks)
</span><span class="cx">         WeakBlock::destroy(block);
</span><del>-
-    // Destroy our marking threads.
-    {
-        std::lock_guard&lt;Lock&gt; markingLock(m_markingMutex);
-        std::lock_guard&lt;Lock&gt; phaseLock(m_phaseMutex);
-        ASSERT(m_currentPhase == NoPhase);
-        m_parallelMarkersShouldExit = true;
-        m_gcThreadsShouldWait = false;
-        m_currentPhase = Exit;
-        m_phaseConditionVariable.notifyAll();
-    }
-    for (unsigned i = 0; i &lt; m_gcThreads.size(); ++i) {
-        waitForThreadCompletion(m_gcThreads[i]-&gt;threadID());
-        delete m_gcThreads[i];
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Heap::isPagedOut(double deadline)
</span><span class="lines">@@ -570,12 +541,39 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_operationInProgress == FullCollection)
</span><span class="cx">         m_opaqueRoots.clear();
</span><del>-    {
-        std::lock_guard&lt;Lock&gt; lock(m_markingMutex);
-        m_parallelMarkersShouldExit = false;
-        startNextPhase(Mark);
-    }
</del><ins>+
+    m_shouldHashCons = m_vm-&gt;haveEnoughNewStringsToHashCons();
+
+    m_parallelMarkersShouldExit = false;
+
+    m_helperClient.setFunction(
+        [this] () {
+            SlotVisitor* slotVisitor;
+            {
+                LockHolder locker(m_parallelSlotVisitorLock);
+                if (m_availableParallelSlotVisitors.isEmpty()) {
+                    std::unique_ptr&lt;SlotVisitor&gt; newVisitor =
+                        std::make_unique&lt;SlotVisitor&gt;(*this);
+                    slotVisitor = newVisitor.get();
+                    m_parallelSlotVisitors.append(WTF::move(newVisitor));
+                } else
+                    slotVisitor = m_availableParallelSlotVisitors.takeLast();
+            }
+
+            {
+                ParallelModeEnabler parallelModeEnabler(*slotVisitor);
+                slotVisitor-&gt;didStartMarking();
+                slotVisitor-&gt;drainFromShared(SlotVisitor::SlaveDrain);
+            }
+
+            {
+                LockHolder locker(m_parallelSlotVisitorLock);
+                m_availableParallelSlotVisitors.append(slotVisitor);
+            }
+        });
+
</ins><span class="cx">     m_slotVisitor.didStartMarking();
</span><ins>+    
</ins><span class="cx">     HeapRootVisitor heapRootVisitor(m_slotVisitor);
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -603,8 +601,7 @@
</span><span class="cx">         m_parallelMarkersShouldExit = true;
</span><span class="cx">         m_markingConditionVariable.notifyAll();
</span><span class="cx">     }
</span><del>-    ASSERT(m_currentPhase == Mark);
-    endCurrentPhase();
</del><ins>+    m_helperClient.finish();
</ins><span class="cx">     updateObjectCounts(gcStartTime);
</span><span class="cx">     resetVisitors();
</span><span class="cx"> }
</span><span class="lines">@@ -633,15 +630,15 @@
</span><span class="cx">             }
</span><span class="cx">             m_copyIndex = 0;
</span><span class="cx">         }
</span><del>-        
-        startNextPhase(Copy);
-        
-        m_copyVisitor.startCopying();
-        m_copyVisitor.copyFromShared();
-        m_copyVisitor.doneCopying();
</del><span class="cx"> 
</span><del>-        ASSERT(m_currentPhase == Copy);
-        endCurrentPhase();
</del><ins>+        m_helperClient.runFunctionInParallel(
+            [this] () {
+                CopyVisitor copyVisitor(*this);
+                copyVisitor.startCopying();
+                copyVisitor.copyFromShared();
+                copyVisitor.doneCopying();
+                WTF::releaseFastMallocFreeMemoryForThisThread();
+            });
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     m_storageSpace.doneCopying();
</span><span class="lines">@@ -870,8 +867,8 @@
</span><span class="cx"> {
</span><span class="cx">     m_slotVisitor.reset();
</span><span class="cx"> 
</span><del>-    for (GCThread* thread : m_gcThreads)
-        thread-&gt;slotVisitor()-&gt;reset();
</del><ins>+    for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+        parallelVisitor-&gt;reset();
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(m_sharedMarkStack.isEmpty());
</span><span class="cx">     m_weakReferenceHarvesters.removeAll();
</span><span class="lines">@@ -1532,45 +1529,25 @@
</span><span class="cx"> size_t Heap::threadVisitCount()
</span><span class="cx"> {       
</span><span class="cx">     unsigned long result = 0;
</span><del>-    for (unsigned i = 0; i &lt; m_gcThreads.size(); ++i)
-        result += m_gcThreads[i]-&gt;slotVisitor()-&gt;visitCount();
</del><ins>+    for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+        result += parallelVisitor-&gt;visitCount();
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t Heap::threadBytesVisited()
</span><span class="cx"> {       
</span><span class="cx">     size_t result = 0;
</span><del>-    for (unsigned i = 0; i &lt; m_gcThreads.size(); ++i)
-        result += m_gcThreads[i]-&gt;slotVisitor()-&gt;bytesVisited();
</del><ins>+    for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+        result += parallelVisitor-&gt;bytesVisited();
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t Heap::threadBytesCopied()
</span><span class="cx"> {       
</span><span class="cx">     size_t result = 0;
</span><del>-    for (unsigned i = 0; i &lt; m_gcThreads.size(); ++i)
-        result += m_gcThreads[i]-&gt;slotVisitor()-&gt;bytesCopied();
</del><ins>+    for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+        result += parallelVisitor-&gt;bytesCopied();
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::startNextPhase(GCPhase phase)
-{
-    std::lock_guard&lt;Lock&gt; lock(m_phaseMutex);
-    ASSERT(!m_gcThreadsShouldWait);
-    ASSERT(m_currentPhase == NoPhase);
-    m_gcThreadsShouldWait = true;
-    m_currentPhase = phase;
-    m_phaseConditionVariable.notifyAll();
-}
-
-void Heap::endCurrentPhase()
-{
-    ASSERT(m_gcThreadsShouldWait);
-    std::unique_lock&lt;Lock&gt; lock(m_phaseMutex);
-    m_currentPhase = NoPhase;
-    m_gcThreadsShouldWait = false;
-    m_phaseConditionVariable.notifyAll();
-    m_activityConditionVariable.wait(lock, [this] { return !m_numberOfActiveGCThreads; });
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -26,7 +26,6 @@
</span><span class="cx"> #include &quot;CodeBlockSet.h&quot;
</span><span class="cx"> #include &quot;CopyVisitor.h&quot;
</span><span class="cx"> #include &quot;GCIncomingRefCountedSet.h&quot;
</span><del>-#include &quot;GCThread.h&quot;
</del><span class="cx"> #include &quot;HandleSet.h&quot;
</span><span class="cx"> #include &quot;HandleStack.h&quot;
</span><span class="cx"> #include &quot;HeapOperation.h&quot;
</span><span class="lines">@@ -46,6 +45,7 @@
</span><span class="cx"> #include &quot;WriteBarrierSupport.h&quot;
</span><span class="cx"> #include &lt;wtf/HashCountedSet.h&gt;
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><ins>+#include &lt;wtf/ParallelHelperPool.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -347,8 +347,6 @@
</span><span class="cx">     size_t threadDupStrings();
</span><span class="cx"> 
</span><span class="cx">     void getNextBlocksToCopy(size_t&amp;, size_t&amp;);
</span><del>-    void startNextPhase(GCPhase);
-    void endCurrentPhase();
</del><span class="cx"> 
</span><span class="cx">     const HeapType m_heapType;
</span><span class="cx">     const size_t m_ramSize;
</span><span class="lines">@@ -383,8 +381,15 @@
</span><span class="cx">     MachineThreads m_machineThreads;
</span><span class="cx">     
</span><span class="cx">     SlotVisitor m_slotVisitor;
</span><del>-    CopyVisitor m_copyVisitor;
</del><span class="cx"> 
</span><ins>+    // We pool the slot visitors used by parallel marking threads. It's useful to be able to
+    // enumerate over them, and it's useful to have them cache some small amount of memory from
+    // one GC to the next. GC marking threads claim these at the start of marking, and return
+    // them at the end.
+    Vector&lt;std::unique_ptr&lt;SlotVisitor&gt;&gt; m_parallelSlotVisitors;
+    Vector&lt;SlotVisitor*&gt; m_availableParallelSlotVisitors;
+    Lock m_parallelSlotVisitorLock;
+
</ins><span class="cx">     HandleSet m_handleSet;
</span><span class="cx">     HandleStack m_handleStack;
</span><span class="cx">     CodeBlockSet m_codeBlocks;
</span><span class="lines">@@ -422,8 +427,6 @@
</span><span class="cx"> 
</span><span class="cx">     bool m_shouldHashCons { false };
</span><span class="cx"> 
</span><del>-    Vector&lt;GCThread*&gt; m_gcThreads;
-
</del><span class="cx">     Lock m_markingMutex;
</span><span class="cx">     Condition m_markingConditionVariable;
</span><span class="cx">     MarkStackArray m_sharedMarkStack;
</span><span class="lines">@@ -439,15 +442,10 @@
</span><span class="cx">     size_t m_copyIndex { 0 };
</span><span class="cx">     static const size_t s_blockFragmentLength = 32;
</span><span class="cx"> 
</span><del>-    Lock m_phaseMutex;
-    Condition m_phaseConditionVariable;
-    Condition m_activityConditionVariable;
-    unsigned m_numberOfActiveGCThreads { 0 };
-    bool m_gcThreadsShouldWait { false };
-    GCPhase m_currentPhase { NoPhase };
-
</del><span class="cx">     ListableHandler&lt;WeakReferenceHarvester&gt;::List m_weakReferenceHarvesters;
</span><span class="cx">     ListableHandler&lt;UnconditionalFinalizer&gt;::List m_unconditionalFinalizers;
</span><ins>+
+    ParallelHelperClient m_helperClient;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapHelperPoolcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/HeapHelperPool.cpp (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapHelperPool.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/HeapHelperPool.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,48 @@
</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. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;HeapHelperPool.h&quot;
+
+#include &lt;mutex&gt;
+#include &quot;Options.h&quot;
+
+namespace JSC {
+
+ParallelHelperPool&amp; heapHelperPool()
+{
+    static std::once_flag initializeHelperPoolOnceFlag;
+    static ParallelHelperPool* helperPool;
+    std::call_once(
+        initializeHelperPoolOnceFlag,
+        [] {
+            helperPool = new ParallelHelperPool();
+            helperPool-&gt;ensureThreads(Options::numberOfGCMarkers() - 1);
+        });
+    return *helperPool;
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapHelperPoolh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/HeapHelperPool.h (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapHelperPool.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/HeapHelperPool.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,38 @@
</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 HeapHelperPool_h
+#define HeapHelperPool_h
+
+#include &lt;wtf/ParallelHelperPool.h&gt;
+
+namespace JSC {
+
+ParallelHelperPool&amp; heapHelperPool();
+
+} // namespace JSC
+
+#endif // HeapHelperPool_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkStackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkStack.cpp (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkStack.cpp        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/MarkStack.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2009, 2011, 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">@@ -107,7 +107,8 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    size_t numberOfCellsToSteal = (other.size() + idleThreadCount - 1) / idleThreadCount; // Round up to steal 1 / 1.
</del><ins>+    // Steal ceil(other.size() / idleThreadCount) things.
+    size_t numberOfCellsToSteal = (other.size() + idleThreadCount - 1) / idleThreadCount;
</ins><span class="cx">     while (numberOfCellsToSteal-- &gt; 0 &amp;&amp; other.canRemoveLast())
</span><span class="cx">         append(other.removeLast());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -30,7 +30,6 @@
</span><span class="cx"> #include &quot;ConservativeRoots.h&quot;
</span><span class="cx"> #include &quot;CopiedSpace.h&quot;
</span><span class="cx"> #include &quot;CopiedSpaceInlines.h&quot;
</span><del>-#include &quot;GCThread.h&quot;
</del><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSDestructibleObject.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -67,10 +66,7 @@
</span><span class="cx">     if (heap()-&gt;operationInProgress() == FullCollection)
</span><span class="cx">         ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
</span><span class="cx"> 
</span><del>-    m_heap.m_shouldHashCons = m_heap.m_vm-&gt;haveEnoughNewStringsToHashCons();
</del><span class="cx">     m_shouldHashCons = m_heap.m_shouldHashCons;
</span><del>-    for (unsigned i = 0; i &lt; m_heap.m_gcThreads.size(); ++i)
-        m_heap.m_gcThreads[i]-&gt;slotVisitor()-&gt;m_shouldHashCons = m_heap.m_shouldHashCons;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::reset()
</span><span class="lines">@@ -221,7 +217,7 @@
</span><span class="cx">                 if (m_heap.m_parallelMarkersShouldExit)
</span><span class="cx">                     return;
</span><span class="cx">             }
</span><del>-           
</del><ins>+
</ins><span class="cx">             m_stack.stealSomeCellsFrom(
</span><span class="cx">                 m_heap.m_sharedMarkStack, m_heap.m_numberOfWaitingParallelMarkers);
</span><span class="cx">             m_heap.m_numberOfActiveParallelMarkers++;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitBinarySwitchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/BinarySwitch.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/BinarySwitch.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/jit/BinarySwitch.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><del>-#include &quot;WeakRandom.h&quot;
</del><ins>+#include &lt;wtf/WeakRandom.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCodeCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CodeCache.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CodeCache.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/runtime/CodeCache.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -31,10 +31,10 @@
</span><span class="cx"> #include &quot;SourceCode.h&quot;
</span><span class="cx"> #include &quot;Strong.h&quot;
</span><span class="cx"> #include &quot;VariableEnvironment.h&quot;
</span><del>-#include &quot;WeakRandom.h&quot;
</del><span class="cx"> #include &lt;wtf/CurrentTime.h&gt;
</span><span class="cx"> #include &lt;wtf/Forward.h&gt;
</span><span class="cx"> #include &lt;wtf/RandomNumber.h&gt;
</span><ins>+#include &lt;wtf/WeakRandom.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -54,7 +54,6 @@
</span><span class="cx"> #include &quot;TypedArrayController.h&quot;
</span><span class="cx"> #include &quot;VMEntryRecord.h&quot;
</span><span class="cx"> #include &quot;Watchpoint.h&quot;
</span><del>-#include &quot;WeakRandom.h&quot;
</del><span class="cx"> #include &lt;wtf/Bag.h&gt;
</span><span class="cx"> #include &lt;wtf/BumpPointerAllocator.h&gt;
</span><span class="cx"> #include &lt;wtf/DateMath.h&gt;
</span><span class="lines">@@ -67,6 +66,7 @@
</span><span class="cx"> #include &lt;wtf/ThreadSafeRefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/ThreadSpecific.h&gt;
</span><span class="cx"> #include &lt;wtf/WTFThreadData.h&gt;
</span><ins>+#include &lt;wtf/WeakRandom.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/SymbolRegistry.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeWeakRandomh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/runtime/WeakRandom.h (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/WeakRandom.h        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/JavaScriptCore/runtime/WeakRandom.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,100 +0,0 @@
</span><del>-/*
- * Copyright (C) 2009 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. 
- *
- *
- * Copyright (c) 2009 Ian C. Bullard
- * 
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the &quot;Software&quot;), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef WeakRandom_h
-#define WeakRandom_h
-
-#include &lt;limits.h&gt;
-#include &lt;wtf/StdLibExtras.h&gt;
-
-namespace JSC {
-
-class WeakRandom {
-friend class JSGlobalObject; // For access to initializeSeed() during replay.
-public:
-    WeakRandom(unsigned seed)
-    {
-        initializeSeed(seed);
-    }
-    
-    // Returns the seed provided that you've never called get() or getUint32().
-    unsigned seedUnsafe() const { return m_high; }
-
-    double get()
-    {
-        return advance() / (UINT_MAX + 1.0);
-    }
-
-    unsigned getUint32()
-    {
-        return advance();
-    }
-
-private:
-    unsigned advance()
-    {
-        m_high = (m_high &lt;&lt; 16) + (m_high &gt;&gt; 16);
-        m_high += m_low;
-        m_low += m_high;
-        return m_high;
-    }
-
-    void initializeSeed(unsigned seed)
-    {
-        m_low = seed ^ 0x49616E42;
-        m_high = seed;
-    }
-
-    unsigned m_low;
-    unsigned m_high;
-};
-
-} // namespace JSC
-
-#endif // WeakRandom_h
</del></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/WTF/ChangeLog        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,3 +1,100 @@
</span><ins>+2015-09-24  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        VMs should share GC threads
+        https://bugs.webkit.org/show_bug.cgi?id=149433
+        rdar://problem/12859344
+
+        Reviewed by Geoffrey Garen.
+
+        This adds two major things to WTF: WeakRandom and ParallelHelperPool. WeakRandom was
+        already in JSC; we're just hoisting it into WTF. It's just a weak random number generator
+        that's suitable for places where you need just a tiny bit of randomness.
+
+        ParallelHelperPool is a new API that simplifies data-parallel algorithms like the JSC GC.
+        In a data-parallel algorithm, we want to run one task on as many cores as possible and let
+        the task worry about which subset of the input data to work on. In some cases, the
+        algorithm will not need to do any load balancing - and if load balancing is required, it's
+        up to the user. This is appropriate in contexts where the load balancing needs to be
+        custom-tuned for performance, like the GC's marking phase.
+
+        This new API has three concepts: task, client, and pool. A task is a reference counted
+        object with a run() method, which may be run in parallel. It is usually used to wrap a
+        functor. A pool is a pool of threads that can run things. A client is a placeholder for a
+        task. A client can have zero or one tasks. A client must be registered with a pool. When a
+        client has a task, the pool's threads may choose to run it. If a thread starts running a
+        task, it will run it to completion. When the task returns on any thread, the client takes
+        it to mean that the task should be removed. That means that any currently running instances
+        of the task will finish but no new threads will attempt to run the task. You can easily ask
+        a client to wait until a task finishes. You can also easily ask a client to run a task on
+        the current thread in addition to possibly some helper threads from the pool.
+
+        For some data-parallel algorithms, programming with ParallelHelperPool is as easy as:
+
+        client.runFunctionInParallel(
+            [=] () {
+                do things;
+            });
+
+        Note that you cannot tell ahead of time how many threads will join to help the task.
+        Threads may become available after the task has already started running. Those threads may
+        join after the other threads have already started. It's not advisable to make algorithmic
+        decisions based on client.numberOfActiveThreads(), since that number may change. Usually
+        the best way to use ParallelHelperPool is with an algorithm that has its own custom
+        worklist. An example of a very simple custom worklist is the one in the JSC GC's copying
+        phase - it's just a Vector and an index that indicates the next set of elements to process.
+
+        This new API was initially designed to simplify how GCThread works, by replacing Phase with
+        a callback that contains the phase's workload. I then realized that with a few tweaks, I
+        could make this somewhat general enough that it might become interesting outside GC. I also
+        realized that I could use this to enable thread sharing. So, although the API is kinda
+        quirky, it's grounded in the reality of how the JSC GC does parallelism.
+
+        * WTF.vcxproj/WTF.vcxproj:
+        * WTF.vcxproj/WTF.vcxproj.filters:
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/CMakeLists.txt:
+        * wtf/ParallelHelperPool.cpp: Added.
+        (WTF::ParallelHelperClient::ParallelHelperClient):
+        (WTF::ParallelHelperClient::~ParallelHelperClient):
+        (WTF::ParallelHelperClient::setTask):
+        (WTF::ParallelHelperClient::finish):
+        (WTF::ParallelHelperClient::doSomeHelping):
+        (WTF::ParallelHelperClient::runTaskInParallel):
+        (WTF::ParallelHelperClient::claimTask):
+        (WTF::ParallelHelperClient::runTask):
+        (WTF::ParallelHelperPool::ParallelHelperPool):
+        (WTF::ParallelHelperPool::~ParallelHelperPool):
+        (WTF::ParallelHelperPool::addThreads):
+        (WTF::ParallelHelperPool::ensureThreads):
+        (WTF::ParallelHelperPool::doSomeHelping):
+        (WTF::ParallelHelperPool::didMakeWorkAvailable):
+        (WTF::ParallelHelperPool::helperThreadBody):
+        (WTF::ParallelHelperPool::hasClientWithTask):
+        (WTF::ParallelHelperPool::getClientWithTask):
+        (WTF::ParallelHelperPool::waitForClientWithTask):
+        * wtf/ParallelHelperPool.h: Added.
+        (WTF::ParallelHelperClient::setFunction):
+        (WTF::ParallelHelperClient::runFunctionInParallel):
+        (WTF::ParallelHelperClient::pool):
+        (WTF::ParallelHelperClient::numberOfActiveThreads):
+        (WTF::ParallelHelperPool::numberOfThreads):
+        * wtf/SharedTask.h: Added.
+        (WTF::SharedTask::SharedTask):
+        (WTF::SharedTask::~SharedTask):
+        (WTF::SharedTaskFunctor::SharedTaskFunctor):
+        (WTF::createSharedTask):
+        * wtf/WeakRandom.h: Copied from Source/JavaScriptCore/runtime/WeakRandom.h.
+        (WTF::WeakRandom::WeakRandom):
+        (WTF::WeakRandom::initializeSeed):
+        (WTF::WeakRandom::seedUnsafe):
+        (WTF::WeakRandom::getUint32):
+        (WTF::WeakRandom::advance):
+        (JSC::WeakRandom::WeakRandom): Deleted.
+        (JSC::WeakRandom::seedUnsafe): Deleted.
+        (JSC::WeakRandom::getUint32): Deleted.
+        (JSC::WeakRandom::advance): Deleted.
+        (JSC::WeakRandom::initializeSeed): Deleted.
+
</ins><span class="cx"> 2015-09-25  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Clean up CMake build on Mac
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -115,6 +115,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\OSAllocatorWin.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\OSRandomSource.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\PageBlock.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\wtf\ParallelHelperPool.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\ParallelJobsGeneric.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\ParkingLot.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\PrintStream.cpp&quot; /&gt;
</span><span class="lines">@@ -246,6 +247,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PageAllocation.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PageBlock.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PageReservation.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\ParallelHelperPool.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobs.h&quot; /&gt;
</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="lines">@@ -269,6 +271,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SegmentedVector.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SentinelLinkedList.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SHA1.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\SharedTask.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SinglyLinkedList.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SixCharacterHash.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\StackBounds.h&quot; /&gt;
</span><span class="lines">@@ -313,6 +316,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\VMTags.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\win\GDIObject.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\win\WorkItemWin.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\wtf\WeakRandom.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\WordLock.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\WorkQueue.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\WTFThreadData.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceWTFWTFvcxprojWTFvcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
</del><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
</ins><span class="cx"> &lt;Project ToolsVersion=&quot;4.0&quot; xmlns=&quot;http://schemas.microsoft.com/developer/msbuild/2003&quot;&gt;
</span><span class="cx">   &lt;ItemGroup&gt;
</span><span class="cx">     &lt;Filter Include=&quot;dtoa&quot;&gt;
</span><span class="lines">@@ -174,6 +174,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\PageBlock.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;wtf&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\wtf\ParallelHelperPool.cpp&quot;&gt;
+      &lt;Filter&gt;wtf&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\wtf\ParallelJobsGeneric.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;wtf&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -547,6 +550,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\PageReservation.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\ParallelHelperPool.h&quot;&gt;
+      &lt;Filter&gt;wtf&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\ParallelJobs.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;wtf&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><span class="lines">@@ -604,6 +610,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SHA1.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\SharedTask.h&quot;&gt;
+      &lt;Filter&gt;wtf&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\wtf\SinglyLinkedList.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 (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx">                 0F0D85B417234CC100338210 /* NoLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0D85B317234CB100338210 /* NoLock.h */; };
</span><span class="cx">                 0F2B66A617B6B4FB00A7AE3F /* DeferrableRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */; };
</span><span class="cx">                 0F2B66A717B6B4FD00A7AE3F /* FlipBytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */; };
</span><ins>+                0F3501641BB258D500F0A2A3 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3501631BB258C800F0A2A3 /* WeakRandom.h */; };
</ins><span class="cx">                 0F824A681B7443A0002E345D /* ParkingLot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F824A641B7443A0002E345D /* ParkingLot.cpp */; };
</span><span class="cx">                 0F824A691B7443A0002E345D /* ParkingLot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F824A651B7443A0002E345D /* ParkingLot.h */; };
</span><span class="cx">                 0F87105A16643F190090B0AD /* RawPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F87105916643F190090B0AD /* RawPointer.h */; };
</span><span class="lines">@@ -47,7 +48,10 @@
</span><span class="cx">                 0FE1646B1B6FFC9600400E7C /* Lock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE164691B6FFC9600400E7C /* Lock.h */; };
</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><ins>+                0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */; };
</ins><span class="cx">                 0FED67B61B22D4D80066CE15 /* TinyPtrSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */; };
</span><ins>+                0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */; };
+                0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */; };
</ins><span class="cx">                 14022F4118F5C3FC007FF0EB /* libbmalloc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14022F4018F5C3FC007FF0EB /* libbmalloc.a */; };
</span><span class="cx">                 143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; };
</span><span class="cx">                 143F61201565F0F900DB514A /* RAMSize.h in Headers */ = {isa = PBXBuildFile; fileRef = 143F611E1565F0F900DB514A /* RAMSize.h */; settings = {ATTRIBUTES = (); }; };
</span><span class="lines">@@ -312,6 +316,7 @@
</span><span class="cx">                 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeferrableRefCounted.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlipBytes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F300B7D18AB48B400A6D72E /* HashMethod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashMethod.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F3501631BB258C800F0A2A3 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F824A641B7443A0002E345D /* ParkingLot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParkingLot.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F824A651B7443A0002E345D /* ParkingLot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParkingLot.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F87105916643F190090B0AD /* RawPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawPointer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -335,7 +340,10 @@
</span><span class="cx">                 0FE164691B6FFC9600400E7C /* Lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lock.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</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><ins>+                0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTask.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><ins>+                0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParallelHelperPool.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelHelperPool.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 14022F4018F5C3FC007FF0EB /* libbmalloc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libbmalloc.a; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="cx">                 143F611D1565F0F900DB514A /* RAMSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RAMSize.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 143F611E1565F0F900DB514A /* RAMSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAMSize.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -818,6 +826,8 @@
</span><span class="cx">                                 A8A472E3151A825B004123FF /* PageBlock.cpp */,
</span><span class="cx">                                 A8A472E4151A825B004123FF /* PageBlock.h */,
</span><span class="cx">                                 A8A472E5151A825B004123FF /* PageReservation.h */,
</span><ins>+                                0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */,
+                                0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */,
</ins><span class="cx">                                 A8A472E6151A825B004123FF /* ParallelJobs.h */,
</span><span class="cx">                                 A8A472E9151A825B004123FF /* ParallelJobsLibdispatch.h */,
</span><span class="cx">                                 0F824A641B7443A0002E345D /* ParkingLot.cpp */,
</span><span class="lines">@@ -855,6 +865,7 @@
</span><span class="cx">                                 A8A47307151A825B004123FF /* SentinelLinkedList.h */,
</span><span class="cx">                                 A8A47308151A825B004123FF /* SHA1.cpp */,
</span><span class="cx">                                 A8A47309151A825B004123FF /* SHA1.h */,
</span><ins>+                                0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */,
</ins><span class="cx">                                 A8A4730A151A825B004123FF /* SimpleStats.h */,
</span><span class="cx">                                 A8A4730B151A825B004123FF /* SinglyLinkedList.h */,
</span><span class="cx">                                 A748744F17A0BDAE00FA04CB /* SixCharacterHash.cpp */,
</span><span class="lines">@@ -892,6 +903,7 @@
</span><span class="cx">                                 A8A47371151A825B004123FF /* VectorTraits.h */,
</span><span class="cx">                                 A8A47372151A825B004123FF /* VMTags.h */,
</span><span class="cx">                                 974CFC8D16A4F327006D5404 /* WeakPtr.h */,
</span><ins>+                                0F3501631BB258C800F0A2A3 /* WeakRandom.h */,
</ins><span class="cx">                                 0FE4479A1B7AAA03009498EB /* WordLock.cpp */,
</span><span class="cx">                                 0FE4479B1B7AAA03009498EB /* WordLock.h */,
</span><span class="cx">                                 E4A0AD371A96245500536DF6 /* WorkQueue.cpp */,
</span><span class="lines">@@ -1063,6 +1075,7 @@
</span><span class="cx">                                 A8A47385151A825B004123FF /* ASCIICType.h in Headers */,
</span><span class="cx">                                 A8A47434151A825B004123FF /* ASCIIFastPath.h in Headers */,
</span><span class="cx">                                 A8A47387151A825B004123FF /* Assertions.h in Headers */,
</span><ins>+                                0F3501641BB258D500F0A2A3 /* WeakRandom.h in Headers */,
</ins><span class="cx">                                 A8A47388151A825B004123FF /* Atomics.h in Headers */,
</span><span class="cx">                                 A8A47436151A825B004123FF /* AtomicString.h in Headers */,
</span><span class="cx">                                 A8A47437151A825B004123FF /* AtomicStringHash.h in Headers */,
</span><span class="lines">@@ -1074,6 +1087,7 @@
</span><span class="cx">                                 8134013915B092FD001FF0B8 /* Base64.h in Headers */,
</span><span class="cx">                                 A8A473A9151A825B004123FF /* bignum-dtoa.h in Headers */,
</span><span class="cx">                                 A8A473AB151A825B004123FF /* bignum.h in Headers */,
</span><ins>+                                0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */,
</ins><span class="cx">                                 A8A47452151A825B004123FF /* BinarySemaphore.h in Headers */,
</span><span class="cx">                                 A8A4738A151A825B004123FF /* Bitmap.h in Headers */,
</span><span class="cx">                                 A8A4738C151A825B004123FF /* BitVector.h in Headers */,
</span><span class="lines">@@ -1126,6 +1140,7 @@
</span><span class="cx">                                 A8A473D4151A825B004123FF /* HashFunctions.h in Headers */,
</span><span class="cx">                                 A8A473D5151A825B004123FF /* HashIterators.h in Headers */,
</span><span class="cx">                                 A8A473D6151A825B004123FF /* HashMap.h in Headers */,
</span><ins>+                                0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */,
</ins><span class="cx">                                 A8A473D7151A825B004123FF /* HashSet.h in Headers */,
</span><span class="cx">                                 A8A473D9151A825B004123FF /* HashTable.h in Headers */,
</span><span class="cx">                                 A8A473DA151A825B004123FF /* HashTraits.h in Headers */,
</span><span class="lines">@@ -1392,6 +1407,7 @@
</span><span class="cx">                                 2CDED0F318115C85004DBA70 /* RunLoop.cpp in Sources */,
</span><span class="cx">                                 2CDED0EF18115C38004DBA70 /* RunLoopCF.cpp in Sources */,
</span><span class="cx">                                 1469419316EAAF6D0024E146 /* RunLoopTimerCF.cpp in Sources */,
</span><ins>+                                0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */,
</ins><span class="cx">                                 1469419916EAB0410024E146 /* SchedulePairCF.cpp in Sources */,
</span><span class="cx">                                 1469419716EAAFF80024E146 /* SchedulePairMac.mm in Sources */,
</span><span class="cx">                                 A8A47421151A825B004123FF /* SHA1.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWTFwtfCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CMakeLists.txt (190266 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CMakeLists.txt        2015-09-26 09:35:40 UTC (rev 190266)
+++ trunk/Source/WTF/wtf/CMakeLists.txt        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     RetainPtr.h
</span><span class="cx">     RunLoop.h
</span><span class="cx">     SHA1.h
</span><ins>+    SharedTask.h
</ins><span class="cx">     SaturatedArithmetic.h
</span><span class="cx">     SegmentedVector.h
</span><span class="cx">     StackBounds.h
</span><span class="lines">@@ -167,6 +168,7 @@
</span><span class="cx">     NumberOfCores.cpp
</span><span class="cx">     OSRandomSource.cpp
</span><span class="cx">     PageBlock.cpp
</span><ins>+    ParallelHelperPool.cpp
</ins><span class="cx">     ParallelJobsGeneric.cpp
</span><span class="cx">     ParkingLot.cpp
</span><span class="cx">     PrintStream.cpp
</span></span></pre></div>
<a id="trunkSourceWTFwtfParallelHelperPoolcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/ParallelHelperPool.cpp (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParallelHelperPool.cpp                                (rev 0)
+++ trunk/Source/WTF/wtf/ParallelHelperPool.cpp        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,241 @@
</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. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;ParallelHelperPool.h&quot;
+
+#include &quot;DataLog.h&quot;
+#include &quot;StringPrintStream.h&quot;
+
+namespace WTF {
+
+ParallelHelperClient::ParallelHelperClient(RefPtr&lt;ParallelHelperPool&gt; pool)
+    : m_pool(pool)
+{
+    LockHolder locker(m_pool-&gt;m_lock);
+    RELEASE_ASSERT(!m_pool-&gt;m_isDying);
+    m_pool-&gt;m_clients.append(this);
+}
+
+ParallelHelperClient::~ParallelHelperClient()
+{
+    LockHolder locker(m_pool-&gt;m_lock);
+    finish(locker);
+
+    for (size_t i = 0; i &lt; m_pool-&gt;m_clients.size(); ++i) {
+        if (m_pool-&gt;m_clients[i] == this) {
+            m_pool-&gt;m_clients[i] = m_pool-&gt;m_clients.last();
+            m_pool-&gt;m_clients.removeLast();
+            break;
+        }
+    }
+}
+
+void ParallelHelperClient::setTask(RefPtr&lt;SharedTask&gt; task)
+{
+    LockHolder locker(m_pool-&gt;m_lock);
+    RELEASE_ASSERT(!m_task);
+    m_task = task;
+    m_pool-&gt;didMakeWorkAvailable(locker);
+}
+
+void ParallelHelperClient::finish()
+{
+    LockHolder locker(m_pool-&gt;m_lock);
+    finish(locker);
+}
+
+void ParallelHelperClient::doSomeHelping()
+{
+    RefPtr&lt;SharedTask&gt; task;
+    {
+        LockHolder locker(m_pool-&gt;m_lock);
+        task = claimTask(locker);
+        if (!task)
+            return;
+    }
+
+    runTask(task);
+}
+
+void ParallelHelperClient::runTaskInParallel(RefPtr&lt;SharedTask&gt; task)
+{
+    setTask(task);
+    doSomeHelping();
+    finish();
+}
+
+void ParallelHelperClient::finish(const LockHolder&amp;)
+{
+    m_task = nullptr;
+    while (m_numActive)
+        m_pool-&gt;m_workCompleteCondition.wait(m_pool-&gt;m_lock);
+}
+
+RefPtr&lt;SharedTask&gt; ParallelHelperClient::claimTask(const LockHolder&amp;)
+{
+    if (!m_task)
+        return nullptr;
+    
+    m_numActive++;
+    return m_task;
+}
+
+void ParallelHelperClient::runTask(RefPtr&lt;SharedTask&gt; task)
+{
+    RELEASE_ASSERT(m_numActive);
+    RELEASE_ASSERT(task);
+
+    task-&gt;run();
+
+    {
+        LockHolder locker(m_pool-&gt;m_lock);
+        RELEASE_ASSERT(m_numActive);
+        // No new task could have been installed, since we were still active.
+        RELEASE_ASSERT(!m_task || m_task == task);
+        m_task = nullptr;
+        m_numActive--;
+        if (!m_numActive)
+            m_pool-&gt;m_workCompleteCondition.notifyAll();
+    }
+}
+
+ParallelHelperPool::ParallelHelperPool()
+{
+}
+
+ParallelHelperPool::~ParallelHelperPool()
+{
+    RELEASE_ASSERT(m_clients.isEmpty());
+    
+    {
+        LockHolder locker(m_lock);
+        m_isDying = true;
+        m_workAvailableCondition.notifyAll();
+    }
+
+    for (ThreadIdentifier threadIdentifier : m_threads)
+        waitForThreadCompletion(threadIdentifier);
+}
+
+void ParallelHelperPool::ensureThreads(unsigned numThreads)
+{
+    LockHolder locker(m_lock);
+    if (numThreads &lt; m_numThreads)
+        return;
+    m_numThreads = numThreads;
+    if (getClientWithTask(locker))
+        didMakeWorkAvailable(locker);
+}
+
+void ParallelHelperPool::doSomeHelping()
+{
+    ParallelHelperClient* client;
+    RefPtr&lt;SharedTask&gt; task;
+    {
+        LockHolder locker(m_lock);
+        client = getClientWithTask(locker);
+        if (!client)
+            return;
+        task = client-&gt;claimTask(locker);
+    }
+
+    client-&gt;runTask(task);
+}
+
+void ParallelHelperPool::didMakeWorkAvailable(const LockHolder&amp;)
+{
+    while (m_numThreads &gt; m_threads.size()) {
+        ThreadIdentifier threadIdentifier = createThread(
+            &quot;WTF Parallel Helper Thread&quot;,
+            [this] () {
+                helperThreadBody();
+            });
+        m_threads.append(threadIdentifier);
+    }
+    m_workAvailableCondition.notifyAll();
+}
+
+void ParallelHelperPool::helperThreadBody()
+{
+    for (;;) {
+        ParallelHelperClient* client;
+        RefPtr&lt;SharedTask&gt; task;
+
+        {
+            LockHolder locker(m_lock);
+            client = waitForClientWithTask(locker);
+            if (!client) {
+                RELEASE_ASSERT(m_isDying);
+                return;
+            }
+
+            task = client-&gt;claimTask(locker);
+        }
+
+        client-&gt;runTask(task);
+    }
+}
+
+bool ParallelHelperPool::hasClientWithTask(const LockHolder&amp; locker)
+{
+    return !!getClientWithTask(locker);
+}
+
+ParallelHelperClient* ParallelHelperPool::getClientWithTask(const LockHolder&amp;)
+{
+    // We load-balance by being random.
+    unsigned startIndex = m_random.getUint32(m_clients.size());
+    for (unsigned index = startIndex; index &lt; m_clients.size(); ++index) {
+        ParallelHelperClient* client = m_clients[index];
+        if (client-&gt;m_task)
+            return client;
+    }
+    for (unsigned index = 0; index &lt; startIndex; ++index) {
+        ParallelHelperClient* client = m_clients[index];
+        if (client-&gt;m_task)
+            return client;
+    }
+
+    return nullptr;
+}
+
+ParallelHelperClient* ParallelHelperPool::waitForClientWithTask(const LockHolder&amp; locker)
+{
+    for (;;) {
+        // It might be quittin' time.
+        if (m_isDying)
+            return nullptr;
+
+        if (ParallelHelperClient* result = getClientWithTask(locker))
+            return result;
+
+        // Wait until work becomes available.
+        m_workAvailableCondition.wait(m_lock);
+    }
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfParallelHelperPoolh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/ParallelHelperPool.h (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParallelHelperPool.h                                (rev 0)
+++ trunk/Source/WTF/wtf/ParallelHelperPool.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,215 @@
</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 ParallelHelperPool_h
+#define ParallelHelperPool_h
+
+#include &lt;wtf/Condition.h&gt;
+#include &lt;wtf/Lock.h&gt;
+#include &lt;wtf/RefPtr.h&gt;
+#include &lt;wtf/SharedTask.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+#include &lt;wtf/Threading.h&gt;
+#include &lt;wtf/Vector.h&gt;
+#include &lt;wtf/WeakRandom.h&gt;
+
+namespace WTF {
+
+// A ParallelHelperPool is a shared pool of threads that can be asked to help with some finite-time
+// parallel activity. It's designed to work well when there are multiple concurrent tasks that may
+// all want parallel help. In that case, we don't want each task to start its own thread pool. It's
+// also designed to work well for tasks that do their own load balancing and do not wish to
+// participate in microtask-style load balancing.
+//
+// A pool can have many clients, and each client may have zero or one tasks. The pool will have up
+// to some number of threads, configurable with ParallelHelperPool::addThreads(); usually you bound
+// this by the number of CPUs. Whenever a thread is idle and it notices that some client has a
+// task, it will run the task. A task may be run on anywhere between zero and N threads, where N is
+// the number of threads in the pool. Tasks run to completion. It's expected that a task will have
+// its own custom ideas about how to participate in some parallel activity's load balancing, and it
+// will return when the parallel activity is done. For example, a parallel marking task will return
+// when the mark phase is done.
+//
+// Threads may have a choice between many tasks, since there may be many clients and each client
+// may have a task. For the marking example, that may happen if there are multiple VM instances and
+// each instance decides to start parallel marking at the same time. In that case, threads choose
+// a task at random. So long as any client has a task, all threads in the pool will continue
+// running the available tasks. Threads go idle when no client has tasks to run.
+
+class ParallelHelperPool;
+
+// A client is a placeholder for a parallel algorithm. A parallel algorithm will have a task that
+// can be run concurrently. Whenever a client has a task set (you have called setTask() or
+// setFunction()), threads in the pool may run that task. If a task returns on any thread, the
+// client will assume that the task is done and will clear the task. If the task is cleared (the
+// task runs to completion on any thread or you call finish()), any threads in the pool already
+// running the last set task(s) will continue to run them. You can wait for all of them to finish
+// by calling finish(). That method will clear the task and wait for any threads running the last
+// set task to finish. There are two known-good patterns for using a client:
+//
+// 1) Tasks intrinsically know when the algorithm reaches termination, and simply returns when
+//    this happens. The main thread runs the task by doing:
+//
+//    client-&gt;setFunction(
+//        [=] () {
+//            do things;
+//        });
+//    client-&gt;doSomeHelping();
+//    client-&gt;finish();
+//
+//    Calling doSomeHelping() ensures that the algorithm runs on at least one thread (this one).
+//    Tasks will know when to complete, and will return when they are done. This will clear the
+//    task to ensure that no new threads will run the task. Then, finish() clears the current task
+//    and waits for any parallel tasks to finish after the main thread has finished. It's possible
+//    for threads to still be running the last set task (i.e. the one set by setFunction()) even
+//    after the task has been cleared. Waiting for idle ensures that no old tasks are running
+//    anymore.
+//
+//    You can do this more easily by using the runFunctionInParallel() helper:
+//
+//    clients-&gt;runFunctionInParallel(
+//        [=] () {
+//            do things;
+//        });
+//
+// 2) Tasks keep doing things until they are told to quit using some custom notification mechanism.
+//    The main thread runs the task by doing:
+//
+//    bool keepGoing = true;
+//    client-&gt;setFunction(
+//        [=] () {
+//            while (keepGoing) {
+//                do things;
+//            }
+//        });
+//
+//    When work runs out, the main thread will inform tasks that there is no more work, and then
+//    wait until no more tasks are running:
+//
+//    keepGoing = false;
+//    client-&gt;finish();
+//
+//    This works best when the main thread doesn't actually want to run the task that it set in the
+//    client. This happens for example in parallel marking. The main thread uses a somewhat
+//    different marking algorithm than the helpers. The main thread may provide work that the
+//    helpers steal. The main thread knows when termination is reached, and simply tells the
+//    helpers to stop upon termination.
+//
+// The known-good styles of using ParallelHelperClient all involve a parallel algorithm that has
+// its own work distribution and load balancing.
+//
+// Note that it is not valid to use the same ParallelHelperClient instance from multiple threads.
+// Each thread should have its own ParallelHelperClient in that case. Failure to follow this advice
+// will lead to RELEASE_ASSERT's or worse.
+class ParallelHelperClient {
+    WTF_MAKE_NONCOPYABLE(ParallelHelperClient);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ParallelHelperClient(RefPtr&lt;ParallelHelperPool&gt;);
+    ~ParallelHelperClient();
+
+    void setTask(RefPtr&lt;SharedTask&gt;);
+
+    template&lt;typename Functor&gt;
+    void setFunction(const Functor&amp; functor)
+    {
+        setTask(createSharedTask(functor));
+    }
+    
+    void finish();
+
+    void doSomeHelping();
+
+    // Equivalent to:
+    // client-&gt;setTask(task);
+    // client-&gt;doSomeHelping();
+    // client-&gt;finish();
+    void runTaskInParallel(RefPtr&lt;SharedTask&gt;);
+
+    // Equivalent to:
+    // client-&gt;setFunction(functor);
+    // client-&gt;doSomeHelping();
+    // client-&gt;finish();
+    template&lt;typename Functor&gt;
+    void runFunctionInParallel(const Functor&amp; functor)
+    {
+        runTaskInParallel(createSharedTask(functor));
+    }
+
+    ParallelHelperPool&amp; pool() { return *m_pool; }
+    unsigned numberOfActiveThreads() const { return m_numActive; }
+
+private:
+    friend class ParallelHelperPool;
+
+    void finish(const LockHolder&amp;);
+    RefPtr&lt;SharedTask&gt; claimTask(const LockHolder&amp;);
+    void runTask(RefPtr&lt;SharedTask&gt;);
+    
+    RefPtr&lt;ParallelHelperPool&gt; m_pool;
+    RefPtr&lt;SharedTask&gt; m_task;
+    unsigned m_numActive { 0 };
+};
+
+class ParallelHelperPool : public ThreadSafeRefCounted&lt;ParallelHelperPool&gt; {
+public:
+    ParallelHelperPool();
+    ~ParallelHelperPool();
+
+    void ensureThreads(unsigned numThreads);
+
+    unsigned numberOfThreads() const { return m_numThreads; }
+    
+    void doSomeHelping();
+
+private:
+    friend class ParallelHelperClient;
+
+    void didMakeWorkAvailable(const LockHolder&amp;);
+    void helperThreadBody();
+
+    bool hasClientWithTask(const LockHolder&amp;);
+    ParallelHelperClient* getClientWithTask(const LockHolder&amp;);
+    ParallelHelperClient* waitForClientWithTask(const LockHolder&amp;);
+    
+    Lock m_lock;
+    Condition m_workAvailableCondition;
+    Condition m_workCompleteCondition;
+
+    WeakRandom m_random;
+    
+    Vector&lt;ParallelHelperClient*&gt; m_clients;
+    Vector&lt;ThreadIdentifier&gt; m_threads;
+    unsigned m_numThreads { 0 }; // This can be larger than m_threads.size() because we start threads only once there is work.
+    bool m_isDying { false };
+};
+
+} // namespace WTF
+
+using WTF::ParallelHelperClient;
+using WTF::ParallelHelperPool;
+
+#endif // ParallelHelperPool_h
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfSharedTaskh"></a>
<div class="addfile"><h4>Added: trunk/Source/WTF/wtf/SharedTask.h (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/SharedTask.h                                (rev 0)
+++ trunk/Source/WTF/wtf/SharedTask.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,118 @@
</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 SharedTask_h
+#define SharedTask_h
+
+#include &lt;wtf/Ref.h&gt;
+#include &lt;wtf/ThreadSafeRefCounted.h&gt;
+
+namespace WTF {
+
+// SharedTask is a replacement for std::function for cases where:
+//
+// - You'd like to avoid the cost of copying, and would prefer to have reference semantics rather
+//   than value semantics.
+// - You want to use FastMalloc rather than system malloc. Note that std::function may avoid malloc
+//   entirely in some cases, but that's hard to guarantee.
+// - You intend to share the task with other threads and so want thread-safe reference counting.
+//
+// Here's an example of how SharedTask can be better than std::function. If you do:
+//
+// std::function a = b;
+//
+// Then &quot;a&quot; will get its own copy of all captured by-value variables. The act of copying may
+// require calls to system malloc, and it may be linear time in the total size of captured
+// variables. On the other hand, if you do:
+//
+// RefPtr&lt;SharedTask&gt; a = b;
+//
+// Then &quot;a&quot; will point to the same task as b, and the only work involved is the CAS to increase the
+// reference count.
+//
+// Also, SharedTask allows for more flexibility when sharing state between everyone who runs the
+// task. With std::function, you can only share state using by-reference captured variables.
+// SharedTask supports this since, like std::function, it can be built from a lambda (see
+// createSharedTask(), below). But SharedTask also allows you to create your own subclass and put
+// state in member fields. This can be more natural if you want fine-grained control over what
+// state is shared between instances of the task.
+class SharedTask : public ThreadSafeRefCounted&lt;SharedTask&gt; {
+public:
+    SharedTask() { }
+    virtual ~SharedTask() { }
+
+    virtual void run() = 0;
+};
+
+// This is a utility class that allows you to create a SharedTask subclass using a lambda. Usually,
+// you don't want to use this class directly. Use createSharedTask() instead.
+template&lt;typename Functor&gt;
+class SharedTaskFunctor : public SharedTask {
+public:
+    SharedTaskFunctor(const Functor&amp; functor)
+        : m_functor(functor)
+    {
+    }
+
+private:
+    void run() override
+    {
+        m_functor();
+    }
+
+    Functor m_functor;
+};
+
+// Create a SharedTask from a functor, such as a lambda. You can use this like so:
+//
+// RefPtr&lt;SharedTask&gt; task = createSharedTask(
+//     [=] () {
+//         do things;
+//     });
+//
+// Note that if you use the [&amp;] capture list, then you're probably doing it wrong. That's because
+// [&amp;] will lead to pointers to the stack (the only exception is if you do something like &amp;x where
+// x is a reference to the heap - but in that case, it's better to use [=, &amp;x] to be explicit). You
+// probably don't want pointers to the stack if you will have tasks running on other threads.
+// Probably the best way to be sure that you're not making a horrible mistake is to always use
+// explicit capture lists. In many cases, [this] is sufficient.
+//
+// On the other hand, if you use something like ParallelHelperClient::runTaskInParallel() (or its
+// helper, runFunctionInParallel(), which does createSharedTask() for you), then it can be OK to
+// use [&amp;], since the stack frame will remain live for the entire duration of the task's lifetime.
+template&lt;typename Functor&gt;
+Ref&lt;SharedTask&gt; createSharedTask(const Functor&amp; functor)
+{
+    return adoptRef(*new SharedTaskFunctor&lt;Functor&gt;(functor));
+}
+
+} // namespace WTF
+
+using WTF::createSharedTask;
+using WTF::SharedTask;
+using WTF::SharedTaskFunctor;
+
+#endif // SharedTask_h
+
</ins></span></pre></div>
<a id="trunkSourceWTFwtfWeakRandomhfromrev190151trunkSourceJavaScriptCoreruntimeWeakRandomh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WTF/wtf/WeakRandom.h (from rev 190151, trunk/Source/JavaScriptCore/runtime/WeakRandom.h) (0 => 190267)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WeakRandom.h                                (rev 0)
+++ trunk/Source/WTF/wtf/WeakRandom.h        2015-09-26 18:07:09 UTC (rev 190267)
</span><span class="lines">@@ -0,0 +1,120 @@
</span><ins>+/*
+ * Copyright (C) 2009, 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. 
+ *
+ *
+ * Copyright (c) 2009 Ian C. Bullard
+ * 
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the &quot;Software&quot;), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef WeakRandom_h
+#define WeakRandom_h
+
+#include &lt;limits.h&gt;
+#include &lt;wtf/RandomNumber.h&gt;
+#include &lt;wtf/StdLibExtras.h&gt;
+
+namespace WTF {
+
+class WeakRandom {
+public:
+    WeakRandom()
+    {
+        initializeSeed(randomNumber() * (std::numeric_limits&lt;unsigned&gt;::max() + 1.0));
+    }
+    
+    WeakRandom(unsigned seed)
+    {
+        initializeSeed(seed);
+    }
+    
+    void initializeSeed(unsigned seed)
+    {
+        m_low = seed ^ 0x49616E42;
+        m_high = seed;
+    }
+
+    // Returns the seed provided that you've never called get() or getUint32().
+    unsigned seedUnsafe() const { return m_high; }
+
+    double get()
+    {
+        return advance() / (UINT_MAX + 1.0);
+    }
+
+    unsigned getUint32()
+    {
+        return advance();
+    }
+
+    unsigned getUint32(unsigned limit)
+    {
+        if (limit &lt;= 1)
+            return 0;
+        uint64_t cutoff = (static_cast&lt;uint64_t&gt;(UINT_MAX) + 1) / limit * limit;
+        for (;;) {
+            uint64_t value = getUint32();
+            if (value &gt;= cutoff)
+                continue;
+            return value % limit;
+        }
+    }
+
+private:
+    unsigned advance()
+    {
+        m_high = (m_high &lt;&lt; 16) + (m_high &gt;&gt; 16);
+        m_high += m_low;
+        m_low += m_high;
+        return m_high;
+    }
+
+    unsigned m_low;
+    unsigned m_high;
+};
+
+} // namespace WTF
+
+using WTF::WeakRandom;
+
+#endif // WeakRandom_h
</ins></span></pre>
</div>
</div>

</body>
</html>