Index: third_party/WebKit/Source/core/workers/WorkerThread.cpp |
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp |
index f9f67b0cf5944f3188743bafedacbb4d0c8aa788..50f4af9a0a09974b4ca49269b4c4a3137ff6e757 100644 |
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp |
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp |
@@ -35,6 +35,7 @@ |
#include "core/inspector/InspectorTaskRunner.h" |
#include "core/inspector/WorkerThreadDebugger.h" |
#include "core/workers/DedicatedWorkerGlobalScope.h" |
+#include "core/workers/WorkerBackingThread.h" |
#include "core/workers/WorkerClients.h" |
#include "core/workers/WorkerReportingProxy.h" |
#include "core/workers/WorkerThreadStartupData.h" |
@@ -43,7 +44,6 @@ |
#include "platform/heap/SafePoint.h" |
#include "platform/heap/ThreadState.h" |
#include "platform/weborigin/KURL.h" |
-#include "public/platform/Platform.h" |
#include "public/platform/WebScheduler.h" |
#include "public/platform/WebThread.h" |
#include "wtf/Functional.h" |
@@ -143,7 +143,6 @@ WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work |
, m_workerLoaderProxy(workerLoaderProxy) |
, m_workerReportingProxy(workerReportingProxy) |
, m_webScheduler(nullptr) |
- , m_isolate(nullptr) |
, m_shutdownEvent(adoptPtr(new WaitableEvent( |
WaitableEvent::ResetPolicy::Manual, |
WaitableEvent::InitialState::NonSignaled))) |
@@ -170,14 +169,14 @@ void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData) |
return; |
m_started = true; |
- backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::initialize, AllowCrossThreadAccess(this), startupData)); |
+ workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::initialize, AllowCrossThreadAccess(this), startupData)); |
} |
PlatformThreadId WorkerThread::platformThreadId() |
{ |
if (!m_started) |
return 0; |
- return backingThread().platformThread().threadId(); |
+ return workerBackingThread().backingThread().platformThread().threadId(); |
} |
void WorkerThread::initialize(PassOwnPtr<WorkerThreadStartupData> startupData) |
@@ -187,7 +186,7 @@ void WorkerThread::initialize(PassOwnPtr<WorkerThreadStartupData> startupData) |
WorkerThreadStartMode startMode = startupData->m_startMode; |
OwnPtr<Vector<char>> cachedMetaData = startupData->m_cachedMetaData.release(); |
V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions; |
- m_webScheduler = backingThread().platformThread().scheduler(); |
+ m_webScheduler = workerBackingThread().backingThread().platformThread().scheduler(); |
{ |
MutexLocker lock(m_threadStateMutex); |
@@ -202,18 +201,18 @@ void WorkerThread::initialize(PassOwnPtr<WorkerThreadStartupData> startupData) |
return; |
} |
+ workerBackingThread().attach(); |
+ |
+ if (shouldAttachThreadDebugger()) |
+ V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new WorkerThreadDebugger(this, isolate()))); |
m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); |
- initializeBackingThread(); |
- backingThread().addTaskObserver(m_microtaskRunner.get()); |
+ workerBackingThread().backingThread().addTaskObserver(m_microtaskRunner.get()); |
- m_isolate = initializeIsolate(); |
// Optimize for memory usage instead of latency for the worker isolate. |
- m_isolate->IsolateInBackgroundNotification(); |
+ isolate()->IsolateInBackgroundNotification(); |
m_workerGlobalScope = createWorkerGlobalScope(startupData); |
m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.get() ? cachedMetaData->size() : 0); |
- didStartWorkerThread(); |
- |
// Notify proxy that a new WorkerGlobalScope has been created and started. |
m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
@@ -252,11 +251,7 @@ void WorkerThread::shutdown() |
workerGlobalScope()->dispose(); |
- // This should be called after the WorkerGlobalScope's disposed (which may |
- // trigger some last-minutes cleanups) and before the thread actually stops. |
- willStopWorkerThread(); |
- |
- backingThread().removeTaskObserver(m_microtaskRunner.get()); |
+ workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.get()); |
postTask(BLINK_FROM_HERE, createSameThreadTask(&WorkerThread::performShutdownTask, this)); |
} |
@@ -268,10 +263,8 @@ void WorkerThread::performShutdownTask() |
m_workerGlobalScope->notifyContextDestroyed(); |
m_workerGlobalScope = nullptr; |
- willDestroyIsolate(); |
- shutdownBackingThread(); |
- destroyIsolate(); |
- m_isolate = nullptr; |
+ workerBackingThread().detach(); |
+ // We must not touch workerBackingThread() from now on. |
m_microtaskRunner = nullptr; |
@@ -336,29 +329,34 @@ void WorkerThread::terminateInternal() |
// 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. |
m_workerGlobalScope->scriptController()->willScheduleExecutionTermination(); |
- // Terminating during debugger task may lead to crash due to heavy use of v8 api in debugger. |
- // Any debugger task is guaranteed to finish, so we can postpone termination after task has finished. |
- // Note: m_runningDebuggerTask and m_shouldTerminateV8Execution access must be guarded by the lock. |
- if (m_runningDebuggerTask) |
- m_shouldTerminateV8Execution = true; |
- else |
- terminateV8Execution(); |
+ if (workerBackingThread().workerScriptCount() == 1) { |
+ // This condition is not entirely correct because other scripts |
+ // can be being initialized or terminated simuletaneously. Though this |
+ // function itself is protected by a mutex, it is possible that |
+ // |workerScriptCount()| here is not consistent with that in |
+ // |initialize| and |shutdown|. |
+ // TODO(yhirano): TerminateExecution should be called more carefully. |
+ // https://crbug.com/413518 |
+ if (m_runningDebuggerTask) { |
+ // Terminating during debugger task may lead to crash due to heavy |
+ // use of v8 api in debugger. Any debugger task is guaranteed to |
+ // finish, so we can postpone termination after task has finished. |
+ // Note: m_runningDebuggerTask and m_shouldTerminateV8Execution |
+ // access must be guarded by the lock. |
+ m_shouldTerminateV8Execution = true; |
+ } else { |
+ isolate()->TerminateExecution(); |
+ } |
+ } |
InspectorInstrumentation::allAsyncTasksCanceled(m_workerGlobalScope.get()); |
m_inspectorTaskRunner->kill(); |
- backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::shutdown, AllowCrossThreadAccess(this))); |
+ workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::shutdown, AllowCrossThreadAccess(this))); |
} |
-void WorkerThread::didStartWorkerThread() |
+v8::Isolate* WorkerThread::isolate() |
{ |
- ASSERT(isCurrentThread()); |
- Platform::current()->didStartWorkerThread(); |
-} |
- |
-void WorkerThread::willStopWorkerThread() |
-{ |
- ASSERT(isCurrentThread()); |
- Platform::current()->willStopWorkerThread(); |
+ return workerBackingThread().isolate(); |
} |
void WorkerThread::terminateAndWaitForAllWorkers() |
@@ -375,58 +373,12 @@ void WorkerThread::terminateAndWaitForAllWorkers() |
bool WorkerThread::isCurrentThread() |
{ |
- return m_started && backingThread().isCurrentThread(); |
+ return m_started && workerBackingThread().backingThread().isCurrentThread(); |
} |
void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<ExecutionContextTask> task) |
{ |
- backingThread().postTask(location, createWorkerThreadTask(task, true)); |
-} |
- |
-void WorkerThread::initializeBackingThread() |
-{ |
- ASSERT(isCurrentThread()); |
- backingThread().initialize(); |
-} |
- |
-void WorkerThread::shutdownBackingThread() |
-{ |
- ASSERT(isCurrentThread()); |
- backingThread().shutdown(); |
-} |
- |
-v8::Isolate* WorkerThread::initializeIsolate() |
-{ |
- ASSERT(isCurrentThread()); |
- ASSERT(!m_isolate); |
- v8::Isolate* isolate = V8PerIsolateData::initialize(); |
- V8Initializer::initializeWorker(isolate); |
- |
- OwnPtr<V8IsolateInterruptor> interruptor = adoptPtr(new V8IsolateInterruptor(isolate)); |
- ThreadState::current()->addInterruptor(interruptor.release()); |
- ThreadState::current()->registerTraceDOMWrappers(isolate, V8GCController::traceDOMWrappers); |
- if (RuntimeEnabledFeatures::v8IdleTasksEnabled()) |
- V8PerIsolateData::enableIdleTasks(isolate, adoptPtr(new V8IdleTaskRunner(m_webScheduler))); |
- V8PerIsolateData::from(isolate)->setThreadDebugger(adoptPtr(new WorkerThreadDebugger(this, isolate))); |
- return isolate; |
-} |
- |
-void WorkerThread::willDestroyIsolate() |
-{ |
- ASSERT(isCurrentThread()); |
- ASSERT(m_isolate); |
- V8PerIsolateData::willBeDestroyed(m_isolate); |
-} |
- |
-void WorkerThread::destroyIsolate() |
-{ |
- ASSERT(isCurrentThread()); |
- V8PerIsolateData::destroy(m_isolate); |
-} |
- |
-void WorkerThread::terminateV8Execution() |
-{ |
- m_isolate->TerminateExecution(); |
+ workerBackingThread().backingThread().postTask(location, createWorkerThreadTask(task, true)); |
} |
void WorkerThread::runDebuggerTaskDontWait() |
@@ -446,10 +398,10 @@ void WorkerThread::appendDebuggerTask(PassOwnPtr<CrossThreadClosure> task) |
m_inspectorTaskRunner->appendTask(threadSafeBind(&WorkerThread::runDebuggerTask, AllowCrossThreadAccess(this), task)); |
{ |
MutexLocker lock(m_threadStateMutex); |
- if (m_isolate) |
- m_inspectorTaskRunner->interruptAndRunAllTasksDontWait(m_isolate); |
+ if (isolate()) |
+ m_inspectorTaskRunner->interruptAndRunAllTasksDontWait(isolate()); |
} |
- backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::runDebuggerTaskDontWait, AllowCrossThreadAccess(this))); |
+ workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::runDebuggerTaskDontWait, AllowCrossThreadAccess(this))); |
} |
void WorkerThread::runDebuggerTask(PassOwnPtr<CrossThreadClosure> task) |
@@ -468,7 +420,7 @@ void WorkerThread::runDebuggerTask(PassOwnPtr<CrossThreadClosure> task) |
m_runningDebuggerTask = false; |
if (m_shouldTerminateV8Execution) { |
m_shouldTerminateV8Execution = false; |
- terminateV8Execution(); |
+ isolate()->TerminateExecution(); |
} |
} |
} |