Title: [268897] trunk/Source/WebCore
Revision
268897
Author
[email protected]
Date
2020-10-22 15:25:44 -0700 (Thu, 22 Oct 2020)

Log Message

Share more code between WorkerThread and AudioWorkletThread
https://bugs.webkit.org/show_bug.cgi?id=218051

Reviewed by Geoffrey Garen.

Share more code between WorkerThread and AudioWorkletThread by moving more logic
to the WorkerOrWorklet base class.

No new tests, no web-facing behavior change.

* Modules/webaudio/AudioWorkletMessagingProxy.cpp:
(WebCore::generateWorkletParameters):
* Modules/webaudio/AudioWorkletThread.cpp:
(WebCore::AudioWorkletThread::AudioWorkletThread):
(WebCore::AudioWorkletThread::createGlobalScope):
(WebCore::AudioWorkletThread::workerLoaderProxy):
(WebCore::AudioWorkletThread::createThread):
(WebCore::AudioWorkletThread::globalScope const):
* Modules/webaudio/AudioWorkletThread.h:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* page/MemoryRelease.cpp:
(WebCore::releaseMemory):
* page/cocoa/ResourceUsageThreadCocoa.mm:
(WebCore::ResourceUsageThread::platformCollectCPUData):
* page/linux/ResourceUsageThreadLinux.cpp:
(WebCore::ResourceUsageThread::platformCollectCPUData):
* workers/DedicatedWorkerThread.cpp:
(WebCore::DedicatedWorkerThread::runEventLoop):
* workers/WorkerGlobalScope.h:
* workers/WorkerOrWorkletGlobalScope.h:
(WebCore::WorkerOrWorkletGlobalScope::suspend):
(WebCore::WorkerOrWorkletGlobalScope::resume):
* workers/WorkerOrWorkletThread.cpp: Copied from Source/WebCore/workers/WorkerThread.cpp.
(WebCore::WorkerOrWorkletThread::workerOrWorkletThreadsLock):
(WebCore::WorkerOrWorkletThread::WorkerOrWorkletThread):
(WebCore::WorkerOrWorkletThread::~WorkerOrWorkletThread):
(WebCore::WorkerOrWorkletThread::startRunningDebuggerTasks):
(WebCore::WorkerOrWorkletThread::stopRunningDebuggerTasks):
(WebCore::WorkerOrWorkletThread::runEventLoop):
(WebCore::WorkerOrWorkletThread::workerOrWorkletThread):
(WebCore::WorkerOrWorkletThread::start):
(WebCore::WorkerOrWorkletThread::stop):
(WebCore::WorkerOrWorkletThread::suspend):
(WebCore::WorkerOrWorkletThread::resume):
(WebCore::WorkerOrWorkletThread::releaseFastMallocFreeMemoryInAllThreads):
* workers/WorkerOrWorkletThread.h:
(WebCore::WorkerOrWorkletThread::thread const):
(WebCore::WorkerOrWorkletThread::globalScope const):
(WebCore::WorkerOrWorkletThread::runLoop):
(WebCore::WorkerOrWorkletThread::start):
(WebCore::WorkerOrWorkletThread::stop):
(WebCore::WorkerOrWorkletThread::identifier const):
(WebCore::WorkerOrWorkletThread::evaluateScriptIfNecessary):
(WebCore::WorkerOrWorkletThread::shouldWaitForWebInspectorOnStartup const):
* workers/WorkerThread.cpp:
(WebCore::WorkerThread::workerThreadCount):
(WebCore::WorkerThread::WorkerThread):
(WebCore::WorkerThread::~WorkerThread):
(WebCore::WorkerThread::createThread):
(WebCore::WorkerThread::createGlobalScope):
(WebCore::WorkerThread::shouldWaitForWebInspectorOnStartup const):
(WebCore::WorkerThread::evaluateScriptIfNecessary):
(WebCore::WorkerThread::globalScope):
* workers/WorkerThread.h:
* workers/service/context/ServiceWorkerThread.cpp:
(WebCore::ServiceWorkerThread::queueTaskToFireFetchEvent):
(WebCore::ServiceWorkerThread::queueTaskToPostMessage):
(WebCore::ServiceWorkerThread::queueTaskToFireInstallEvent):
(WebCore::ServiceWorkerThread::queueTaskToFireActivateEvent):
(WebCore::ServiceWorkerThread::finishedEvaluatingScript):
* worklets/Worklet.cpp:
(WebCore::Worklet::Worklet):
* worklets/Worklet.h:
(WebCore::Worklet::identifier const):
* worklets/WorkletParameters.h:
(WebCore::WorkletParameters::isolatedCopy const):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (268896 => 268897)


--- trunk/Source/WebCore/ChangeLog	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/ChangeLog	2020-10-22 22:25:44 UTC (rev 268897)
@@ -1,3 +1,83 @@
+2020-10-22  Chris Dumez  <[email protected]>
+
+        Share more code between WorkerThread and AudioWorkletThread
+        https://bugs.webkit.org/show_bug.cgi?id=218051
+
+        Reviewed by Geoffrey Garen.
+
+        Share more code between WorkerThread and AudioWorkletThread by moving more logic
+        to the WorkerOrWorklet base class.
+
+        No new tests, no web-facing behavior change.
+
+        * Modules/webaudio/AudioWorkletMessagingProxy.cpp:
+        (WebCore::generateWorkletParameters):
+        * Modules/webaudio/AudioWorkletThread.cpp:
+        (WebCore::AudioWorkletThread::AudioWorkletThread):
+        (WebCore::AudioWorkletThread::createGlobalScope):
+        (WebCore::AudioWorkletThread::workerLoaderProxy):
+        (WebCore::AudioWorkletThread::createThread):
+        (WebCore::AudioWorkletThread::globalScope const):
+        * Modules/webaudio/AudioWorkletThread.h:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * page/MemoryRelease.cpp:
+        (WebCore::releaseMemory):
+        * page/cocoa/ResourceUsageThreadCocoa.mm:
+        (WebCore::ResourceUsageThread::platformCollectCPUData):
+        * page/linux/ResourceUsageThreadLinux.cpp:
+        (WebCore::ResourceUsageThread::platformCollectCPUData):
+        * workers/DedicatedWorkerThread.cpp:
+        (WebCore::DedicatedWorkerThread::runEventLoop):
+        * workers/WorkerGlobalScope.h:
+        * workers/WorkerOrWorkletGlobalScope.h:
+        (WebCore::WorkerOrWorkletGlobalScope::suspend):
+        (WebCore::WorkerOrWorkletGlobalScope::resume):
+        * workers/WorkerOrWorkletThread.cpp: Copied from Source/WebCore/workers/WorkerThread.cpp.
+        (WebCore::WorkerOrWorkletThread::workerOrWorkletThreadsLock):
+        (WebCore::WorkerOrWorkletThread::WorkerOrWorkletThread):
+        (WebCore::WorkerOrWorkletThread::~WorkerOrWorkletThread):
+        (WebCore::WorkerOrWorkletThread::startRunningDebuggerTasks):
+        (WebCore::WorkerOrWorkletThread::stopRunningDebuggerTasks):
+        (WebCore::WorkerOrWorkletThread::runEventLoop):
+        (WebCore::WorkerOrWorkletThread::workerOrWorkletThread):
+        (WebCore::WorkerOrWorkletThread::start):
+        (WebCore::WorkerOrWorkletThread::stop):
+        (WebCore::WorkerOrWorkletThread::suspend):
+        (WebCore::WorkerOrWorkletThread::resume):
+        (WebCore::WorkerOrWorkletThread::releaseFastMallocFreeMemoryInAllThreads):
+        * workers/WorkerOrWorkletThread.h:
+        (WebCore::WorkerOrWorkletThread::thread const):
+        (WebCore::WorkerOrWorkletThread::globalScope const):
+        (WebCore::WorkerOrWorkletThread::runLoop):
+        (WebCore::WorkerOrWorkletThread::start):
+        (WebCore::WorkerOrWorkletThread::stop):
+        (WebCore::WorkerOrWorkletThread::identifier const):
+        (WebCore::WorkerOrWorkletThread::evaluateScriptIfNecessary):
+        (WebCore::WorkerOrWorkletThread::shouldWaitForWebInspectorOnStartup const):
+        * workers/WorkerThread.cpp:
+        (WebCore::WorkerThread::workerThreadCount):
+        (WebCore::WorkerThread::WorkerThread):
+        (WebCore::WorkerThread::~WorkerThread):
+        (WebCore::WorkerThread::createThread):
+        (WebCore::WorkerThread::createGlobalScope):
+        (WebCore::WorkerThread::shouldWaitForWebInspectorOnStartup const):
+        (WebCore::WorkerThread::evaluateScriptIfNecessary):
+        (WebCore::WorkerThread::globalScope):
+        * workers/WorkerThread.h:
+        * workers/service/context/ServiceWorkerThread.cpp:
+        (WebCore::ServiceWorkerThread::queueTaskToFireFetchEvent):
+        (WebCore::ServiceWorkerThread::queueTaskToPostMessage):
+        (WebCore::ServiceWorkerThread::queueTaskToFireInstallEvent):
+        (WebCore::ServiceWorkerThread::queueTaskToFireActivateEvent):
+        (WebCore::ServiceWorkerThread::finishedEvaluatingScript):
+        * worklets/Worklet.cpp:
+        (WebCore::Worklet::Worklet):
+        * worklets/Worklet.h:
+        (WebCore::Worklet::identifier const):
+        * worklets/WorkletParameters.h:
+        (WebCore::WorkletParameters::isolatedCopy const):
+
 2020-10-22  Adrian Perez de Castro  <[email protected]>
 
         Non-unified build fixes, late-ish October 2020 edition

