OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010 Google, Inc. All Rights Reserved. | 2 * Copyright (C) 2010 Google, 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 12 matching lines...) Expand all Loading... | |
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 #include "config.h" | 26 #include "config.h" |
27 #include "core/dom/ScriptRunner.h" | 27 #include "core/dom/ScriptRunner.h" |
28 | 28 |
29 #include "core/dom/Document.h" | 29 #include "core/dom/Document.h" |
30 #include "core/dom/Element.h" | 30 #include "core/dom/Element.h" |
31 #include "core/dom/ScriptLoader.h" | 31 #include "core/dom/ScriptLoader.h" |
32 #include "platform/heap/Handle.h" | 32 #include "platform/heap/Handle.h" |
33 #include "platform/scheduler/Scheduler.h" | |
34 #include "wtf/Functional.h" | |
33 | 35 |
34 namespace blink { | 36 namespace blink { |
35 | 37 |
36 ScriptRunner::ScriptRunner(Document* document) | 38 ScriptRunner::ScriptRunner(Document* document) |
37 : m_document(document) | 39 : m_document(document) |
38 , m_timer(this, &ScriptRunner::timerFired) | 40 , m_executeScriptsTaskFactory(WTF::bind(&ScriptRunner::executeScripts, this) ) |
39 { | 41 { |
40 ASSERT(document); | 42 ASSERT(document); |
41 } | 43 } |
42 | 44 |
43 ScriptRunner::~ScriptRunner() | 45 ScriptRunner::~ScriptRunner() |
44 { | 46 { |
45 #if !ENABLE(OILPAN) | 47 #if !ENABLE(OILPAN) |
46 // Make sure that ScriptLoaders don't keep their PendingScripts alive. | 48 // Make sure that ScriptLoaders don't keep their PendingScripts alive. |
47 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) | 49 for (ScriptLoader* scriptLoader : m_scriptsToExecuteInOrder) |
48 scriptLoader->detach(); | 50 scriptLoader->detach(); |
(...skipping 21 matching lines...) Expand all Loading... | |
70 | 72 |
71 case IN_ORDER_EXECUTION: | 73 case IN_ORDER_EXECUTION: |
72 m_document->incrementLoadEventDelayCount(); | 74 m_document->incrementLoadEventDelayCount(); |
73 m_scriptsToExecuteInOrder.append(scriptLoader); | 75 m_scriptsToExecuteInOrder.append(scriptLoader); |
74 break; | 76 break; |
75 } | 77 } |
76 } | 78 } |
77 | 79 |
78 void ScriptRunner::suspend() | 80 void ScriptRunner::suspend() |
79 { | 81 { |
80 m_timer.stop(); | 82 m_executeScriptsTaskFactory.cancel(); |
81 } | 83 } |
82 | 84 |
83 void ScriptRunner::resume() | 85 void ScriptRunner::resume() |
84 { | 86 { |
85 if (hasPendingScripts()) | 87 if (hasPendingScripts()) |
86 m_timer.startOneShot(0, FROM_HERE); | 88 postTaskIfOneIsNotAlreadyInFlight(); |
87 } | 89 } |
88 | 90 |
89 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e xecutionType) | 91 void ScriptRunner::notifyScriptReady(ScriptLoader* scriptLoader, ExecutionType e xecutionType) |
90 { | 92 { |
91 switch (executionType) { | 93 switch (executionType) { |
92 case ASYNC_EXECUTION: | 94 case ASYNC_EXECUTION: |
93 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); | 95 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); |
94 m_scriptsToExecuteSoon.append(scriptLoader); | 96 m_scriptsToExecuteSoon.append(scriptLoader); |
95 m_pendingAsyncScripts.remove(scriptLoader); | 97 m_pendingAsyncScripts.remove(scriptLoader); |
96 break; | 98 break; |
97 | 99 |
98 case IN_ORDER_EXECUTION: | 100 case IN_ORDER_EXECUTION: |
99 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); | 101 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); |
100 break; | 102 break; |
101 } | 103 } |
102 m_timer.startOneShot(0, FROM_HERE); | 104 postTaskIfOneIsNotAlreadyInFlight(); |
103 } | 105 } |
104 | 106 |
105 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy pe executionType) | 107 void ScriptRunner::notifyScriptLoadError(ScriptLoader* scriptLoader, ExecutionTy pe executionType) |
106 { | 108 { |
107 switch (executionType) { | 109 switch (executionType) { |
108 case ASYNC_EXECUTION: | 110 case ASYNC_EXECUTION: |
109 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); | 111 ASSERT(m_pendingAsyncScripts.contains(scriptLoader)); |
110 m_pendingAsyncScripts.remove(scriptLoader); | 112 m_pendingAsyncScripts.remove(scriptLoader); |
111 scriptLoader->detach(); | 113 scriptLoader->detach(); |
112 m_document->decrementLoadEventDelayCount(); | 114 m_document->decrementLoadEventDelayCount(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 | 148 |
147 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader* scriptLoader) | 149 void ScriptRunner::movePendingAsyncScript(ScriptRunner* newRunner, ScriptLoader* scriptLoader) |
148 { | 150 { |
149 if (m_pendingAsyncScripts.contains(scriptLoader)) { | 151 if (m_pendingAsyncScripts.contains(scriptLoader)) { |
150 newRunner->addPendingAsyncScript(scriptLoader); | 152 newRunner->addPendingAsyncScript(scriptLoader); |
151 m_pendingAsyncScripts.remove(scriptLoader); | 153 m_pendingAsyncScripts.remove(scriptLoader); |
152 m_document->decrementLoadEventDelayCount(); | 154 m_document->decrementLoadEventDelayCount(); |
153 } | 155 } |
154 } | 156 } |
155 | 157 |
156 void ScriptRunner::timerFired(Timer<ScriptRunner>* timer) | 158 void ScriptRunner::executeScripts() |
157 { | 159 { |
158 ASSERT_UNUSED(timer, timer == &m_timer); | |
159 | |
160 RefPtrWillBeRawPtr<Document> protect(m_document.get()); | 160 RefPtrWillBeRawPtr<Document> protect(m_document.get()); |
161 | 161 |
162 WillBeHeapVector<RawPtrWillBeMember<ScriptLoader> > scriptLoaders; | 162 // New scripts are always appended to m_scriptsToExecuteSoon and m_scriptsTo ExecuteInOrder (never prepended) |
163 scriptLoaders.swap(m_scriptsToExecuteSoon); | 163 // so as long as we keep track of the current totals, we can ensure the orde r of execution if new scripts |
164 | 164 // are added while executing the current ones. |
165 size_t numInOrderScriptsToExecute = 0; | 165 // NOTE a yield followed by a notifyScriptReady(... ASYNC_EXECUTION) will re sult in that script executing |
166 for (; numInOrderScriptsToExecute < m_scriptsToExecuteInOrder.size() && m_sc riptsToExecuteInOrder[numInOrderScriptsToExecute]->isReady(); ++numInOrderScript sToExecute) | 166 // before any pre-existing ScriptsToExecuteInOrder. |
167 scriptLoaders.append(m_scriptsToExecuteInOrder[numInOrderScriptsToExecut e]); | 167 size_t numScriptsToExecuteSoon = m_scriptsToExecuteSoon.size(); |
168 if (numInOrderScriptsToExecute) | 168 size_t numScriptsToExecuteInOrder = m_scriptsToExecuteInOrder.size(); |
169 m_scriptsToExecuteInOrder.remove(0, numInOrderScriptsToExecute); | 169 for (size_t i = 0; i < numScriptsToExecuteSoon; i++) { |
170 | 170 if (shouldYieldForHighPriorityWork()) |
marja
2015/02/20 12:06:52
Another behavioral consideration: when this execut
alex clarke (OOO till 29th)
2015/02/20 13:40:17
The Scheduler shouldn't run a task from the Loadin
| |
171 size_t size = scriptLoaders.size(); | 171 return; |
172 for (size_t i = 0; i < size; ++i) { | 172 ASSERT(!m_scriptsToExecuteSoon.isEmpty()); |
173 scriptLoaders[i]->execute(); | 173 m_scriptsToExecuteSoon.takeFirst()->execute(); |
174 m_document->decrementLoadEventDelayCount(); | 174 m_document->decrementLoadEventDelayCount(); |
175 } | 175 } |
176 | |
177 for (size_t i = 0; i < numScriptsToExecuteInOrder; i++) { | |
178 ASSERT(!m_scriptsToExecuteInOrder.isEmpty()); | |
179 if (!m_scriptsToExecuteInOrder.first()->isReady() || shouldYieldForHighP riorityWork()) | |
180 return; | |
181 m_scriptsToExecuteInOrder.takeFirst()->execute(); | |
182 m_document->decrementLoadEventDelayCount(); | |
183 } | |
184 } | |
185 | |
186 bool ScriptRunner::shouldYieldForHighPriorityWork() | |
marja
2015/02/20 12:06:52
Nit: this function name is confusing, I'd just exp
alex clarke (OOO till 29th)
2015/02/20 13:40:17
Lets go with yieldForHighPriorityWork.
| |
187 { | |
188 if (!Scheduler::shared()->shouldYieldForHighPriorityWork()) | |
189 return false; | |
190 | |
191 postTaskIfOneIsNotAlreadyInFlight(); | |
192 return true; | |
193 } | |
194 | |
195 void ScriptRunner::postTaskIfOneIsNotAlreadyInFlight() | |
196 { | |
197 if (m_executeScriptsTaskFactory.isPending()) | |
198 return; | |
199 | |
200 // FIXME: Rename task() so that it's obvious it cancels any pending task. | |
201 Scheduler::shared()->postLoadingTask(FROM_HERE, m_executeScriptsTaskFactory. task()); | |
176 } | 202 } |
177 | 203 |
178 void ScriptRunner::trace(Visitor* visitor) | 204 void ScriptRunner::trace(Visitor* visitor) |
179 { | 205 { |
180 #if ENABLE(OILPAN) | 206 #if ENABLE(OILPAN) |
181 visitor->trace(m_document); | 207 visitor->trace(m_document); |
182 visitor->trace(m_scriptsToExecuteInOrder); | 208 visitor->trace(m_scriptsToExecuteInOrder); |
183 visitor->trace(m_scriptsToExecuteSoon); | 209 visitor->trace(m_scriptsToExecuteSoon); |
184 visitor->trace(m_pendingAsyncScripts); | 210 visitor->trace(m_pendingAsyncScripts); |
185 #endif | 211 #endif |
186 } | 212 } |
187 | 213 |
188 } | 214 } |
OLD | NEW |