| 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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 ASSERT(context->isWorkerGlobalScope()); | 249 ASSERT(context->isWorkerGlobalScope()); |
| 250 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); | 250 m_thread->runDebuggerTask(WorkerThread::DontWaitForMessage); |
| 251 } | 251 } |
| 252 | 252 |
| 253 private: | 253 private: |
| 254 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } | 254 explicit RunDebuggerQueueTask(WorkerThread* thread) : m_thread(thread) { } |
| 255 | 255 |
| 256 WorkerThread* m_thread; | 256 WorkerThread* m_thread; |
| 257 }; | 257 }; |
| 258 | 258 |
| 259 WorkerThread::WorkerThread(const char* threadName, PassRefPtr<WorkerLoaderProxy>
workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtr<Worke
rThreadStartupData> startupData) | 259 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work
erReportingProxy& workerReportingProxy, PassOwnPtr<WorkerThreadStartupData> star
tupData) |
| 260 : m_threadName(threadName) | 260 : m_started(false) |
| 261 , m_terminated(false) | 261 , m_terminated(false) |
| 262 , m_workerLoaderProxy(workerLoaderProxy) | 262 , m_workerLoaderProxy(workerLoaderProxy) |
| 263 , m_workerReportingProxy(workerReportingProxy) | 263 , m_workerReportingProxy(workerReportingProxy) |
| 264 , m_startupData(startupData) | 264 , m_startupData(startupData) |
| 265 , m_isolate(nullptr) | 265 , m_isolate(nullptr) |
| 266 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 266 , m_shutdownEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
| 267 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) | 267 , m_terminationEvent(adoptPtr(Platform::current()->createWaitableEvent())) |
| 268 { | 268 { |
| 269 MutexLocker lock(threadSetMutex()); | 269 MutexLocker lock(threadSetMutex()); |
| 270 workerThreads().add(this); | 270 workerThreads().add(this); |
| 271 } | 271 } |
| 272 | 272 |
| 273 WorkerThread::~WorkerThread() | 273 WorkerThread::~WorkerThread() |
| 274 { | 274 { |
| 275 MutexLocker lock(threadSetMutex()); | 275 MutexLocker lock(threadSetMutex()); |
| 276 ASSERT(workerThreads().contains(this)); | 276 ASSERT(workerThreads().contains(this)); |
| 277 workerThreads().remove(this); | 277 workerThreads().remove(this); |
| 278 } | 278 } |
| 279 | 279 |
| 280 void WorkerThread::start() | 280 void WorkerThread::start() |
| 281 { | 281 { |
| 282 if (m_thread) | 282 if (m_started) |
| 283 return; | 283 return; |
| 284 | 284 |
| 285 m_thread = createWebThreadSupportingGC(); | 285 m_started = true; |
| 286 m_thread->postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::initial
ize, AllowCrossThreadAccess(this)))); | 286 backingThread().postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::i
nitialize, AllowCrossThreadAccess(this)))); |
| 287 } | 287 } |
| 288 | 288 |
| 289 void WorkerThread::interruptAndDispatchInspectorCommands() | 289 void WorkerThread::interruptAndDispatchInspectorCommands() |
| 290 { | 290 { |
| 291 MutexLocker locker(m_workerInspectorControllerMutex); | 291 MutexLocker locker(m_workerInspectorControllerMutex); |
| 292 if (m_workerInspectorController) | 292 if (m_workerInspectorController) |
| 293 m_workerInspectorController->interruptAndDispatchInspectorCommands(); | 293 m_workerInspectorController->interruptAndDispatchInspectorCommands(); |
| 294 } | 294 } |
| 295 | 295 |
| 296 PlatformThreadId WorkerThread::platformThreadId() const | 296 PlatformThreadId WorkerThread::platformThreadId() |
| 297 { | 297 { |
| 298 if (!m_thread) | 298 if (!m_started) |
| 299 return 0; | 299 return 0; |
| 300 return m_thread->platformThread().threadId(); | 300 return backingThread().platformThread().threadId(); |
| 301 } | 301 } |
| 302 | 302 |
| 303 void WorkerThread::initialize() | 303 void WorkerThread::initialize() |
| 304 { | 304 { |
| 305 KURL scriptURL = m_startupData->m_scriptURL; | 305 KURL scriptURL = m_startupData->m_scriptURL; |
| 306 String sourceCode = m_startupData->m_sourceCode; | 306 String sourceCode = m_startupData->m_sourceCode; |
| 307 WorkerThreadStartMode startMode = m_startupData->m_startMode; | 307 WorkerThreadStartMode startMode = m_startupData->m_startMode; |
| 308 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); | 308 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas
e(); |
| 309 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; | 309 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; |
| 310 | 310 |
| 311 { | 311 { |
| 312 MutexLocker lock(m_threadCreationMutex); | 312 MutexLocker lock(m_threadCreationMutex); |
| 313 | 313 |
| 314 // The worker was terminated before the thread had a chance to run. | 314 // The worker was terminated before the thread had a chance to run. |
| 315 if (m_terminated) { | 315 if (m_terminated) { |
| 316 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 316 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
| 317 // This can free this thread object, hence it must not be touched af
terwards. | 317 // This can free this thread object, hence it must not be touched af
terwards. |
| 318 m_workerReportingProxy.workerThreadTerminated(); | 318 m_workerReportingProxy.workerThreadTerminated(); |
| 319 return; | 319 return; |
| 320 } | 320 } |
| 321 | 321 |
| 322 m_microtaskRunner = adoptPtr(new MicrotaskRunner(this)); | 322 m_microtaskRunner = adoptPtr(new MicrotaskRunner(this)); |
| 323 m_thread->addTaskObserver(m_microtaskRunner.get()); | 323 backingThread().addTaskObserver(m_microtaskRunner.get()); |
| 324 m_thread->attachGC(); | 324 backingThread().attachGC(); |
| 325 | 325 |
| 326 m_isolate = initializeIsolate(); | 326 m_isolate = initializeIsolate(); |
| 327 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); | 327 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); |
| 328 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); | 328 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge
t() ? cachedMetaData->size() : 0); |
| 329 | 329 |
| 330 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); | 330 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new
WorkerSharedTimer(this))); |
| 331 } | 331 } |
| 332 | 332 |
| 333 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). | 333 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). |
| 334 didStartRunLoop(); | 334 didStartRunLoop(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 345 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); | 345 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip
tCachedMetadataHandler(scriptURL, cachedMetaData.get())); |
| 346 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); | 346 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul
lptr, handler.get(), v8CacheOptions); |
| 347 m_workerGlobalScope->didEvaluateWorkerScript(); | 347 m_workerGlobalScope->didEvaluateWorkerScript(); |
| 348 m_workerReportingProxy.didEvaluateWorkerScript(success); | 348 m_workerReportingProxy.didEvaluateWorkerScript(success); |
| 349 | 349 |
| 350 postInitialize(); | 350 postInitialize(); |
| 351 | 351 |
| 352 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), kShortIdleHandlerDelayMs); | 352 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), kShortIdleHandlerDelayMs); |
| 353 } | 353 } |
| 354 | 354 |
| 355 PassOwnPtr<WebThreadSupportingGC> WorkerThread::createWebThreadSupportingGC() | |
| 356 { | |
| 357 return WebThreadSupportingGC::create(m_threadName); | |
| 358 } | |
| 359 | |
| 360 void WorkerThread::cleanup() | 355 void WorkerThread::cleanup() |
| 361 { | 356 { |
| 362 // This should be called before we start the shutdown procedure. | 357 // This should be called before we start the shutdown procedure. |
| 363 workerReportingProxy().willDestroyWorkerGlobalScope(); | 358 workerReportingProxy().willDestroyWorkerGlobalScope(); |
| 364 | 359 |
| 365 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 360 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
| 366 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 361 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
| 367 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. | 362 // If Oilpan is enabled, we detach of the context/global scope, with the fin
al heap cleanup below sweeping it out. |
| 368 #if !ENABLE(OILPAN) | 363 #if !ENABLE(OILPAN) |
| 369 ASSERT(m_workerGlobalScope->hasOneRef()); | 364 ASSERT(m_workerGlobalScope->hasOneRef()); |
| 370 #endif | 365 #endif |
| 371 m_workerGlobalScope->notifyContextDestroyed(); | 366 m_workerGlobalScope->notifyContextDestroyed(); |
| 372 m_workerGlobalScope = nullptr; | 367 m_workerGlobalScope = nullptr; |
| 373 | 368 |
| 374 m_thread->detachGC(); | 369 backingThread().detachGC(); |
| 375 destroyIsolate(); | 370 destroyIsolate(); |
| 376 | 371 |
| 377 m_thread->removeTaskObserver(m_microtaskRunner.get()); | 372 backingThread().removeTaskObserver(m_microtaskRunner.get()); |
| 378 m_microtaskRunner = nullptr; | 373 m_microtaskRunner = nullptr; |
| 379 | 374 |
| 380 // Notify the proxy that the WorkerGlobalScope has been disposed of. | 375 // Notify the proxy that the WorkerGlobalScope has been disposed of. |
| 381 // This can free this thread object, hence it must not be touched afterwards
. | 376 // This can free this thread object, hence it must not be touched afterwards
. |
| 382 workerReportingProxy().workerThreadTerminated(); | 377 workerReportingProxy().workerThreadTerminated(); |
| 383 | 378 |
| 384 m_terminationEvent->signal(); | 379 m_terminationEvent->signal(); |
| 385 | 380 |
| 386 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! | 381 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! |
| 387 PlatformThreadData::current().destroy(); | 382 PlatformThreadData::current().destroy(); |
| 388 } | 383 } |
| 389 | 384 |
| 390 class WorkerThreadShutdownFinishTask : public ExecutionContextTask { | 385 class WorkerThreadShutdownFinishTask : public ExecutionContextTask { |
| 391 public: | 386 public: |
| 392 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() | 387 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() |
| 393 { | 388 { |
| 394 return adoptPtr(new WorkerThreadShutdownFinishTask()); | 389 return adoptPtr(new WorkerThreadShutdownFinishTask()); |
| 395 } | 390 } |
| 396 | 391 |
| 397 virtual void performTask(ExecutionContext *context) | 392 virtual void performTask(ExecutionContext *context) |
| 398 { | 393 { |
| 399 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); | 394 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); |
| 400 workerGlobalScope->dispose(); | 395 workerGlobalScope->dispose(); |
| 401 | 396 |
| 402 WorkerThread* workerThread = workerGlobalScope->thread(); | 397 WorkerThread* workerThread = workerGlobalScope->thread(); |
| 403 workerThread->willDestroyIsolate(); | 398 workerThread->willDestroyIsolate(); |
| 404 workerThread->m_thread->postTask(FROM_HERE, new Task(WTF::bind(&WorkerTh
read::cleanup, workerThread))); | 399 workerThread->backingThread().postTask(FROM_HERE, new Task(WTF::bind(&Wo
rkerThread::cleanup, workerThread))); |
| 405 } | 400 } |
| 406 | 401 |
| 407 virtual bool isCleanupTask() const { return true; } | 402 virtual bool isCleanupTask() const { return true; } |
| 408 }; | 403 }; |
| 409 | 404 |
| 410 class WorkerThreadShutdownStartTask : public ExecutionContextTask { | 405 class WorkerThreadShutdownStartTask : public ExecutionContextTask { |
| 411 public: | 406 public: |
| 412 static PassOwnPtr<WorkerThreadShutdownStartTask> create() | 407 static PassOwnPtr<WorkerThreadShutdownStartTask> create() |
| 413 { | 408 { |
| 414 return adoptPtr(new WorkerThreadShutdownStartTask()); | 409 return adoptPtr(new WorkerThreadShutdownStartTask()); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 // Keep this lock to prevent WorkerThread instances from being destroyed. | 493 // Keep this lock to prevent WorkerThread instances from being destroyed. |
| 499 MutexLocker lock(threadSetMutex()); | 494 MutexLocker lock(threadSetMutex()); |
| 500 HashSet<WorkerThread*> threads = workerThreads(); | 495 HashSet<WorkerThread*> threads = workerThreads(); |
| 501 for (WorkerThread* thread : threads) | 496 for (WorkerThread* thread : threads) |
| 502 thread->stopInShutdownSequence(); | 497 thread->stopInShutdownSequence(); |
| 503 | 498 |
| 504 for (WorkerThread* thread : threads) | 499 for (WorkerThread* thread : threads) |
| 505 thread->terminationEvent()->wait(); | 500 thread->terminationEvent()->wait(); |
| 506 } | 501 } |
| 507 | 502 |
| 508 bool WorkerThread::isCurrentThread() const | 503 bool WorkerThread::isCurrentThread() |
| 509 { | 504 { |
| 510 return m_thread && m_thread->isCurrentThread(); | 505 return m_started && backingThread().isCurrentThread(); |
| 511 } | 506 } |
| 512 | 507 |
| 513 void WorkerThread::idleHandler() | 508 void WorkerThread::idleHandler() |
| 514 { | 509 { |
| 515 ASSERT(m_workerGlobalScope.get()); | 510 ASSERT(m_workerGlobalScope.get()); |
| 516 int64_t delay = kLongIdleHandlerDelayMs; | 511 int64_t delay = kLongIdleHandlerDelayMs; |
| 517 | 512 |
| 518 // Do a script engine idle notification if the next event is distant enough. | 513 // Do a script engine idle notification if the next event is distant enough. |
| 519 const double kMinIdleTimespan = 0.3; | 514 const double kMinIdleTimespan = 0.3; |
| 520 const double nextFireTime = PlatformThreadData::current().threadTimers().nex
tFireTime(); | 515 const double nextFireTime = PlatformThreadData::current().threadTimers().nex
tFireTime(); |
| 521 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan)
{ | 516 if (nextFireTime == 0.0 || nextFireTime > currentTime() + kMinIdleTimespan)
{ |
| 522 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren
t()->monotonicallyIncreasingTime() + 1.0); | 517 bool hasMoreWork = !isolate()->IdleNotificationDeadline(Platform::curren
t()->monotonicallyIncreasingTime() + 1.0); |
| 523 if (hasMoreWork) | 518 if (hasMoreWork) |
| 524 delay = kShortIdleHandlerDelayMs; | 519 delay = kShortIdleHandlerDelayMs; |
| 525 } | 520 } |
| 526 | 521 |
| 527 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), delay); | 522 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler,
this), delay); |
| 528 } | 523 } |
| 529 | 524 |
| 530 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) | 525 void WorkerThread::postTask(const WebTraceLocation& location, PassOwnPtr<Executi
onContextTask> task) |
| 531 { | 526 { |
| 532 m_thread->postTask(location, WorkerThreadTask::create(*this, task, true).lea
kPtr()); | 527 backingThread().postTask(location, WorkerThreadTask::create(*this, task, tru
e).leakPtr()); |
| 533 } | 528 } |
| 534 | 529 |
| 535 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) | 530 void WorkerThread::postDelayedTask(const WebTraceLocation& location, PassOwnPtr<
ExecutionContextTask> task, long long delayMs) |
| 536 { | 531 { |
| 537 m_thread->postDelayedTask(location, WorkerThreadTask::create(*this, task, tr
ue).leakPtr(), delayMs); | 532 backingThread().postDelayedTask(location, WorkerThreadTask::create(*this, ta
sk, true).leakPtr(), delayMs); |
| 538 } | 533 } |
| 539 | 534 |
| 540 v8::Isolate* WorkerThread::initializeIsolate() | 535 v8::Isolate* WorkerThread::initializeIsolate() |
| 541 { | 536 { |
| 542 ASSERT(isCurrentThread()); | 537 ASSERT(isCurrentThread()); |
| 543 ASSERT(!m_isolate); | 538 ASSERT(!m_isolate); |
| 544 v8::Isolate* isolate = V8PerIsolateData::initialize(); | 539 v8::Isolate* isolate = V8PerIsolateData::initialize(); |
| 545 V8Initializer::initializeWorker(isolate); | 540 V8Initializer::initializeWorker(isolate); |
| 546 | 541 |
| 547 m_interruptor = adoptPtr(new V8IsolateInterruptor(isolate)); | 542 m_interruptor = adoptPtr(new V8IsolateInterruptor(isolate)); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); | 606 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); |
| 612 } | 607 } |
| 613 | 608 |
| 614 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) | 609 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke
rInspectorController) |
| 615 { | 610 { |
| 616 MutexLocker locker(m_workerInspectorControllerMutex); | 611 MutexLocker locker(m_workerInspectorControllerMutex); |
| 617 m_workerInspectorController = workerInspectorController; | 612 m_workerInspectorController = workerInspectorController; |
| 618 } | 613 } |
| 619 | 614 |
| 620 } // namespace blink | 615 } // namespace blink |
| OLD | NEW |