| 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 28 matching lines...) Expand all Loading... |
| 39 #include "core/workers/WorkerReportingProxy.h" | 39 #include "core/workers/WorkerReportingProxy.h" |
| 40 #include "core/workers/WorkerThreadStartupData.h" | 40 #include "core/workers/WorkerThreadStartupData.h" |
| 41 #include "platform/PlatformThreadData.h" | 41 #include "platform/PlatformThreadData.h" |
| 42 #include "platform/Task.h" | 42 #include "platform/Task.h" |
| 43 #include "platform/ThreadSafeFunctional.h" | 43 #include "platform/ThreadSafeFunctional.h" |
| 44 #include "platform/ThreadTimers.h" | 44 #include "platform/ThreadTimers.h" |
| 45 #include "platform/heap/SafePoint.h" | 45 #include "platform/heap/SafePoint.h" |
| 46 #include "platform/heap/ThreadState.h" | 46 #include "platform/heap/ThreadState.h" |
| 47 #include "platform/weborigin/KURL.h" | 47 #include "platform/weborigin/KURL.h" |
| 48 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
| 49 #include "public/platform/WebScheduler.h" | |
| 50 #include "public/platform/WebThread.h" | 49 #include "public/platform/WebThread.h" |
| 51 #include "public/platform/WebWaitableEvent.h" | 50 #include "public/platform/WebWaitableEvent.h" |
| 52 #include "wtf/Noncopyable.h" | 51 #include "wtf/Noncopyable.h" |
| 53 #include "wtf/WeakPtr.h" | 52 #include "wtf/WeakPtr.h" |
| 54 #include "wtf/text/WTFString.h" | 53 #include "wtf/text/WTFString.h" |
| 55 | 54 |
| 56 namespace blink { | 55 namespace blink { |
| 57 | 56 |
| 58 namespace { | 57 namespace { |
| 59 const double kLongIdlePeriodSecs = 1.0; | 58 const int64_t kShortIdleHandlerDelayMs = 1000; |
| 59 const int64_t kLongIdleHandlerDelayMs = 10*1000; |
| 60 | 60 |
| 61 } // namespace | 61 } // namespace |
| 62 | 62 |
| 63 class WorkerMicrotaskRunner : public WebThread::TaskObserver { | 63 class WorkerMicrotaskRunner : public WebThread::TaskObserver { |
| 64 public: | 64 public: |
| 65 explicit WorkerMicrotaskRunner(WorkerThread* workerThread) | 65 explicit WorkerMicrotaskRunner(WorkerThread* workerThread) |
| 66 : m_workerThread(workerThread) | 66 : m_workerThread(workerThread) |
| 67 { | 67 { |
| 68 } | 68 } |
| 69 | 69 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | 260 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } |
| 261 | 261 |
| 262 WorkerThread* m_thread; | 262 WorkerThread* m_thread; |
| 263 }; | 263 }; |
| 264 | 264 |
| 265 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work
erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star
tupData) | 265 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work
erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star
tupData) |
| 266 : m_started(false) | 266 : m_started(false) |
| 267 , m_terminated(false) | 267 , m_terminated(false) |
| 268 , m_workerLoaderProxy(workerLoaderProxy) | 268 , m_workerLoaderProxy(workerLoaderProxy) |
| 269 , m_workerReportingProxy(workerReportingProxy) | 269 , m_workerReportingProxy(workerReportingProxy) |
| 270 , m_webScheduler(nullptr) | |
| 271 , m_startupData(startupData) | 270 , m_startupData(startupData) |
| 272 , m_isolate(nullptr) | 271 , m_isolate(nullptr) |
| 273 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 272 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
| 274 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 273 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
| 275 { | 274 { |
| 276 MutexLocker lock(threadSetMutex()); | 275 MutexLocker lock(threadSetMutex()); |
| 277 workerThreads().add(this); | 276 workerThreads().add(this); |
| 278 } | 277 } |
| 279 | 278 |
| 280 WorkerThread::~WorkerThread() | 279 WorkerThread::~WorkerThread() |
| (...skipping 19 matching lines...) Expand all Loading... |
| 300 m_workerInspectorController->interruptAndDispatchInspectorCommands(); | 299 m_workerInspectorController->interruptAndDispatchInspectorCommands(); |
| 301 } | 300 } |
| 302 | 301 |
| 303 PlatformThreadId WorkerThread::platformThreadId() | 302 PlatformThreadId WorkerThread::platformThreadId() |
| 304 { | 303 { |
| 305 if (!m_started) | 304 if (!m_started) |
| 306 return 0; | 305 return 0; |
| 307 return backingThread().platformThread().threadId(); | 306 return backingThread().platformThread().threadId(); |
| 308 } | 307 } |
| 309 | 308 |
| 310 // TODO(alexclarke): Use base::Bind instead of this class when the repo's merge.
Unfortunately we | |
| 311 // can't use WTF::bind because the type-erasure for member function pointers wit
h parameters is broken. | |
| 312 class WorkerThreadIdleTask : public WebThread::IdleTask { | |
| 313 public: | |
| 314 explicit WorkerThreadIdleTask(WorkerThread* thread) | |
| 315 : m_thread(thread) { } | |
| 316 | |
| 317 ~WorkerThreadIdleTask() override { } | |
| 318 | |
| 319 void run(double deadlineSeconds) override | |
| 320 { | |
| 321 m_thread->performIdleWork(deadlineSeconds); | |
| 322 } | |
| 323 | |
| 324 private: | |
| 325 RawPtr<WorkerThread> m_thread; // NOT OWNED | |
| 326 }; | |
| 327 | |
| 328 void WorkerThread::initialize() | 309 void WorkerThread::initialize() |
| 329 { | 310 { |
| 330 KURL scriptURL = m_startupData->m_scriptURL; | 311 KURL scriptURL = m_startupData->m_scriptURL; |
| 331 String sourceCode = m_startupData->m_sourceCode; | 312 String sourceCode = m_startupData->m_sourceCode; |
| 332 WorkerThreadStartMode startMode = m_startupData->m_startMode; | 313 WorkerThreadStartMode startMode = m_startupData->m_startMode; |
| 333 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); | 314 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); |
| 334 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; | 315 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; |
| 335 | 316 |
| 336 m_webScheduler = backingThread().platformThread().scheduler(); | |
| 337 { | 317 { |
| 338 MutexLocker lock(m_threadStateMutex); | 318 MutexLocker lock(m_threadStateMutex); |
| 339 | 319 |
| 340 // The worker was terminated before the thread had a chance to run. | 320 // The worker was terminated before the thread had a chance to run. |
| 341 if (m_terminated) { | 321 if (m_terminated) { |
| 342 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 322 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
| 343 // This can free this thread object, hence it must not be touched af
terwards. | 323 // This can free this thread object, hence it must not be touched af
terwards. |
| 344 m_workerReportingProxy.workerThreadTerminated(); | 324 m_workerReportingProxy.workerThreadTerminated(); |
| 345 return; | 325 return; |
| 346 } | 326 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 368 if (startMode == PauseWorkerGlobalScopeOnStart) | 348 if (startMode == PauseWorkerGlobalScopeOnStart) |
| 369 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); | 349 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); |
| 370 | 350 |
| 371 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); | 351 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); |
| 372 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); | 352 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); |
| 373 m_workerGlobalScope->didEvaluateWorkerScript(); | 353 m_workerGlobalScope->didEvaluateWorkerScript(); |
| 374 m_workerReportingProxy.didEvaluateWorkerScript(success); | 354 m_workerReportingProxy.didEvaluateWorkerScript(success); |
| 375 | 355 |
| 376 postInitialize(); | 356 postInitialize(); |
| 377 | 357 |
| 378 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(
this)); | 358 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), kShortIdleHandlerDelayMs); |
| 379 } | 359 } |
| 380 | 360 |
| 381 void WorkerThread::shutdown() | 361 void WorkerThread::shutdown() |
| 382 { | 362 { |
| 383 MutexLocker lock(m_threadStateMutex); | 363 MutexLocker lock(m_threadStateMutex); |
| 384 ASSERT(isCurrentThread()); | 364 ASSERT(isCurrentThread()); |
| 385 | 365 |
| 386 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); | 366 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); |
| 387 workerGlobalScope()->dispose(); | 367 workerGlobalScope()->dispose(); |
| 388 willDestroyIsolate(); | 368 willDestroyIsolate(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 | 467 |
| 488 for (WorkerThread* thread : threads) | 468 for (WorkerThread* thread : threads) |
| 489 thread->terminationEvent()->wait(); | 469 thread->terminationEvent()->wait(); |
| 490 } | 470 } |
| 491 | 471 |
| 492 bool WorkerThread::isCurrentThread() | 472 bool WorkerThread::isCurrentThread() |
| 493 { | 473 { |
| 494 return m_started && backingThread().isCurrentThread(); | 474 return m_started && backingThread().isCurrentThread(); |
| 495 } | 475 } |
| 496 | 476 |
| 497 void WorkerThread::performIdleWork(double deadlineSeconds) | 477 void WorkerThread::idleHandler() |
| 498 { | 478 { |
| 499 double gcDeadlineSeconds = deadlineSeconds; | 479 ASSERT(m_workerGlobalScope.get()); |
| 480 int64_t delay = kLongIdleHandlerDelayMs; |
| 500 | 481 |
| 501 // The V8 GC does some GC steps (e.g. compaction) only when the idle notific
ation is ~1s. | 482 // Do a script engine idle notification if the next event is distant enough. |
| 502 // TODO(rmcilroy): Refactor so extending the deadline like this this isn't n
eeded. | 483 const double kMinIdleTimespan = 0.3; |
| 503 if (m_webScheduler->canExceedIdleDeadlineIfRequired()) | 484 const double nextFireTime = PlatformThreadData::current().threadTimers().nex
tFireTime(); |
| 504 gcDeadlineSeconds = Platform::current()->monotonicallyIncreasingTime() +
kLongIdlePeriodSecs; | 485 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan)
{ |
| 486 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren
t()->monotonicallyIncreasingTime() + 1.0); |
| 487 if (hasMoreWork) |
| 488 delay = kShortIdleHandlerDelayMs; |
| 489 } |
| 505 | 490 |
| 506 if (doIdleGc(gcDeadlineSeconds)) | 491 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), delay); |
| 507 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleT
ask(this)); | |
| 508 else | |
| 509 m_webScheduler->postIdleTask(FROM_HERE, new WorkerThreadIdleTask(this)); | |
| 510 } | |
| 511 | |
| 512 bool WorkerThread::doIdleGc(double deadlineSeconds) | |
| 513 { | |
| 514 bool gcFinished = false; | |
| 515 if (deadlineSeconds > Platform::current()->monotonicallyIncreasingTime()) | |
| 516 gcFinished = isolate()->IdleNotificationDeadline(deadlineSeconds); | |
| 517 return gcFinished; | |
| 518 } | 492 } |
| 519 | 493 |
| 520 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) | 494 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) |
| 521 { | 495 { |
| 522 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru
e).leakPtr()); | 496 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru
e).leakPtr()); |
| 523 } | 497 } |
| 524 | 498 |
| 525 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) | 499 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) |
| 526 { | 500 { |
| 527 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta
sk, true).leakPtr(), delayMs); | 501 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta
sk, true).leakPtr(), delayMs); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 575 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 602 } | 576 } |
| 603 | 577 |
| 604 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 578 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
| 605 { | 579 { |
| 606 MutexLocker locker(m_workerInspectorControllerMutex); | 580 MutexLocker locker(m_workerInspectorControllerMutex); |
| 607 m_workerInspectorController = workerInspectorController; | 581 m_workerInspectorController = workerInspectorController; |
| 608 } | 582 } |
| 609 | 583 |
| 610 } // namespace blink | 584 } // namespace blink |
| OLD | NEW |