Chromium Code Reviews| Index: Source/core/workers/WorkerThread.cpp |
| diff --git a/Source/core/workers/WorkerThread.cpp b/Source/core/workers/WorkerThread.cpp |
| index 76e11fb84e4fc2afaac33648e86ff83c665d1f4d..779b6aa3ac6c33ce037f8db59ac0ec1c784786dd 100644 |
| --- a/Source/core/workers/WorkerThread.cpp |
| +++ b/Source/core/workers/WorkerThread.cpp |
| @@ -38,13 +38,12 @@ |
| #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/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/WebScheduler.h" |
| #include "public/platform/WebThread.h" |
| #include "public/platform/WebWaitableEvent.h" |
| #include "wtf/Noncopyable.h" |
| @@ -54,8 +53,7 @@ |
| namespace blink { |
| namespace { |
| -const int64_t kShortIdleHandlerDelayMs = 1000; |
| -const int64_t kLongIdleHandlerDelayMs = 10*1000; |
| +const double kLongIdleHandlerDelaySecs = 1.0; |
| class MicrotaskRunner : public WebThread::TaskObserver { |
| public: |
| @@ -131,69 +129,6 @@ private: |
| 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 blink::WebThread::Task { |
| WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThreadTask); |
| public: |
| @@ -264,6 +199,7 @@ WorkerThread::WorkerThread(const char* threadName, PassRefPtr<WorkerLoaderProxy> |
| , m_isolate(nullptr) |
| , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) |
| , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEvent())) |
| + , m_webScheduler(nullptr) |
| { |
| MutexLocker lock(threadSetMutex()); |
| workerThreads().add(this); |
| @@ -299,6 +235,24 @@ PlatformThreadId WorkerThread::platformThreadId() const |
| return m_thread->platformThread().threadId(); |
| } |
| +// TODO(alexclarke): Use base::Bind instead of this class when the repo's merge. Unfortunately we |
| +// can't use WTF::bind because the type-erasure for member function pointers with parameters is broken. |
| +class WorkerThreadIdleTask : public WebThread::IdleTask { |
| +public: |
| + explicit WorkerThreadIdleTask(WorkerThread* thread) |
| + : m_thread(thread) { } |
| + |
| + ~WorkerThreadIdleTask() override { } |
| + |
| + void run(double deadlineSeconds) override |
| + { |
| + m_thread->idleTask(deadlineSeconds); |
| + } |
| + |
| +private: |
| + RawPtr<WorkerThread> m_thread; |
|
Sami
2015/04/17 15:34:31
// Not owned?
alex clarke (OOO till 29th)
2015/04/20 10:06:53
Done.
|
| +}; |
| + |
| void WorkerThread::initialize() |
| { |
| KURL scriptURL = m_startupData->m_scriptURL; |
| @@ -325,8 +279,6 @@ void WorkerThread::initialize() |
| 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(). |
| @@ -348,7 +300,8 @@ void WorkerThread::initialize() |
| postInitialize(); |
| - postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); |
| + m_webScheduler = m_thread->platformThread().scheduler(); |
| + m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(this)); |
| } |
| PassOwnPtr<WebThreadSupportingGC> WorkerThread::createWebThreadSupportingGC() |
| @@ -381,9 +334,6 @@ void WorkerThread::cleanup() |
| workerReportingProxy().workerThreadTerminated(); |
| m_terminationEvent->signal(); |
| - |
| - // Clean up PlatformThreadData before WTF::WTFThreadData goes away! |
| - PlatformThreadData::current().destroy(); |
| } |
| class WorkerThreadShutdownFinishTask : public ExecutionContextTask { |
| @@ -417,7 +367,6 @@ public: |
| { |
| 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. |
| @@ -509,21 +458,28 @@ bool WorkerThread::isCurrentThread() const |
| return m_thread && m_thread->isCurrentThread(); |
| } |
| -void WorkerThread::idleHandler() |
| +void WorkerThread::idleTask(double deadlineSeconds) |
| { |
| - ASSERT(m_workerGlobalScope.get()); |
| - int64_t delay = kLongIdleHandlerDelayMs; |
| + double gcDeadlineSeconds = deadlineSeconds; |
| + |
| + // The V8 GC does some GC steps (e.g. compaction) only when the idle notification is ~1s. |
| + // TODO(rmcilroy): Refactor so extending the deadline like this this isn't needed. |
| + if (m_webScheduler->canExceedIdleDeadlineIfRequired()) |
| + gcDeadlineSeconds = Platform::current()->monotonicallyIncreasingTime() + kLongIdleHandlerDelaySecs; |
| - // 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; |
| + if (doIdleGc(gcDeadlineSeconds)) |
| + m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(this)); |
| + else |
| + m_webScheduler->postIdleTask(FROM_HERE, new WorkerThreadIdleTask(this)); |
| +} |
| + |
| +bool WorkerThread::doIdleGc(double deadlineSeconds) |
| +{ |
| + if (deadlineSeconds > Platform::current()->monotonicallyIncreasingTime()) { |
| + return isolate()->IdleNotificationDeadline(deadlineSeconds); |
| } |
| - postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), delay); |
| + return false; |
| } |
| void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<ExecutionContextTask> task) |