Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(958)

Unified Diff: Source/core/workers/WorkerThread.cpp

Issue 1115923002: workers: Rename WorkerThread to WorkerScript. Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: . Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/workers/WorkerThread.cpp
diff --git a/Source/core/workers/WorkerThread.cpp b/Source/core/workers/WorkerThread.cpp
deleted file mode 100644
index d8f75cc105c1285c6f3df3d80327ff396782a07a..0000000000000000000000000000000000000000
--- a/Source/core/workers/WorkerThread.cpp
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (C) 2008 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 COMPUTER, 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 COMPUTER, 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 "core/workers/WorkerThread.h"
-
-#include "bindings/core/v8/ScriptSourceCode.h"
-#include "bindings/core/v8/V8GCController.h"
-#include "bindings/core/v8/V8Initializer.h"
-#include "core/dom/Microtask.h"
-#include "core/inspector/InspectorInstrumentation.h"
-#include "core/inspector/WorkerInspectorController.h"
-#include "core/workers/DedicatedWorkerGlobalScope.h"
-#include "core/workers/WorkerClients.h"
-#include "core/workers/WorkerReportingProxy.h"
-#include "core/workers/WorkerThreadStartupData.h"
-#include "platform/PlatformThreadData.h"
-#include "platform/Task.h"
-#include "platform/ThreadSafeFunctional.h"
-#include "platform/ThreadTimers.h"
-#include "platform/heap/SafePoint.h"
-#include "platform/heap/ThreadState.h"
-#include "platform/weborigin/KURL.h"
-#include "public/platform/Platform.h"
-#include "public/platform/WebThread.h"
-#include "public/platform/WebWaitableEvent.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/WeakPtr.h"
-#include "wtf/text/WTFString.h"
-
-namespace blink {
-
-namespace {
-const int64_t kShortIdleHandlerDelayMs = 1000;
-const int64_t kLongIdleHandlerDelayMs = 10*1000;
-
-class MicrotaskRunner : public WebThread::TaskObserver {
-public:
- explicit MicrotaskRunner(WorkerThread* workerThread)
- : m_workerThread(workerThread)
- {
- }
-
- virtual void willProcessTask() override { }
- virtual void didProcessTask() override
- {
- Microtask::performCheckpoint();
- if (WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope()) {
- if (WorkerScriptController* scriptController = globalScope->script())
- scriptController->rejectedPromises()->processQueue();
- }
- }
-
-private:
- // Thread owns the microtask runner; reference remains
- // valid for the lifetime of this object.
- WorkerThread* m_workerThread;
-};
-
-} // namespace
-
-static Mutex& threadSetMutex()
-{
- AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
- return mutex;
-}
-
-static HashSet<WorkerThread*>& workerThreads()
-{
- DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
- return threads;
-}
-
-unsigned WorkerThread::workerThreadCount()
-{
- MutexLocker lock(threadSetMutex());
- return workerThreads().size();
-}
-
-class WorkerThreadCancelableTask final : public ExecutionContextTask {
- WTF_MAKE_NONCOPYABLE(WorkerThreadCancelableTask); WTF_MAKE_FAST_ALLOCATED(WorkerThreadCancelableTask);
-public:
- static PassOwnPtr<WorkerThreadCancelableTask> create(PassOwnPtr<Closure> closure)
- {
- return adoptPtr(new WorkerThreadCancelableTask(closure));
- }
-
- virtual ~WorkerThreadCancelableTask() { }
-
- virtual void performTask(ExecutionContext*) override
- {
- if (!m_taskCanceled)
- (*m_closure)();
- }
-
- WeakPtr<WorkerThreadCancelableTask> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
- void cancelTask() { m_taskCanceled = true; }
-
-private:
- explicit WorkerThreadCancelableTask(PassOwnPtr<Closure> closure)
- : m_closure(closure)
- , m_weakFactory(this)
- , m_taskCanceled(false)
- { }
-
- OwnPtr<Closure> m_closure;
- WeakPtrFactory<WorkerThreadCancelableTask> m_weakFactory;
- bool m_taskCanceled;
-};
-
-class WorkerSharedTimer : public SharedTimer {
-public:
- explicit WorkerSharedTimer(WorkerThread* workerThread)
- : m_workerThread(workerThread)
- , m_running(false)
- { }
-
- typedef void (*SharedTimerFunction)();
- virtual void setFiredFunction(SharedTimerFunction func)
- {
- m_sharedTimerFunction = func;
- }
-
- virtual void setFireInterval(double interval)
- {
- ASSERT(m_sharedTimerFunction);
-
- // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of
- // why ceil is used in the interval calculation.
- int64_t delay = static_cast<int64_t>(ceil(interval * 1000));
-
- if (delay < 0) {
- delay = 0;
- }
-
- m_running = true;
-
- if (m_lastQueuedTask.get())
- m_lastQueuedTask->cancelTask();
-
- // Now queue the task as a cancellable one.
- OwnPtr<WorkerThreadCancelableTask> task = WorkerThreadCancelableTask::create(bind(&WorkerSharedTimer::OnTimeout, this));
- m_lastQueuedTask = task->createWeakPtr();
- m_workerThread->postDelayedTask(FROM_HERE, task.release(), delay);
- }
-
- virtual void stop()
- {
- m_running = false;
- m_lastQueuedTask = nullptr;
- }
-
-private:
- void OnTimeout()
- {
- ASSERT(m_workerThread->workerGlobalScope());
-
- m_lastQueuedTask = nullptr;
-
- if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalScope()->isClosing())
- m_sharedTimerFunction();
- }
-
- WorkerThread* m_workerThread;
- SharedTimerFunction m_sharedTimerFunction;
- bool m_running;
-
- // The task to run OnTimeout, if any. While OnTimeout resets
- // m_lastQueuedTask, this must be a weak pointer because the
- // worker runloop may delete the task as it is shutting down.
- WeakPtr<WorkerThreadCancelableTask> m_lastQueuedTask;
-};
-
-class WorkerThreadTask : public WebThread::Task {
- WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThreadTask);
-public:
- static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
- {
- return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented));
- }
-
- virtual ~WorkerThreadTask() { }
-
- virtual void run() override
- {
- WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope();
- // Tasks could be put on the message loop after the cleanup task,
- // ensure none of those are ran.
- if (!workerGlobalScope)
- return;
-
- if (m_isInstrumented)
- InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get());
- if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask())
- m_task->performTask(workerGlobalScope);
- if (m_isInstrumented)
- InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope);
- }
-
-private:
- WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
- : m_workerThread(workerThread)
- , m_task(task)
- , m_isInstrumented(isInstrumented)
- {
- if (m_isInstrumented)
- m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty();
- if (m_isInstrumented)
- InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.workerGlobalScope(), m_task.get());
- }
-
- WorkerThread& m_workerThread;
- OwnPtr<ExecutionContextTask> m_task;
- bool m_isInstrumented;
-};
-
-class RunDebuggerQueueTask final : public ExecutionContextTask {
-public:
- static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread)
- {
- return adoptPtr(new RunDebuggerQueueTask(thread));
- }
- virtual void performTask(ExecutionContext* context) override
- {
- ASSERT(context->isWorkerGlobalScope());
- m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage);
- }
-
-private:
- explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { }
-
- WorkerThread* m_thread;
-};
-
-WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> startupData)
- : m_started(false)
- , m_terminated(false)
- , m_workerLoaderProxy(workerLoaderProxy)
- , m_workerReportingProxy(workerReportingProxy)
- , m_startupData(startupData)
- , m_isolate(nullptr)
- , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent()))
- , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent()))
-{
- MutexLocker lock(threadSetMutex());
- workerThreads().add(this);
-}
-
-WorkerThread::~WorkerThread()
-{
- MutexLocker lock(threadSetMutex());
- ASSERT(workerThreads().contains(this));
- workerThreads().remove(this);
-}
-
-void WorkerThread::start()
-{
- if (m_started)
- return;
-
- m_started = true;
- backingThread().postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::initialize, AllowCrossThreadAccess(this))));
-}
-
-void WorkerThread::interruptAndDispatchInspectorCommands()
-{
- MutexLocker locker(m_workerInspectorControllerMutex);
- if (m_workerInspectorController)
- m_workerInspectorController->interruptAndDispatchInspectorCommands();
-}
-
-PlatformThreadId WorkerThread::platformThreadId()
-{
- if (!m_started)
- return 0;
- return backingThread().platformThread().threadId();
-}
-
-void WorkerThread::initialize()
-{
- KURL scriptURL = m_startupData->m_scriptURL;
- String sourceCode = m_startupData->m_sourceCode;
- WorkerThreadStartMode startMode = m_startupData->m_startMode;
- OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.release();
- V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions;
-
- {
- MutexLocker lock(m_threadCreationMutex);
-
- // The worker was terminated before the thread had a chance to run.
- if (m_terminated) {
- // Notify the proxy that the WorkerGlobalScope has been disposed of.
- // This can free this thread object, hence it must not be touched afterwards.
- m_workerReportingProxy.workerThreadTerminated();
- return;
- }
-
- m_microtaskRunner = adoptPtr(new MicrotaskRunner(this));
- backingThread().addTaskObserver(m_microtaskRunner.get());
- backingThread().attachGC();
-
- m_isolate = initializeIsolate();
- m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
- m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.get() ? cachedMetaData->size() : 0);
-
- PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new WorkerSharedTimer(this)));
- }
-
- // The corresponding call to stopRunLoop() is in ~WorkerScriptController().
- didStartRunLoop();
-
- // Notify proxy that a new WorkerGlobalScope has been created and started.
- m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get());
-
- WorkerScriptController* script = m_workerGlobalScope->script();
- if (!script->isExecutionForbidden())
- script->initializeContextIfNeeded();
- if (startMode == PauseWorkerGlobalScopeOnStart)
- m_workerGlobalScope->workerInspectorController()->pauseOnStart();
-
- OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScriptCachedMetadataHandler(scriptURL, cachedMetaData.get()));
- bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nullptr, handler.get(), v8CacheOptions);
- m_workerGlobalScope->didEvaluateWorkerScript();
- m_workerReportingProxy.didEvaluateWorkerScript(success);
-
- postInitialize();
-
- postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs);
-}
-
-void WorkerThread::cleanup()
-{
- // This should be called before we start the shutdown procedure.
- workerReportingProxy().willDestroyWorkerGlobalScope();
-
- // 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.
- // If Oilpan is enabled, we detach of the context/global scope, with the final heap cleanup below sweeping it out.
-#if !ENABLE(OILPAN)
- ASSERT(m_workerGlobalScope->hasOneRef());
-#endif
- m_workerGlobalScope->notifyContextDestroyed();
- m_workerGlobalScope = nullptr;
-
- backingThread().detachGC();
- destroyIsolate();
-
- backingThread().removeTaskObserver(m_microtaskRunner.get());
- m_microtaskRunner = nullptr;
-
- // Notify the proxy that the WorkerGlobalScope has been disposed of.
- // This can free this thread object, hence it must not be touched afterwards.
- workerReportingProxy().workerThreadTerminated();
-
- m_terminationEvent->signal();
-
- // Clean up PlatformThreadData before WTF::WTFThreadData goes away!
- PlatformThreadData::current().destroy();
-}
-
-class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
-public:
- static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
- {
- return adoptPtr(new WorkerThreadShutdownFinishTask());
- }
-
- virtual void performTask(ExecutionContext *context)
- {
- WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
- workerGlobalScope->dispose();
-
- WorkerThread* workerThread = workerGlobalScope->thread();
- workerThread->willDestroyIsolate();
- workerThread->backingThread().postTask(FROM_HERE, new Task(WTF::bind(&WorkerThread::cleanup, workerThread)));
- }
-
- virtual bool isCleanupTask() const { return true; }
-};
-
-class WorkerThreadShutdownStartTask : public ExecutionContextTask {
-public:
- static PassOwnPtr<WorkerThreadShutdownStartTask> create()
- {
- return adoptPtr(new WorkerThreadShutdownStartTask());
- }
-
- virtual void performTask(ExecutionContext *context)
- {
- WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
- workerGlobalScope->stopActiveDOMObjects();
- PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
-
- // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects,
- // which become dangling once Heap is destroyed.
- workerGlobalScope->removeAllEventListeners();
-
- // 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(FROM_HERE, WorkerThreadShutdownFinishTask::create());
- }
-
- virtual bool isCleanupTask() const { return true; }
-};
-
-void WorkerThread::stop()
-{
- // Prevent the deadlock between GC and an attempt to stop a thread.
- SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
- stopInternal();
-}
-
-void WorkerThread::stopInShutdownSequence()
-{
- stopInternal();
-}
-
-void WorkerThread::terminateAndWait()
-{
- stop();
- m_terminationEvent->wait();
-}
-
-bool WorkerThread::terminated()
-{
- MutexLocker lock(m_threadCreationMutex);
- return m_terminated;
-}
-
-void WorkerThread::stopInternal()
-{
- // Protect against this method and initialize() racing each other.
- MutexLocker lock(m_threadCreationMutex);
-
- // If stop has already been called, just return.
- if (m_terminated)
- return;
- m_terminated = true;
-
- // Signal the thread to notify that the thread's stopping.
- if (m_shutdownEvent)
- m_shutdownEvent->signal();
-
- if (!m_workerGlobalScope)
- 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.
- terminateV8Execution();
-
- InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScope.get());
- m_debuggerMessageQueue.kill();
- postTask(FROM_HERE, WorkerThreadShutdownStartTask::create());
-}
-
-void WorkerThread::didStartRunLoop()
-{
- ASSERT(isCurrentThread());
- Platform::current()->didStartWorkerRunLoop();
-}
-
-void WorkerThread::didStopRunLoop()
-{
- ASSERT(isCurrentThread());
- Platform::current()->didStopWorkerRunLoop();
-}
-
-void WorkerThread::terminateAndWaitForAllWorkers()
-{
- // Keep this lock to prevent WorkerThread instances from being destroyed.
- MutexLocker lock(threadSetMutex());
- HashSet<WorkerThread*> threads = workerThreads();
- for (WorkerThread* thread : threads)
- thread->stopInShutdownSequence();
-
- for (WorkerThread* thread : threads)
- thread->terminationEvent()->wait();
-}
-
-bool WorkerThread::isCurrentThread()
-{
- return m_started && backingThread().isCurrentThread();
-}
-
-void WorkerThread::idleHandler()
-{
- ASSERT(m_workerGlobalScope.get());
- int64_t delay = kLongIdleHandlerDelayMs;
-
- // Do a script engine idle notification if the next event is distant enough.
- const double kMinIdleTimespan = 0.3;
- const double nextFireTime = PlatformThreadData::current().threadTimers().nextFireTime();
- if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan) {
- bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::current()->monotonicallyIncreasingTime() + 1.0);
- if (hasMoreWork)
- delay = kShortIdleHandlerDelayMs;
- }
-
- postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), delay);
-}
-
-void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<ExecutionContextTask> task)
-{
- backingThread().postTask(location, WorkerThreadTask::create(*this, task, true).leakPtr());
-}
-
-void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<ExecutionContextTask> task, long long delayMs)
-{
- backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, task, true).leakPtr(), delayMs);
-}
-
-v8::Isolate* WorkerThread::initializeIsolate()
-{
- ASSERT(isCurrentThread());
- ASSERT(!m_isolate);
- v8::Isolate* isolate = V8PerIsolateData::initialize();
- V8Initializer::initializeWorker(isolate);
-
- m_interruptor = adoptPtr(new V8IsolateInterruptor(isolate));
- ThreadState::current()->addInterruptor(m_interruptor.get());
- ThreadState::current()->registerTraceDOMWrappers(isolate, V8GCController::traceDOMWrappers);
-
- return isolate;
-}
-
-void WorkerThread::willDestroyIsolate()
-{
- ASSERT(isCurrentThread());
- ASSERT(m_isolate);
- V8PerIsolateData::willBeDestroyed(m_isolate);
- ThreadState::current()->removeInterruptor(m_interruptor.get());
-}
-
-void WorkerThread::destroyIsolate()
-{
- ASSERT(isCurrentThread());
- V8PerIsolateData::destroy(m_isolate);
- m_isolate = nullptr;
-}
-
-void WorkerThread::terminateV8Execution()
-{
- ASSERT(isMainThread());
- m_workerGlobalScope->script()->willScheduleExecutionTermination();
- v8::V8::TerminateExecution(m_isolate);
-}
-
-void WorkerThread::postDebuggerTask(const WebTraceLocation& location, PassOwnPtr<ExecutionContextTask> task)
-{
- m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false));
- postTask(location, RunDebuggerQueueTask::create(this));
-}
-
-MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode)
-{
- ASSERT(isCurrentThread());
- MessageQueueWaitResult result;
- double absoluteTime = MessageQueue<WebThread::Task>::infiniteTime();
- OwnPtr<WebThread::Task> task;
- {
- if (waitMode == DontWaitForMessage)
- absoluteTime = 0.0;
- SafePointScope safePointScope(ThreadState::NoHeapPointersOnStack);
- task = m_debuggerMessageQueue.waitForMessageWithTimeout(result, absoluteTime);
- }
-
- if (result == MessageQueueMessageReceived) {
- InspectorInstrumentation::willProcessTask(workerGlobalScope());
- task->run();
- InspectorInstrumentation::didProcessTask(workerGlobalScope());
- }
-
- return result;
-}
-
-void WorkerThread::willEnterNestedLoop()
-{
- InspectorInstrumentation::willEnterNestedRunLoop(m_workerGlobalScope.get());
-}
-
-void WorkerThread::didLeaveNestedLoop()
-{
- InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
-}
-
-void WorkerThread::setWorkerInspectorController(WorkerInspectorController* workerInspectorController)
-{
- MutexLocker locker(m_workerInspectorControllerMutex);
- m_workerInspectorController = workerInspectorController;
-}
-
-} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698