| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 m_sharedTimerFunction(); | 173 m_sharedTimerFunction(); |
| 174 } | 174 } |
| 175 | 175 |
| 176 WorkerThread* m_workerThread; | 176 WorkerThread* m_workerThread; |
| 177 SharedTimerFunction m_sharedTimerFunction; | 177 SharedTimerFunction m_sharedTimerFunction; |
| 178 double m_nextFireTime; | 178 double m_nextFireTime; |
| 179 bool m_running; | 179 bool m_running; |
| 180 WorkerThreadCancelableTask* m_lastQueuedTask; | 180 WorkerThreadCancelableTask* m_lastQueuedTask; |
| 181 }; | 181 }; |
| 182 | 182 |
| 183 class WorkerThreadTask : public blink::WebThread::Task { | 183 // WorkerThreadTask made private to WorkerThread |
| 184 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED; | 184 PassOwnPtr<WorkerThread::WorkerThreadTask> WorkerThread::WorkerThreadTask::creat
e(WorkerThread& workerThread |
| 185 public: | 185 , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| 186 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) | 186 { |
| 187 { | 187 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)); |
| 188 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); | 188 } |
| 189 |
| 190 void WorkerThread::WorkerThreadTask::run() |
| 191 { |
| 192 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(); |
| 193 // Tasks could be put on the message loop after the cleanup task, |
| 194 // ensure none of those are ran. |
| 195 if (!workerGlobalScope || m_isTaskCanceled) |
| 196 return; |
| 197 |
| 198 if (m_isInstrumented) |
| 199 InspectorInstrumentation::willPerformExecutionContextTask(workerGlobalSc
ope, m_task.get()); |
| 200 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_t
ask->isCleanupTask()) { |
| 201 if (!m_isIdleHandlerTask || (m_isIdleHandlerTask && !m_workerThread.task
Count())) |
| 202 m_task->performTask(workerGlobalScope); |
| 189 } | 203 } |
| 204 if (m_isInstrumented) |
| 205 InspectorInstrumentation::didPerformExecutionContextTask(workerGlobalSco
pe); |
| 190 | 206 |
| 191 virtual ~WorkerThreadTask() { } | 207 // If no more tasks are queued up after this, then queue up the idleHandler |
| 208 // to trigger GC. |
| 209 if (!m_isIdleHandlerTask && !m_workerThread.decrementAndReturnTaskCount() &&
!m_workerThread.m_lastQueuedIdleHandlerTask) |
| 210 m_workerThread.queueUpIdleHandlerNow(kLongIdleHandlerDelayMs); |
| 211 } |
| 192 | 212 |
| 193 virtual void run() override | 213 WorkerThread::WorkerThreadTask::WorkerThreadTask(WorkerThread& workerThread |
| 194 { | 214 , PassOwnPtr<ExecutionContextTask> task, bool isInstrumented) |
| 195 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope(
); | 215 : m_workerThread(workerThread) |
| 196 // Tasks could be put on the message loop after the cleanup task, | 216 , m_task(task) |
| 197 // ensure none of those are ran. | 217 , m_isInstrumented(isInstrumented) |
| 198 if (!workerGlobalScope) | 218 , m_isIdleHandlerTask(false) |
| 199 return; | 219 , m_isTaskCanceled(false) |
| 200 | 220 , m_timeStamp(currentTime()) |
| 201 if (m_isInstrumented) | 221 { |
| 202 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob
alScope, m_task.get()); | 222 if (m_isInstrumented) |
| 203 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) ||
m_task->isCleanupTask()) | 223 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); |
| 204 m_task->performTask(workerGlobalScope); | 224 if (m_isInstrumented) |
| 205 if (m_isInstrumented) | 225 InspectorInstrumentation::didPostExecutionContextTask(m_workerThread.wor
kerGlobalScope(), m_task.get()); |
| 206 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba
lScope); | 226 } |
| 207 } | |
| 208 | |
| 209 private: | |
| 210 WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask
> task, bool isInstrumented) | |
| 211 : m_workerThread(workerThread) | |
| 212 , m_task(task) | |
| 213 , m_isInstrumented(isInstrumented) | |
| 214 { | |
| 215 if (m_isInstrumented) | |
| 216 m_isInstrumented = !m_task->taskNameForInstrumentation().isEmpty(); | |
| 217 if (m_isInstrumented) | |
| 218 InspectorInstrumentation::didPostExecutionContextTask(m_workerThread
.workerGlobalScope(), m_task.get()); | |
| 219 } | |
| 220 | |
| 221 WorkerThread& m_workerThread; | |
| 222 OwnPtr<ExecutionContextTask> m_task; | |
| 223 bool m_isInstrumented; | |
| 224 }; | |
| 225 | 227 |
| 226 class RunDebuggerQueueTask final : public ExecutionContextTask { | 228 class RunDebuggerQueueTask final : public ExecutionContextTask { |
| 227 public: | 229 public: |
| 228 static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) | 230 static PassOwnPtr<RunDebuggerQueueTask> create(WorkerThread* thread) |
| 229 { | 231 { |
| 230 return adoptPtr(new RunDebuggerQueueTask(thread)); | 232 return adoptPtr(new RunDebuggerQueueTask(thread)); |
| 231 } | 233 } |
| 232 virtual void performTask(ExecutionContext* context) override | 234 virtual void performTask(ExecutionContext* context) override |
| 233 { | 235 { |
| 234 ASSERT(context->isWorkerGlobalScope()); | 236 ASSERT(context->isWorkerGlobalScope()); |
| 235 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); | 237 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); |
| 236 } | 238 } |
| 237 | 239 |
| 238 private: | 240 private: |
| 239 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | 241 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } |
| 240 | 242 |
| 241 WorkerThread* m_thread; | 243 WorkerThread* m_thread; |
| 242 }; | 244 }; |
| 243 | 245 |
| 244 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting
Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta
rtupData) | 246 WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReporting
Proxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> sta
rtupData) |
| 245 : m_terminated(false) | 247 : m_terminated(false) |
| 246 , m_workerLoaderProxy(workerLoaderProxy) | 248 , m_workerLoaderProxy(workerLoaderProxy) |
| 247 , m_workerReportingProxy(workerReportingProxy) | 249 , m_workerReportingProxy(workerReportingProxy) |
| 248 , m_startupData(startupData) | 250 , m_startupData(startupData) |
| 249 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()
)) | 251 , m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()
)) |
| 250 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven
t())) | 252 , m_terminationEvent(adoptPtr(blink::Platform::current()->createWaitableEven
t())) |
| 253 , m_lastQueuedIdleHandlerTask(nullptr) |
| 254 , m_tasksCount(0) |
| 251 { | 255 { |
| 252 MutexLocker lock(threadSetMutex()); | 256 MutexLocker lock(threadSetMutex()); |
| 253 workerThreads().add(this); | 257 workerThreads().add(this); |
| 254 } | 258 } |
| 255 | 259 |
| 256 WorkerThread::~WorkerThread() | 260 WorkerThread::~WorkerThread() |
| 257 { | 261 { |
| 258 MutexLocker lock(threadSetMutex()); | 262 MutexLocker lock(threadSetMutex()); |
| 259 ASSERT(workerThreads().contains(this)); | 263 ASSERT(workerThreads().contains(this)); |
| 260 workerThreads().remove(this); | 264 workerThreads().remove(this); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); | 327 script->evaluate(ScriptSourceCode(sourceCode, scriptURL)); |
| 324 m_workerGlobalScope->didEvaluateWorkerScript(); | 328 m_workerGlobalScope->didEvaluateWorkerScript(); |
| 325 | 329 |
| 326 postInitialize(); | 330 postInitialize(); |
| 327 | 331 |
| 328 postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kSho
rtIdleHandlerDelayMs); | 332 postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), kSho
rtIdleHandlerDelayMs); |
| 329 } | 333 } |
| 330 | 334 |
| 331 void WorkerThread::cleanup() | 335 void WorkerThread::cleanup() |
| 332 { | 336 { |
| 333 | |
| 334 // This should be called before we start the shutdown procedure. | 337 // This should be called before we start the shutdown procedure. |
| 335 workerReportingProxy().willDestroyWorkerGlobalScope(); | 338 workerReportingProxy().willDestroyWorkerGlobalScope(); |
| 336 | 339 |
| 337 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 340 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
| 338 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 341 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
| 339 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 342 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
| 340 #if !ENABLE(OILPAN) | 343 #if !ENABLE(OILPAN) |
| 341 ASSERT(m_workerGlobalScope->hasOneRef()); | 344 ASSERT(m_workerGlobalScope->hasOneRef()); |
| 342 #endif | 345 #endif |
| 343 m_workerGlobalScope->dispose(); | 346 m_workerGlobalScope->dispose(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 | 458 |
| 456 for (WorkerThread* thread : threads) | 459 for (WorkerThread* thread : threads) |
| 457 thread->terminationEvent()->wait(); | 460 thread->terminationEvent()->wait(); |
| 458 } | 461 } |
| 459 | 462 |
| 460 bool WorkerThread::isCurrentThread() const | 463 bool WorkerThread::isCurrentThread() const |
| 461 { | 464 { |
| 462 return m_thread && m_thread->isCurrentThread(); | 465 return m_thread && m_thread->isCurrentThread(); |
| 463 } | 466 } |
| 464 | 467 |
| 468 void WorkerThread::queueUpIdleHandlerNow(long long delayMs) |
| 469 { |
| 470 OwnPtr<WorkerThreadTask> idleHandlerTask = WorkerThreadTask::create(*this, c
reateSameThreadTask(&WorkerThread::idleHandler, this), true); |
| 471 |
| 472 idleHandlerTask->setIsIdleHandlerTask(true); |
| 473 |
| 474 if (clearIdleHandlerTaskIfSet()) { |
| 475 WorkerThreadTask* tmp = idleHandlerTask.get(); |
| 476 m_thread->postDelayedTask(idleHandlerTask.leakPtr(), delayMs); |
| 477 m_lastQueuedIdleHandlerTask = tmp; |
| 478 } |
| 479 } |
| 480 |
| 465 void WorkerThread::idleHandler() | 481 void WorkerThread::idleHandler() |
| 466 { | 482 { |
| 467 ASSERT(m_workerGlobalScope.get()); | 483 ASSERT(m_workerGlobalScope.get()); |
| 468 int64_t delay = kLongIdleHandlerDelayMs; | 484 int64_t delay = kLongIdleHandlerDelayMs; |
| 485 m_lastQueuedIdleHandlerTask = nullptr; |
| 486 |
| 487 // Some tasks may have been started in the mean time, so lets return back |
| 488 // and wait for the next idleHandler to be fired. |
| 489 if (m_tasksCount) |
| 490 return; |
| 469 | 491 |
| 470 // Do a script engine idle notification if the next event is distant enough. | 492 // Do a script engine idle notification if the next event is distant enough. |
| 471 const double kMinIdleTimespan = 0.3; | 493 const double kMinIdleTimespan = 0.3; |
| 494 // This is set to true when idleNotification returns false. |
| 495 // idleNotification returns false only when more GC is required. It returns |
| 496 // true if no more GC is required and that is when callGCAgain will be set t
o false. |
| 497 bool callGCAgain = false; |
| 472 if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() >
currentTime() + kMinIdleTimespan) { | 498 if (m_sharedTimer->nextFireTime() == 0.0 || m_sharedTimer->nextFireTime() >
currentTime() + kMinIdleTimespan) { |
| 473 bool hasMoreWork = !m_workerGlobalScope->idleNotification(); | 499 callGCAgain = !m_workerGlobalScope->idleNotification(); |
| 474 if (hasMoreWork) | 500 if (callGCAgain) |
| 475 delay = kShortIdleHandlerDelayMs; | 501 delay = kShortIdleHandlerDelayMs; |
| 476 } | 502 } |
| 477 | 503 |
| 478 postDelayedTask(createSameThreadTask(&WorkerThread::idleHandler, this), dela
y); | 504 if (callGCAgain) |
| 505 queueUpIdleHandlerNow(delay); |
| 506 } |
| 507 |
| 508 int WorkerThread::decrementAndReturnTaskCount() |
| 509 { |
| 510 atomicDecrement(&m_tasksCount); |
| 511 return m_tasksCount; |
| 512 } |
| 513 |
| 514 bool WorkerThread::clearIdleHandlerTaskIfSet() |
| 515 { |
| 516 // If the event was created more than 3 seconds ago, so its too close to the
task completion |
| 517 // hence cancel it and create a new one. |
| 518 const double kIdleHandlerAgeThreshold = 3.0; |
| 519 if (!m_lastQueuedIdleHandlerTask) |
| 520 return true; |
| 521 double idleTaskHandlerAge = currentTime() - m_lastQueuedIdleHandlerTask->cre
ationTimeStamp(); |
| 522 if (idleTaskHandlerAge < kIdleHandlerAgeThreshold) |
| 523 return false; |
| 524 |
| 525 m_lastQueuedIdleHandlerTask->cancelTask(); |
| 526 m_lastQueuedIdleHandlerTask = nullptr; |
| 527 |
| 528 return true; |
| 479 } | 529 } |
| 480 | 530 |
| 481 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) | 531 void WorkerThread::postTask(PassOwnPtr<ExecutionContextTask> task) |
| 482 { | 532 { |
| 533 atomicIncrement(&m_tasksCount); |
| 534 clearIdleHandlerTaskIfSet(); |
| 483 m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); | 535 m_thread->postTask(WorkerThreadTask::create(*this, task, true).leakPtr()); |
| 484 } | 536 } |
| 485 | 537 |
| 486 void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long l
ong delayMs) | 538 void WorkerThread::postDelayedTask(PassOwnPtr<ExecutionContextTask> task, long l
ong delayMs) |
| 487 { | 539 { |
| 540 atomicIncrement(&m_tasksCount); |
| 541 clearIdleHandlerTaskIfSet(); |
| 488 m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPt
r(), delayMs); | 542 m_thread->postDelayedTask(WorkerThreadTask::create(*this, task, true).leakPt
r(), delayMs); |
| 489 } | 543 } |
| 490 | 544 |
| 491 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) | 545 void WorkerThread::postDebuggerTask(PassOwnPtr<ExecutionContextTask> task) |
| 492 { | 546 { |
| 493 m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); | 547 m_debuggerMessageQueue.append(WorkerThreadTask::create(*this, task, false)); |
| 494 postTask(RunDebuggerQueueTask::create(this)); | 548 postTask(RunDebuggerQueueTask::create(this)); |
| 495 } | 549 } |
| 496 | 550 |
| 497 MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) | 551 MessageQueueWaitResult WorkerThread::runDebuggerTask(WaitMode waitMode) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 526 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 580 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 527 } | 581 } |
| 528 | 582 |
| 529 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 583 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
| 530 { | 584 { |
| 531 MutexLocker locker(m_workerInspectorControllerMutex); | 585 MutexLocker locker(m_workerInspectorControllerMutex); |
| 532 m_workerInspectorController = workerInspectorController; | 586 m_workerInspectorController = workerInspectorController; |
| 533 } | 587 } |
| 534 | 588 |
| 535 } // namespace blink | 589 } // namespace blink |
| OLD | NEW |