Changeset 190267 in webkit


Ignore:
Timestamp:
Sep 26, 2015 11:07:09 AM (9 years ago)
Author:
fpizlo@apple.com
Message:

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.

Location:
trunk/Source
Files:
5 added
2 deleted
19 edited
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r186966 r190267  
    3333
    3434#import <pthread.h>
     35#import <vector>
    3536
    3637extern "C" void JSSynchronousGarbageCollectForDebugging(JSContextRef);
     
    482483    TestObject *testObject = [TestObject testObject];
    483484    context[@"testObject"] = testObject;
    484     pthread_exit(nullptr);
     485    return nullptr;
     486}
     487
     488static void* multiVMThreadMain(void* okPtr)
     489{
     490    bool& ok = *static_cast<bool*>(okPtr);
     491    JSVirtualMachine *vm = [[JSVirtualMachine alloc] init];
     492    JSContext* context = [[JSContext alloc] initWithVirtualMachine:vm];
     493    [context evaluateScript:
     494        @"var array = [{}];\n"
     495         "for (var i = 0; i < 20; ++i) {\n"
     496         "    var newArray = new Array(array.length * 2);\n"
     497         "    for (var j = 0; j < newArray.length; ++j)\n"
     498         "        newArray[j] = {parent: array[j / 2]};\n"
     499         "    array = newArray;\n"
     500         "}\n"];
     501    if (context.exception) {
     502        NSLog(@"Uncaught exception.\n");
     503        ok = false;
     504    }
     505    if (![context.globalObject valueForProperty:@"array"].toObject) {
     506        NSLog(@"Did not find \"array\" variable.\n");
     507        ok = false;
     508    }
     509    JSSynchronousGarbageCollectForDebugging([context JSGlobalContextRef]);
     510    return nullptr;
    485511}
    486512
     
    14171443    }
    14181444   
     1445    @autoreleasepool {
     1446        std::vector<pthread_t> threads;
     1447        bool ok = true;
     1448        for (unsigned i = 0; i < 5; ++i) {
     1449            pthread_t threadID;
     1450            pthread_create(&threadID, nullptr, multiVMThreadMain, &ok);
     1451            threads.push_back(threadID);
     1452        }
     1453
     1454        for (pthread_t thread : threads)
     1455            pthread_join(thread, nullptr);
     1456
     1457        checkResult(@"Ran code in five concurrent VMs that GC'd", ok);
     1458    }
     1459   
    14191460    currentThisInsideBlockGetterTest();
    14201461    runDateTests();
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r190155 r190267  
    295295    heap/GCActivityCallback.cpp
    296296    heap/GCLogging.cpp
    297     heap/GCThread.cpp
    298297    heap/HandleSet.cpp
    299298    heap/HandleStack.cpp
    300299    heap/Heap.cpp
     300    heap/HeapHelperPool.cpp
    301301    heap/HeapStatistics.cpp
    302302    heap/HeapTimer.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r190261 r190267  
     12015-09-24  Filip Pizlo  <fpizlo@apple.com>
     2
     3        VMs should share GC threads
     4        https://bugs.webkit.org/show_bug.cgi?id=149433
     5        rdar://problem/12859344
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        This changes the GC to use a new WTF abstraction for parallelism called ParallelHelperPool.
     10        This allows us to remove GCThread and all of the GCPhase machinery. This kills a lot of
     11        code and also gives our GC magical thread sharing powers. If two GCs in two different VMs
     12        fire at the same time, then they will both get a random subset of the available shared GC
     13        threads. If one GC happens before the other, then it will probably get all of the available
     14        threads. If a GC happens while another VM already started GCing, then it will probably not
     15        get any helper threads. This is probably fine, since in multi-VM scenarios we have no
     16        reason to optimize for anything other than total throughput.
     17
     18        The GC has one static helper pool. This pool is available via JSC::heapHelperPool(). It
     19        would be OK for other parts of JSC to use it in the future for parallel tasks. Each Heap
     20        instance has a helper client attached to the pool.
     21
     22        The marking phase tells the ParallelHelperClient to asynchronously run a function that
     23        joins parallel marking and finishes once marking reaches termination. It uses the
     24        client.setFunction() idiom where the threads share work with each other using a specialized
     25        worklist. The ParallelHelperPool is not involved in deciding when threads should terminate.
     26
     27        The copying phase tells the ParallelHelperClient to run a copying function in parallel. It
     28        uses the client.runFunctionInParallel() idiom. The copying function gets work from the
     29        m_blocksToCopy worklist inside Heap.
     30
     31        To test that multiple VMs work properly, this adds a multi-VM test to testapi.mm. This test
     32        creates five concurrent VMs and has each of them allocate about 30MB of memory before doing
     33        a full GC. I've confirmed that this tests uses only 6 total GC threads on my 8-core
     34        computer (this is correct since we are currently configured for 7-way parallelism).
     35
     36        This shouldn't affect performance on benchmarks, but it will sure help apps with a lot of
     37        VM instances.
     38
     39        * CMakeLists.txt:
     40        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     41        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     42        * JavaScriptCore.xcodeproj/project.pbxproj:
     43        * assembler/AbstractMacroAssembler.h:
     44        * heap/GCThread.cpp: Removed.
     45        * heap/GCThread.h: Removed.
     46        * heap/Heap.cpp:
     47        (JSC::Heap::Heap):
     48        (JSC::Heap::~Heap):
     49        (JSC::Heap::isPagedOut):
     50        (JSC::Heap::markRoots):
     51        (JSC::Heap::copyBackingStores):
     52        (JSC::Heap::resetVisitors):
     53        (JSC::Heap::threadVisitCount):
     54        (JSC::Heap::threadBytesVisited):
     55        (JSC::Heap::threadBytesCopied):
     56        (JSC::Heap::startNextPhase): Deleted.
     57        (JSC::Heap::endCurrentPhase): Deleted.
     58        * heap/Heap.h:
     59        * heap/HeapHelperPool.cpp: Added.
     60        (JSC::heapHelperPool):
     61        * heap/HeapHelperPool.h: Added.
     62        * heap/MarkStack.cpp:
     63        (JSC::MarkStackArray::stealSomeCellsFrom):
     64        * heap/SlotVisitor.cpp:
     65        (JSC::SlotVisitor::didStartMarking):
     66        (JSC::SlotVisitor::reset):
     67        (JSC::SlotVisitor::drainFromShared):
     68        * jit/BinarySwitch.h:
     69        * runtime/CodeCache.h:
     70        * runtime/VM.h:
     71        * runtime/WeakRandom.h: Removed.
     72        * API/tests/testapi.mm:
     73
    1742015-09-25  Saam barati  <sbarati@apple.com>
    275
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r190151 r190267  
    570570    <ClCompile Include="..\heap\HandleStack.cpp" />
    571571    <ClCompile Include="..\heap\Heap.cpp" />
     572    <ClCompile Include="..\heap\HeapHelperPool.cpp" />
    572573    <ClCompile Include="..\heap\HeapStatistics.cpp" />
    573574    <ClCompile Include="..\heap\HeapTimer.cpp" />
     
    13511352    <ClInclude Include="..\heap\HandleTypes.h" />
    13521353    <ClInclude Include="..\heap\Heap.h" />
     1354    <ClInclude Include="..\heap\HeapHelperPool.h" />
    13531355    <ClInclude Include="..\heap\HeapInlines.h" />
    13541356    <ClInclude Include="..\heap\HeapOperation.h" />
     
    18101812    <ClInclude Include="..\runtime\WeakSetConstructor.h" />
    18111813    <ClInclude Include="..\runtime\WeakSetPrototype.h" />
    1812     <ClInclude Include="..\runtime\WeakRandom.h" />
    18131814    <ClInclude Include="..\runtime\WriteBarrier.h" />
    18141815    <ClInclude Include="..\runtime\WriteBarrierInlines.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r190151 r190267  
    292292      <Filter>heap</Filter>
    293293    </ClCompile>
     294    <ClCompile Include="..\heap\HeapHelperPool.cpp">
     295      <Filter>heap</Filter>
     296    </ClCompile>
    294297    <ClCompile Include="..\heap\HeapStatistics.cpp">
    295298      <Filter>heap</Filter>
     
    22892292      <Filter>heap</Filter>
    22902293    </ClInclude>
     2294    <ClInclude Include="..\heap\HeapHelperPool.h">
     2295      <Filter>heap</Filter>
     2296    </ClInclude>
    22912297    <ClInclude Include="..\heap\HeapInlines.h">
    22922298      <Filter>heap</Filter>
     
    31663172    </ClInclude>
    31673173    <ClInclude Include="..\runtime\WeakGCMap.h">
    3168       <Filter>runtime</Filter>
    3169     </ClInclude>
    3170     <ClInclude Include="..\runtime\WeakRandom.h">
    31713174      <Filter>runtime</Filter>
    31723175    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r190201 r190267  
    275275                0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */; };
    276276                0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; };
     277                0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */; };
     278                0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */; };
    277279                0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
    278280                0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; };
     
    776778                141448CD13A1783700F5BA1A /* TinyBloomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
    777779                14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 14150132154BB13F005D8C98 /* WeakSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    778                 1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */; settings = {ATTRIBUTES = (Private, ); }; };
    779780                1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1421359A0A677F4F00A8195E /* JSBase.cpp */; };
    780781                14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8580255597D01FF60F7 /* Debugger.cpp */; };
     
    16661667                C2239D1816262BDD005AC5FD /* CopyVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1316262BDD005AC5FD /* CopyVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    16671668                C2239D1916262BDD005AC5FD /* CopyVisitorInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1668                 C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2239D1516262BDD005AC5FD /* GCThread.cpp */; };
    1669                 C2239D1B16262BDD005AC5FD /* GCThread.h in Headers */ = {isa = PBXBuildFile; fileRef = C2239D1616262BDD005AC5FD /* GCThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
    16701669                C225494315F7DBAA0065E898 /* SlotVisitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C225494215F7DBAA0065E898 /* SlotVisitor.cpp */; };
    16711670                C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    21202119                0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = "<group>"; };
    21212120                0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = "<group>"; };
     2121                0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapHelperPool.cpp; sourceTree = "<group>"; };
     2122                0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapHelperPool.h; sourceTree = "<group>"; };
    21222123                0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; };
    21232124                0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; };
     
    26172618                141448CC13A1783700F5BA1A /* TinyBloomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyBloomFilter.h; sourceTree = "<group>"; };
    26182619                14150132154BB13F005D8C98 /* WeakSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakSetInlines.h; sourceTree = "<group>"; };
    2619                 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = "<group>"; };
    26202620                1421359A0A677F4F00A8195E /* JSBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBase.cpp; sourceTree = "<group>"; };
    26212621                142711380A460BBB0080EEEA /* JSBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBase.h; sourceTree = "<group>"; };
     
    35383538                C2239D1316262BDD005AC5FD /* CopyVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyVisitor.h; sourceTree = "<group>"; };
    35393539                C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyVisitorInlines.h; sourceTree = "<group>"; };
    3540                 C2239D1516262BDD005AC5FD /* GCThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCThread.cpp; sourceTree = "<group>"; };
    3541                 C2239D1616262BDD005AC5FD /* GCThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCThread.h; sourceTree = "<group>"; };
    35423540                C225494215F7DBAA0065E898 /* SlotVisitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SlotVisitor.cpp; sourceTree = "<group>"; };
    35433541                C240305314B404C90079EB64 /* CopiedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopiedSpace.cpp; sourceTree = "<group>"; };
     
    42524250                                2A343F7418A1748B0039B085 /* GCSegmentedArray.h */,
    42534251                                2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */,
    4254                                 C2239D1516262BDD005AC5FD /* GCThread.cpp */,
    4255                                 C2239D1616262BDD005AC5FD /* GCThread.h */,
    42564252                                142E312B134FF0A600AFADB5 /* Handle.h */,
    42574253                                C28318FF16FE4B7D00157BFD /* HandleBlock.h */,
     
    42644260                                14BA7A9513AADFF8005B7C2C /* Heap.cpp */,
    42654261                                14BA7A9613AADFF8005B7C2C /* Heap.h */,
     4262                                0F32BD0E1BB34F190093A57F /* HeapHelperPool.cpp */,
     4263                                0F32BD0F1BB34F190093A57F /* HeapHelperPool.h */,
    42664264                                C2DA778218E259990066FCB6 /* HeapInlines.h */,
    42674265                                2AD8932917E3868F00668276 /* HeapIterationScope.h */,
     
    50935091                                A7CA3ADF17DA41AE006538AF /* WeakMapPrototype.cpp */,
    50945092                                A7CA3AE017DA41AE006538AF /* WeakMapPrototype.h */,
    5095                                 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
    50965093                                709FB8631AE335C60039D069 /* WeakSetConstructor.cpp */,
    50975094                                709FB8641AE335C60039D069 /* WeakSetConstructor.h */,
     
    61566153                                0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */,
    61576154                                0F9D339717FFC4E60073C2BC /* DFGFlushedAt.h in Headers */,
     6155                                0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */,
    61586156                                A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
    61596157                                0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */,
     
    69326930                                A7CA3AEC17DA5168006538AF /* WeakMapData.h in Headers */,
    69336931                                A7CA3AE617DA41AE006538AF /* WeakMapPrototype.h in Headers */,
    6934                                 1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */,
    69356932                                0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */,
    69366933                                14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */,
     
    80638060                                0FF42743158EBE91004CB9FF /* udis86_input.c in Sources */,
    80648061                                0FF4274D158EBFE6004CB9FF /* udis86_itab_holder.c in Sources */,
     8062                                0F32BD101BB34F190093A57F /* HeapHelperPool.cpp in Sources */,
    80658063                                0FF42745158EBE91004CB9FF /* udis86_syn-att.c in Sources */,
    80668064                                0FF42746158EBE91004CB9FF /* udis86_syn-intel.c in Sources */,
  • trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r189884 r190267  
    3232#include "MacroAssemblerCodeRef.h"
    3333#include "Options.h"
    34 #include "WeakRandom.h"
    3534#include <wtf/CryptographicallyRandomNumber.h>
    3635#include <wtf/Noncopyable.h>
     36#include <wtf/WeakRandom.h>
    3737
    3838#if ENABLE(ASSEMBLER)
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r190185 r190267  
    11/*
    2  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2013, 2014 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2003-2009, 2011, 2013-2015 Apple Inc. All rights reserved.
    33 *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
    44 *
     
    3232#include "GCActivityCallback.h"
    3333#include "GCIncomingRefCountedSetInlines.h"
     34#include "HeapHelperPool.h"
    3435#include "HeapIterationScope.h"
    3536#include "HeapRootVisitor.h"
     
    337338    , m_machineThreads(this)
    338339    , m_slotVisitor(*this)
    339     , m_copyVisitor(*this)
    340340    , m_handleSet(vm)
    341341    , m_isSafeToCollect(false)
     
    357357    , m_delayedReleaseRecursionCount(0)
    358358#endif
    359 {
    360     {
    361         // Grab the lock so the new GC threads can be properly initialized before they start running.
    362         std::unique_lock<Lock> lock(m_phaseMutex);
    363         for (unsigned i = 1; i < Options::numberOfGCMarkers(); ++i) {
    364             m_numberOfActiveGCThreads++;
    365             GCThread* newThread = new GCThread(*this, std::make_unique<SlotVisitor>(*this));
    366             ThreadIdentifier threadID = createThread(GCThread::gcThreadStartFunc, newThread, "JavaScriptCore::Marking");
    367             newThread->initializeThreadID(threadID);
    368             m_gcThreads.append(newThread);
    369         }
    370        
    371         // Wait for all the GCThreads to get to the right place.
    372         m_activityConditionVariable.wait(lock, [this] { return !m_numberOfActiveGCThreads; });
    373     }
    374    
     359    , m_helperClient(&heapHelperPool())
     360{
    375361    m_storageSpace.init();
    376362    if (Options::verifyHeap())
     
    382368    for (WeakBlock* block : m_logicallyEmptyWeakBlocks)
    383369        WeakBlock::destroy(block);
    384 
    385     // Destroy our marking threads.
    386     {
    387         std::lock_guard<Lock> markingLock(m_markingMutex);
    388         std::lock_guard<Lock> phaseLock(m_phaseMutex);
    389         ASSERT(m_currentPhase == NoPhase);
    390         m_parallelMarkersShouldExit = true;
    391         m_gcThreadsShouldWait = false;
    392         m_currentPhase = Exit;
    393         m_phaseConditionVariable.notifyAll();
    394     }
    395     for (unsigned i = 0; i < m_gcThreads.size(); ++i) {
    396         waitForThreadCompletion(m_gcThreads[i]->threadID());
    397         delete m_gcThreads[i];
    398     }
    399370}
    400371
     
    571542    if (m_operationInProgress == FullCollection)
    572543        m_opaqueRoots.clear();
    573     {
    574         std::lock_guard<Lock> lock(m_markingMutex);
    575         m_parallelMarkersShouldExit = false;
    576         startNextPhase(Mark);
    577     }
     544
     545    m_shouldHashCons = m_vm->haveEnoughNewStringsToHashCons();
     546
     547    m_parallelMarkersShouldExit = false;
     548
     549    m_helperClient.setFunction(
     550        [this] () {
     551            SlotVisitor* slotVisitor;
     552            {
     553                LockHolder locker(m_parallelSlotVisitorLock);
     554                if (m_availableParallelSlotVisitors.isEmpty()) {
     555                    std::unique_ptr<SlotVisitor> newVisitor =
     556                        std::make_unique<SlotVisitor>(*this);
     557                    slotVisitor = newVisitor.get();
     558                    m_parallelSlotVisitors.append(WTF::move(newVisitor));
     559                } else
     560                    slotVisitor = m_availableParallelSlotVisitors.takeLast();
     561            }
     562
     563            {
     564                ParallelModeEnabler parallelModeEnabler(*slotVisitor);
     565                slotVisitor->didStartMarking();
     566                slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
     567            }
     568
     569            {
     570                LockHolder locker(m_parallelSlotVisitorLock);
     571                m_availableParallelSlotVisitors.append(slotVisitor);
     572            }
     573        });
     574
    578575    m_slotVisitor.didStartMarking();
     576   
    579577    HeapRootVisitor heapRootVisitor(m_slotVisitor);
    580578
     
    604602        m_markingConditionVariable.notifyAll();
    605603    }
    606     ASSERT(m_currentPhase == Mark);
    607     endCurrentPhase();
     604    m_helperClient.finish();
    608605    updateObjectCounts(gcStartTime);
    609606    resetVisitors();
     
    634631            m_copyIndex = 0;
    635632        }
    636        
    637         startNextPhase(Copy);
    638        
    639         m_copyVisitor.startCopying();
    640         m_copyVisitor.copyFromShared();
    641         m_copyVisitor.doneCopying();
    642 
    643         ASSERT(m_currentPhase == Copy);
    644         endCurrentPhase();
     633
     634        m_helperClient.runFunctionInParallel(
     635            [this] () {
     636                CopyVisitor copyVisitor(*this);
     637                copyVisitor.startCopying();
     638                copyVisitor.copyFromShared();
     639                copyVisitor.doneCopying();
     640                WTF::releaseFastMallocFreeMemoryForThisThread();
     641            });
    645642    }
    646643   
     
    871868    m_slotVisitor.reset();
    872869
    873     for (GCThread* thread : m_gcThreads)
    874         thread->slotVisitor()->reset();
     870    for (auto& parallelVisitor : m_parallelSlotVisitors)
     871        parallelVisitor->reset();
    875872
    876873    ASSERT(m_sharedMarkStack.isEmpty());
     
    15331530{       
    15341531    unsigned long result = 0;
    1535     for (unsigned i = 0; i < m_gcThreads.size(); ++i)
    1536         result += m_gcThreads[i]->slotVisitor()->visitCount();
     1532    for (auto& parallelVisitor : m_parallelSlotVisitors)
     1533        result += parallelVisitor->visitCount();
    15371534    return result;
    15381535}
     
    15411538{       
    15421539    size_t result = 0;
    1543     for (unsigned i = 0; i < m_gcThreads.size(); ++i)
    1544         result += m_gcThreads[i]->slotVisitor()->bytesVisited();
     1540    for (auto& parallelVisitor : m_parallelSlotVisitors)
     1541        result += parallelVisitor->bytesVisited();
    15451542    return result;
    15461543}
     
    15491546{       
    15501547    size_t result = 0;
    1551     for (unsigned i = 0; i < m_gcThreads.size(); ++i)
    1552         result += m_gcThreads[i]->slotVisitor()->bytesCopied();
     1548    for (auto& parallelVisitor : m_parallelSlotVisitors)
     1549        result += parallelVisitor->bytesCopied();
    15531550    return result;
    15541551}
    15551552
    1556 void Heap::startNextPhase(GCPhase phase)
    1557 {
    1558     std::lock_guard<Lock> lock(m_phaseMutex);
    1559     ASSERT(!m_gcThreadsShouldWait);
    1560     ASSERT(m_currentPhase == NoPhase);
    1561     m_gcThreadsShouldWait = true;
    1562     m_currentPhase = phase;
    1563     m_phaseConditionVariable.notifyAll();
    1564 }
    1565 
    1566 void Heap::endCurrentPhase()
    1567 {
    1568     ASSERT(m_gcThreadsShouldWait);
    1569     std::unique_lock<Lock> lock(m_phaseMutex);
    1570     m_currentPhase = NoPhase;
    1571     m_gcThreadsShouldWait = false;
    1572     m_phaseConditionVariable.notifyAll();
    1573     m_activityConditionVariable.wait(lock, [this] { return !m_numberOfActiveGCThreads; });
    1574 }
    1575 
    15761553} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r190217 r190267  
    2727#include "CopyVisitor.h"
    2828#include "GCIncomingRefCountedSet.h"
    29 #include "GCThread.h"
    3029#include "HandleSet.h"
    3130#include "HandleStack.h"
     
    4746#include <wtf/HashCountedSet.h>
    4847#include <wtf/HashSet.h>
     48#include <wtf/ParallelHelperPool.h>
    4949
    5050namespace JSC {
     
    348348
    349349    void getNextBlocksToCopy(size_t&, size_t&);
    350     void startNextPhase(GCPhase);
    351     void endCurrentPhase();
    352350
    353351    const HeapType m_heapType;
     
    384382   
    385383    SlotVisitor m_slotVisitor;
    386     CopyVisitor m_copyVisitor;
     384
     385    // We pool the slot visitors used by parallel marking threads. It's useful to be able to
     386    // enumerate over them, and it's useful to have them cache some small amount of memory from
     387    // one GC to the next. GC marking threads claim these at the start of marking, and return
     388    // them at the end.
     389    Vector<std::unique_ptr<SlotVisitor>> m_parallelSlotVisitors;
     390    Vector<SlotVisitor*> m_availableParallelSlotVisitors;
     391    Lock m_parallelSlotVisitorLock;
    387392
    388393    HandleSet m_handleSet;
     
    422427
    423428    bool m_shouldHashCons { false };
    424 
    425     Vector<GCThread*> m_gcThreads;
    426429
    427430    Lock m_markingMutex;
     
    440443    static const size_t s_blockFragmentLength = 32;
    441444
    442     Lock m_phaseMutex;
    443     Condition m_phaseConditionVariable;
    444     Condition m_activityConditionVariable;
    445     unsigned m_numberOfActiveGCThreads { 0 };
    446     bool m_gcThreadsShouldWait { false };
    447     GCPhase m_currentPhase { NoPhase };
    448 
    449445    ListableHandler<WeakReferenceHarvester>::List m_weakReferenceHarvesters;
    450446    ListableHandler<UnconditionalFinalizer>::List m_unconditionalFinalizers;
     447
     448    ParallelHelperClient m_helperClient;
    451449};
    452450
  • trunk/Source/JavaScriptCore/heap/MarkStack.cpp

    r179348 r190267  
    11/*
    2  * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2011, 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    108108    }
    109109
    110     size_t numberOfCellsToSteal = (other.size() + idleThreadCount - 1) / idleThreadCount; // Round up to steal 1 / 1.
     110    // Steal ceil(other.size() / idleThreadCount) things.
     111    size_t numberOfCellsToSteal = (other.size() + idleThreadCount - 1) / idleThreadCount;
    111112    while (numberOfCellsToSteal-- > 0 && other.canRemoveLast())
    112113        append(other.removeLast());
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r190217 r190267  
    3131#include "CopiedSpace.h"
    3232#include "CopiedSpaceInlines.h"
    33 #include "GCThread.h"
    3433#include "JSArray.h"
    3534#include "JSDestructibleObject.h"
     
    6867        ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
    6968
    70     m_heap.m_shouldHashCons = m_heap.m_vm->haveEnoughNewStringsToHashCons();
    7169    m_shouldHashCons = m_heap.m_shouldHashCons;
    72     for (unsigned i = 0; i < m_heap.m_gcThreads.size(); ++i)
    73         m_heap.m_gcThreads[i]->slotVisitor()->m_shouldHashCons = m_heap.m_shouldHashCons;
    7470}
    7571
     
    222218                    return;
    223219            }
    224            
     220
    225221            m_stack.stealSomeCellsFrom(
    226222                m_heap.m_sharedMarkStack, m_heap.m_numberOfWaitingParallelMarkers);
  • trunk/Source/JavaScriptCore/jit/BinarySwitch.h

    r189586 r190267  
    3131#include "GPRInfo.h"
    3232#include "MacroAssembler.h"
    33 #include "WeakRandom.h"
     33#include <wtf/WeakRandom.h>
    3434
    3535namespace JSC {
  • trunk/Source/JavaScriptCore/runtime/CodeCache.h

    r189201 r190267  
    3232#include "Strong.h"
    3333#include "VariableEnvironment.h"
    34 #include "WeakRandom.h"
    3534#include <wtf/CurrentTime.h>
    3635#include <wtf/Forward.h>
    3736#include <wtf/RandomNumber.h>
     37#include <wtf/WeakRandom.h>
    3838#include <wtf/text/WTFString.h>
    3939
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r190076 r190267  
    5555#include "VMEntryRecord.h"
    5656#include "Watchpoint.h"
    57 #include "WeakRandom.h"
    5857#include <wtf/Bag.h>
    5958#include <wtf/BumpPointerAllocator.h>
     
    6867#include <wtf/ThreadSpecific.h>
    6968#include <wtf/WTFThreadData.h>
     69#include <wtf/WeakRandom.h>
    7070#include <wtf/text/SymbolRegistry.h>
    7171#include <wtf/text/WTFString.h>
  • trunk/Source/WTF/ChangeLog

    r190255 r190267  
     12015-09-24  Filip Pizlo  <fpizlo@apple.com>
     2
     3        VMs should share GC threads
     4        https://bugs.webkit.org/show_bug.cgi?id=149433
     5        rdar://problem/12859344
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        This adds two major things to WTF: WeakRandom and ParallelHelperPool. WeakRandom was
     10        already in JSC; we're just hoisting it into WTF. It's just a weak random number generator
     11        that's suitable for places where you need just a tiny bit of randomness.
     12
     13        ParallelHelperPool is a new API that simplifies data-parallel algorithms like the JSC GC.
     14        In a data-parallel algorithm, we want to run one task on as many cores as possible and let
     15        the task worry about which subset of the input data to work on. In some cases, the
     16        algorithm will not need to do any load balancing - and if load balancing is required, it's
     17        up to the user. This is appropriate in contexts where the load balancing needs to be
     18        custom-tuned for performance, like the GC's marking phase.
     19
     20        This new API has three concepts: task, client, and pool. A task is a reference counted
     21        object with a run() method, which may be run in parallel. It is usually used to wrap a
     22        functor. A pool is a pool of threads that can run things. A client is a placeholder for a
     23        task. A client can have zero or one tasks. A client must be registered with a pool. When a
     24        client has a task, the pool's threads may choose to run it. If a thread starts running a
     25        task, it will run it to completion. When the task returns on any thread, the client takes
     26        it to mean that the task should be removed. That means that any currently running instances
     27        of the task will finish but no new threads will attempt to run the task. You can easily ask
     28        a client to wait until a task finishes. You can also easily ask a client to run a task on
     29        the current thread in addition to possibly some helper threads from the pool.
     30
     31        For some data-parallel algorithms, programming with ParallelHelperPool is as easy as:
     32
     33        client.runFunctionInParallel(
     34            [=] () {
     35                do things;
     36            });
     37
     38        Note that you cannot tell ahead of time how many threads will join to help the task.
     39        Threads may become available after the task has already started running. Those threads may
     40        join after the other threads have already started. It's not advisable to make algorithmic
     41        decisions based on client.numberOfActiveThreads(), since that number may change. Usually
     42        the best way to use ParallelHelperPool is with an algorithm that has its own custom
     43        worklist. An example of a very simple custom worklist is the one in the JSC GC's copying
     44        phase - it's just a Vector and an index that indicates the next set of elements to process.
     45
     46        This new API was initially designed to simplify how GCThread works, by replacing Phase with
     47        a callback that contains the phase's workload. I then realized that with a few tweaks, I
     48        could make this somewhat general enough that it might become interesting outside GC. I also
     49        realized that I could use this to enable thread sharing. So, although the API is kinda
     50        quirky, it's grounded in the reality of how the JSC GC does parallelism.
     51
     52        * WTF.vcxproj/WTF.vcxproj:
     53        * WTF.vcxproj/WTF.vcxproj.filters:
     54        * WTF.xcodeproj/project.pbxproj:
     55        * wtf/CMakeLists.txt:
     56        * wtf/ParallelHelperPool.cpp: Added.
     57        (WTF::ParallelHelperClient::ParallelHelperClient):
     58        (WTF::ParallelHelperClient::~ParallelHelperClient):
     59        (WTF::ParallelHelperClient::setTask):
     60        (WTF::ParallelHelperClient::finish):
     61        (WTF::ParallelHelperClient::doSomeHelping):
     62        (WTF::ParallelHelperClient::runTaskInParallel):
     63        (WTF::ParallelHelperClient::claimTask):
     64        (WTF::ParallelHelperClient::runTask):
     65        (WTF::ParallelHelperPool::ParallelHelperPool):
     66        (WTF::ParallelHelperPool::~ParallelHelperPool):
     67        (WTF::ParallelHelperPool::addThreads):
     68        (WTF::ParallelHelperPool::ensureThreads):
     69        (WTF::ParallelHelperPool::doSomeHelping):
     70        (WTF::ParallelHelperPool::didMakeWorkAvailable):
     71        (WTF::ParallelHelperPool::helperThreadBody):
     72        (WTF::ParallelHelperPool::hasClientWithTask):
     73        (WTF::ParallelHelperPool::getClientWithTask):
     74        (WTF::ParallelHelperPool::waitForClientWithTask):
     75        * wtf/ParallelHelperPool.h: Added.
     76        (WTF::ParallelHelperClient::setFunction):
     77        (WTF::ParallelHelperClient::runFunctionInParallel):
     78        (WTF::ParallelHelperClient::pool):
     79        (WTF::ParallelHelperClient::numberOfActiveThreads):
     80        (WTF::ParallelHelperPool::numberOfThreads):
     81        * wtf/SharedTask.h: Added.
     82        (WTF::SharedTask::SharedTask):
     83        (WTF::SharedTask::~SharedTask):
     84        (WTF::SharedTaskFunctor::SharedTaskFunctor):
     85        (WTF::createSharedTask):
     86        * wtf/WeakRandom.h: Copied from Source/JavaScriptCore/runtime/WeakRandom.h.
     87        (WTF::WeakRandom::WeakRandom):
     88        (WTF::WeakRandom::initializeSeed):
     89        (WTF::WeakRandom::seedUnsafe):
     90        (WTF::WeakRandom::getUint32):
     91        (WTF::WeakRandom::advance):
     92        (JSC::WeakRandom::WeakRandom): Deleted.
     93        (JSC::WeakRandom::seedUnsafe): Deleted.
     94        (JSC::WeakRandom::getUint32): Deleted.
     95        (JSC::WeakRandom::advance): Deleted.
     96        (JSC::WeakRandom::initializeSeed): Deleted.
     97
    1982015-09-25  Alex Christensen  <achristensen@webkit.org>
    299
  • trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj

    r188677 r190267  
    116116    <ClCompile Include="..\wtf\OSRandomSource.cpp" />
    117117    <ClCompile Include="..\wtf\PageBlock.cpp" />
     118    <ClCompile Include="..\wtf\ParallelHelperPool.cpp" />
    118119    <ClCompile Include="..\wtf\ParallelJobsGeneric.cpp" />
    119120    <ClCompile Include="..\wtf\ParkingLot.cpp" />
     
    247248    <ClInclude Include="..\wtf\PageBlock.h" />
    248249    <ClInclude Include="..\wtf\PageReservation.h" />
     250    <ClInclude Include="..\wtf\ParallelHelperPool.h" />
    249251    <ClInclude Include="..\wtf\ParallelJobs.h" />
    250252    <ClInclude Include="..\wtf\ParallelJobsGeneric.h" />
     
    270272    <ClInclude Include="..\wtf\SentinelLinkedList.h" />
    271273    <ClInclude Include="..\wtf\SHA1.h" />
     274    <ClInclude Include="..\wtf\SharedTask.h" />
    272275    <ClInclude Include="..\wtf\SinglyLinkedList.h" />
    273276    <ClInclude Include="..\wtf\SixCharacterHash.h" />
     
    314317    <ClInclude Include="..\wtf\win\GDIObject.h" />
    315318    <ClInclude Include="..\wtf\win\WorkItemWin.h" />
     319    <ClInclude Include="..\wtf\WeakRandom.h" />
    316320    <ClInclude Include="..\wtf\WordLock.h" />
    317321    <ClInclude Include="..\wtf\WorkQueue.h" />
  • trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters

    r188557 r190267  
    1 <?xml version="1.0" encoding="utf-8"?>
     1<?xml version="1.0" encoding="utf-8"?>
    22<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    33  <ItemGroup>
     
    175175      <Filter>wtf</Filter>
    176176    </ClCompile>
     177    <ClCompile Include="..\wtf\ParallelHelperPool.cpp">
     178      <Filter>wtf</Filter>
     179    </ClCompile>
    177180    <ClCompile Include="..\wtf\ParallelJobsGeneric.cpp">
    178181      <Filter>wtf</Filter>
     
    548551      <Filter>wtf</Filter>
    549552    </ClInclude>
     553    <ClInclude Include="..\wtf\ParallelHelperPool.h">
     554      <Filter>wtf</Filter>
     555    </ClInclude>
    550556    <ClInclude Include="..\wtf\ParallelJobs.h">
    551557      <Filter>wtf</Filter>
     
    603609    </ClInclude>
    604610    <ClInclude Include="..\wtf\SHA1.h">
     611      <Filter>wtf</Filter>
     612    </ClInclude>
     613    <ClInclude Include="..\wtf\SharedTask.h">
    605614      <Filter>wtf</Filter>
    606615    </ClInclude>
  • trunk/Source/WTF/WTF.xcodeproj/project.pbxproj

    r190201 r190267  
    2525                0F2B66A617B6B4FB00A7AE3F /* DeferrableRefCounted.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A417B6B4F700A7AE3F /* DeferrableRefCounted.h */; };
    2626                0F2B66A717B6B4FD00A7AE3F /* FlipBytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */; };
     27                0F3501641BB258D500F0A2A3 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3501631BB258C800F0A2A3 /* WeakRandom.h */; };
    2728                0F824A681B7443A0002E345D /* ParkingLot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F824A641B7443A0002E345D /* ParkingLot.cpp */; };
    2829                0F824A691B7443A0002E345D /* ParkingLot.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F824A651B7443A0002E345D /* ParkingLot.h */; };
     
    4849                0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE4479A1B7AAA03009498EB /* WordLock.cpp */; };
    4950                0FE4479D1B7AAA03009498EB /* WordLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE4479B1B7AAA03009498EB /* WordLock.h */; };
     51                0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */; };
    5052                0FED67B61B22D4D80066CE15 /* TinyPtrSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */; };
     53                0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */; };
     54                0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */; };
    5155                14022F4118F5C3FC007FF0EB /* libbmalloc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14022F4018F5C3FC007FF0EB /* libbmalloc.a */; };
    5256                143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; };
     
    313317                0F2B66A517B6B4F700A7AE3F /* FlipBytes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FlipBytes.h; sourceTree = "<group>"; };
    314318                0F300B7D18AB48B400A6D72E /* HashMethod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashMethod.h; sourceTree = "<group>"; };
     319                0F3501631BB258C800F0A2A3 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = "<group>"; };
    315320                0F824A641B7443A0002E345D /* ParkingLot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParkingLot.cpp; sourceTree = "<group>"; };
    316321                0F824A651B7443A0002E345D /* ParkingLot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParkingLot.h; sourceTree = "<group>"; };
     
    336341                0FE4479A1B7AAA03009498EB /* WordLock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WordLock.cpp; sourceTree = "<group>"; };
    337342                0FE4479B1B7AAA03009498EB /* WordLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WordLock.h; sourceTree = "<group>"; };
     343                0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTask.h; sourceTree = "<group>"; };
    338344                0FED67B51B22D4D80066CE15 /* TinyPtrSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyPtrSet.h; sourceTree = "<group>"; };
     345                0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParallelHelperPool.cpp; sourceTree = "<group>"; };
     346                0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelHelperPool.h; sourceTree = "<group>"; };
    339347                14022F4018F5C3FC007FF0EB /* libbmalloc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libbmalloc.a; sourceTree = BUILT_PRODUCTS_DIR; };
    340348                143F611D1565F0F900DB514A /* RAMSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RAMSize.cpp; sourceTree = "<group>"; };
     
    819827                                A8A472E4151A825B004123FF /* PageBlock.h */,
    820828                                A8A472E5151A825B004123FF /* PageReservation.h */,
     829                                0FFF19DA1BB334EB00886D91 /* ParallelHelperPool.cpp */,
     830                                0FFF19DB1BB334EB00886D91 /* ParallelHelperPool.h */,
    821831                                A8A472E6151A825B004123FF /* ParallelJobs.h */,
    822832                                A8A472E9151A825B004123FF /* ParallelJobsLibdispatch.h */,
     
    856866                                A8A47308151A825B004123FF /* SHA1.cpp */,
    857867                                A8A47309151A825B004123FF /* SHA1.h */,
     868                                0FEB3DCE1BB5D684009D7AAD /* SharedTask.h */,
    858869                                A8A4730A151A825B004123FF /* SimpleStats.h */,
    859870                                A8A4730B151A825B004123FF /* SinglyLinkedList.h */,
     
    893904                                A8A47372151A825B004123FF /* VMTags.h */,
    894905                                974CFC8D16A4F327006D5404 /* WeakPtr.h */,
     906                                0F3501631BB258C800F0A2A3 /* WeakRandom.h */,
    895907                                0FE4479A1B7AAA03009498EB /* WordLock.cpp */,
    896908                                0FE4479B1B7AAA03009498EB /* WordLock.h */,
     
    10641076                                A8A47434151A825B004123FF /* ASCIIFastPath.h in Headers */,
    10651077                                A8A47387151A825B004123FF /* Assertions.h in Headers */,
     1078                                0F3501641BB258D500F0A2A3 /* WeakRandom.h in Headers */,
    10661079                                A8A47388151A825B004123FF /* Atomics.h in Headers */,
    10671080                                A8A47436151A825B004123FF /* AtomicString.h in Headers */,
     
    10751088                                A8A473A9151A825B004123FF /* bignum-dtoa.h in Headers */,
    10761089                                A8A473AB151A825B004123FF /* bignum.h in Headers */,
     1090                                0FFF19DD1BB334EB00886D91 /* ParallelHelperPool.h in Headers */,
    10771091                                A8A47452151A825B004123FF /* BinarySemaphore.h in Headers */,
    10781092                                A8A4738A151A825B004123FF /* Bitmap.h in Headers */,
     
    11271141                                A8A473D5151A825B004123FF /* HashIterators.h in Headers */,
    11281142                                A8A473D6151A825B004123FF /* HashMap.h in Headers */,
     1143                                0FEB3DCF1BB5D684009D7AAD /* SharedTask.h in Headers */,
    11291144                                A8A473D7151A825B004123FF /* HashSet.h in Headers */,
    11301145                                A8A473D9151A825B004123FF /* HashTable.h in Headers */,
     
    13931408                                2CDED0EF18115C38004DBA70 /* RunLoopCF.cpp in Sources */,
    13941409                                1469419316EAAF6D0024E146 /* RunLoopTimerCF.cpp in Sources */,
     1410                                0FFF19DC1BB334EB00886D91 /* ParallelHelperPool.cpp in Sources */,
    13951411                                1469419916EAB0410024E146 /* SchedulePairCF.cpp in Sources */,
    13961412                                1469419716EAAFF80024E146 /* SchedulePairMac.mm in Sources */,
  • trunk/Source/WTF/wtf/CMakeLists.txt

    r188677 r190267  
    8383    RunLoop.h
    8484    SHA1.h
     85    SharedTask.h
    8586    SaturatedArithmetic.h
    8687    SegmentedVector.h
     
    168169    OSRandomSource.cpp
    169170    PageBlock.cpp
     171    ParallelHelperPool.cpp
    170172    ParallelJobsGeneric.cpp
    171173    ParkingLot.cpp
  • trunk/Source/WTF/wtf/WeakRandom.h

    r190151 r190267  
    11/*
    2  * Copyright (C) 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5252
    5353#include <limits.h>
     54#include <wtf/RandomNumber.h>
    5455#include <wtf/StdLibExtras.h>
    5556
    56 namespace JSC {
     57namespace WTF {
    5758
    5859class WeakRandom {
    59 friend class JSGlobalObject; // For access to initializeSeed() during replay.
    6060public:
     61    WeakRandom()
     62    {
     63        initializeSeed(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0));
     64    }
     65   
    6166    WeakRandom(unsigned seed)
    6267    {
     
    6469    }
    6570   
     71    void initializeSeed(unsigned seed)
     72    {
     73        m_low = seed ^ 0x49616E42;
     74        m_high = seed;
     75    }
     76
    6677    // Returns the seed provided that you've never called get() or getUint32().
    6778    unsigned seedUnsafe() const { return m_high; }
     
    7788    }
    7889
     90    unsigned getUint32(unsigned limit)
     91    {
     92        if (limit <= 1)
     93            return 0;
     94        uint64_t cutoff = (static_cast<uint64_t>(UINT_MAX) + 1) / limit * limit;
     95        for (;;) {
     96            uint64_t value = getUint32();
     97            if (value >= cutoff)
     98                continue;
     99            return value % limit;
     100        }
     101    }
     102
    79103private:
    80104    unsigned advance()
     
    86110    }
    87111
    88     void initializeSeed(unsigned seed)
    89     {
    90         m_low = seed ^ 0x49616E42;
    91         m_high = seed;
    92     }
    93 
    94112    unsigned m_low;
    95113    unsigned m_high;
    96114};
    97115
    98 } // namespace JSC
     116} // namespace WTF
     117
     118using WTF::WeakRandom;
    99119
    100120#endif // WeakRandom_h
Note: See TracChangeset for help on using the changeset viewer.