Changeset 233158 in webkit


Ignore:
Timestamp:
Jun 25, 2018 11:30:47 AM (6 years ago)
Author:
commit-queue@webkit.org
Message:

Add API for configuring the number of threads used by DFG and FTL
https://bugs.webkit.org/show_bug.cgi?id=186859
<rdar://problem/41093519>

Patch by Tadeu Zagallo <Tadeu Zagallo> on 2018-06-25
Reviewed by Filip Pizlo.

Add new private APIs for limiting the number of threads to be used by
the DFG and FTL compilers. It was already possible to configure the
limit through JSC Options, but now it can be changed at runtime, even
in the case when the VM is already running.

Add a test for both cases: when trying to configure the limit before
and after the Worklist has been created, but in order to simulate the
first scenario, we must guarantee that the test runs at the very
beginning, so I also added a check for that.

  • API/JSVirtualMachine.mm:

(+[JSVirtualMachine setNumberOfDFGCompilerThreads:]):
(+[JSVirtualMachine setNumberOfFTLCompilerThreads:]):

  • API/JSVirtualMachinePrivate.h:
  • API/tests/testapi.mm:

(runJITThreadLimitTests):
(testObjectiveCAPIMain):

  • dfg/DFGWorklist.cpp:

(JSC::DFG::Worklist::finishCreation):
(JSC::DFG::Worklist::createNewThread):
(JSC::DFG::Worklist::setNumberOfThreads):

  • dfg/DFGWorklist.h:
Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSVirtualMachine.mm

    r232788 r233158  
    3131
    3232#import "APICast.h"
     33#import "DFGWorklist.h"
    3334#import "JSManagedValueInternal.h"
    3435#import "JSVirtualMachine.h"
     
    275276    vm->shrinkFootprintWhenIdle();
    276277}
     278
     279#if ENABLE(DFG_JIT)
     280
     281+ (NSUInteger)setNumberOfDFGCompilerThreads:(NSUInteger)numberOfThreads
     282{
     283    JSC::DFG::Worklist* worklist = JSC::DFG::existingGlobalDFGWorklistOrNull();
     284    if (worklist)
     285        return worklist->setNumberOfThreads(numberOfThreads, JSC::Options::priorityDeltaOfDFGCompilerThreads());
     286
     287    auto currentNumberOfThreads = JSC::Options::numberOfDFGCompilerThreads();
     288    JSC::Options::numberOfDFGCompilerThreads() = numberOfThreads;
     289    return currentNumberOfThreads;
     290}
     291
     292+ (NSUInteger)setNumberOfFTLCompilerThreads:(NSUInteger)numberOfThreads
     293{
     294    JSC::DFG::Worklist* worklist = JSC::DFG::existingGlobalFTLWorklistOrNull();
     295    if (worklist)
     296        return worklist->setNumberOfThreads(numberOfThreads, JSC::Options::priorityDeltaOfFTLCompilerThreads());
     297
     298    auto currentNumberOfThreads = JSC::Options::numberOfFTLCompilerThreads();
     299    JSC::Options::numberOfFTLCompilerThreads() = numberOfThreads;
     300    return currentNumberOfThreads;
     301}
     302
     303#endif // ENABLE(DFG_JIT)
    277304
    278305@end
  • trunk/Source/JavaScriptCore/API/JSVirtualMachinePrivate.h

    r232900 r233158  
    2424 */
    2525
     26#include "JSExportMacros.h"
    2627#include <JavaScriptCore/JavaScript.h>
    2728
     
    4546- (void)shrinkFootprintWhenIdle NS_AVAILABLE(10_14, 12_0);
    4647
     48#if ENABLE(DFG_JIT)
     49
     50/*!
     51@method
     52@abstract Set the number of threads to be used by the DFG JIT compiler.
     53@discussion If called after the VM has been initialized, it will terminate
     54 threads until it meets the new limit or create new threads accordingly if the
     55 new limit is higher than the previous limit. If called before initialization,
     56 the Options value for the number of DFG threads will be updated to ensure the
     57 DFG compiler already starts with the up-to-date limit.
     58@param numberOfThreads The number of threads the DFG compiler should use going forward
     59@result The previous number of threads being used by the DFG compiler
     60*/
     61+ (NSUInteger)setNumberOfDFGCompilerThreads:(NSUInteger)numberOfThreads NS_AVAILABLE(10_14, 12_0);
     62
     63/*!
     64@method
     65@abstract Set the number of threads to be used by the FTL JIT compiler.
     66@discussion If called after the VM has been initialized, it will terminate
     67 threads until it meets the new limit or create new threads accordingly if the
     68 new limit is higher than the previous limit. If called before initialization,
     69 the Options value for the number of FTL threads will be updated to ensure the
     70 FTL compiler already starts with the up-to-date limit.
     71@param numberOfThreads The number of threads the FTL compiler should use going forward
     72@result The previous number of threads being used by the FTL compiler
     73*/
     74+ (NSUInteger)setNumberOfFTLCompilerThreads:(NSUInteger)numberOfThreads NS_AVAILABLE(10_14, 12_0);
     75
     76#endif // ENABLE(DFG_JIT)
     77
    4778@end
    4879
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r233079 r233158  
    2424 */
    2525
     26#import "JSExportMacros.h"
    2627#import <JavaScriptCore/JavaScriptCore.h>
    2728
     29#undef NS_AVAILABLE
     30#define NS_AVAILABLE(_mac, _ios)
     31
    2832#import "CurrentThisInsideBlockGetterTest.h"
     33#import "DFGWorklist.h"
    2934#import "DateTests.h"
    3035#import "JSExportTests.h"
     
    515520}
    516521
     522static void runJITThreadLimitTests()
     523{
     524    auto testDFG = [] {
     525        unsigned defaultNumberOfThreads = JSC::Options::numberOfDFGCompilerThreads();
     526        unsigned targetNumberOfThreads = 1;
     527        unsigned initialNumberOfThreads = [JSVirtualMachine setNumberOfDFGCompilerThreads:1];
     528        checkResult(@"Initial number of DFG threads should be the value provided through Options", initialNumberOfThreads == defaultNumberOfThreads);
     529        unsigned updatedNumberOfThreads = [JSVirtualMachine setNumberOfDFGCompilerThreads:initialNumberOfThreads];
     530        checkResult(@"Number of DFG threads should have been updated", updatedNumberOfThreads == targetNumberOfThreads);
     531    };
     532
     533    auto testFTL = [] {
     534        unsigned defaultNumberOfThreads = JSC::Options::numberOfFTLCompilerThreads();
     535        unsigned targetNumberOfThreads = 3;
     536        unsigned initialNumberOfThreads = [JSVirtualMachine setNumberOfFTLCompilerThreads:1];
     537        checkResult(@"Initial number of FTL threads should be the value provided through Options", initialNumberOfThreads == defaultNumberOfThreads);
     538        unsigned updatedNumberOfThreads = [JSVirtualMachine setNumberOfFTLCompilerThreads:initialNumberOfThreads];
     539        checkResult(@"Number of FTL threads should have been updated", updatedNumberOfThreads == targetNumberOfThreads);
     540    };
     541
     542    checkResult(@"runJITThreadLimitTests() must run at the very beginning to test the case where the global JIT worklist was not initialized yet", !JSC::DFG::existingGlobalDFGWorklistOrNull() && !JSC::DFG::existingGlobalFTLWorklistOrNull());
     543
     544    testDFG();
     545    JSC::DFG::ensureGlobalDFGWorklist();
     546    testDFG();
     547
     548    testFTL();
     549    JSC::DFG::ensureGlobalFTLWorklist();
     550    testFTL();
     551}
     552
    517553static void testObjectiveCAPIMain()
    518554{
     555    runJITThreadLimitTests();
     556
    519557    @autoreleasepool {
    520558        JSVirtualMachine* vm = [[JSVirtualMachine alloc] init];
  • trunk/Source/JavaScriptCore/ChangeLog

    r233139 r233158  
     12018-06-25  Tadeu Zagallo  <tzagallo@apple.com>
     2
     3        Add API for configuring the number of threads used by DFG and FTL
     4        https://bugs.webkit.org/show_bug.cgi?id=186859
     5        <rdar://problem/41093519>
     6
     7        Reviewed by Filip Pizlo.
     8
     9        Add new private APIs for limiting the number of threads to be used by
     10        the DFG and FTL compilers. It was already possible to configure the
     11        limit through JSC Options, but now it can be changed at runtime, even
     12        in the case when the VM is already running.
     13
     14        Add a test for both cases: when trying to configure the limit before
     15        and after the Worklist has been created, but in order to simulate the
     16        first scenario, we must guarantee that the test runs at the very
     17        beginning, so I also added a check for that.
     18
     19        * API/JSVirtualMachine.mm:
     20        (+[JSVirtualMachine setNumberOfDFGCompilerThreads:]):
     21        (+[JSVirtualMachine setNumberOfFTLCompilerThreads:]):
     22        * API/JSVirtualMachinePrivate.h:
     23        * API/tests/testapi.mm:
     24        (runJITThreadLimitTests):
     25        (testObjectiveCAPIMain):
     26        * dfg/DFGWorklist.cpp:
     27        (JSC::DFG::Worklist::finishCreation):
     28        (JSC::DFG::Worklist::createNewThread):
     29        (JSC::DFG::Worklist::setNumberOfThreads):
     30        * dfg/DFGWorklist.h:
     31
    1322018-06-25  Yusuke Suzuki  <utatane.tea@gmail.com>
    233
  • trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp

    r233123 r233158  
    201201    LockHolder locker(*m_lock);
    202202    for (unsigned i = numberOfThreads; i--;) {
    203         std::unique_ptr<ThreadData> data = std::make_unique<ThreadData>(this);
    204         data->m_thread = adoptRef(new ThreadBody(locker, *this, *data, m_lock, m_planEnqueued.copyRef(), relativePriority));
    205         m_threads.append(WTFMove(data));
    206     }
     203        createNewThread(locker, relativePriority);
     204    }
     205}
     206
     207void Worklist::createNewThread(const AbstractLocker& locker, int relativePriority)
     208{
     209    std::unique_ptr<ThreadData> data = std::make_unique<ThreadData>(this);
     210    data->m_thread = adoptRef(new ThreadBody(locker, *this, *data, m_lock, m_planEnqueued.copyRef(), relativePriority));
     211    m_threads.append(WTFMove(data));
    207212}
    208213
     
    489494}
    490495
     496unsigned Worklist::setNumberOfThreads(unsigned numberOfThreads, int relativePriority)
     497{
     498    LockHolder locker(m_suspensionLock);
     499    auto currentNumberOfThreads = m_threads.size();
     500    if (numberOfThreads < currentNumberOfThreads) {
     501        {
     502            LockHolder locker(*m_lock);
     503            for (unsigned i = currentNumberOfThreads; i-- > numberOfThreads;) {
     504                if (m_threads[i]->m_thread->hasUnderlyingThread(locker)) {
     505                    m_queue.append(nullptr);
     506                    m_threads[i]->m_thread->notify(locker);
     507                }
     508            }
     509        }
     510        for (unsigned i = currentNumberOfThreads; i-- > numberOfThreads;) {
     511            bool isStopped = false;
     512            {
     513                LockHolder locker(*m_lock);
     514                isStopped = m_threads[i]->m_thread->tryStop(locker);
     515            }
     516            if (!isStopped)
     517                m_threads[i]->m_thread->join();
     518            m_threads.remove(i);
     519        }
     520        m_threads.shrinkToFit();
     521        ASSERT(m_numberOfActiveThreads <= numberOfThreads);
     522    } else if (numberOfThreads > currentNumberOfThreads) {
     523        LockHolder locker(*m_lock);
     524        for (unsigned i = currentNumberOfThreads; i < numberOfThreads; i++)
     525            createNewThread(locker, relativePriority);
     526    }
     527    return currentNumberOfThreads;
     528}
     529
    491530static Worklist* theGlobalDFGWorklist;
    492531
  • trunk/Source/JavaScriptCore/dfg/DFGWorklist.h

    r233123 r233158  
    8080   
    8181    void dump(PrintStream&) const;
     82    unsigned setNumberOfThreads(unsigned, int);
    8283   
    8384private:
    8485    Worklist(CString worklistName);
    8586    void finishCreation(unsigned numberOfThreads, int);
     87    void createNewThread(const AbstractLocker&, int);
    8688   
    8789    class ThreadBody;
     
    122124
    123125// For DFGMode compilations.
    124 Worklist& ensureGlobalDFGWorklist();
    125 Worklist* existingGlobalDFGWorklistOrNull();
     126JS_EXPORT_PRIVATE Worklist& ensureGlobalDFGWorklist();
     127JS_EXPORT_PRIVATE Worklist* existingGlobalDFGWorklistOrNull();
    126128
    127129// For FTLMode and FTLForOSREntryMode compilations.
    128 Worklist& ensureGlobalFTLWorklist();
    129 Worklist* existingGlobalFTLWorklistOrNull();
     130JS_EXPORT_PRIVATE Worklist& ensureGlobalFTLWorklist();
     131JS_EXPORT_PRIVATE Worklist* existingGlobalFTLWorklistOrNull();
    130132
    131133Worklist& ensureGlobalWorklistFor(CompilationMode);
Note: See TracChangeset for help on using the changeset viewer.