| 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 20 matching lines...) Expand all Loading... |
| 31 #include "bindings/core/v8/ScriptSourceCode.h" | 31 #include "bindings/core/v8/ScriptSourceCode.h" |
| 32 #include "bindings/core/v8/V8GCController.h" | 32 #include "bindings/core/v8/V8GCController.h" |
| 33 #include "bindings/core/v8/V8Initializer.h" | 33 #include "bindings/core/v8/V8Initializer.h" |
| 34 #include "core/dom/Microtask.h" | 34 #include "core/dom/Microtask.h" |
| 35 #include "core/inspector/InspectorInstrumentation.h" | 35 #include "core/inspector/InspectorInstrumentation.h" |
| 36 #include "core/inspector/WorkerInspectorController.h" | 36 #include "core/inspector/WorkerInspectorController.h" |
| 37 #include "core/workers/DedicatedWorkerGlobalScope.h" | 37 #include "core/workers/DedicatedWorkerGlobalScope.h" |
| 38 #include "core/workers/WorkerClients.h" | 38 #include "core/workers/WorkerClients.h" |
| 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" | |
| 42 #include "platform/Task.h" | 41 #include "platform/Task.h" |
| 43 #include "platform/ThreadSafeFunctional.h" | 42 #include "platform/ThreadSafeFunctional.h" |
| 44 #include "platform/ThreadTimers.h" | |
| 45 #include "platform/heap/SafePoint.h" | 43 #include "platform/heap/SafePoint.h" |
| 46 #include "platform/heap/ThreadState.h" | 44 #include "platform/heap/ThreadState.h" |
| 47 #include "platform/weborigin/KURL.h" | 45 #include "platform/weborigin/KURL.h" |
| 48 #include "public/platform/Platform.h" | 46 #include "public/platform/Platform.h" |
| 49 #include "public/platform/WebScheduler.h" | 47 #include "public/platform/WebScheduler.h" |
| 50 #include "public/platform/WebThread.h" | 48 #include "public/platform/WebThread.h" |
| 51 #include "public/platform/WebWaitableEvent.h" | 49 #include "public/platform/WebWaitableEvent.h" |
| 52 #include "wtf/Noncopyable.h" | 50 #include "wtf/Noncopyable.h" |
| 53 #include "wtf/WeakPtr.h" | 51 #include "wtf/WeakPtr.h" |
| 54 #include "wtf/text/WTFString.h" | 52 #include "wtf/text/WTFString.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); | 102 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); |
| 105 return threads; | 103 return threads; |
| 106 } | 104 } |
| 107 | 105 |
| 108 unsigned WorkerThread::workerThreadCount() | 106 unsigned WorkerThread::workerThreadCount() |
| 109 { | 107 { |
| 110 MutexLocker lock(threadSetMutex()); | 108 MutexLocker lock(threadSetMutex()); |
| 111 return workerThreads().size(); | 109 return workerThreads().size(); |
| 112 } | 110 } |
| 113 | 111 |
| 114 class WorkerThreadCancelableTask final : public ExecutionContextTask { | |
| 115 WTF_MAKE_NONCOPYABLE(WorkerThreadCancelableTask); WTF_MAKE_FAST_ALLOCATED(Wo
rkerThreadCancelableTask); | |
| 116 public: | |
| 117 static PassOwnPtr<WorkerThreadCancelableTask> create(PassOwnPtr<Closure> clo
sure) | |
| 118 { | |
| 119 return adoptPtr(new WorkerThreadCancelableTask(closure)); | |
| 120 } | |
| 121 | |
| 122 virtual ~WorkerThreadCancelableTask() { } | |
| 123 | |
| 124 virtual void performTask(ExecutionContext*) override | |
| 125 { | |
| 126 if (!m_taskCanceled) | |
| 127 (*m_closure)(); | |
| 128 } | |
| 129 | |
| 130 WeakPtr<WorkerThreadCancelableTask> createWeakPtr() { return m_weakFactory.c
reateWeakPtr(); } | |
| 131 void cancelTask() { m_taskCanceled = true; } | |
| 132 | |
| 133 private: | |
| 134 explicit WorkerThreadCancelableTask(PassOwnPtr<Closure> closure) | |
| 135 : m_closure(closure) | |
| 136 , m_weakFactory(this) | |
| 137 , m_taskCanceled(false) | |
| 138 { } | |
| 139 | |
| 140 OwnPtr<Closure> m_closure; | |
| 141 WeakPtrFactory<WorkerThreadCancelableTask> m_weakFactory; | |
| 142 bool m_taskCanceled; | |
| 143 }; | |
| 144 | |
| 145 class WorkerSharedTimer : public SharedTimer { | |
| 146 public: | |
| 147 explicit WorkerSharedTimer(WorkerThread* workerThread) | |
| 148 : m_workerThread(workerThread) | |
| 149 , m_running(false) | |
| 150 { } | |
| 151 | |
| 152 typedef void (*SharedTimerFunction)(); | |
| 153 virtual void setFiredFunction(SharedTimerFunction func) | |
| 154 { | |
| 155 m_sharedTimerFunction = func; | |
| 156 } | |
| 157 | |
| 158 virtual void setFireInterval(double interval) | |
| 159 { | |
| 160 ASSERT(m_sharedTimerFunction); | |
| 161 | |
| 162 // See BlinkPlatformImpl::setSharedTimerFireInterval for explanation of | |
| 163 // why ceil is used in the interval calculation. | |
| 164 int64_t delay = static_cast<int64_t>(ceil(interval * 1000)); | |
| 165 | |
| 166 if (delay < 0) { | |
| 167 delay = 0; | |
| 168 } | |
| 169 | |
| 170 m_running = true; | |
| 171 | |
| 172 if (m_lastQueuedTask.get()) | |
| 173 m_lastQueuedTask->cancelTask(); | |
| 174 | |
| 175 // Now queue the task as a cancellable one. | |
| 176 OwnPtr<WorkerThreadCancelableTask> task = WorkerThreadCancelableTask::cr
eate(bind(&WorkerSharedTimer::OnTimeout, this)); | |
| 177 m_lastQueuedTask = task->createWeakPtr(); | |
| 178 m_workerThread->postDelayedTask(FROM_HERE, task.release(), delay); | |
| 179 } | |
| 180 | |
| 181 virtual void stop() | |
| 182 { | |
| 183 m_running = false; | |
| 184 m_lastQueuedTask = nullptr; | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 void OnTimeout() | |
| 189 { | |
| 190 ASSERT(m_workerThread->workerGlobalScope()); | |
| 191 | |
| 192 m_lastQueuedTask = nullptr; | |
| 193 | |
| 194 if (m_sharedTimerFunction && m_running && !m_workerThread->workerGlobalS
cope()->isClosing()) | |
| 195 m_sharedTimerFunction(); | |
| 196 } | |
| 197 | |
| 198 WorkerThread* m_workerThread; | |
| 199 SharedTimerFunction m_sharedTimerFunction; | |
| 200 bool m_running; | |
| 201 | |
| 202 // The task to run OnTimeout, if any. While OnTimeout resets | |
| 203 // m_lastQueuedTask, this must be a weak pointer because the | |
| 204 // worker runloop may delete the task as it is shutting down. | |
| 205 WeakPtr<WorkerThreadCancelableTask> m_lastQueuedTask; | |
| 206 }; | |
| 207 | |
| 208 class WorkerThreadTask : public WebThread::Task { | 112 class WorkerThreadTask : public WebThread::Task { |
| 209 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); | 113 WTF_MAKE_NONCOPYABLE(WorkerThreadTask); WTF_MAKE_FAST_ALLOCATED(WorkerThread
Task); |
| 210 public: | 114 public: |
| 211 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) | 115 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO
wnPtr<ExecutionContextTask> task, bool isInstrumented) |
| 212 { | 116 { |
| 213 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); | 117 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented)
); |
| 214 } | 118 } |
| 215 | 119 |
| 216 virtual ~WorkerThreadTask() { } | 120 virtual ~WorkerThreadTask() { } |
| 217 | 121 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 return; | 249 return; |
| 346 } | 250 } |
| 347 | 251 |
| 348 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); | 252 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); |
| 349 backingThread().addTaskObserver(m_microtaskRunner.get()); | 253 backingThread().addTaskObserver(m_microtaskRunner.get()); |
| 350 backingThread().initialize(); | 254 backingThread().initialize(); |
| 351 | 255 |
| 352 m_isolate = initializeIsolate(); | 256 m_isolate = initializeIsolate(); |
| 353 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); | 257 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); |
| 354 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); | 258 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); |
| 355 | |
| 356 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); | |
| 357 } | 259 } |
| 358 | 260 |
| 359 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). | 261 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). |
| 360 didStartRunLoop(); | 262 didStartRunLoop(); |
| 361 | 263 |
| 362 // Notify proxy that a new WorkerGlobalScope has been created and started. | 264 // Notify proxy that a new WorkerGlobalScope has been created and started. |
| 363 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); | 265 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get()); |
| 364 | 266 |
| 365 WorkerScriptController* script = m_workerGlobalScope->script(); | 267 WorkerScriptController* script = m_workerGlobalScope->script(); |
| 366 if (!script->isExecutionForbidden()) | 268 if (!script->isExecutionForbidden()) |
| 367 script->initializeContextIfNeeded(); | 269 script->initializeContextIfNeeded(); |
| 368 if (startMode == PauseWorkerGlobalScopeOnStart) | 270 if (startMode == PauseWorkerGlobalScopeOnStart) |
| 369 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); | 271 m_workerGlobalScope->workerInspectorController()->pauseOnStart(); |
| 370 | 272 |
| 371 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); | 273 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); |
| 372 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); | 274 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); |
| 373 m_workerGlobalScope->didEvaluateWorkerScript(); | 275 m_workerGlobalScope->didEvaluateWorkerScript(); |
| 374 m_workerReportingProxy.didEvaluateWorkerScript(success); | 276 m_workerReportingProxy.didEvaluateWorkerScript(success); |
| 375 | 277 |
| 376 postInitialize(); | 278 postInitialize(); |
| 377 | 279 |
| 378 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(
this)); | 280 m_webScheduler->postIdleTaskAfterWakeup(FROM_HERE, new WorkerThreadIdleTask(
this)); |
| 379 } | 281 } |
| 380 | 282 |
| 381 void WorkerThread::shutdown() | 283 void WorkerThread::shutdown() |
| 382 { | 284 { |
| 383 MutexLocker lock(m_threadStateMutex); | 285 MutexLocker lock(m_threadStateMutex); |
| 384 ASSERT(isCurrentThread()); | 286 ASSERT(isCurrentThread()); |
| 385 | 287 |
| 386 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr); | |
| 387 workerGlobalScope()->dispose(); | 288 workerGlobalScope()->dispose(); |
| 388 willDestroyIsolate(); | 289 willDestroyIsolate(); |
| 389 | 290 |
| 390 // This should be called before we start the shutdown procedure. | 291 // This should be called before we start the shutdown procedure. |
| 391 workerReportingProxy().willDestroyWorkerGlobalScope(); | 292 workerReportingProxy().willDestroyWorkerGlobalScope(); |
| 392 | 293 |
| 393 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 294 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
| 394 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 295 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
| 395 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 296 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
| 396 #if !ENABLE(OILPAN) | 297 #if !ENABLE(OILPAN) |
| 397 ASSERT(m_workerGlobalScope->hasOneRef()); | 298 ASSERT(m_workerGlobalScope->hasOneRef()); |
| 398 #endif | 299 #endif |
| 399 m_workerGlobalScope->notifyContextDestroyed(); | 300 m_workerGlobalScope->notifyContextDestroyed(); |
| 400 m_workerGlobalScope = nullptr; | 301 m_workerGlobalScope = nullptr; |
| 401 | 302 |
| 402 backingThread().removeTaskObserver(m_microtaskRunner.get()); | 303 backingThread().removeTaskObserver(m_microtaskRunner.get()); |
| 403 backingThread().shutdown(); | 304 backingThread().shutdown(); |
| 404 destroyIsolate(); | 305 destroyIsolate(); |
| 405 | 306 |
| 406 m_microtaskRunner = nullptr; | 307 m_microtaskRunner = nullptr; |
| 407 | 308 |
| 408 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 309 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
| 409 // This can free this thread object, hence it must not be touched afterwards
. | 310 // This can free this thread object, hence it must not be touched afterwards
. |
| 410 workerReportingProxy().workerThreadTerminated(); | 311 workerReportingProxy().workerThreadTerminated(); |
| 411 | 312 |
| 412 m_terminationEvent->signal(); | 313 m_terminationEvent->signal(); |
| 413 | |
| 414 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! | |
| 415 PlatformThreadData::current().destroy(); | |
| 416 } | 314 } |
| 417 | 315 |
| 418 | 316 |
| 419 void WorkerThread::stop() | 317 void WorkerThread::stop() |
| 420 { | 318 { |
| 421 // Prevent the deadlock between GC and an attempt to stop a thread. | 319 // Prevent the deadlock between GC and an attempt to stop a thread. |
| 422 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); | 320 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); |
| 423 stopInternal(); | 321 stopInternal(); |
| 424 } | 322 } |
| 425 | 323 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 499 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 602 } | 500 } |
| 603 | 501 |
| 604 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 502 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
| 605 { | 503 { |
| 606 MutexLocker locker(m_workerInspectorControllerMutex); | 504 MutexLocker locker(m_workerInspectorControllerMutex); |
| 607 m_workerInspectorController = workerInspectorController; | 505 m_workerInspectorController = workerInspectorController; |
| 608 } | 506 } |
| 609 | 507 |
| 610 } // namespace blink | 508 } // namespace blink |
| OLD | NEW |