Modified: trunk/Source/WebCore/Modules/webaudio/AudioWorkletMessagingProxy.cpp (268896 => 268897)


--- trunk/Source/WebCore/Modules/webaudio/AudioWorkletMessagingProxy.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/Modules/webaudio/AudioWorkletMessagingProxy.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -51,7 +51,8 @@
     return {
         document->url(),
         jsRuntimeFlags,
-        worklet.audioContext() ? worklet.audioContext()->sampleRate() : 0.0f
+        worklet.audioContext() ? worklet.audioContext()->sampleRate() : 0.0f,
+        worklet.identifier()
     };
 }
 

Modified: trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.cpp (268896 => 268897)


--- trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -33,20 +33,13 @@
 
 #include "AudioWorkletGlobalScope.h"
 #include "AudioWorkletMessagingProxy.h"
-#include "WorkerOrWorkletScriptController.h"
+#include <wtf/Threading.h>
 
-#if PLATFORM(IOS_FAMILY)
-#include "FloatingPointEnvironment.h"
-#endif
-
-#if USE(GLIB)
-#include <wtf/glib/GRefPtr.h>
-#endif
-
 namespace WebCore {
 
 AudioWorkletThread::AudioWorkletThread(AudioWorkletMessagingProxy& messagingProxy, const WorkletParameters& parameters)
-    : m_messagingProxy(messagingProxy)
+    : WorkerOrWorkletThread(parameters.identifier.isolatedCopy())
+    , m_messagingProxy(messagingProxy)
     , m_parameters(parameters.isolatedCopy())
 {
 }
@@ -53,130 +46,28 @@
 
 AudioWorkletThread::~AudioWorkletThread() = default;
 
-void AudioWorkletThread::start()
+Ref<WorkerOrWorkletGlobalScope> AudioWorkletThread::createGlobalScope()
 {
-    auto lock = holdLock(m_threadCreationAndWorkletGlobalScopeLock);
-
-    Ref<Thread> thread = Thread::create("WebCore: AudioWorklet", [this] {
-        workletThread();
-    }, ThreadType::Audio);
-    // Force the Thread object to be initialized fully before storing it to m_thread (and becoming visible to other threads).
-    WTF::storeStoreFence();
-    m_thread = WTFMove(thread);
+    return AudioWorkletGlobalScope::create(*this, m_parameters);
 }
 
-void AudioWorkletThread::stop()
+WorkerLoaderProxy& AudioWorkletThread::workerLoaderProxy()
 {
-    // Mutex protection is necessary to ensure that m_workerGlobalScope isn't changed by
-    // WorkerThread::workerThread() while we're accessing it. Note also that stop() can
-    // be called before m_workerGlobalScope is fully created.
-    auto locker = tryHoldLock(m_threadCreationAndWorkletGlobalScopeLock);
-    if (!locker) {
-        // The thread is still starting, spin the runloop and try again to avoid deadlocks if the worker thread
-        // needs to interact with the main thread during startup.
-        callOnMainThread([this]() mutable {
-            stop();
-        });
-        return;
-    }
-
-    // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever.
-    if (m_workletGlobalScope) {
-        m_workletGlobalScope->script()->scheduleExecutionTermination();
-
-        m_runLoop.postTaskAndTerminate({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context ) {
-            auto& workletGlobalScope = downcast<AudioWorkletGlobalScope>(context);
-
-            workletGlobalScope.prepareForDestruction();
-
-            // Stick a shutdown command at the end of the queue, so that we deal
-            // with all the cleanup tasks the databases post first.
-            workletGlobalScope.postTask({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context) {
-                auto& workletGlobalScope = downcast<AudioWorkletGlobalScope>(context);
-                // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed.
-                workletGlobalScope.clearScript();
-            } });
-
-        } });
-        return;
-    }
-    m_runLoop.terminate();
+    return m_messagingProxy;
 }
 
