Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: third_party/WebKit/Source/core/workers/WorkerThread.cpp

Issue 1733353004: Introduce WorkerBackingThread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 * 24 *
25 */ 25 */
26 26
27 #include "core/workers/WorkerThread.h" 27 #include "core/workers/WorkerThread.h"
28 28
29 #include "bindings/core/v8/ScriptSourceCode.h" 29 #include "bindings/core/v8/ScriptSourceCode.h"
30 #include "bindings/core/v8/V8GCController.h"
31 #include "bindings/core/v8/V8IdleTaskRunner.h"
32 #include "bindings/core/v8/V8Initializer.h"
33 #include "core/dom/Microtask.h" 30 #include "core/dom/Microtask.h"
34 #include "core/inspector/InspectorInstrumentation.h" 31 #include "core/inspector/InspectorInstrumentation.h"
35 #include "core/inspector/WorkerInspectorController.h" 32 #include "core/inspector/WorkerInspectorController.h"
36 #include "core/workers/DedicatedWorkerGlobalScope.h" 33 #include "core/workers/DedicatedWorkerGlobalScope.h"
34 #include "core/workers/WorkerBackingThread.h"
37 #include "core/workers/WorkerClients.h" 35 #include "core/workers/WorkerClients.h"
38 #include "core/workers/WorkerReportingProxy.h" 36 #include "core/workers/WorkerReportingProxy.h"
39 #include "core/workers/WorkerThreadStartupData.h" 37 #include "core/workers/WorkerThreadStartupData.h"
40 #include "platform/ThreadSafeFunctional.h" 38 #include "platform/ThreadSafeFunctional.h"
41 #include "platform/WaitableEvent.h" 39 #include "platform/WaitableEvent.h"
42 #include "platform/heap/SafePoint.h" 40 #include "platform/heap/SafePoint.h"
43 #include "platform/heap/ThreadState.h" 41 #include "platform/heap/ThreadState.h"
44 #include "platform/weborigin/KURL.h" 42 #include "platform/weborigin/KURL.h"
45 #include "public/platform/Platform.h"
46 #include "public/platform/WebScheduler.h" 43 #include "public/platform/WebScheduler.h"
47 #include "public/platform/WebThread.h" 44 #include "public/platform/WebThread.h"
48 #include "wtf/Functional.h" 45 #include "wtf/Functional.h"
49 #include "wtf/Noncopyable.h" 46 #include "wtf/Noncopyable.h"
50 #include "wtf/WeakPtr.h" 47 #include "wtf/WeakPtr.h"
51 #include "wtf/text/WTFString.h" 48 #include "wtf/text/WTFString.h"
52 #include <limits.h> 49 #include <limits.h>
53 50
54 namespace blink { 51 namespace blink {
55 52
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 184
188 static double infiniteTime() { return std::numeric_limits<double>::max(); } 185 static double infiniteTime() { return std::numeric_limits<double>::max(); }
189 186
190 private: 187 private:
191 Mutex m_mutex; 188 Mutex m_mutex;
192 ThreadCondition m_condition; 189 ThreadCondition m_condition;
193 Deque<OwnPtr<Task>> m_queue; 190 Deque<OwnPtr<Task>> m_queue;
194 bool m_killed = false; 191 bool m_killed = false;
195 }; 192 };
196 193
197 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy) 194 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy, PassRefPtr<WorkerBackingThread> thread)
198 : m_started(false) 195 : m_started(false)
199 , m_terminated(false) 196 , m_terminated(false)
200 , m_shutdown(false) 197 , m_shutdown(false)
201 , m_debuggerTaskQueue(adoptPtr(new DebuggerTaskQueue)) 198 , m_debuggerTaskQueue(adoptPtr(new DebuggerTaskQueue))
202 , m_workerLoaderProxy(workerLoaderProxy) 199 , m_workerLoaderProxy(workerLoaderProxy)
203 , m_workerReportingProxy(workerReportingProxy) 200 , m_workerReportingProxy(workerReportingProxy)
204 , m_webScheduler(nullptr) 201 , m_webScheduler(nullptr)
205 , m_isolate(nullptr) 202 , m_workerBackingThread(thread)
206 , m_shutdownEvent(adoptPtr(new WaitableEvent( 203 , m_shutdownEvent(adoptPtr(new WaitableEvent(
207 WaitableEvent::ResetPolicy::Manual, 204 WaitableEvent::ResetPolicy::Manual,
208 WaitableEvent::InitialState::NonSignaled))) 205 WaitableEvent::InitialState::NonSignaled)))
209 , m_terminationEvent(adoptPtr(new WaitableEvent( 206 , m_terminationEvent(adoptPtr(new WaitableEvent(
210 WaitableEvent::ResetPolicy::Manual, 207 WaitableEvent::ResetPolicy::Manual,
211 WaitableEvent::InitialState::NonSignaled))) 208 WaitableEvent::InitialState::NonSignaled)))
212 { 209 {
213 MutexLocker lock(threadSetMutex()); 210 MutexLocker lock(threadSetMutex());
214 workerThreads().add(this); 211 workerThreads().add(this);
215 } 212 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 // The worker was terminated before the thread had a chance to run. 258 // The worker was terminated before the thread had a chance to run.
262 if (m_terminated) { 259 if (m_terminated) {
263 // Notify the proxy that the WorkerGlobalScope has been disposed of. 260 // Notify the proxy that the WorkerGlobalScope has been disposed of.
264 // This can free this thread object, hence it must not be touched af terwards. 261 // This can free this thread object, hence it must not be touched af terwards.
265 m_workerReportingProxy.workerThreadTerminated(); 262 m_workerReportingProxy.workerThreadTerminated();
266 // Notify the main thread that it is safe to deallocate our resource s. 263 // Notify the main thread that it is safe to deallocate our resource s.
267 m_terminationEvent->signal(); 264 m_terminationEvent->signal();
268 return; 265 return;
269 } 266 }
270 267
268 m_workerBackingThread->attach();
269
271 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); 270 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this));
272 initializeBackingThread();
273 backingThread().addTaskObserver(m_microtaskRunner.get()); 271 backingThread().addTaskObserver(m_microtaskRunner.get());
274 272
275 m_isolate = initializeIsolate();
276 // Optimize for memory usage instead of latency for the worker isolate. 273 // Optimize for memory usage instead of latency for the worker isolate.
277 m_isolate->IsolateInBackgroundNotification(); 274 isolate()->IsolateInBackgroundNotification();
278 m_workerGlobalScope = createWorkerGlobalScope(startupData); 275 m_workerGlobalScope = createWorkerGlobalScope(startupData);
279 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0); 276 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0);
280 277
281 didStartWorkerThread();
282
283 // Notify proxy that a new WorkerGlobalScope has been created and starte d. 278 // Notify proxy that a new WorkerGlobalScope has been created and starte d.
284 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get( )); 279 m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get( ));
285 280
286 WorkerOrWorkletScriptController* scriptController = m_workerGlobalScope- >scriptController(); 281 WorkerOrWorkletScriptController* scriptController = m_workerGlobalScope- >scriptController();
287 if (!scriptController->isExecutionForbidden()) 282 if (!scriptController->isExecutionForbidden())
288 scriptController->initializeContextIfNeeded(); 283 scriptController->initializeContextIfNeeded();
289 } 284 }
290 m_workerGlobalScope->workerInspectorController()->workerContextInitialized(s tartMode == PauseWorkerGlobalScopeOnStart); 285 m_workerGlobalScope->workerInspectorController()->workerContextInitialized(s tartMode == PauseWorkerGlobalScopeOnStart);
291 286
292 if (m_workerGlobalScope->scriptController()->isContextInitialized()) { 287 if (m_workerGlobalScope->scriptController()->isContextInitialized()) {
(...skipping 16 matching lines...) Expand all
309 if (m_shutdown) 304 if (m_shutdown)
310 return; 305 return;
311 m_shutdown = true; 306 m_shutdown = true;
312 } 307 }
313 308
314 // This should be called before we start the shutdown procedure. 309 // This should be called before we start the shutdown procedure.
315 workerReportingProxy().willDestroyWorkerGlobalScope(); 310 workerReportingProxy().willDestroyWorkerGlobalScope();
316 311
317 workerGlobalScope()->dispose(); 312 workerGlobalScope()->dispose();
318 313
319 // This should be called after the WorkerGlobalScope's disposed (which may
320 // trigger some last-minutes cleanups) and before the thread actually stops.
321 willStopWorkerThread();
322
323 backingThread().removeTaskObserver(m_microtaskRunner.get()); 314 backingThread().removeTaskObserver(m_microtaskRunner.get());
324 postTask(BLINK_FROM_HERE, createSameThreadTask(&WorkerThread::performShutdow nTask, this)); 315 postTask(BLINK_FROM_HERE, createSameThreadTask(&WorkerThread::performShutdow nTask, this));
325 } 316 }
326 317
327 void WorkerThread::performShutdownTask() 318 void WorkerThread::performShutdownTask()
328 { 319 {
329 // The below assignment will destroy the context, which will in turn notify messaging proxy. 320 // The below assignment will destroy the context, which will in turn notify messaging proxy.
330 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. 321 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them.
331 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out. 322 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out.
332 #if !ENABLE(OILPAN) 323 #if !ENABLE(OILPAN)
333 ASSERT(m_workerGlobalScope->hasOneRef()); 324 ASSERT(m_workerGlobalScope->hasOneRef());
334 #endif 325 #endif
335 m_workerGlobalScope->notifyContextDestroyed(); 326 m_workerGlobalScope->notifyContextDestroyed();
336 m_workerGlobalScope = nullptr; 327 m_workerGlobalScope = nullptr;
337 328
338 willDestroyIsolate(); 329 m_workerBackingThread->detach();
339 shutdownBackingThread(); 330 m_workerBackingThread = nullptr;
340 destroyIsolate();
341 m_isolate = nullptr;
342
343 m_microtaskRunner = nullptr; 331 m_microtaskRunner = nullptr;
344 332
345 // Notify the proxy that the WorkerGlobalScope has been disposed of. 333 // Notify the proxy that the WorkerGlobalScope has been disposed of.
346 // This can free this thread object, hence it must not be touched afterwards . 334 // This can free this thread object, hence it must not be touched afterwards .
347 workerReportingProxy().workerThreadTerminated(); 335 workerReportingProxy().workerThreadTerminated();
348 336
349 m_terminationEvent->signal(); 337 m_terminationEvent->signal();
350 } 338 }
351 339
352 void WorkerThread::terminate() 340 void WorkerThread::terminate()
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 return; 383 return;
396 384
397 // If the worker thread was never initialized, don't start another 385 // If the worker thread was never initialized, don't start another
398 // shutdown, but still wait for the thread to signal when termination has 386 // shutdown, but still wait for the thread to signal when termination has
399 // completed. 387 // completed.
400 if (!m_workerGlobalScope) 388 if (!m_workerGlobalScope)
401 return; 389 return;
402 390
403 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r. 391 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r.
404 m_workerGlobalScope->scriptController()->willScheduleExecutionTermination(); 392 m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
405 terminateV8Execution(); 393
394 if (1 == m_workerBackingThread->workerScriptCount()) {
395 // This condition is not entirely correct because other scripts
396 // can be being initialized or terminated simuletaneously. Though this
397 // function itself is protected by a mutex, it is possible that
398 // |workerScriptCount()| here is not consistent with that in
399 // |initialize| and |shutdown|.
400 isolate()->TerminateExecution();
401 }
kinuko 2016/02/29 09:32:53 The comment just leaves readers unsure if this cod
yhirano 2016/02/29 23:47:32 Imagine there are two WorkerThread x and y attache
yhirano 2016/03/01 00:04:52 Correction: before x->shutdown() on the worker th
406 402
407 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScop e.get()); 403 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScop e.get());
408 m_debuggerTaskQueue->kill(); 404 m_debuggerTaskQueue->kill();
409 backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::shut down, AllowCrossThreadAccess(this))); 405 backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::shut down, AllowCrossThreadAccess(this)));
410 } 406 }
411 407
412 void WorkerThread::didStartWorkerThread() 408 WorkerBackingThread& WorkerThread::workerBackingThread()
413 { 409 {
414 ASSERT(isCurrentThread()); 410 ASSERT(m_workerBackingThread);
415 Platform::current()->didStartWorkerThread(); 411 return *m_workerBackingThread;
416 } 412 }
417 413
418 void WorkerThread::willStopWorkerThread() 414 WebThreadSupportingGC& WorkerThread::backingThread()
419 { 415 {
420 ASSERT(isCurrentThread()); 416 ASSERT(m_workerBackingThread);
421 Platform::current()->willStopWorkerThread(); 417 return m_workerBackingThread->backingThread();
418 }
419
420 v8::Isolate* WorkerThread::isolate() const
421 {
422 return m_workerBackingThread->isolate();
422 } 423 }
423 424
424 void WorkerThread::terminateAndWaitForAllWorkers() 425 void WorkerThread::terminateAndWaitForAllWorkers()
425 { 426 {
426 // Keep this lock to prevent WorkerThread instances from being destroyed. 427 // Keep this lock to prevent WorkerThread instances from being destroyed.
427 MutexLocker lock(threadSetMutex()); 428 MutexLocker lock(threadSetMutex());
428 HashSet<WorkerThread*> threads = workerThreads(); 429 HashSet<WorkerThread*> threads = workerThreads();
429 for (WorkerThread* thread : threads) 430 for (WorkerThread* thread : threads)
430 thread->terminateInternal(); 431 thread->terminateInternal();
431 432
432 for (WorkerThread* thread : threads) 433 for (WorkerThread* thread : threads)
433 thread->m_terminationEvent->wait(); 434 thread->m_terminationEvent->wait();
434 } 435 }
435 436
436 bool WorkerThread::isCurrentThread() 437 bool WorkerThread::isCurrentThread()
437 { 438 {
438 return m_started && backingThread().isCurrentThread(); 439 return m_started && backingThread().isCurrentThread();
439 } 440 }
440 441
441 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task) 442 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi onContextTask> task)
442 { 443 {
443 backingThread().postTask(location, createWorkerThreadTask(task, true)); 444 backingThread().postTask(location, createWorkerThreadTask(task, true));
444 } 445 }
445 446
446 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs) 447 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr< ExecutionContextTask> task, long long delayMs)
447 { 448 {
448 backingThread().postDelayedTask(location, createWorkerThreadTask(task, true) , delayMs); 449 backingThread().postDelayedTask(location, createWorkerThreadTask(task, true) , delayMs);
449 } 450 }
450 451
451 void WorkerThread::initializeBackingThread()
452 {
453 ASSERT(isCurrentThread());
454 backingThread().initialize();
455 }
456
457 void WorkerThread::shutdownBackingThread()
458 {
459 ASSERT(isCurrentThread());
460 backingThread().shutdown();
461 }
462
463 v8::Isolate* WorkerThread::initializeIsolate()
464 {
465 ASSERT(isCurrentThread());
466 ASSERT(!m_isolate);
467 v8::Isolate* isolate = V8PerIsolateData::initialize();
468 V8Initializer::initializeWorker(isolate);
469
470 OwnPtr<V8IsolateInterruptor> interruptor = adoptPtr(new V8IsolateInterruptor (isolate));
471 ThreadState::current()->addInterruptor(interruptor.release());
472 ThreadState::current()->registerTraceDOMWrappers(isolate, V8GCController::tr aceDOMWrappers);
473 if (RuntimeEnabledFeatures::v8IdleTasksEnabled())
474 V8PerIsolateData::enableIdleTasks(isolate, adoptPtr(new V8IdleTaskRunner (m_webScheduler)));
475 return isolate;
476 }
477
478 void WorkerThread::willDestroyIsolate()
479 {
480 ASSERT(isCurrentThread());
481 ASSERT(m_isolate);
482 V8PerIsolateData::willBeDestroyed(m_isolate);
483 }
484
485 void WorkerThread::destroyIsolate()
486 {
487 ASSERT(isCurrentThread());
488 V8PerIsolateData::destroy(m_isolate);
489 }
490
491 void WorkerThread::terminateV8Execution()
492 {
493 ASSERT(isMainThread());
494 m_isolate->TerminateExecution();
495 }
496
497 void WorkerThread::appendDebuggerTask(PassOwnPtr<Closure> task) 452 void WorkerThread::appendDebuggerTask(PassOwnPtr<Closure> task)
498 { 453 {
499 { 454 {
500 MutexLocker lock(m_threadStateMutex); 455 MutexLocker lock(m_threadStateMutex);
501 if (m_shutdown) 456 if (m_shutdown)
502 return; 457 return;
503 } 458 }
504 m_debuggerTaskQueue->append(task); 459 m_debuggerTaskQueue->append(task);
505 } 460 }
506 461
(...skipping 29 matching lines...) Expand all
536 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); 491 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
537 } 492 }
538 493
539 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) 494 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController)
540 { 495 {
541 MutexLocker locker(m_workerInspectorControllerMutex); 496 MutexLocker locker(m_workerInspectorControllerMutex);
542 m_workerInspectorController = workerInspectorController; 497 m_workerInspectorController = workerInspectorController;
543 } 498 }
544 499
545 } // namespace blink 500 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698