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 |