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" |
49 #include "public/platform/WebThread.h" | 50 #include "public/platform/WebThread.h" |
50 #include "public/platform/WebWaitableEvent.h" | 51 #include "public/platform/WebWaitableEvent.h" |
51 #include "wtf/Noncopyable.h" | 52 #include "wtf/Noncopyable.h" |
52 #include "wtf/WeakPtr.h" | 53 #include "wtf/WeakPtr.h" |
53 #include "wtf/text/WTFString.h" | 54 #include "wtf/text/WTFString.h" |
54 | 55 |
55 namespace blink { | 56 namespace blink { |
56 | 57 |
57 namespace { | 58 namespace { |
58 const int64_t kShortIdleHandlerDelayMs = 1000; | 59 const double kLongIdlePeriodSecs = 1.0; |
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 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | 265 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } |
266 | 266 |
267 WorkerThread* m_thread; | 267 WorkerThread* m_thread; |
268 }; | 268 }; |
269 | 269 |
270 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work
erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star
tupData) | 270 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work
erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star
tupData) |
271 : m_started(false) | 271 : m_started(false) |
272 , m_terminated(false) | 272 , m_terminated(false) |
273 , m_workerLoaderProxy(workerLoaderProxy) | 273 , m_workerLoaderProxy(workerLoaderProxy) |
274 , m_workerReportingProxy(workerReportingProxy) | 274 , m_workerReportingProxy(workerReportingProxy) |
| 275 , m_webScheduler(nullptr) |
275 , m_startupData(startupData) | 276 , m_startupData(startupData) |
276 , m_isolate(nullptr) | 277 , m_isolate(nullptr) |
277 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 278 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
278 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 279 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
279 { | 280 { |
280 MutexLocker lock(threadSetMutex()); | 281 MutexLocker lock(threadSetMutex()); |
281 workerThreads().add(this); | 282 workerThreads().add(this); |
282 } | 283 } |
283 | 284 |
284 WorkerThread::~WorkerThread() | 285 WorkerThread::~WorkerThread() |
(...skipping 27 matching lines...) Expand all Loading... |
312 } | 313 } |
313 | 314 |
314 void WorkerThread::initialize() | 315 void WorkerThread::initialize() |
315 { | 316 { |
316 KURL scriptURL = m_startupData->m_scriptURL; | 317 KURL scriptURL = m_startupData->m_scriptURL; |
317 String sourceCode = m_startupData->m_sourceCode; | 318 String sourceCode = m_startupData->m_sourceCode; |
318 WorkerThreadStartMode startMode = m_startupData->m_startMode; | 319 WorkerThreadStartMode startMode = m_startupData->m_startMode; |
319 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); | 320 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); |
320 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; | 321 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; |
321 | 322 |
| 323 m_webScheduler = backingThread().platformThread().scheduler(); |
322 { | 324 { |
323 MutexLocker lock(m_threadStateMutex); | 325 MutexLocker lock(m_threadStateMutex); |
324 | 326 |
325 // The worker was terminated before the thread had a chance to run. | 327 // The worker was terminated before the thread had a chance to run. |
326 if (m_terminated) { | 328 if (m_terminated) { |
327 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 329 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
328 // This can free this thread object, hence it must not be touched af
terwards. | 330 // This can free this thread object, hence it must not be touched af
terwards. |
329 m_workerReportingProxy.workerThreadTerminated(); | 331 m_workerReportingProxy.workerThreadTerminated(); |
330 return; | 332 return; |
331 } | 333 } |
(...skipping 21 matching lines...) Expand all Loading... |
353 if (startMode == PauseWorkerGlobalScopeOnStart) | 355 if (startMode == PauseWorkerGlobalScopeOnStart) |
354 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); | 356 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); |
355 | 357 |
356 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); | 358 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); |
357 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); | 359 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); |
358 m_workerGlobalScope->didEvaluateWorkerScript(); | 360 m_workerGlobalScope->didEvaluateWorkerScript(); |
359 m_workerReportingProxy.didEvaluateWorkerScript(success); | 361 m_workerReportingProxy.didEvaluateWorkerScript(success); |
360 | 362 |
361 postInitialize(); | 363 postInitialize(); |
362 | 364 |
363 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), kShortIdleHandlerDelayMs); | 365 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, WTF::bind<double>(&Worker
Thread::performIdleWork, this)); |
364 } | 366 } |
365 | 367 |
366 void WorkerThread::shutdown() | 368 void WorkerThread::shutdown() |
367 { | 369 { |
368 MutexLocker lock(m_threadStateMutex); | 370 MutexLocker lock(m_threadStateMutex); |
369 ASSERT(isCurrentThread()); | 371 ASSERT(isCurrentThread()); |
370 | 372 |
371 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); | 373 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); |
372 workerGlobalScope()->dispose(); | 374 workerGlobalScope()->dispose(); |
373 willDestroyIsolate(); | 375 willDestroyIsolate(); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 | 474 |
473 for (WorkerThread* thread : threads) | 475 for (WorkerThread* thread : threads) |
474 thread->terminationEvent()->wait(); | 476 thread->terminationEvent()->wait(); |
475 } | 477 } |
476 | 478 |
477 bool WorkerThread::isCurrentThread() | 479 bool WorkerThread::isCurrentThread() |
478 { | 480 { |
479 return m_started && backingThread().isCurrentThread(); | 481 return m_started && backingThread().isCurrentThread(); |
480 } | 482 } |
481 | 483 |
482 void WorkerThread::idleHandler() | 484 void WorkerThread::performIdleWork(double deadlineSeconds) |
483 { | 485 { |
484 ASSERT(m_workerGlobalScope.get()); | 486 double gcDeadlineSeconds = deadlineSeconds; |
485 int64_t delay = kLongIdleHandlerDelayMs; | |
486 | 487 |
487 // Do a script engine idle notification if the next event is distant enough. | 488 // The V8 GC does some GC steps (e.g. compaction) only when the idle notific
ation is ~1s. |
488 const double kMinIdleTimespan = 0.3; | 489 // TODO(rmcilroy): Refactor so extending the deadline like this this isn't n
eeded. |
489 const double nextFireTime = PlatformThreadData::current().threadTimers().nex
tFireTime(); | 490 if (m_webScheduler->canExceedIdleDeadlineIfRequired()) |
490 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan)
{ | 491 gcDeadlineSeconds = Platform::current()->monotonicallyIncreasingTime() +
kLongIdlePeriodSecs; |
491 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren
t()->monotonicallyIncreasingTime() + 1.0); | |
492 if (hasMoreWork) | |
493 delay = kShortIdleHandlerDelayMs; | |
494 } | |
495 | 492 |
496 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), delay); | 493 if (doIdleGc(gcDeadlineSeconds)) |
| 494 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, WTF::bind<double>(&Wo
rkerThread::performIdleWork, this)); |
| 495 else |
| 496 m_webScheduler->postIdleTask(FROM_HERE, WTF::bind<double>(&WorkerThread:
:performIdleWork, this)); |
| 497 } |
| 498 |
| 499 bool WorkerThread::doIdleGc(double deadlineSeconds) |
| 500 { |
| 501 bool gcFinished = false; |
| 502 if (deadlineSeconds > Platform::current()->monotonicallyIncreasingTime()) |
| 503 gcFinished = isolate()->IdleNotificationDeadline(deadlineSeconds); |
| 504 return gcFinished; |
497 } | 505 } |
498 | 506 |
499 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) | 507 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) |
500 { | 508 { |
501 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru
e).leakPtr()); | 509 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru
e).leakPtr()); |
502 } | 510 } |
503 | 511 |
504 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) | 512 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) |
505 { | 513 { |
506 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta
sk, true).leakPtr(), delayMs); | 514 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta
sk, true).leakPtr(), delayMs); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 588 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
581 } | 589 } |
582 | 590 |
583 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 591 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
584 { | 592 { |
585 MutexLocker locker(m_workerInspectorControllerMutex); | 593 MutexLocker locker(m_workerInspectorControllerMutex); |
586 m_workerInspectorController = workerInspectorController; | 594 m_workerInspectorController = workerInspectorController; |
587 } | 595 } |
588 | 596 |
589 } // namespace blink | 597 } // namespace blink |
OLD | NEW |