-void AudioWorkletThread::workletThread()
+Ref<Thread> AudioWorkletThread::createThread()
 {
-    auto protectedThis = makeRef(*this);
-
-    // Propagate the mainThread's fenv to workers.
-#if PLATFORM(IOS_FAMILY)
-    FloatingPointEnvironment::singleton().propagateMainThreadEnvironment();
-#endif
-
-#if USE(GLIB)
-    GRefPtr<GMainContext> mainContext = adoptGRef(g_main_context_new());
-    g_main_context_push_thread_default(mainContext.get());
-#endif
-
-    WorkerOrWorkletScriptController* scriptController;
-    {
-        auto lock = holdLock(m_threadCreationAndWorkletGlobalScopeLock);
-        m_workletGlobalScope = AudioWorkletGlobalScope::create(*this, m_parameters);
-
-        scriptController = m_workletGlobalScope->script();
-
-        if (m_runLoop.terminated()) {
-            // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
-            // forbidExecution() couldn't be called from stop().
-            scriptController->scheduleExecutionTermination();
-            scriptController->forbidExecution();
-        }
-    }
-
-    runEventLoop();
-
-#if USE(GLIB)
-    g_main_context_pop_thread_default(mainContext.get());
-#endif
-
-    RefPtr<Thread> protector = m_thread;
-
-    ASSERT(m_workletGlobalScope->hasOneRef());
-
-    RefPtr<AudioWorkletGlobalScope> workletGlobalScopeToDelete;
-    {
-        // Mutex protection is necessary to ensure that we don't change m_workerGlobalScope
-        // while WorkerThread::stop is accessing it.
-        auto lock = holdLock(m_threadCreationAndWorkletGlobalScopeLock);
-
-        // Delay the destruction of the WorkerGlobalScope context until after we've unlocked the
-        // m_threadCreationAndWorkerGlobalScopeMutex. This is needed because destructing the
-        // context will trigger the main thread to race against us to delete the WorkerThread
-        // object, and the WorkerThread object owns the mutex we need to unlock after this.
-        workletGlobalScopeToDelete = WTFMove(m_workletGlobalScope);
-    }
-
-    // The below assignment will destroy the context, which will in turn notify messaging proxy.
-    // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
-    workletGlobalScopeToDelete = nullptr;
-
-    // Send the last WorkerThread Ref to be Deref'ed on the main thread.
-    callOnMainThread([protectedThis = WTFMove(protectedThis)] { });
-
-    // The thread object may be already destroyed from notification now, don't try to access "this".
-    protector->detach();
+    return Thread::create("WebCore: AudioWorklet", [this] {
+        workerOrWorkletThread();
+    }, ThreadType::Audio);
 }
 
-void AudioWorkletThread::runEventLoop()
+AudioWorkletGlobalScope* AudioWorkletThread::globalScope() const
 {
-    // Does not return until terminated.
-    m_runLoop.run(m_workletGlobalScope.get());
+    return downcast<AudioWorkletGlobalScope>(WorkerOrWorkletThread::globalScope());
 }
 
-WorkerLoaderProxy& AudioWorkletThread::workerLoaderProxy()
-{
-    return m_messagingProxy;
-}
-
 } // namespace WebCore
 
 #endif // ENABLE(WEB_AUDIO)

Modified: trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.h (268896 => 268897)


--- trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/Modules/webaudio/AudioWorkletThread.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -30,11 +30,7 @@
 
 #if ENABLE(WEB_AUDIO)
 #include "WorkerOrWorkletThread.h"
-#include "WorkerRunLoop.h"
 #include "WorkletParameters.h"
-#include <wtf/Forward.h>
-#include <wtf/Lock.h>
-#include <wtf/Threading.h>
 
 namespace WebCore {
 
@@ -49,29 +45,22 @@
     }
     ~AudioWorkletThread();
 
-    AudioWorkletGlobalScope* globalScope() const { return m_workletGlobalScope.get(); }
+    AudioWorkletGlobalScope* globalScope() const;
 
-    void start();
-    void stop();
-
     // WorkerOrWorkletThread.
-    WorkerRunLoop& runLoop() final { return m_runLoop; }
     WorkerLoaderProxy& workerLoaderProxy() final;
-    Thread* thread() const final { return m_thread.get(); }
+
     AudioWorkletMessagingProxy& messagingProxy() { return m_messagingProxy; }
 
 private:
     AudioWorkletThread(AudioWorkletMessagingProxy&, const WorkletParameters&);
 
-    void runEventLoop();
-    void workletThread();
+    // WorkerOrWorkletThread.
+    Ref<WTF::Thread> createThread() final;
+    Ref<WorkerOrWorkletGlobalScope> createGlobalScope() final;
 
     AudioWorkletMessagingProxy& m_messagingProxy;
-    RefPtr<Thread> m_thread;
-    WorkerRunLoop m_runLoop;
     WorkletParameters m_parameters;
-    RefPtr<AudioWorkletGlobalScope> m_workletGlobalScope;
-    Lock m_threadCreationAndWorkletGlobalScopeLock;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Sources.txt (268896 => 268897)


--- trunk/Source/WebCore/Sources.txt	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/Sources.txt	2020-10-22 22:25:44 UTC (rev 268897)
@@ -2563,6 +2563,7 @@
 workers/WorkerMessagingProxy.cpp
 workers/WorkerOrWorkletGlobalScope.cpp
 workers/WorkerOrWorkletScriptController.cpp
+workers/WorkerOrWorkletThread.cpp
 workers/WorkerRunLoop.cpp
 workers/WorkerScriptLoader.cpp
 workers/WorkerThread.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (268896 => 268897)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-10-22 22:25:44 UTC (rev 268897)
@@ -10754,6 +10754,7 @@
 		837FB3401F9EA06600D0FC31 /* ExtendableMessageEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExtendableMessageEvent.h; sourceTree = "<group>"; };
 		837FB3421F9EA06700D0FC31 /* ExtendableMessageEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtendableMessageEvent.cpp; sourceTree = "<group>"; };
 		837FB3431F9EA06800D0FC31 /* ExtendableMessageEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ExtendableMessageEvent.idl; sourceTree = "<group>"; };
+		837FCB4D2540E3C700934D4F /* WorkerOrWorkletThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerOrWorkletThread.cpp; sourceTree = "<group>"; };
 		8386A96E19F61E4F00E1EC4A /* StyleBuilderGenerated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StyleBuilderGenerated.cpp; path = DerivedSources/WebCore/StyleBuilderGenerated.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		838867341D13BA59003697D0 /* RenderObjectEnums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderObjectEnums.h; sourceTree = "<group>"; };
 		838869EB1CE81E9E00D16A9E /* JSTextCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTextCustom.cpp; sourceTree = "<group>"; };
@@ -18879,6 +18880,7 @@
 				83D6AAE42524EE1300428B4B /* WorkerOrWorkletGlobalScope.h */,
 				835AA388253F55BB00746554 /* WorkerOrWorkletScriptController.cpp */,
 				839A095B2524F37600EEF328 /* WorkerOrWorkletScriptController.h */,
+				837FCB4D2540E3C700934D4F /* WorkerOrWorkletThread.cpp */,
 				83E828B2252794CD0027E0F7 /* WorkerOrWorkletThread.h */,
 				416E29A5102FA962007FC14E /* WorkerReportingProxy.h */,
 				2E4346400F546A8200B0F1BA /* WorkerRunLoop.cpp */,

Modified: trunk/Source/WebCore/page/MemoryRelease.cpp (268896 => 268897)


