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()
};
}
};