summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp79
1 files changed, 45 insertions, 34 deletions
diff --git a/chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index 6f842e8db42..b04391a18c0 100644
--- a/chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/chromium/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -32,12 +32,13 @@
#include "core/inspector/InspectorInstrumentation.h"
#include "core/workers/DedicatedWorkerGlobalScope.h"
#include "core/workers/WorkerClients.h"
+#include "core/workers/WorkerReportingProxy.h"
#include "core/workers/WorkerThreadStartupData.h"
-#include "modules/webdatabase/DatabaseManager.h"
-#include "modules/webdatabase/DatabaseTask.h"
#include "platform/PlatformThreadData.h"
+#include "platform/heap/ThreadState.h"
#include "platform/weborigin/KURL.h"
#include "public/platform/Platform.h"
+#include "public/platform/WebWaitableEvent.h"
#include "public/platform/WebWorkerRunLoop.h"
#include "wtf/Noncopyable.h"
#include "wtf/text/WTFString.h"
@@ -64,12 +65,13 @@ unsigned WorkerThread::workerThreadCount()
return workerThreads().size();
}
-WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> startupData)
+WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData)
: m_threadID(0)
, m_workerLoaderProxy(workerLoaderProxy)
, m_workerReportingProxy(workerReportingProxy)
, m_startupData(startupData)
, m_notificationClient(0)
+ , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()))
{
MutexLocker lock(threadSetMutex());
workerThreads().add(this);
@@ -108,8 +110,9 @@ void WorkerThread::workerThread()
{
MutexLocker lock(m_threadCreationMutex);
-
+ ThreadState::attach();
m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
+ m_runLoop.setWorkerGlobalScope(workerGlobalScope());
if (m_runLoop.terminated()) {
// The worker was terminated before the thread had a chance to run. Since the context didn't exist yet,
@@ -121,19 +124,44 @@ void WorkerThread::workerThread()
// ~WorkerScriptController.
blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(&m_runLoop));
+ // 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();
InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), startMode);
script->evaluate(ScriptSourceCode(sourceCode, scriptURL));
runEventLoop();
- ThreadIdentifier threadID = m_threadID;
+ // This should be called before we start the shutdown procedure.
+ workerReportingProxy().willDestroyWorkerGlobalScope();
- ASSERT(m_workerGlobalScope->hasOneRef());
+ ThreadIdentifier threadID = m_threadID;
// 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.
- m_workerGlobalScope = 0;
+ // 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->dispose();
+ m_workerGlobalScope = nullptr;
+
+ // Detach the ThreadState, cleaning out the thread's heap by
+ // performing a final GC. The cleanup operation will at the end
+ // assert that the heap is empty. If the heap does not become
+ // empty, there are still pointers into the heap and those
+ // pointers will be dangling after thread termination because we
+ // are destroying the heap. It is important to detach while the
+ // thread is still valid. In particular, finalizers for objects in
+ // the heap for this thread will need to access thread local data.
+ ThreadState::detach();
+
+ // Notify the proxy that the WorkerGlobalScope has been disposed of.
+ // This can free this thread object, hence it must not be touched afterwards.
+ workerReportingProxy().workerGlobalScopeDestroyed();
// Clean up PlatformThreadData before WTF::WTFThreadData goes away!
PlatformThreadData::current().destroy();
@@ -145,7 +173,7 @@ void WorkerThread::workerThread()
void WorkerThread::runEventLoop()
{
// Does not return until terminated.
- m_runLoop.run(m_workerGlobalScope.get());
+ m_runLoop.run();
}
class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
@@ -176,23 +204,13 @@ public:
virtual void performTask(ExecutionContext *context)
{
WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
-
- // FIXME: Should we stop the databases as part of stopActiveDOMObjects() below?
- DatabaseTaskSynchronizer cleanupSync;
- DatabaseManager::manager().stopDatabases(workerGlobalScope, &cleanupSync);
-
+ workerGlobalScope->stopFetch();
workerGlobalScope->stopActiveDOMObjects();
- workerGlobalScope->notifyObserversOfStop();
-
// 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();
- // We wait for the database thread to clean up all its stuff so that we
- // can do more stringent leak checks as we exit.
- cleanupSync.waitForTaskCompletion();
-
// 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(WorkerThreadShutdownFinishTask::create());
@@ -203,14 +221,20 @@ public:
void WorkerThread::stop()
{
+ // Prevent the deadlock between GC and an attempt to stop a thread.
+ ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
+
// Mutex protection is necessary because stop() can be called before the context is fully created.
MutexLocker lock(m_threadCreationMutex);
+ // Signal the thread to notify that the thread's stopping.
+ if (m_shutdownEvent)
+ m_shutdownEvent->signal();
+
// 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();
-
- DatabaseManager::manager().interruptAllDatabasesForContext(m_workerGlobalScope.get());
+ m_workerGlobalScope->wasRequestedToTerminate();
m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create());
return;
}
@@ -222,17 +246,4 @@ bool WorkerThread::isCurrentThread() const
return m_threadID == currentThread();
}
-class ReleaseFastMallocFreeMemoryTask : public ExecutionContextTask {
- virtual void performTask(ExecutionContext*) OVERRIDE { WTF::releaseFastMallocFreeMemory(); }
-};
-
-void WorkerThread::releaseFastMallocFreeMemoryInAllThreads()
-{
- MutexLocker lock(threadSetMutex());
- HashSet<WorkerThread*>& threads = workerThreads();
- HashSet<WorkerThread*>::iterator end = threads.end();
- for (HashSet<WorkerThread*>::iterator it = threads.begin(); it != end; ++it)
- (*it)->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask));
-}
-
} // namespace WebCore