--- trunk/Source/WebCore/page/MemoryRelease.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/page/MemoryRelease.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -147,7 +147,7 @@
 
     if (synchronous == Synchronous::Yes) {
         // FastMalloc has lock-free thread specific caches that can only be cleared from the thread itself.
-        WorkerThread::releaseFastMallocFreeMemoryInAllThreads();
+        WorkerOrWorkletThread::releaseFastMallocFreeMemoryInAllThreads();
 #if ENABLE(SCROLLING_THREAD)
         ScrollingThread::dispatch(WTF::releaseFastMallocFreeMemory);
 #endif

Modified: trunk/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm (268896 => 268897)


--- trunk/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm	2020-10-22 22:25:44 UTC (rev 268897)
@@ -171,8 +171,8 @@
 
     HashMap<mach_port_t, String> knownWorkerThreads;
     {
-        LockHolder lock(WorkerThread::workerThreadsMutex());
-        for (auto* thread : WorkerThread::workerThreads(lock)) {
+        auto locker = holdLock(WorkerOrWorkletThread::workerOrWorkletThreadsLock());
+        for (auto* thread : WorkerOrWorkletThread::workerOrWorkletThreads()) {
             // Ignore worker threads that have not been fully started yet.
             if (!thread->thread())
                 continue;

Modified: trunk/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp (268896 => 268897)


--- trunk/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -246,8 +246,8 @@
 
     HashMap<pid_t, String> knownWorkerThreads;
     {
-        LockHolder lock(WorkerThread::workerThreadsMutex());
-        for (auto* thread : WorkerThread::workerThreads(lock)) {
+        auto locker = holdLock(WorkerOrWorkletThread::workerOrWorkletThreadsLock());
+        for (auto* thread : WorkerOrWorkletThread::workerOrWorkletThreads()) {
             // Ignore worker threads that have not been fully started yet.
             if (!thread->thread())
                 continue;

Modified: trunk/Source/WebCore/workers/DedicatedWorkerThread.cpp (268896 => 268897)


--- trunk/Source/WebCore/workers/DedicatedWorkerThread.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/DedicatedWorkerThread.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -54,7 +54,7 @@
 void DedicatedWorkerThread::runEventLoop()
 {
     // Notify the parent object of our current active state before calling the superclass to run the event loop.
-    m_workerObjectProxy.reportPendingActivity(workerGlobalScope()->hasPendingActivity());
+    m_workerObjectProxy.reportPendingActivity(globalScope()->hasPendingActivity());
     WorkerThread::runEventLoop();
 }
 

Modified: trunk/Source/WebCore/workers/WorkerGlobalScope.h (268896 => 268897)


--- trunk/Source/WebCore/workers/WorkerGlobalScope.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/WorkerGlobalScope.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -71,8 +71,8 @@
 
 #if ENABLE(INDEXED_DATABASE)
     IDBClient::IDBConnectionProxy* idbConnectionProxy() final;
-    void suspend();
-    void resume();
+    void suspend() final;
+    void resume() final;
 #endif
 
     WorkerCacheStorageConnection& cacheStorageConnection();

Modified: trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h (268896 => 268897)


--- trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletGlobalScope.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -61,6 +61,9 @@
     using RefCounted::ref;
     using RefCounted::deref;
 
+    virtual void suspend() { }
+    virtual void resume() { }
+
 protected:
     WorkerOrWorkletGlobalScope(Ref<JSC::VM>&&, WorkerOrWorkletThread*);
 

Copied: trunk/Source/WebCore/workers/WorkerOrWorkletThread.cpp (from rev 268896, trunk/Source/WebCore/workers/WorkerThread.cpp) (0 => 268897)


--- trunk/Source/WebCore/workers/WorkerOrWorkletThread.cpp	                        (rev 0)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletThread.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2008-2020 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 "config.h"
+#include "WorkerOrWorkletThread.h"
+
+#include "WorkerOrWorkletScriptController.h"
+
+#if PLATFORM(IOS_FAMILY)
+#include "FloatingPointEnvironment.h"
+#endif
+
+#if USE(GLIB)
+#include <wtf/glib/GRefPtr.h>
+#endif
+
+namespace WebCore {
+
+Lock& WorkerOrWorkletThread::workerOrWorkletThreadsLock()
+{
+    static Lock mutex;
+    return mutex;
+}
+
+HashSet<WorkerOrWorkletThread*>& WorkerOrWorkletThread::workerOrWorkletThreads()
+{
+    ASSERT(workerOrWorkletThreadsLock().isHeld());
+    static NeverDestroyed<HashSet<WorkerOrWorkletThread*>> workerOrWorkletThreads;
+    return workerOrWorkletThreads;
+}
+
+WorkerOrWorkletThread::WorkerOrWorkletThread(const String& identifier)
+    : m_identifier(identifier)
+{
+    auto locker = holdLock(workerOrWorkletThreadsLock());
+    workerOrWorkletThreads().add(this);
+}
+
+WorkerOrWorkletThread::~WorkerOrWorkletThread()
+{
+    auto locker = holdLock(workerOrWorkletThreadsLock());
+    ASSERT(workerOrWorkletThreads().contains(this));
+    workerOrWorkletThreads().remove(this);
+}
+
+void WorkerOrWorkletThread::startRunningDebuggerTasks()
+{
+    ASSERT(!m_pausedForDebugger);
+    m_pausedForDebugger = true;
+
+    MessageQueueWaitResult result;
+    do {
+        result = m_runLoop.runInDebuggerMode(*m_globalScope);
+    } while (result != MessageQueueTerminated && m_pausedForDebugger);
+}
+
+void WorkerOrWorkletThread::stopRunningDebuggerTasks()
+{
+    m_pausedForDebugger = false;
+}
+
+void WorkerOrWorkletThread::runEventLoop()
+{
+    // Does not return until terminated.
+    m_runLoop.run(m_globalScope.get());
+}
+
+void WorkerOrWorkletThread::workerOrWorkletThread()
+{
+    auto protectedThis = makeRef(*this);
+
+    // Propagate the mainThread's fenv to workers.
+#if PLATFORM(IOS_FAMILY)
+    FloatingPointEnvironment::singleton().propagateMainThreadEnvironment();
+#endif
+
+#if USE(GLIB)
+    GRefPtr<GMainContext> mainContext = adoptGRef(g_main_context_new());
+    g_main_context_push_thread_default(mainContext.get());
+#endif
+
+    WorkerOrWorkletScriptController* scriptController;
+    {
+        // Mutex protection is necessary to ensure that we don't change m_globalScope
+        // while WorkerThread::stop() is accessing it. Note that WorkerThread::stop() can
+        // be called before we've finished creating the WorkerGlobalScope.
+        auto locker = holdLock(m_threadCreationAndGlobalScopeLock);
+        m_globalScope = createGlobalScope();
+
+        scriptController = m_globalScope->script();
+
+        if (m_runLoop.terminated()) {
+            // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
+            // forbidExecution() couldn't be called from stop().
+            scriptController->scheduleExecutionTermination();
+            scriptController->forbidExecution();
+        }
+    }
+
+    if (shouldWaitForWebInspectorOnStartup()) {
+        startRunningDebuggerTasks();
+
+        // If the worker was somehow terminated while processing debugger commands.
+        if (m_runLoop.terminated())
+            scriptController->forbidExecution();
+    }
+
+    String exceptionMessage;
+    evaluateScriptIfNecessary(exceptionMessage);
+
+    callOnMainThread([evaluateCallback = WTFMove(m_evaluateCallback), message = exceptionMessage.isolatedCopy()] {
+        if (evaluateCallback)
+            evaluateCallback(message);
+    });
+
+    runEventLoop();
+
+#if USE(GLIB)
+    g_main_context_pop_thread_default(mainContext.get());
+#endif
+
+    RefPtr<Thread> protector = m_thread;
+
+    ASSERT(m_globalScope->hasOneRef());
+
+    RefPtr<WorkerOrWorkletGlobalScope> workerGlobalScopeToDelete;
+    {
+        // Mutex protection is necessary to ensure that we don't change m_globalScope
+        // while WorkerThread::stop is accessing it.
+        auto locker = holdLock(m_threadCreationAndGlobalScopeLock);
+
+        // Delay the destruction of the WorkerGlobalScope context until after we've unlocked the
+        // m_threadCreationAndWorkerGlobalScopeMutex. This is needed because destructing the
+        // context will trigger the main thread to race against us to delete the WorkerThread
+        // object, and the WorkerThread object owns the mutex we need to unlock after this.
+        workerGlobalScopeToDelete = std::exchange(m_globalScope, nullptr);
+
+        if (m_stoppedCallback)
+            callOnMainThread(WTFMove(m_stoppedCallback));
+    }
+
+    // The below assignment will destroy the context, which will in turn notify messaging proxy.
+    // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
+    workerGlobalScopeToDelete = nullptr;
+
+    // Clean up WebCore::ThreadGlobalData before WTF::Thread goes away!
+    threadGlobalData().destroy();
+
+    // Send the last WorkerThread Ref to be Deref'ed on the main thread.
+    callOnMainThread([protectedThis = WTFMove(protectedThis)] { });
+
+    // The thread object may be already destroyed from notification now, don't try to access "this".
+    protector->detach();
+}
+
+void WorkerOrWorkletThread::start(WTF::Function<void(const String&)>&& evaluateCallback)
+{
+    // Mutex protection is necessary to ensure that m_thread is initialized when the thread starts.
+    auto locker = holdLock(m_threadCreationAndGlobalScopeLock);
+
+    if (m_thread)
+        return;
+
+    m_evaluateCallback = WTFMove(evaluateCallback);
+
+    auto thread = createThread();
+
+    // Force the Thread object to be initialized fully before storing it to m_thread (and becoming visible to other threads).
+    WTF::storeStoreFence();
+
+    m_thread = WTFMove(thread);
+}
+
+void WorkerOrWorkletThread::stop(Function<void()>&& stoppedCallback)
+{
+    // Mutex protection is necessary to ensure that m_workerGlobalScope isn't changed by
+    // WorkerThread::workerThread() while we're accessing it. Note also that stop() can
+    // be called before m_workerGlobalScope is fully created.
+    auto locker = tryHoldLock(m_threadCreationAndGlobalScopeLock);
+    if (!locker) {
+        // The thread is still starting, spin the runloop and try again to avoid deadlocks if the worker thread
+        // needs to interact with the main thread during startup.
+        callOnMainThread([this, stoppedCallback = WTFMove(stoppedCallback)]() mutable {
+            stop(WTFMove(stoppedCallback));
+        });
+        return;
+    }
+
+    // If the thread is suspended, resume it now so that we can dispatch the cleanup tasks below.
+    if (m_isSuspended)
+        resume();
+
+    ASSERT(!m_stoppedCallback);
+    m_stoppedCallback = WTFMove(stoppedCallback);
+
+    // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever.
+    if (globalScope()) {
+        globalScope()->script()->scheduleExecutionTermination();
+
+        m_runLoop.postTaskAndTerminate({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context ) {
+            auto& globalScope = downcast<WorkerOrWorkletGlobalScope>(context);
+
+            globalScope.prepareForDestruction();
+
+            // Stick a shutdown command at the end of the queue, so that we deal
+            // with all the cleanup tasks the databases post first.
+            globalScope.postTask({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context) {
+                auto& globalScope = downcast<WorkerOrWorkletGlobalScope>(context);
+                // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed.
+                globalScope.clearScript();
+            } });
+
+        } });
+        return;
+    }
+    m_runLoop.terminate();
+}
+
+void WorkerOrWorkletThread::suspend()
+{
+    m_isSuspended = true;
+    m_runLoop.postTask([&](ScriptExecutionContext&) {
+        if (globalScope())
+            globalScope()->suspend();
+
+        m_suspensionSemaphore.wait();
+
+        if (globalScope())
+            globalScope()->resume();
+    });
+}
+
+void WorkerOrWorkletThread::resume()
+{
+    ASSERT(m_isSuspended);
+    m_isSuspended = false;
+    m_suspensionSemaphore.signal();
+}
+
+void WorkerOrWorkletThread::releaseFastMallocFreeMemoryInAllThreads()
+{
+    auto locker = holdLock(workerOrWorkletThreadsLock());
+    for (auto* workerOrWorkletThread : workerOrWorkletThreads()) {
+        workerOrWorkletThread->runLoop().postTask([] (ScriptExecutionContext&) {
+            WTF::releaseFastMallocFreeMemory();
+        });
+    }
+}
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerOrWorkletThread.h (268896 => 268897)


--- trunk/Source/WebCore/workers/WorkerOrWorkletThread.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/WorkerOrWorkletThread.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2020 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,7 +25,12 @@
 
 #pragma once
 
+#include "WorkerRunLoop.h"
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
+#include <wtf/Lock.h>
 #include <wtf/ThreadSafeRefCounted.h>
+#include <wtf/threads/BinarySemaphore.h>
 
 namespace WTF {
 class Thread;
@@ -38,11 +43,52 @@
 
 class WorkerOrWorkletThread : public ThreadSafeRefCounted<WorkerOrWorkletThread> {
 public:
-    virtual ~WorkerOrWorkletThread() = default;
+    virtual ~WorkerOrWorkletThread();
 
-    virtual WTF::Thread* thread() const = 0;
-    virtual WorkerRunLoop& runLoop() = 0;
+    WTF::Thread* thread() const { return m_thread.get(); }
     virtual WorkerLoaderProxy& workerLoaderProxy() = 0;
+
+    WorkerOrWorkletGlobalScope* globalScope() const { return m_globalScope.get(); }
+    WorkerRunLoop& runLoop() { return m_runLoop; }
+
+    void start(Function<void(const String&)>&& evaluateCallback = { });
+    void stop(Function<void()>&& terminatedCallback = { });
+
+    void startRunningDebuggerTasks();
+    void stopRunningDebuggerTasks();
+
+    void suspend();
+    void resume();
+
+    const String& identifier() const { return m_identifier; }
+
+    static HashSet<WorkerOrWorkletThread*>& workerOrWorkletThreads();
+    static Lock& workerOrWorkletThreadsLock();
+    static void releaseFastMallocFreeMemoryInAllThreads();
+
+protected:
+    explicit WorkerOrWorkletThread(const String& identifier);
+    void workerOrWorkletThread();
+
+    // Executes the event loop for the worker thread. Derived classes can override to perform actions before/after entering the event loop.
+    virtual void runEventLoop();
+
+private:
+    virtual Ref<WTF::Thread> createThread() = 0;
+    virtual Ref<WorkerOrWorkletGlobalScope> createGlobalScope() = 0;
+    virtual void evaluateScriptIfNecessary(String&) { }
+    virtual bool shouldWaitForWebInspectorOnStartup() const { return false; }
+
+    String m_identifier;
+    Lock m_threadCreationAndGlobalScopeLock;
+    RefPtr<WorkerOrWorkletGlobalScope> m_globalScope;
+    RefPtr<WTF::Thread> m_thread;
+    WorkerRunLoop m_runLoop;
+    Function<void(const String&)> m_evaluateCallback;
+    Function<void()> m_stoppedCallback;
+    BinarySemaphore m_suspensionSemaphore;
+    bool m_isSuspended { false };
+    bool m_pausedForDebugger { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerThread.cpp (268896 => 268897)


--- trunk/Source/WebCore/workers/WorkerThread.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/WorkerThread.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -31,42 +31,16 @@
 #include "ScriptSourceCode.h"
 #include "SecurityOrigin.h"
 #include "SocketProvider.h"
-#include "ThreadGlobalData.h"
 #include "WorkerGlobalScope.h"
-#include "WorkerInspectorController.h"
-#include <utility>
-#include <wtf/Lock.h>
-#include <wtf/NeverDestroyed.h>
-#include <wtf/Noncopyable.h>
-#include <wtf/text/WTFString.h>
+#include <wtf/Threading.h>
 
-#if PLATFORM(IOS_FAMILY)
-#include "FloatingPointEnvironment.h"
-#include "WebCoreThread.h"
-#endif
-
-#if USE(GLIB)
-#include <wtf/glib/GRefPtr.h>
-#endif
-
 namespace WebCore {
 
-HashSet<WorkerThread*>& WorkerThread::workerThreads(const LockHolder&)
-{
-    static NeverDestroyed<HashSet<WorkerThread*>> workerThreads;
-    return workerThreads;
-}
+static std::atomic<unsigned> workerThreadCounter { 0 };
 
-Lock& WorkerThread::workerThreadsMutex()
-{
-    static Lock mutex;
-    return mutex;
-}
-
 unsigned WorkerThread::workerThreadCount()
 {
-    LockHolder lock(workerThreadsMutex());
-    return workerThreads(lock).size();
+    return workerThreadCounter;
 }
 
 WorkerParameters WorkerParameters::isolatedCopy() const
@@ -109,7 +83,7 @@
 }
 
 WorkerThread::WorkerThread(const WorkerParameters& params, const String& sourceCode, WorkerLoaderProxy& workerLoaderProxy, WorkerDebuggerProxy& workerDebuggerProxy, WorkerReportingProxy& workerReportingProxy, WorkerThreadStartMode startMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy* connectionProxy, SocketProvider* socketProvider, JSC::RuntimeFlags runtimeFlags)
-    : m_identifier(params.identifier.isolatedCopy())
+    : WorkerOrWorkletThread(params.identifier.isolatedCopy())
     , m_workerLoaderProxy(workerLoaderProxy)
     , m_workerDebuggerProxy(workerDebuggerProxy)
     , m_workerReportingProxy(workerReportingProxy)
@@ -123,229 +97,44 @@
 #if !ENABLE(INDEXED_DATABASE)
     UNUSED_PARAM(connectionProxy);
 #endif
-
-    LockHolder lock(workerThreadsMutex());
-    workerThreads(lock).add(this);
+    ++workerThreadCounter;
 }
 
 WorkerThread::~WorkerThread()
 {
-    LockHolder lock(workerThreadsMutex());
-    ASSERT(workerThreads(lock).contains(this));
-    workerThreads(lock).remove(this);
+    ASSERT(workerThreadCounter);
+    --workerThreadCounter;
 }
 
-void WorkerThread::start(WTF::Function<void(const String&)>&& evaluateCallback)
+Ref<Thread> WorkerThread::createThread()
 {
-    // Mutex protection is necessary to ensure that m_thread is initialized when the thread starts.
-    LockHolder lock(m_threadCreationAndWorkerGlobalScopeMutex);
-
-    if (m_thread)
-        return;
-
-    m_evaluateCallback = WTFMove(evaluateCallback);
-
-    Ref<Thread> thread = Thread::create(isServiceWorkerThread() ? "WebCore: Service Worker" : "WebCore: Worker", [this] {
-        workerThread();
+    return Thread::create(isServiceWorkerThread() ? "WebCore: Service Worker" : "WebCore: Worker", [this] {
+        workerOrWorkletThread();
     }, ThreadType::_javascript_);
-    // Force the Thread object to be initialized fully before storing it to m_thread (and becoming visible to other threads).
-    WTF::storeStoreFence();
-    m_thread = WTFMove(thread);
 }
 
-void WorkerThread::workerThread()
+Ref<WorkerOrWorkletGlobalScope> WorkerThread::createGlobalScope()
 {
-    auto protectedThis = makeRef(*this);
+    return createWorkerGlobalScope(m_startupData->params, WTFMove(m_startupData->origin), WTFMove(m_startupData->topOrigin));
+}
 
-    // Propagate the mainThread's fenv to workers.
-#if PLATFORM(IOS_FAMILY)
-    FloatingPointEnvironment::singleton().propagateMainThreadEnvironment();
-#endif
+bool WorkerThread::shouldWaitForWebInspectorOnStartup() const
+{
+    return m_startupData->startMode == WorkerThreadStartMode::WaitForInspector;
+}
 
-#if USE(GLIB)
-    GRefPtr<GMainContext> mainContext = adoptGRef(g_main_context_new());
-    g_main_context_push_thread_default(mainContext.get());
-#endif
+void WorkerThread::evaluateScriptIfNecessary(String& exceptionMessage)
+{
+    globalScope()->script()->evaluate(ScriptSourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)), &exceptionMessage);
 
-    WorkerOrWorkletScriptController* scriptController;
-    {
-        // Mutex protection is necessary to ensure that we don't change m_workerGlobalScope
-        // while WorkerThread::stop() is accessing it. Note that WorkerThread::stop() can
-        // be called before we've finished creating the WorkerGlobalScope.
-        LockHolder lock(m_threadCreationAndWorkerGlobalScopeMutex);
-        m_workerGlobalScope = createWorkerGlobalScope(m_startupData->params, WTFMove(m_startupData->origin), WTFMove(m_startupData->topOrigin));
-
-        scriptController = m_workerGlobalScope->script();
-
-        if (m_runLoop.terminated()) {
-            // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
-            // forbidExecution() couldn't be called from stop().
-            scriptController->scheduleExecutionTermination();
-            scriptController->forbidExecution();
-        }
-    }
-
-    if (m_startupData->startMode == WorkerThreadStartMode::WaitForInspector) {
-        startRunningDebuggerTasks();
-
-        // If the worker was somehow terminated while processing debugger commands.
-        if (m_runLoop.terminated())
-            scriptController->forbidExecution();
-    }
-
-    String exceptionMessage;
-    scriptController->evaluate(ScriptSourceCode(m_startupData->sourceCode, URL(m_startupData->params.scriptURL)), &exceptionMessage);
-
     finishedEvaluatingScript();
 
-    callOnMainThread([evaluateCallback = WTFMove(m_evaluateCallback), message = exceptionMessage.isolatedCopy()] {
-        if (evaluateCallback)
-            evaluateCallback(message);
-    });
-
     // Free the startup data to cause its member variable deref's happen on the worker's thread (since
     // all ref/derefs of these objects are happening on the thread at this point). Note that
     // WorkerThread::~WorkerThread happens on a different thread where it was created.
     m_startupData = nullptr;
-
-    runEventLoop();
-
-#if USE(GLIB)
-    g_main_context_pop_thread_default(mainContext.get());
-#endif
-
-    RefPtr<Thread> protector = m_thread;
-
-    ASSERT(m_workerGlobalScope->hasOneRef());
-
-    RefPtr<WorkerGlobalScope> workerGlobalScopeToDelete;
-    {
-        // Mutex protection is necessary to ensure that we don't change m_workerGlobalScope
-        // while WorkerThread::stop is accessing it.
-        LockHolder lock(m_threadCreationAndWorkerGlobalScopeMutex);
-
-        // Delay the destruction of the WorkerGlobalScope context until after we've unlocked the
-        // m_threadCreationAndWorkerGlobalScopeMutex. This is needed because destructing the
-        // context will trigger the main thread to race against us to delete the WorkerThread
-        // object, and the WorkerThread object owns the mutex we need to unlock after this.
-        workerGlobalScopeToDelete = WTFMove(m_workerGlobalScope);
-
-        if (m_stoppedCallback)
-            callOnMainThread(WTFMove(m_stoppedCallback));
-    }
-
-    // The below assignment will destroy the context, which will in turn notify messaging proxy.
-    // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
-    workerGlobalScopeToDelete = nullptr;
-
-    // Clean up WebCore::ThreadGlobalData before WTF::Thread goes away!
-    threadGlobalData().destroy();
-
-    // Send the last WorkerThread Ref to be Deref'ed on the main thread.
-    callOnMainThread([protectedThis = WTFMove(protectedThis)] { });
-
-    // The thread object may be already destroyed from notification now, don't try to access "this".
-    protector->detach();
 }
 
-void WorkerThread::startRunningDebuggerTasks()
-{
-    ASSERT(!m_pausedForDebugger);
-    m_pausedForDebugger = true;
-
-    MessageQueueWaitResult result;
-    do {
-        result = m_runLoop.runInDebuggerMode(*m_workerGlobalScope);
-    } while (result != MessageQueueTerminated && m_pausedForDebugger);
-}
-
-void WorkerThread::stopRunningDebuggerTasks()
-{
-    m_pausedForDebugger = false;
-}
-
-void WorkerThread::runEventLoop()
-{
-    // Does not return until terminated.
-    m_runLoop.run(m_workerGlobalScope.get());
-}
-
-void WorkerThread::suspend()
-{
-    m_isSuspended = true;
-    runLoop().postTask([&](ScriptExecutionContext&) {
-        if (m_workerGlobalScope)
-            m_workerGlobalScope->suspend();
-
-        m_suspensionSemaphore.wait();
-
-        if (m_workerGlobalScope)
-            m_workerGlobalScope->resume();
-    });
-}
-
-void WorkerThread::resume()
-{
-    ASSERT(m_isSuspended);
-    m_isSuspended = false;
-    m_suspensionSemaphore.signal();
-}
-
-void WorkerThread::stop(WTF::Function<void()>&& stoppedCallback)
-{
-    // Mutex protection is necessary to ensure that m_workerGlobalScope isn't changed by
-    // WorkerThread::workerThread() while we're accessing it. Note also that stop() can
-    // be called before m_workerGlobalScope is fully created.
-    auto locker = Locker<Lock>::tryLock(m_threadCreationAndWorkerGlobalScopeMutex);
-    if (!locker) {
-        // The thread is still starting, spin the runloop and try again to avoid deadlocks if the worker thread
-        // needs to interact with the main thread during startup.
-        callOnMainThread([this, stoppedCallback = WTFMove(stoppedCallback)]() mutable {
-            stop(WTFMove(stoppedCallback));
-        });
-        return;
-    }
-
-    // If the thread is suspended, resume it now so that we can dispatch the cleanup tasks below.
-    if (m_isSuspended)
-        resume();
-
-    ASSERT(!m_stoppedCallback);
-    m_stoppedCallback = WTFMove(stoppedCallback);
-
-    // Ensure that tasks are being handled by thread event loop. If script execution weren't forbidden, a while(1) loop in JS could keep the thread alive forever.
-    if (m_workerGlobalScope) {
-        m_workerGlobalScope->script()->scheduleExecutionTermination();
-
-        m_runLoop.postTaskAndTerminate({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context ) {
-            WorkerGlobalScope& workerGlobalScope = downcast<WorkerGlobalScope>(context);
-
-            workerGlobalScope.prepareForDestruction();
-
-            // Stick a shutdown command at the end of the queue, so that we deal
-            // with all the cleanup tasks the databases post first.
-            workerGlobalScope.postTask({ ScriptExecutionContext::Task::CleanupTask, [] (ScriptExecutionContext& context) {
-                WorkerGlobalScope& workerGlobalScope = downcast<WorkerGlobalScope>(context);
-                // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed.
-                workerGlobalScope.clearScript();
-            } });
-
-        } });
-        return;
-    }
-    m_runLoop.terminate();
-}
-
-void WorkerThread::releaseFastMallocFreeMemoryInAllThreads()
-{
-    LockHolder lock(workerThreadsMutex());
-    for (auto* workerThread : workerThreads(lock)) {
-        workerThread->runLoop().postTask([] (ScriptExecutionContext&) {
-            WTF::releaseFastMallocFreeMemory();
-        });
-    }
-}
-
 IDBClient::IDBConnectionProxy* WorkerThread::idbConnectionProxy()
 {
 #if ENABLE(INDEXED_DATABASE)
@@ -360,4 +149,9 @@
     return m_socketProvider.get();
 }
 
+WorkerGlobalScope* WorkerThread::globalScope()
+{
+    return downcast<WorkerGlobalScope>(WorkerOrWorkletThread::globalScope());
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/WorkerThread.h (268896 => 268897)


--- trunk/Source/WebCore/workers/WorkerThread.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/WorkerThread.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -27,18 +27,12 @@
 
 #include "ContentSecurityPolicyResponseHeaders.h"
 #include "WorkerOrWorkletThread.h"
-#include "WorkerRunLoop.h"
 #include <_javascript_Core/RuntimeFlags.h>
 #include <memory>
-#include <wtf/Forward.h>
-#include <wtf/Function.h>
-#include <wtf/RefCounted.h>
 #include <wtf/URL.h>
-#include <wtf/threads/BinarySemaphore.h>
 
 namespace WebCore {
 
-class ContentSecurityPolicyResponseHeaders;
 class NotificationClient;
 class SecurityOrigin;
 class SocketProvider;
@@ -80,16 +74,6 @@
 public:
     virtual ~WorkerThread();
 
-    static HashSet<WorkerThread*>& workerThreads(const LockHolder&);
-    static Lock& workerThreadsMutex();
-
-    void stop(WTF::Function<void()>&& terminatedCallback);
-
-    void suspend();
-    void resume();
-
-    Thread* thread() const final { return m_thread.get(); }
-    WorkerRunLoop& runLoop() final { return m_runLoop; }
     WorkerLoaderProxy& workerLoaderProxy() final { return m_workerLoaderProxy; }
     WorkerDebuggerProxy& workerDebuggerProxy() const { return m_workerDebuggerProxy; }
     WorkerReportingProxy& workerReportingProxy() const { return m_workerReportingProxy; }
@@ -96,20 +80,14 @@
 
     // Number of active worker threads.
     WEBCORE_EXPORT static unsigned workerThreadCount();
-    static void releaseFastMallocFreeMemoryInAllThreads();
 
 #if ENABLE(NOTIFICATIONS)
     NotificationClient* getNotificationClient() { return m_notificationClient; }
     void setNotificationClient(NotificationClient* client) { m_notificationClient = client; }
 #endif
-
-    void startRunningDebuggerTasks();
-    void stopRunningDebuggerTasks();
     
     JSC::RuntimeFlags runtimeFlags() const { return m_runtimeFlags; }
 
-    String identifier() const { return m_identifier; }
-
 protected:
     WorkerThread(const WorkerParameters&, const String& sourceCode, WorkerLoaderProxy&, WorkerDebuggerProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const SecurityOrigin& topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*, JSC::RuntimeFlags);
 
@@ -116,37 +94,28 @@
     // Factory method for creating a new worker context for the thread.
     virtual Ref<WorkerGlobalScope> createWorkerGlobalScope(const WorkerParameters&, Ref<SecurityOrigin>&&, Ref<SecurityOrigin>&& topOrigin) = 0;
 
-    // Executes the event loop for the worker thread. Derived classes can override to perform actions before/after entering the event loop.
-    virtual void runEventLoop();
+    WorkerGlobalScope* globalScope();
 
-    WorkerGlobalScope* workerGlobalScope() { return m_workerGlobalScope.get(); }
-
     IDBClient::IDBConnectionProxy* idbConnectionProxy();
     SocketProvider* socketProvider();
 
-    void start(Function<void(const String&)>&& evaluateCallback);
-
 private:
-    void workerThread();
     virtual bool isServiceWorkerThread() const { return false; }
 
     virtual void finishedEvaluatingScript() { }
 
-    RefPtr<Thread> m_thread;
-    String m_identifier;
-    WorkerRunLoop m_runLoop;
+    // WorkerOrWorkletThread.
+    Ref<WTF::Thread> createThread() final;
+    Ref<WorkerOrWorkletGlobalScope> createGlobalScope() final;
+    void evaluateScriptIfNecessary(String& exceptionMessage) final;
+    bool shouldWaitForWebInspectorOnStartup() const final;
+
     WorkerLoaderProxy& m_workerLoaderProxy;
     WorkerDebuggerProxy& m_workerDebuggerProxy;
     WorkerReportingProxy& m_workerReportingProxy;
     JSC::RuntimeFlags m_runtimeFlags;
-    bool m_pausedForDebugger { false };
 
-    RefPtr<WorkerGlobalScope> m_workerGlobalScope;
-    Lock m_threadCreationAndWorkerGlobalScopeMutex;
-
     std::unique_ptr<WorkerThreadStartupData> m_startupData;
-    
-    WTF::Function<void(const String&)> m_evaluateCallback;
 
 #if ENABLE(NOTIFICATIONS)
     NotificationClient* m_notificationClient { nullptr };
@@ -156,10 +125,6 @@
     RefPtr<IDBClient::IDBConnectionProxy> m_idbConnectionProxy;
 #endif
     RefPtr<SocketProvider> m_socketProvider;
-
-    WTF::Function<void()> m_stoppedCallback;
-    BinarySemaphore m_suspensionSemaphore;
-    bool m_isSuspended { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp (268896 => 268897)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -99,7 +99,7 @@
 
 void ServiceWorkerThread::queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&& client, Optional<ServiceWorkerClientIdentifier>&& clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options)
 {
-    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*workerGlobalScope()));
+    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*globalScope()));
     serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [serviceWorkerGlobalScope, client = WTFMove(client), clientId, request = WTFMove(request), referrer = WTFMove(referrer), options = WTFMove(options)]() mutable {
         ServiceWorkerFetch::dispatchFetchEvent(WTFMove(client), serviceWorkerGlobalScope, clientId, WTFMove(request), WTFMove(referrer), WTFMove(options));
     });
@@ -116,7 +116,7 @@
 
 void ServiceWorkerThread::queueTaskToPostMessage(MessageWithMessagePorts&& message, ServiceWorkerOrClientData&& sourceData)
 {
-    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*workerGlobalScope()));
+    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*globalScope()));
     serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = makeWeakPtr(this), serviceWorkerGlobalScope, message = WTFMove(message), sourceData = WTFMove(sourceData)]() mutable {
         URL sourceURL;
         ExtendableMessageEventSource source;
@@ -145,7 +145,7 @@
 
 void ServiceWorkerThread::queueTaskToFireInstallEvent()
 {
-    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*workerGlobalScope()));
+    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*globalScope()));
     serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = makeWeakPtr(this), serviceWorkerGlobalScope]() mutable {
         RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFireInstallEvent firing event for worker %llu", serviceWorkerGlobalScope->thread().identifier().toUInt64());
 
@@ -171,7 +171,7 @@
 
 void ServiceWorkerThread::queueTaskToFireActivateEvent()
 {
-    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*workerGlobalScope()));
+    auto serviceWorkerGlobalScope = makeRef(downcast<ServiceWorkerGlobalScope>(*globalScope()));
     serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = makeWeakPtr(this), serviceWorkerGlobalScope]() mutable {
         RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFireActivateEvent firing event for worker %llu", serviceWorkerGlobalScope->thread().identifier().toUInt64());
 
@@ -191,7 +191,7 @@
 void ServiceWorkerThread::finishedEvaluatingScript()
 {
     ASSERT(!isMainThread());
-    m_doesHandleFetch = workerGlobalScope()->hasEventListeners(eventNames().fetchEvent);
+    m_doesHandleFetch = globalScope()->hasEventListeners(eventNames().fetchEvent);
 }
 
 void ServiceWorkerThread::start(Function<void(const String&, bool)>&& callback)

Modified: trunk/Source/WebCore/worklets/Worklet.cpp (268896 => 268897)


--- trunk/Source/WebCore/worklets/Worklet.cpp	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/worklets/Worklet.cpp	2020-10-22 22:25:44 UTC (rev 268897)
@@ -33,6 +33,7 @@
 #include "WorkletGlobalScope.h"
 #include "WorkletGlobalScopeProxy.h"
 #include "WorkletPendingTasks.h"
+#include <_javascript_Core/IdentifiersFactory.h>
 #include <wtf/CrossThreadCopier.h>
 #include <wtf/IsoMallocInlines.h>
 
@@ -42,6 +43,7 @@
 
 Worklet::Worklet(Document& document)
     : ActiveDOMObject(&document)
+    , m_identifier("worklet:" + Inspector::IdentifiersFactory::createIdentifier())
 {
 }
 

Modified: trunk/Source/WebCore/worklets/Worklet.h (268896 => 268897)


--- trunk/Source/WebCore/worklets/Worklet.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/worklets/Worklet.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -52,6 +52,7 @@
     Document* document();
 
     const Vector<Ref<WorkletGlobalScopeProxy>>& proxies() const { return m_proxies; }
+    const String& identifier() const { return m_identifier; }
 
 protected:
     explicit Worklet(Document&);
@@ -62,6 +63,7 @@
     // ActiveDOMObject.
     const char* activeDOMObjectName() const final;
 
+    String m_identifier;
     Vector<Ref<WorkletGlobalScopeProxy>> m_proxies;
     HashSet<RefPtr<WorkletPendingTasks>> m_pendingTasksSet;
 };

Modified: trunk/Source/WebCore/worklets/WorkletParameters.h (268896 => 268897)


--- trunk/Source/WebCore/worklets/WorkletParameters.h	2020-10-22 22:13:04 UTC (rev 268896)
+++ trunk/Source/WebCore/worklets/WorkletParameters.h	2020-10-22 22:25:44 UTC (rev 268897)
@@ -34,6 +34,7 @@
     URL windowURL;
     JSC::RuntimeFlags jsRuntimeFlags;
     float sampleRate;
+    String identifier;
 
     WorkletParameters isolatedCopy() const
     {
@@ -40,7 +41,8 @@
         return {
             windowURL.isolatedCopy(),
             jsRuntimeFlags,
-            sampleRate
+            sampleRate,
+            identifier.isolatedCopy()
         };
     }
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to