15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Apple Inc. All Rights Reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerThread.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptSourceCode.h"
32e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "core/dom/Microtask.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/inspector/InspectorInstrumentation.h"
34c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "core/inspector/WorkerInspectorController.h"
35591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/workers/DedicatedWorkerGlobalScope.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerClients.h"
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/workers/WorkerReportingProxy.h"
387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "core/workers/WorkerThreadStartupData.h"
391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformThreadData.h"
40c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "platform/Task.h"
41c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "platform/ThreadTimers.h"
42a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/ThreadState.h"
4351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#include "platform/weborigin/KURL.h"
445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/Platform.h"
45c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#include "public/platform/WebThread.h"
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "public/platform/WebWaitableEvent.h"
475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "public/platform/WebWorkerRunLoop.h"
48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/Noncopyable.h"
49521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/text/WTFString.h"
50521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
51521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <utility>
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
53c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
54c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace {
56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)const int64 kShortIdleHandlerDelayMs = 1000;
57c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)const int64 kLongIdleHandlerDelayMs = 10*1000;
58e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
59e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)class MicrotaskRunner : public WebThread::TaskObserver {
60e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)public:
61e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void willProcessTask() OVERRIDE { }
62e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    virtual void didProcessTask() OVERRIDE
63e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    {
64e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        Microtask::performCheckpoint();
65e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    }
66e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)};
67e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
68e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)} // namespace
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
70926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static Mutex& threadSetMutex()
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return mutex;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static HashSet<WorkerThread*>& workerThreads()
77926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return threads;
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)unsigned WorkerThread::workerThreadCount()
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return workerThreads().size();
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
88c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class WorkerSharedTimer : public SharedTimer {
89c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public:
90c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    explicit WorkerSharedTimer(WorkerThread* workerThread)
91c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        : m_workerThread(workerThread)
92c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        , m_nextFireTime(0.0)
93c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        , m_running(false)
94c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    { }
95c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
96c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    typedef void (*SharedTimerFunction)();
97c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual void setFiredFunction(SharedTimerFunction func)
98c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
99c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_sharedTimerFunction = func;
100c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (!m_sharedTimerFunction)
101c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_nextFireTime = 0.0;
102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
103c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual void setFireInterval(double interval)
105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ASSERT(m_sharedTimerFunction);
107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
108c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of
109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // why ceil is used in the interval calculation.
110c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        int64 delay = static_cast<int64>(ceil(interval * 1000));
111c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
112c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (delay < 0) {
113c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            delay = 0;
114c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_nextFireTime = 0.0;
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        }
116c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_running = true;
118c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_nextFireTime = currentTime() + interval;
119c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_workerThread->postDelayedTask(createSameThreadTask(&WorkerSharedTimer::OnTimeout, this), delay);
120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
121c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
122c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual void stop()
123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
124c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_running = false;
125c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
126c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
127c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    double nextFireTime() { return m_nextFireTime; }
128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
129c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private:
130c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    void OnTimeout()
131c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
132c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ASSERT(m_workerThread->workerGlobalScope());
133c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalScope()->isClosing())
134c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_sharedTimerFunction();
135c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
136c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
137c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    WorkerThread* m_workerThread;
138c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SharedTimerFunction m_sharedTimerFunction;
139c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    double m_nextFireTime;
140c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    bool m_running;
141c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)};
142c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
143c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class WorkerThreadTask : public blink::WebThread::Task {
144c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED;
145c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public:
146c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static PassOwnPtr<WorkerThreadTask> create(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
147c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
148c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented));
149c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
150c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
151c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual ~WorkerThreadTask() { }
152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
153c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual void run() OVERRIDE
154c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
155c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope();
156c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // Tasks could be put on the message loop after the cleanup task,
157c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        // ensure none of those are ran.
158c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (!workerGlobalScope)
159c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            return;
160c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
161c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_isInstrumented)
162c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalScope, m_task.get());
163c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask())
164c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_task->performTask(workerGlobalScope);
165c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_isInstrumented)
166c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalScope);
167c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
168c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
169c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private:
170c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    WorkerThreadTask(const WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask> task, bool isInstrumented)
171c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        : m_workerThread(workerThread)
172c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        , m_task(task)
173c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        , m_isInstrumented(isInstrumented)
174c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
175c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_isInstrumented)
176c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty();
177c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (m_isInstrumented)
178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.workerGlobalScope(), m_task.get());
179c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
181c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    const WorkerThread& m_workerThread;
182c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    OwnPtr<ExecutionContextTask> m_task;
183c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    bool m_isInstrumented;
184c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)};
185c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
186c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)class RunDebuggerQueueTask FINAL : public ExecutionContextTask {
187c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)public:
188c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread)
189c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
190c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return adoptPtr(new RunDebuggerQueueTask(thread));
191c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
192c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    virtual void performTask(ExecutionContext* context) OVERRIDE
193c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
194c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ASSERT(context->isWorkerGlobalScope());
195c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage);
196c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
197c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
198c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)private:
199c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { }
200c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
201c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    WorkerThread* m_thread;
202c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)};
203c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData)
205c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    : m_terminated(false)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_workerLoaderProxy(workerLoaderProxy)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_workerReportingProxy(workerReportingProxy)
2087757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    , m_startupData(startupData)
20909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()))
2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()))
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
212926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
213926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    workerThreads().add(this);
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WorkerThread::~WorkerThread()
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
218926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    MutexLocker lock(threadSetMutex());
219926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(workerThreads().contains(this));
220926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    workerThreads().remove(this);
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
223c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::start()
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
225c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_thread)
226c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_thread = WebThreadSupportingGC::create("WebCore: Worker");
229c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_thread->postTask(new Task(WTF::bind(&WorkerThread::initialize, this)));
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
232c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::interruptAndDispatchInspectorCommands()
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
234c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    MutexLocker locker(m_workerInspectorControllerMutex);
235c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_workerInspectorController)
236c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_workerInspectorController->interruptAndDispatchInspectorCommands();
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciPlatformThreadId WorkerThread::platformThreadId() const
2407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_thread)
2427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return 0;
2437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return m_thread->platformThread().threadId();
2447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
246c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::initialize()
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    KURL scriptURL = m_startupData->m_scriptURL;
2497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    String sourceCode = m_startupData->m_sourceCode;
2507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    WorkerThreadStartMode startMode = m_startupData->m_startMode;
2517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MutexLocker lock(m_threadCreationMutex);
254c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
255e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        // The worker was terminated before the thread had a chance to run.
256e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        if (m_terminated) {
257e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            // Notify the proxy that the WorkerGlobalScope has been disposed of.
258e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            // This can free this thread object, hence it must not be touched afterwards.
259e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            m_workerReportingProxy.workerThreadTerminated();
260e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)            return;
261e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        }
262e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
263e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_microtaskRunner = adoptPtr(new MicrotaskRunner);
264e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        m_thread->addTaskObserver(m_microtaskRunner.get());
2657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        m_thread->attachGC();
2667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch        m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
268c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        m_sharedTimer = adoptPtr(new WorkerSharedTimer(this));
269c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        PlatformThreadData::current().threadTimers().setSharedTimer(m_sharedTimer.get());
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
271c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The corresponding call to didStopWorkerRunLoop is in
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // ~WorkerScriptController.
274c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(this));
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Notify proxy that a new WorkerGlobalScope has been created and started.
27709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get());
27809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    WorkerScriptController* script = m_workerGlobalScope->script();
280d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!script->isExecutionForbidden())
281d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        script->initializeContextIfNeeded();
2827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), startMode);
2837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    script->evaluate(ScriptSourceCode(sourceCode, scriptURL));
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    postInitialize();
286c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
287c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs);
288c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
289c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
290c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::cleanup()
291c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    // This should be called before we start the shutdown procedure.
29410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    workerReportingProxy().willDestroyWorkerGlobalScope();
29510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The below assignment will destroy the context, which will in turn notify messaging proxy.
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them.
298d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // If Oilpan is enabled, we detach of the context/global scope, with the final heap cleanup below sweeping it out.
29910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch#if !ENABLE(OILPAN)
300d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(m_workerGlobalScope->hasOneRef());
301d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif
30210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    m_workerGlobalScope->dispose();
303d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    m_workerGlobalScope = nullptr;
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_thread->detachGC();
30609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
307e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_thread->removeTaskObserver(m_microtaskRunner.get());
308e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_microtaskRunner = nullptr;
309c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
31043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // Notify the proxy that the WorkerGlobalScope has been disposed of.
31143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // This can free this thread object, hence it must not be touched afterwards.
312e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    workerReportingProxy().workerThreadTerminated();
31343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
3147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_terminationEvent->signal();
3157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3161e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    // Clean up PlatformThreadData before WTF::WTFThreadData goes away!
3171e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    PlatformThreadData::current().destroy();
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3201e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptPtr(new WorkerThreadShutdownFinishTask());
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    virtual void performTask(ExecutionContext *context)
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->clearInspector();
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // It's not safe to call clearScript until all the cleanup tasks posted by functions initiated by WorkerThreadShutdownStartTask have completed.
332591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->clearScript();
333c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        workerGlobalScope->thread()->m_thread->postTask(new Task(WTF::bind(&WorkerThread::cleanup, workerGlobalScope->thread())));
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool isCleanupTask() const { return true; }
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class WorkerThreadShutdownStartTask : public ExecutionContextTask {
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static PassOwnPtr<WorkerThreadShutdownStartTask> create()
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return adoptPtr(new WorkerThreadShutdownStartTask());
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3461e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    virtual void performTask(ExecutionContext *context)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
3495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        workerGlobalScope->stopFetch();
350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->stopActiveDOMObjects();
351c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Event listeners would keep DOMWrapperWorld objects alive for too long. Also, they have references to JS objects,
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // which become dangling once Heap is destroyed.
355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->removeAllEventListeners();
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Stick a shutdown command at the end of the queue, so that we deal
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // with all the cleanup tasks the databases post first.
359591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create());
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    virtual bool isCleanupTask() const { return true; }
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void WorkerThread::stop()
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
36709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Prevent the deadlock between GC and an attempt to stop a thread.
36809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
3697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    stopInternal();
3707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
37109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
3727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::stopInShutdownSequence()
3737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
3747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    stopInternal();
3757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
3767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::stopInternal()
3787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
379c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // Protect against this method and initialize() racing each other.
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MutexLocker lock(m_threadCreationMutex);
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
382c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // If stop has already been called, just return.
383c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_terminated)
384c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        return;
385e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    m_terminated = true;
386c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
38709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // Signal the thread to notify that the thread's stopping.
38809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (m_shutdownEvent)
38909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        m_shutdownEvent->signal();
39009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
391c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (!m_workerGlobalScope)
392926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return;
393c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
394c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // 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.
395c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_workerGlobalScope->script()->scheduleExecutionTermination();
396c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScope.get());
397c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_debuggerMessageQueue.kill();
398c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    postTask(WorkerThreadShutdownStartTask::create());
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid WorkerThread::terminateAndWaitForAllWorkers()
4027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
4037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Keep this lock to prevent WorkerThread instances from being destroyed.
4047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    MutexLocker lock(threadSetMutex());
4057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    HashSet<WorkerThread*> threads = workerThreads();
4067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads.end(); ++itr)
4077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        (*itr)->stopInShutdownSequence();
4087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
4097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    for (HashSet<WorkerThread*>::iterator itr = threads.begin(); itr != threads.end(); ++itr)
4107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        (*itr)->terminationEvent()->wait();
4117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
4127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
41393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)bool WorkerThread::isCurrentThread() const
41493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
415c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return m_thread && m_thread->isCurrentThread();
416c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
417c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
418c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::idleHandler()
419c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
420c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(m_workerGlobalScope.get());
421c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    int64 delay = kLongIdleHandlerDelayMs;
422c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
423c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    // Do a script engine idle notification if the next event is distant enough.
424c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    const double kMinIdleTimespan = 0.3;
425c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() > currentTime() + kMinIdleTimespan) {
426c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        bool hasMoreWork = !m_workerGlobalScope->idleNotification();
427c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (hasMoreWork)
428c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            delay = kShortIdleHandlerDelayMs;
429c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
430c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
431c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), delay);
432c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
433c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
434c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task)
435c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
436c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr());
437c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
438c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
439c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long long delayMs)
440c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
441c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPtr(), delayMs);
442c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
443c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
444c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task)
445c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
446c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false));
447c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    postTask(RunDebuggerQueueTask::create(this));
448c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
449c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
450c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode)
451c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
452c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    ASSERT(isCurrentThread());
453c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    MessageQueueWaitResult result;
454c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    double absoluteTime = MessageQueue<blink::WebThread::Task>::infiniteTime();
455c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    OwnPtr<blink::WebThread::Task> task;
456c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
457c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        if (waitMode == DontWaitForMessage)
458c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            absoluteTime = 0.0;
459c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        ThreadState::SafePointScope safePointScope(ThreadState::NoHeapPointersOnStack);
460c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        task = m_debuggerMessageQueue.waitForMessageWithTimeout(result, absoluteTime);
461c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
462c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
463c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (result == MessageQueueMessageReceived) {
464c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        InspectorInstrumentation::willProcessTask(workerGlobalScope());
465c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        task->run();
466c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)        InspectorInstrumentation::didProcessTask(workerGlobalScope());
467c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    }
468c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
469c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return result;
470c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
471c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
472c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::willEnterNestedLoop()
473c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
474c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    InspectorInstrumentation::willEnterNestedRunLoop(m_workerGlobalScope.get());
475c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
476c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
477c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::didLeaveNestedLoop()
478c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
479c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
480c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
481c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
482c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void WorkerThread::setWorkerInspectorController(WorkerInspectorController* workerInspectorController)
483c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
484c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    MutexLocker locker(m_workerInspectorControllerMutex);
485c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    m_workerInspectorController = workerInspectorController;
48693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
48793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
488c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
489