void ThreadGlobalData::setWebCoreThreadData() { ASSERT(isWebThread()); ASSERT(&threadGlobalData() != ThreadGlobalData::sharedMainThreadStaticData); // Set WebThread's ThreadGlobalData object to be the same as the main UI thread. ThreadGlobalData::staticData->replace(ThreadGlobalData::sharedMainThreadStaticData); ASSERT(&threadGlobalData() == ThreadGlobalData::sharedMainThreadStaticData); }
RunLoopSetup(WorkerRunLoop& runLoop) : m_runLoop(runLoop) { if (!m_runLoop.m_nestedCount) threadGlobalData().threadTimers().setSharedTimer(m_runLoop.m_sharedTimer.get()); m_runLoop.m_nestedCount++; }
~RunLoopSetup() { m_runLoop.m_nestedCount--; if (!m_runLoop.m_nestedCount) threadGlobalData().threadTimers().setSharedTimer(0); InspectorInstrumentation::didLeaveNestedRunLoop(m_context); }
void TimerBase::setNextFireTime(double newTime) { ASSERT(m_thread == currentThread()); // Keep heap valid while changing the next-fire time. double oldTime = m_nextFireTime; if (oldTime != newTime) { m_nextFireTime = newTime; static unsigned currentHeapInsertionOrder; m_heapInsertionOrder = currentHeapInsertionOrder++; bool wasFirstTimerInHeap = m_heapIndex == 0; if (oldTime == 0) heapInsert(); else if (newTime == 0) heapDelete(); else if (newTime < oldTime) heapDecreaseKey(); else heapIncreaseKey(); bool isFirstTimerInHeap = m_heapIndex == 0; if (wasFirstTimerInHeap || isFirstTimerInHeap) threadGlobalData().threadTimers().updateSharedTimer(); } checkConsistency(); }
RunLoopSetup(WorkerRunLoop& runLoop, WorkerGlobalScope* context) : m_runLoop(runLoop) , m_context(context) { if (!m_runLoop.m_nestedCount) threadGlobalData().threadTimers().setSharedTimer(m_runLoop.m_sharedTimer.get()); m_runLoop.m_nestedCount++; InspectorInstrumentation::willEnterNestedRunLoop(m_context); }
void ThreadTimers::sharedTimerFired() { TRACE_EVENT_SAMPLING_STATE0("WebKit\0WebKitInternal"); // Redirect to non-static method. threadGlobalData().threadTimers().sharedTimerFiredInternal(); TRACE_EVENT_SAMPLING_STATE0("WebKit\0WebKitSleeping"); }
void WorkerThread::workerThread() { // Propagate the mainThread's fenv to workers. #if PLATFORM(IOS) FloatingPointEnvironment::singleton().propagateMainThreadEnvironment(); #endif #if PLATFORM(GTK) GRefPtr<GMainContext> mainContext = adoptGRef(g_main_context_new()); g_main_context_push_thread_default(mainContext.get()); #endif { LockHolder lock(m_threadCreationMutex); m_workerGlobalScope = createWorkerGlobalScope(m_startupData->m_scriptURL, m_startupData->m_userAgent, m_startupData->m_contentSecurityPolicyResponseHeaders, m_startupData->m_shouldBypassMainWorldContentSecurityPolicy, WTFMove(m_startupData->m_topOrigin)); if (m_runLoop.terminated()) { // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, // forbidExecution() couldn't be called from stop(). m_workerGlobalScope->script()->forbidExecution(); } } WorkerScriptController* script = m_workerGlobalScope->script(); script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL)); // Free the startup data to cause its member variable deref's happen on the worker's thread (since // all ref/derefs of these objects are happening on the thread at this point). Note that // WorkerThread::~WorkerThread happens on a different thread where it was created. m_startupData = nullptr; runEventLoop(); #if PLATFORM(GTK) g_main_context_pop_thread_default(mainContext.get()); #endif ThreadIdentifier threadID = m_threadID; ASSERT(m_workerGlobalScope->hasOneRef()); // The below assignment will destroy the context, which will in turn notify messaging proxy. // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. m_workerGlobalScope = nullptr; // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! threadGlobalData().destroy(); // The thread object may be already destroyed from notification now, don't try to access "this". detachThread(threadID); }
// A worker thread may initialize SharedTimer after some timers are created. // Also, SharedTimer can be replaced with nullptr before all timers are destroyed. void ThreadTimers::setSharedTimer(SharedTimer* sharedTimer) { if (m_sharedTimer) { m_sharedTimer->setFiredFunction(nullptr); m_sharedTimer->stop(); m_pendingSharedTimerFireTime = 0; } m_sharedTimer = sharedTimer; if (sharedTimer) { m_sharedTimer->setFiredFunction([] { threadGlobalData().threadTimers().sharedTimerFiredInternal(); }); updateSharedTimer(); } }
void WorkerThread::workerThread() { // Propagate the mainThread's fenv to workers. #if PLATFORM(IOS) fesetenv(&mainThreadFEnv); #endif { MutexLocker lock(m_threadCreationMutex); m_workerGlobalScope = createWorkerGlobalScope(m_startupData->m_scriptURL, m_startupData->m_userAgent, std::move(m_startupData->m_groupSettings), m_startupData->m_contentSecurityPolicy, m_startupData->m_contentSecurityPolicyType, m_startupData->m_topOrigin.release()); if (m_runLoop.terminated()) { // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, // forbidExecution() couldn't be called from stop(). m_workerGlobalScope->script()->forbidExecution(); } } WorkerScriptController* script = m_workerGlobalScope->script(); #if ENABLE(INSPECTOR) InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), m_startupData->m_startMode); #endif script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL)); // Free the startup data to cause its member variable deref's happen on the worker's thread (since // all ref/derefs of these objects are happening on the thread at this point). Note that // WorkerThread::~WorkerThread happens on a different thread where it was created. m_startupData.clear(); runEventLoop(); ThreadIdentifier threadID = m_threadID; ASSERT(m_workerGlobalScope->hasOneRef()); // The below assignment will destroy the context, which will in turn notify messaging proxy. // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. m_workerGlobalScope = 0; // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! threadGlobalData().destroy(); // The thread object may be already destroyed from notification now, don't try to access "this". detachThread(threadID); }
void* WorkerThread::workerThread() { { MutexLocker lock(m_threadCreationMutex); #if OS(OLYMPIA) m_workerContext = createWorkerContext(m_startupData->m_scriptURL, m_startupData->m_groupName, m_startupData->m_userAgent); Olympia::Platform::didStartWorker(); #else m_workerContext = createWorkerContext(m_startupData->m_scriptURL, m_startupData->m_userAgent); #endif if (m_runLoop.terminated()) { // The worker was terminated before the thread had a chance to run. Since the context didn't exist yet, // forbidExecution() couldn't be called from stop(). m_workerContext->script()->forbidExecution(WorkerScriptController::TerminateRunningScript); } } WorkerScriptController* script = m_workerContext->script(); script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL)); // Free the startup data to cause its member variable deref's happen on the worker's thread (since // all ref/derefs of these objects are happening on the thread at this point). Note that // WorkerThread::~WorkerThread happens on a different thread where it was created. m_startupData.clear(); runEventLoop(); ThreadIdentifier threadID = m_threadID; ASSERT(m_workerContext->hasOneRef()); // The below assignment will destroy the context, which will in turn notify messaging proxy. // We cannot let any objects survive past thread exit, because no other thread will run GC or otherwise destroy them. m_workerContext = 0; // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! threadGlobalData().destroy(); // The thread object may be already destroyed from notification now, don't try to access "this". detachThread(threadID); return 0; }
void TimerBase::setNextFireTime(double newTime) { ASSERT(canAccessThreadLocalDataForThread(m_thread)); ASSERT(!m_wasDeleted); if (m_unalignedNextFireTime != newTime) m_unalignedNextFireTime = newTime; // Accessing thread global data is slow. Cache the heap pointer. if (!m_cachedThreadGlobalTimerHeap) m_cachedThreadGlobalTimerHeap = &threadGlobalTimerHeap(); // Keep heap valid while changing the next-fire time. double oldTime = m_nextFireTime; // Don't realign zero-delay timers. if (newTime) { if (auto newAlignedTime = alignedFireTime(secondsToMS(newTime))) newTime = msToSeconds(newAlignedTime.value()); } if (oldTime != newTime) { m_nextFireTime = newTime; // FIXME: This should be part of ThreadTimers, or another per-thread structure. static std::atomic<unsigned> currentHeapInsertionOrder; m_heapInsertionOrder = currentHeapInsertionOrder++; bool wasFirstTimerInHeap = m_heapIndex == 0; updateHeapIfNeeded(oldTime); bool isFirstTimerInHeap = m_heapIndex == 0; if (wasFirstTimerInHeap || isFirstTimerInHeap) threadGlobalData().threadTimers().updateSharedTimer(); } checkConsistency(); }
static TECConverterWrapper& cachedConverterTEC() { return threadGlobalData().cachedConverterTEC(); }
void ThreadTimers::sharedTimerFired() { // Redirect to non-static method. threadGlobalData().threadTimers().sharedTimerFiredInternal(); }
~RunLoopSetup() { m_runLoop.m_nestedCount--; if (!m_runLoop.m_nestedCount) threadGlobalData().threadTimers().setSharedTimer(0); }
bool DOMImplementation::isXMLMIMEType(const String& mimeType) { if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl") return true; return threadGlobalData().xmlTypeRegExp().isXMLMIMEType(mimeType); }
StringImpl* StringImpl::empty() { return threadGlobalData().emptyString(); }
ThreadLocalInspectorCounters& ThreadLocalInspectorCounters::current() { return threadGlobalData().inspectorCounters(); }
void TimerBase::fireTimersInNestedEventLoop() { // Redirect to ThreadTimers. threadGlobalData().threadTimers().fireTimersInNestedEventLoop(); }
// Simple accessors to thread-specific data. static Vector<TimerBase*>& timerHeap() { return threadGlobalData().threadTimers().timerHeap(); }