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 14 matching lines...) Expand all Loading... |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 | 28 |
29 #include "core/workers/WorkerThread.h" | 29 #include "core/workers/WorkerThread.h" |
30 | 30 |
31 #include "bindings/v8/ScriptSourceCode.h" | 31 #include "bindings/v8/ScriptSourceCode.h" |
32 #include "bindings/v8/ScriptValue.h" | 32 #include "bindings/v8/ScriptValue.h" |
33 #include "core/inspector/InspectorInstrumentation.h" | 33 #include "core/inspector/InspectorInstrumentation.h" |
34 #include "core/platform/ThreadGlobalData.h" | 34 #include "core/platform/ThreadGlobalData.h" |
35 #include "core/workers/DedicatedWorkerContext.h" | 35 #include "core/workers/DedicatedWorkerGlobalScope.h" |
36 #include "modules/webdatabase/DatabaseManager.h" | 36 #include "modules/webdatabase/DatabaseManager.h" |
37 #include "modules/webdatabase/DatabaseTask.h" | 37 #include "modules/webdatabase/DatabaseTask.h" |
38 #include "public/platform/Platform.h" | 38 #include "public/platform/Platform.h" |
39 #include "public/platform/WebWorkerRunLoop.h" | 39 #include "public/platform/WebWorkerRunLoop.h" |
40 #include "weborigin/KURL.h" | 40 #include "weborigin/KURL.h" |
41 #include "wtf/Noncopyable.h" | 41 #include "wtf/Noncopyable.h" |
42 #include "wtf/text/WTFString.h" | 42 #include "wtf/text/WTFString.h" |
43 | 43 |
44 #include <utility> | 44 #include <utility> |
45 | 45 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 | 128 |
129 void WorkerThread::workerThreadStart(void* thread) | 129 void WorkerThread::workerThreadStart(void* thread) |
130 { | 130 { |
131 static_cast<WorkerThread*>(thread)->workerThread(); | 131 static_cast<WorkerThread*>(thread)->workerThread(); |
132 } | 132 } |
133 | 133 |
134 void WorkerThread::workerThread() | 134 void WorkerThread::workerThread() |
135 { | 135 { |
136 { | 136 { |
137 MutexLocker lock(m_threadCreationMutex); | 137 MutexLocker lock(m_threadCreationMutex); |
138 m_workerContext = createWorkerContext(m_startupData->m_scriptURL, m_star
tupData->m_userAgent, m_startupData->m_contentSecurityPolicy, m_startupData->m_c
ontentSecurityPolicyType, m_startupData->m_topOrigin.release()); | 138 m_workerGlobalScope = createWorkerGlobalScope(m_startupData->m_scriptURL
, m_startupData->m_userAgent, m_startupData->m_contentSecurityPolicy, m_startupD
ata->m_contentSecurityPolicyType, m_startupData->m_topOrigin.release()); |
139 | 139 |
140 if (m_runLoop.terminated()) { | 140 if (m_runLoop.terminated()) { |
141 // The worker was terminated before the thread had a chance to run.
Since the context didn't exist yet, | 141 // The worker was terminated before the thread had a chance to run.
Since the context didn't exist yet, |
142 // forbidExecution() couldn't be called from stop(). | 142 // forbidExecution() couldn't be called from stop(). |
143 m_workerContext->script()->forbidExecution(); | 143 m_workerGlobalScope->script()->forbidExecution(); |
144 } | 144 } |
145 } | 145 } |
146 // The corresponding call to didStopWorkerRunLoop is in | 146 // The corresponding call to didStopWorkerRunLoop is in |
147 // ~WorkerScriptController. | 147 // ~WorkerScriptController. |
148 WebKit::Platform::current()->didStartWorkerRunLoop(WebKit::WebWorkerRunLoop(
&m_runLoop)); | 148 WebKit::Platform::current()->didStartWorkerRunLoop(WebKit::WebWorkerRunLoop(
&m_runLoop)); |
149 | 149 |
150 WorkerScriptController* script = m_workerContext->script(); | 150 WorkerScriptController* script = m_workerGlobalScope->script(); |
151 InspectorInstrumentation::willEvaluateWorkerScript(workerContext(), m_startu
pData->m_startMode); | 151 InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), m_st
artupData->m_startMode); |
152 script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData
->m_scriptURL)); | 152 script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData
->m_scriptURL)); |
153 // Free the startup data to cause its member variable deref's happen on the
worker's thread (since | 153 // Free the startup data to cause its member variable deref's happen on the
worker's thread (since |
154 // all ref/derefs of these objects are happening on the thread at this point
). Note that | 154 // all ref/derefs of these objects are happening on the thread at this point
). Note that |
155 // WorkerThread::~WorkerThread happens on a different thread where it was cr
eated. | 155 // WorkerThread::~WorkerThread happens on a different thread where it was cr
eated. |
156 m_startupData.clear(); | 156 m_startupData.clear(); |
157 | 157 |
158 runEventLoop(); | 158 runEventLoop(); |
159 | 159 |
160 ThreadIdentifier threadID = m_threadID; | 160 ThreadIdentifier threadID = m_threadID; |
161 | 161 |
162 ASSERT(m_workerContext->hasOneRef()); | 162 ASSERT(m_workerGlobalScope->hasOneRef()); |
163 | 163 |
164 // The below assignment will destroy the context, which will in turn notify
messaging proxy. | 164 // The below assignment will destroy the context, which will in turn notify
messaging proxy. |
165 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. | 165 // We cannot let any objects survive past thread exit, because no other thre
ad will run GC or otherwise destroy them. |
166 m_workerContext = 0; | 166 m_workerGlobalScope = 0; |
167 | 167 |
168 // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! | 168 // Clean up WebCore::ThreadGlobalData before WTF::WTFThreadData goes away! |
169 threadGlobalData().destroy(); | 169 threadGlobalData().destroy(); |
170 | 170 |
171 // The thread object may be already destroyed from notification now, don't t
ry to access "this". | 171 // The thread object may be already destroyed from notification now, don't t
ry to access "this". |
172 detachThread(threadID); | 172 detachThread(threadID); |
173 } | 173 } |
174 | 174 |
175 void WorkerThread::runEventLoop() | 175 void WorkerThread::runEventLoop() |
176 { | 176 { |
177 // Does not return until terminated. | 177 // Does not return until terminated. |
178 m_runLoop.run(m_workerContext.get()); | 178 m_runLoop.run(m_workerGlobalScope.get()); |
179 } | 179 } |
180 | 180 |
181 class WorkerThreadShutdownFinishTask : public ScriptExecutionContext::Task { | 181 class WorkerThreadShutdownFinishTask : public ScriptExecutionContext::Task { |
182 public: | 182 public: |
183 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() | 183 static PassOwnPtr<WorkerThreadShutdownFinishTask> create() |
184 { | 184 { |
185 return adoptPtr(new WorkerThreadShutdownFinishTask()); | 185 return adoptPtr(new WorkerThreadShutdownFinishTask()); |
186 } | 186 } |
187 | 187 |
188 virtual void performTask(ScriptExecutionContext *context) | 188 virtual void performTask(ScriptExecutionContext *context) |
189 { | 189 { |
190 ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerContext()); | 190 ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); |
191 WorkerContext* workerContext = static_cast<WorkerContext*>(context); | 191 WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(c
ontext); |
192 workerContext->clearInspector(); | 192 workerGlobalScope->clearInspector(); |
193 // It's not safe to call clearScript until all the cleanup tasks posted
by functions initiated by WorkerThreadShutdownStartTask have completed. | 193 // It's not safe to call clearScript until all the cleanup tasks posted
by functions initiated by WorkerThreadShutdownStartTask have completed. |
194 workerContext->clearScript(); | 194 workerGlobalScope->clearScript(); |
195 } | 195 } |
196 | 196 |
197 virtual bool isCleanupTask() const { return true; } | 197 virtual bool isCleanupTask() const { return true; } |
198 }; | 198 }; |
199 | 199 |
200 class WorkerThreadShutdownStartTask : public ScriptExecutionContext::Task { | 200 class WorkerThreadShutdownStartTask : public ScriptExecutionContext::Task { |
201 public: | 201 public: |
202 static PassOwnPtr<WorkerThreadShutdownStartTask> create() | 202 static PassOwnPtr<WorkerThreadShutdownStartTask> create() |
203 { | 203 { |
204 return adoptPtr(new WorkerThreadShutdownStartTask()); | 204 return adoptPtr(new WorkerThreadShutdownStartTask()); |
205 } | 205 } |
206 | 206 |
207 virtual void performTask(ScriptExecutionContext *context) | 207 virtual void performTask(ScriptExecutionContext *context) |
208 { | 208 { |
209 ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerContext()); | 209 ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope()); |
210 WorkerContext* workerContext = static_cast<WorkerContext*>(context); | 210 WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(c
ontext); |
211 | 211 |
212 // FIXME: Should we stop the databases as part of stopActiveDOMObjects()
below? | 212 // FIXME: Should we stop the databases as part of stopActiveDOMObjects()
below? |
213 DatabaseTaskSynchronizer cleanupSync; | 213 DatabaseTaskSynchronizer cleanupSync; |
214 DatabaseManager::manager().stopDatabases(workerContext, &cleanupSync); | 214 DatabaseManager::manager().stopDatabases(workerGlobalScope, &cleanupSync
); |
215 | 215 |
216 workerContext->stopActiveDOMObjects(); | 216 workerGlobalScope->stopActiveDOMObjects(); |
217 | 217 |
218 workerContext->notifyObserversOfStop(); | 218 workerGlobalScope->notifyObserversOfStop(); |
219 | 219 |
220 // Event listeners would keep DOMWrapperWorld objects alive for too long
. Also, they have references to JS objects, | 220 // Event listeners would keep DOMWrapperWorld objects alive for too long
. Also, they have references to JS objects, |
221 // which become dangling once Heap is destroyed. | 221 // which become dangling once Heap is destroyed. |
222 workerContext->removeAllEventListeners(); | 222 workerGlobalScope->removeAllEventListeners(); |
223 | 223 |
224 // We wait for the database thread to clean up all its stuff so that we | 224 // We wait for the database thread to clean up all its stuff so that we |
225 // can do more stringent leak checks as we exit. | 225 // can do more stringent leak checks as we exit. |
226 cleanupSync.waitForTaskCompletion(); | 226 cleanupSync.waitForTaskCompletion(); |
227 | 227 |
228 // Stick a shutdown command at the end of the queue, so that we deal | 228 // Stick a shutdown command at the end of the queue, so that we deal |
229 // with all the cleanup tasks the databases post first. | 229 // with all the cleanup tasks the databases post first. |
230 workerContext->postTask(WorkerThreadShutdownFinishTask::create()); | 230 workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create()); |
231 } | 231 } |
232 | 232 |
233 virtual bool isCleanupTask() const { return true; } | 233 virtual bool isCleanupTask() const { return true; } |
234 }; | 234 }; |
235 | 235 |
236 void WorkerThread::stop() | 236 void WorkerThread::stop() |
237 { | 237 { |
238 // Mutex protection is necessary because stop() can be called before the con
text is fully created. | 238 // Mutex protection is necessary because stop() can be called before the con
text is fully created. |
239 MutexLocker lock(m_threadCreationMutex); | 239 MutexLocker lock(m_threadCreationMutex); |
240 | 240 |
241 // 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. | 241 // 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. |
242 if (m_workerContext) { | 242 if (m_workerGlobalScope) { |
243 m_workerContext->script()->scheduleExecutionTermination(); | 243 m_workerGlobalScope->script()->scheduleExecutionTermination(); |
244 | 244 |
245 DatabaseManager::manager().interruptAllDatabasesForContext(m_workerConte
xt.get()); | 245 DatabaseManager::manager().interruptAllDatabasesForContext(m_workerGloba
lScope.get()); |
246 m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create()); | 246 m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create()); |
247 return; | 247 return; |
248 } | 248 } |
249 m_runLoop.terminate(); | 249 m_runLoop.terminate(); |
250 } | 250 } |
251 | 251 |
252 bool WorkerThread::isCurrentThread() const | 252 bool WorkerThread::isCurrentThread() const |
253 { | 253 { |
254 return m_threadID == currentThread(); | 254 return m_threadID == currentThread(); |
255 } | 255 } |
256 | 256 |
257 class ReleaseFastMallocFreeMemoryTask : public ScriptExecutionContext::Task { | 257 class ReleaseFastMallocFreeMemoryTask : public ScriptExecutionContext::Task { |
258 virtual void performTask(ScriptExecutionContext*) OVERRIDE { WTF::releaseFas
tMallocFreeMemory(); } | 258 virtual void performTask(ScriptExecutionContext*) OVERRIDE { WTF::releaseFas
tMallocFreeMemory(); } |
259 }; | 259 }; |
260 | 260 |
261 void WorkerThread::releaseFastMallocFreeMemoryInAllThreads() | 261 void WorkerThread::releaseFastMallocFreeMemoryInAllThreads() |
262 { | 262 { |
263 MutexLocker lock(threadSetMutex()); | 263 MutexLocker lock(threadSetMutex()); |
264 HashSet<WorkerThread*>& threads = workerThreads(); | 264 HashSet<WorkerThread*>& threads = workerThreads(); |
265 HashSet<WorkerThread*>::iterator end = threads.end(); | 265 HashSet<WorkerThread*>::iterator end = threads.end(); |
266 for (HashSet<WorkerThread*>::iterator it = threads.begin(); it != end; ++it) | 266 for (HashSet<WorkerThread*>::iterator it = threads.begin(); it != end; ++it) |
267 (*it)->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask))
; | 267 (*it)->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask))
; |
268 } | 268 } |
269 | 269 |
270 } // namespace WebCore | 270 } // namespace WebCore |
OLD | NEW |