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

Side by Side Diff: third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp

Issue 2683653004: Put the BackgroundHTMLParser on oilpan heap (Closed)
Patch Set: Make BackgroundHTMLParser on oilpan heap Created 3 years, 10 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
« no previous file with comments | « third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE 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 INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE 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 #include "core/html/parser/HTMLDocumentParser.h" 26 #include "core/html/parser/HTMLDocumentParser.h"
27 27
28 #include <memory>
28 #include "bindings/core/v8/DocumentWriteEvaluator.h" 29 #include "bindings/core/v8/DocumentWriteEvaluator.h"
29 #include "core/HTMLNames.h" 30 #include "core/HTMLNames.h"
30 #include "core/css/MediaValuesCached.h" 31 #include "core/css/MediaValuesCached.h"
31 #include "core/css/resolver/StyleResolver.h" 32 #include "core/css/resolver/StyleResolver.h"
32 #include "core/dom/DocumentFragment.h" 33 #include "core/dom/DocumentFragment.h"
33 #include "core/dom/Element.h" 34 #include "core/dom/Element.h"
34 #include "core/dom/TaskRunnerHelper.h" 35 #include "core/dom/TaskRunnerHelper.h"
35 #include "core/frame/LocalFrame.h" 36 #include "core/frame/LocalFrame.h"
36 #include "core/frame/Settings.h" 37 #include "core/frame/Settings.h"
37 #include "core/html/HTMLDocument.h" 38 #include "core/html/HTMLDocument.h"
38 #include "core/html/parser/AtomicHTMLToken.h" 39 #include "core/html/parser/AtomicHTMLToken.h"
39 #include "core/html/parser/BackgroundHTMLParser.h" 40 #include "core/html/parser/BackgroundHTMLParser.h"
40 #include "core/html/parser/HTMLParserScheduler.h" 41 #include "core/html/parser/HTMLParserScheduler.h"
41 #include "core/html/parser/HTMLParserScriptRunner.h" 42 #include "core/html/parser/HTMLParserScriptRunner.h"
42 #include "core/html/parser/HTMLResourcePreloader.h" 43 #include "core/html/parser/HTMLResourcePreloader.h"
43 #include "core/html/parser/HTMLTreeBuilder.h" 44 #include "core/html/parser/HTMLTreeBuilder.h"
44 #include "core/inspector/InspectorInstrumentation.h" 45 #include "core/inspector/InspectorInstrumentation.h"
45 #include "core/inspector/InspectorTraceEvents.h" 46 #include "core/inspector/InspectorTraceEvents.h"
46 #include "core/loader/DocumentLoader.h" 47 #include "core/loader/DocumentLoader.h"
47 #include "core/loader/LinkLoader.h" 48 #include "core/loader/LinkLoader.h"
48 #include "core/loader/NavigationScheduler.h" 49 #include "core/loader/NavigationScheduler.h"
49 #include "platform/CrossThreadFunctional.h" 50 #include "platform/CrossThreadFunctional.h"
50 #include "platform/Histogram.h" 51 #include "platform/Histogram.h"
51 #include "platform/SharedBuffer.h" 52 #include "platform/SharedBuffer.h"
52 #include "platform/WebFrameScheduler.h" 53 #include "platform/WebFrameScheduler.h"
53 #include "platform/heap/Handle.h" 54 #include "platform/heap/Handle.h"
55 #include "platform/heap/Persistent.h"
54 #include "platform/instrumentation/tracing/TraceEvent.h" 56 #include "platform/instrumentation/tracing/TraceEvent.h"
55 #include "platform/loader/fetch/ResourceFetcher.h" 57 #include "platform/loader/fetch/ResourceFetcher.h"
56 #include "public/platform/Platform.h" 58 #include "public/platform/Platform.h"
57 #include "public/platform/WebLoadingBehaviorFlag.h" 59 #include "public/platform/WebLoadingBehaviorFlag.h"
58 #include "public/platform/WebScheduler.h" 60 #include "public/platform/WebScheduler.h"
59 #include "public/platform/WebThread.h" 61 #include "public/platform/WebThread.h"
60 #include "wtf/AutoReset.h" 62 #include "wtf/AutoReset.h"
61 #include "wtf/PtrUtil.h" 63 #include "wtf/PtrUtil.h"
62 #include <memory>
63 64
64 namespace blink { 65 namespace blink {
65 66
66 using namespace HTMLNames; 67 using namespace HTMLNames;
67 68
68 // This is a direct transcription of step 4 from: 69 // This is a direct transcription of step 4 from:
69 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case 70 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case
70 static HTMLTokenizer::State tokenizerStateForContextElement( 71 static HTMLTokenizer::State tokenizerStateForContextElement(
71 Element* contextElement, 72 Element* contextElement,
72 bool reportErrors, 73 bool reportErrors,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 ParserSynchronizationPolicy syncPolicy) 125 ParserSynchronizationPolicy syncPolicy)
125 : ScriptableDocumentParser(document, contentPolicy), 126 : ScriptableDocumentParser(document, contentPolicy),
126 m_options(&document), 127 m_options(&document),
127 m_reentryPermit(HTMLParserReentryPermit::create()), 128 m_reentryPermit(HTMLParserReentryPermit::create()),
128 m_token(syncPolicy == ForceSynchronousParsing 129 m_token(syncPolicy == ForceSynchronousParsing
129 ? WTF::wrapUnique(new HTMLToken) 130 ? WTF::wrapUnique(new HTMLToken)
130 : nullptr), 131 : nullptr),
131 m_tokenizer(syncPolicy == ForceSynchronousParsing 132 m_tokenizer(syncPolicy == ForceSynchronousParsing
132 ? HTMLTokenizer::create(m_options) 133 ? HTMLTokenizer::create(m_options)
133 : nullptr), 134 : nullptr),
134 m_loadingTaskRunner(
135 TaskRunnerHelper::get(TaskType::Networking, &document)),
136 m_parserScheduler( 135 m_parserScheduler(
137 syncPolicy == AllowAsynchronousParsing 136 syncPolicy == AllowAsynchronousParsing
138 ? HTMLParserScheduler::create(this, m_loadingTaskRunner.get()) 137 ? HTMLParserScheduler::create(
138 this,
139 TaskRunnerHelper::get(TaskType::Networking, &document))
139 : nullptr), 140 : nullptr),
140 m_xssAuditorDelegate(&document), 141 m_xssAuditorDelegate(&document),
141 m_weakFactory(this),
142 m_preloader(HTMLResourcePreloader::create(document)), 142 m_preloader(HTMLResourcePreloader::create(document)),
143 m_tokenizedChunkQueue(TokenizedChunkQueue::create()), 143 m_tokenizedChunkQueue(TokenizedChunkQueue::create()),
144 m_evaluator(DocumentWriteEvaluator::create(document)), 144 m_evaluator(DocumentWriteEvaluator::create(document)),
145 m_pendingCSPMetaToken(nullptr), 145 m_pendingCSPMetaToken(nullptr),
146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing), 146 m_shouldUseThreading(syncPolicy == AllowAsynchronousParsing),
147 m_endWasDelayed(false), 147 m_endWasDelayed(false),
148 m_haveBackgroundParser(false),
149 m_tasksWereSuspended(false), 148 m_tasksWereSuspended(false),
150 m_pumpSessionNestingLevel(0), 149 m_pumpSessionNestingLevel(0),
151 m_pumpSpeculationsSessionNestingLevel(0), 150 m_pumpSpeculationsSessionNestingLevel(0),
152 m_isParsingAtLineNumber(false), 151 m_isParsingAtLineNumber(false),
153 m_triedLoadingLinkHeaders(false), 152 m_triedLoadingLinkHeaders(false),
154 m_addedPendingStylesheetInBody(false), 153 m_addedPendingStylesheetInBody(false),
155 m_isWaitingForStylesheets(false) { 154 m_isWaitingForStylesheets(false) {
156 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); 155 DCHECK(shouldUseThreading() || (m_token && m_tokenizer));
157 // Threading is not allowed in prefetch mode. 156 // Threading is not allowed in prefetch mode.
158 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading()); 157 DCHECK(!document.isPrefetchOnly() || !shouldUseThreading());
159 } 158 }
160 159
161 HTMLDocumentParser::~HTMLDocumentParser() {} 160 HTMLDocumentParser::~HTMLDocumentParser() {}
162 161
163 void HTMLDocumentParser::dispose() {
164 // In Oilpan, HTMLDocumentParser can die together with Document, and detach()
165 // is not called in this case.
166 if (m_haveBackgroundParser)
167 stopBackgroundParser();
168 }
169
170 DEFINE_TRACE(HTMLDocumentParser) { 162 DEFINE_TRACE(HTMLDocumentParser) {
171 visitor->trace(m_treeBuilder); 163 visitor->trace(m_treeBuilder);
172 visitor->trace(m_parserScheduler); 164 visitor->trace(m_parserScheduler);
173 visitor->trace(m_xssAuditorDelegate); 165 visitor->trace(m_xssAuditorDelegate);
174 visitor->trace(m_scriptRunner); 166 visitor->trace(m_scriptRunner);
167 visitor->trace(m_backgroundParser);
175 visitor->trace(m_preloader); 168 visitor->trace(m_preloader);
176 ScriptableDocumentParser::trace(visitor); 169 ScriptableDocumentParser::trace(visitor);
177 HTMLParserScriptRunnerHost::trace(visitor); 170 HTMLParserScriptRunnerHost::trace(visitor);
178 } 171 }
179 172
180 void HTMLDocumentParser::detach() { 173 void HTMLDocumentParser::detach() {
181 if (!isParsingFragment() && m_tokenizedChunkQueue.get() && 174 if (!isParsingFragment() && m_tokenizedChunkQueue.get() &&
182 m_tokenizedChunkQueue->peakPendingChunkCount()) { 175 m_tokenizedChunkQueue->peakPendingChunkCount()) {
183 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingChunkHistogram, 176 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingChunkHistogram,
184 ("Parser.PeakPendingChunkCount", 1, 1000, 50)); 177 ("Parser.PeakPendingChunkCount", 1, 1000, 50));
185 peakPendingChunkHistogram.count( 178 peakPendingChunkHistogram.count(
186 m_tokenizedChunkQueue->peakPendingChunkCount()); 179 m_tokenizedChunkQueue->peakPendingChunkCount());
187 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingTokenHistogram, 180 DEFINE_STATIC_LOCAL(CustomCountHistogram, peakPendingTokenHistogram,
188 ("Parser.PeakPendingTokenCount", 1, 100000, 50)); 181 ("Parser.PeakPendingTokenCount", 1, 100000, 50));
189 peakPendingTokenHistogram.count( 182 peakPendingTokenHistogram.count(
190 m_tokenizedChunkQueue->peakPendingTokenCount()); 183 m_tokenizedChunkQueue->peakPendingTokenCount());
191 } 184 }
192 185
193 if (m_haveBackgroundParser) 186 m_backgroundParser.clear();
194 stopBackgroundParser();
195 DocumentParser::detach(); 187 DocumentParser::detach();
196 if (m_scriptRunner) 188 if (m_scriptRunner)
197 m_scriptRunner->detach(); 189 m_scriptRunner->detach();
198 m_treeBuilder->detach(); 190 m_treeBuilder->detach();
199 // FIXME: It seems wrong that we would have a preload scanner here. Yet during 191 // FIXME: It seems wrong that we would have a preload scanner here. Yet during
200 // fast/dom/HTMLScriptElement/script-load-events.html we do. 192 // fast/dom/HTMLScriptElement/script-load-events.html we do.
201 m_preloadScanner.reset(); 193 m_preloadScanner.reset();
202 m_insertionPreloadScanner.reset(); 194 m_insertionPreloadScanner.reset();
203 if (m_parserScheduler) { 195 if (m_parserScheduler) {
204 m_parserScheduler->detach(); 196 m_parserScheduler->detach();
205 m_parserScheduler.clear(); 197 m_parserScheduler.clear();
206 } 198 }
207 // Oilpan: It is important to clear m_token to deallocate backing memory of 199 // Oilpan: It is important to clear m_token to deallocate backing memory of
208 // HTMLToken::m_data and let the allocator reuse the memory for 200 // HTMLToken::m_data and let the allocator reuse the memory for
209 // HTMLToken::m_data of a next HTMLDocumentParser. We need to clear 201 // HTMLToken::m_data of a next HTMLDocumentParser. We need to clear
210 // m_tokenizer first because m_tokenizer has a raw pointer to m_token. 202 // m_tokenizer first because m_tokenizer has a raw pointer to m_token.
211 m_tokenizer.reset(); 203 m_tokenizer.reset();
212 m_token.reset(); 204 m_token.reset();
213 } 205 }
214 206
215 void HTMLDocumentParser::stopParsing() { 207 void HTMLDocumentParser::stopParsing() {
216 DocumentParser::stopParsing(); 208 DocumentParser::stopParsing();
217 if (m_parserScheduler) { 209 if (m_parserScheduler) {
218 m_parserScheduler->detach(); 210 m_parserScheduler->detach();
219 m_parserScheduler.clear(); 211 m_parserScheduler.clear();
220 } 212 }
221 if (m_haveBackgroundParser) 213 m_backgroundParser.clear();
222 stopBackgroundParser();
223 } 214 }
224 215
225 // This kicks off "Once the user agent stops parsing" as described by: 216 // This kicks off "Once the user agent stops parsing" as described by:
226 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the- end 217 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the- end
227 void HTMLDocumentParser::prepareToStopParsing() { 218 void HTMLDocumentParser::prepareToStopParsing() {
228 // FIXME: It may not be correct to disable this for the background parser. 219 // FIXME: It may not be correct to disable this for the background parser.
229 // That means hasInsertionPoint() may not be correct in some cases. 220 // That means hasInsertionPoint() may not be correct in some cases.
230 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); 221 DCHECK(!hasInsertionPoint() || m_backgroundParser);
231 222
232 // NOTE: This pump should only ever emit buffered character tokens. 223 // NOTE: This pump should only ever emit buffered character tokens.
233 if (m_tokenizer) { 224 if (m_tokenizer) {
234 ASSERT(!m_haveBackgroundParser); 225 DCHECK(!m_backgroundParser);
235 pumpTokenizerIfPossible(); 226 pumpTokenizerIfPossible();
236 } 227 }
237 228
238 if (isStopped()) 229 if (isStopped())
239 return; 230 return;
240 231
241 DocumentParser::prepareToStopParsing(); 232 DocumentParser::prepareToStopParsing();
242 233
243 // We will not have a scriptRunner when parsing a DocumentFragment. 234 // We will not have a scriptRunner when parsing a DocumentFragment.
244 if (m_scriptRunner) 235 if (m_scriptRunner)
(...skipping 18 matching lines...) Expand all
263 254
264 pumpTokenizer(); 255 pumpTokenizer();
265 } 256 }
266 257
267 bool HTMLDocumentParser::isScheduledForResume() const { 258 bool HTMLDocumentParser::isScheduledForResume() const {
268 return m_parserScheduler && m_parserScheduler->isScheduledForResume(); 259 return m_parserScheduler && m_parserScheduler->isScheduledForResume();
269 } 260 }
270 261
271 // Used by HTMLParserScheduler 262 // Used by HTMLParserScheduler
272 void HTMLDocumentParser::resumeParsingAfterYield() { 263 void HTMLDocumentParser::resumeParsingAfterYield() {
273 ASSERT(shouldUseThreading()); 264 DCHECK(shouldUseThreading());
274 ASSERT(m_haveBackgroundParser); 265 DCHECK(m_backgroundParser);
275 266
276 checkIfBodyStlyesheetAdded(); 267 checkIfBodyStlyesheetAdded();
277 if (isStopped() || isPaused()) 268 if (isStopped() || isPaused())
278 return; 269 return;
279 270
280 pumpPendingSpeculations(); 271 pumpPendingSpeculations();
281 } 272 }
282 273
283 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() { 274 void HTMLDocumentParser::runScriptsForPausedTreeBuilder() {
284 ASSERT(scriptingContentIsAllowed(getParserContentPolicy())); 275 DCHECK(scriptingContentIsAllowed(getParserContentPolicy()));
285 276
286 TextPosition scriptStartPosition = TextPosition::belowRangePosition(); 277 TextPosition scriptStartPosition = TextPosition::belowRangePosition();
287 Element* scriptElement = 278 Element* scriptElement =
288 m_treeBuilder->takeScriptToProcess(scriptStartPosition); 279 m_treeBuilder->takeScriptToProcess(scriptStartPosition);
289 // We will not have a scriptRunner when parsing a DocumentFragment. 280 // We will not have a scriptRunner when parsing a DocumentFragment.
290 if (m_scriptRunner) 281 if (m_scriptRunner)
291 m_scriptRunner->processScriptElement(scriptElement, scriptStartPosition); 282 m_scriptRunner->processScriptElement(scriptElement, scriptStartPosition);
292 checkIfBodyStlyesheetAdded(); 283 checkIfBodyStlyesheetAdded();
293 } 284 }
294 285
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 for (auto& request : chunk->preloads) { 344 for (auto& request : chunk->preloads) {
354 // Link rel preloads don't need to wait for AppCache but they 345 // Link rel preloads don't need to wait for AppCache but they
355 // should probably wait for CSP. 346 // should probably wait for CSP.
356 if (!m_pendingCSPMetaToken && request->isLinkRelPreload()) 347 if (!m_pendingCSPMetaToken && request->isLinkRelPreload())
357 linkRelPreloads.push_back(std::move(request)); 348 linkRelPreloads.push_back(std::move(request));
358 else 349 else
359 m_queuedPreloads.push_back(std::move(request)); 350 m_queuedPreloads.push_back(std::move(request));
360 } 351 }
361 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { 352 for (auto& index : chunk->likelyDocumentWriteScriptIndices) {
362 const CompactHTMLToken& token = chunk->tokens->at(index); 353 const CompactHTMLToken& token = chunk->tokens->at(index);
363 ASSERT(token.type() == HTMLToken::TokenType::Character); 354 DCHECK(token.type() == HTMLToken::TokenType::Character);
364 m_queuedDocumentWriteScripts.push_back(token.data()); 355 m_queuedDocumentWriteScripts.push_back(token.data());
365 } 356 }
366 } 357 }
367 m_preloader->takeAndPreload(linkRelPreloads); 358 m_preloader->takeAndPreload(linkRelPreloads);
368 } else { 359 } else {
369 // We can safely assume that there are no queued preloads request after the 360 // We can safely assume that there are no queued preloads request after the
370 // document element is available, as we empty the queue immediately after 361 // document element is available, as we empty the queue immediately after
371 // the document element is created in documentElementAvailable(). 362 // the document element is created in documentElementAvailable().
372 ASSERT(m_queuedPreloads.isEmpty()); 363 DCHECK(m_queuedPreloads.isEmpty());
373 ASSERT(m_queuedDocumentWriteScripts.isEmpty()); 364 DCHECK(m_queuedDocumentWriteScripts.isEmpty());
374 // Loop through the chunks to generate preloads before any document.write 365 // Loop through the chunks to generate preloads before any document.write
375 // script evaluation takes place. Preloading these scripts is valuable and 366 // script evaluation takes place. Preloading these scripts is valuable and
376 // comparably cheap, while evaluating JS can be expensive. 367 // comparably cheap, while evaluating JS can be expensive.
377 for (auto& chunk : pendingChunks) 368 for (auto& chunk : pendingChunks)
378 m_preloader->takeAndPreload(chunk->preloads); 369 m_preloader->takeAndPreload(chunk->preloads);
379 for (auto& chunk : pendingChunks) { 370 for (auto& chunk : pendingChunks) {
380 for (auto& index : chunk->likelyDocumentWriteScriptIndices) { 371 for (auto& index : chunk->likelyDocumentWriteScriptIndices) {
381 const CompactHTMLToken& token = chunk->tokens->at(index); 372 const CompactHTMLToken& token = chunk->tokens->at(index);
382 ASSERT(token.type() == HTMLToken::TokenType::Character); 373 DCHECK(token.type() == HTMLToken::TokenType::Character);
383 evaluateAndPreloadScriptForDocumentWrite(token.data()); 374 evaluateAndPreloadScriptForDocumentWrite(token.data());
384 } 375 }
385 } 376 }
386 } 377 }
387 378
388 for (auto& chunk : pendingChunks) 379 for (auto& chunk : pendingChunks)
389 m_speculations.append(std::move(chunk)); 380 m_speculations.append(std::move(chunk));
390 381
391 if (!isPaused() && !isScheduledForResume()) { 382 if (!isPaused() && !isScheduledForResume()) {
392 if (m_tasksWereSuspended) 383 if (m_tasksWereSuspended)
393 m_parserScheduler->forceResumeAfterYield(); 384 m_parserScheduler->forceResumeAfterYield();
394 else 385 else
395 m_parserScheduler->scheduleForResume(); 386 m_parserScheduler->scheduleForResume();
396 } 387 }
397 } 388 }
398 389
399 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser( 390 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(
400 const DocumentEncodingData& data) { 391 const DocumentEncodingData& data) {
392 if (!isParsing())
Charlie Harrison 2017/02/08 23:48:01 This is necessary because now the bg parser is a m
Yoav Weiss 2017/02/14 06:45:47 ok
393 return;
401 document()->setEncodingData(data); 394 document()->setEncodingData(data);
402 } 395 }
403 396
404 void HTMLDocumentParser::validateSpeculations( 397 void HTMLDocumentParser::validateSpeculations(
405 std::unique_ptr<TokenizedChunk> chunk) { 398 std::unique_ptr<TokenizedChunk> chunk) {
406 ASSERT(chunk); 399 DCHECK(chunk);
407 // TODO(kouhei): We should simplify codepath here by disallowing 400 // TODO(kouhei): We should simplify codepath here by disallowing
408 // validateSpeculations 401 // validateSpeculations
409 // while isPaused, and m_lastChunkBeforePause can simply be 402 // while isPaused, and m_lastChunkBeforePause can simply be
410 // pushed to m_speculations. 403 // pushed to m_speculations.
411 if (isPaused()) { 404 if (isPaused()) {
412 // We're waiting on a network script or stylesheet, just save the chunk, 405 // We're waiting on a network script or stylesheet, just save the chunk,
413 // we'll get a second validateSpeculations call after the script or 406 // we'll get a second validateSpeculations call after the script or
414 // stylesheet completes. This call should have been made immediately after 407 // stylesheet completes. This call should have been made immediately after
415 // runScriptsForPausedTreeBuilder in the script case which may have started 408 // runScriptsForPausedTreeBuilder in the script case which may have started
416 // a network load and left us waiting. 409 // a network load and left us waiting.
(...skipping 15 matching lines...) Expand all
432 // Currently we're only smart enough to reuse the speculation buffer if the 425 // Currently we're only smart enough to reuse the speculation buffer if the
433 // tokenizer both starts and ends in the DataState. That state is simplest 426 // tokenizer both starts and ends in the DataState. That state is simplest
434 // because the HTMLToken is always in the Uninitialized state. We should 427 // because the HTMLToken is always in the Uninitialized state. We should
435 // consider whether we can reuse the speculation buffer in other states, but 428 // consider whether we can reuse the speculation buffer in other states, but
436 // we'd likely need to do something more sophisticated with the HTMLToken. 429 // we'd likely need to do something more sophisticated with the HTMLToken.
437 if (chunk->tokenizerState == HTMLTokenizer::DataState && 430 if (chunk->tokenizerState == HTMLTokenizer::DataState &&
438 tokenizer->getState() == HTMLTokenizer::DataState && 431 tokenizer->getState() == HTMLTokenizer::DataState &&
439 m_input.current().isEmpty() && 432 m_input.current().isEmpty() &&
440 chunk->treeBuilderState == 433 chunk->treeBuilderState ==
441 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get())) { 434 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get())) {
442 ASSERT(token->isUninitialized()); 435 DCHECK(token->isUninitialized());
443 return; 436 return;
444 } 437 }
445 438
446 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token), 439 discardSpeculationsAndResumeFrom(std::move(chunk), std::move(token),
447 std::move(tokenizer)); 440 std::move(tokenizer));
448 } 441 }
449 442
450 void HTMLDocumentParser::discardSpeculationsAndResumeFrom( 443 void HTMLDocumentParser::discardSpeculationsAndResumeFrom(
451 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript, 444 std::unique_ptr<TokenizedChunk> lastChunkBeforeScript,
452 std::unique_ptr<HTMLToken> token, 445 std::unique_ptr<HTMLToken> token,
453 std::unique_ptr<HTMLTokenizer> tokenizer) { 446 std::unique_ptr<HTMLTokenizer> tokenizer) {
454 m_weakFactory.revokeAll();
455
456 size_t discardedTokenCount = 0; 447 size_t discardedTokenCount = 0;
457 for (const auto& speculation : m_speculations) { 448 for (const auto& speculation : m_speculations) {
458 discardedTokenCount += speculation->tokens->size(); 449 discardedTokenCount += speculation->tokens->size();
459 } 450 }
460 DEFINE_STATIC_LOCAL(CustomCountHistogram, discardedTokenCountHistogram, 451 DEFINE_STATIC_LOCAL(CustomCountHistogram, discardedTokenCountHistogram,
461 ("Parser.DiscardedTokenCount", 1, 100000, 50)); 452 ("Parser.DiscardedTokenCount", 1, 100000, 50));
462 discardedTokenCountHistogram.count(discardedTokenCount); 453 discardedTokenCountHistogram.count(discardedTokenCount);
463 454
464 m_speculations.clear(); 455 m_speculations.clear();
465 m_pendingCSPMetaToken = nullptr; 456 m_pendingCSPMetaToken = nullptr;
466 m_queuedPreloads.clear(); 457 m_queuedPreloads.clear();
467 458
468 std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint = 459 std::unique_ptr<BackgroundHTMLParser::Checkpoint> checkpoint =
469 WTF::wrapUnique(new BackgroundHTMLParser::Checkpoint); 460 WTF::wrapUnique(new BackgroundHTMLParser::Checkpoint);
470 checkpoint->parser = m_weakFactory.createWeakPtr();
471 checkpoint->token = std::move(token); 461 checkpoint->token = std::move(token);
472 checkpoint->tokenizer = std::move(tokenizer); 462 checkpoint->tokenizer = std::move(tokenizer);
473 checkpoint->treeBuilderState = 463 checkpoint->treeBuilderState =
474 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get()); 464 HTMLTreeBuilderSimulator::stateFor(m_treeBuilder.get());
475 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; 465 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint;
476 checkpoint->preloadScannerCheckpoint = 466 checkpoint->preloadScannerCheckpoint =
477 lastChunkBeforeScript->preloadScannerCheckpoint; 467 lastChunkBeforeScript->preloadScannerCheckpoint;
478 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); 468 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy();
479 // FIXME: This should be passed in instead of cleared. 469 // FIXME: This should be passed in instead of cleared.
480 m_input.current().clear(); 470 m_input.current().clear();
481 471
482 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); 472 DCHECK(checkpoint->unparsedInput.isSafeToSendToAnotherThread());
483 m_loadingTaskRunner->postTask( 473 m_backgroundParser->resumeFrom(std::move(checkpoint));
484 BLINK_FROM_HERE,
485 WTF::bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser,
486 WTF::passed(std::move(checkpoint))));
487 } 474 }
488 475
489 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser( 476 size_t HTMLDocumentParser::processTokenizedChunkFromBackgroundParser(
490 std::unique_ptr<TokenizedChunk> popChunk) { 477 std::unique_ptr<TokenizedChunk> popChunk) {
491 TRACE_EVENT_WITH_FLOW0( 478 TRACE_EVENT_WITH_FLOW0(
492 "blink,loading", 479 "blink,loading",
493 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser", 480 "HTMLDocumentParser::processTokenizedChunkFromBackgroundParser",
494 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN); 481 popChunk.get(), TRACE_EVENT_FLAG_FLOW_IN);
495 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true); 482 AutoReset<bool> hasLineNumber(&m_isParsingAtLineNumber, true);
496 483
497 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1); 484 SECURITY_DCHECK(m_pumpSpeculationsSessionNestingLevel == 1);
498 SECURITY_DCHECK(!inPumpSession()); 485 SECURITY_DCHECK(!inPumpSession());
499 ASSERT(!isParsingFragment()); 486 DCHECK(!isParsingFragment());
500 DCHECK(!isPaused()); 487 DCHECK(!isPaused());
501 ASSERT(!isStopped()); 488 DCHECK(!isStopped());
502 ASSERT(shouldUseThreading()); 489 DCHECK(shouldUseThreading());
503 ASSERT(!m_tokenizer); 490 DCHECK(!m_tokenizer);
504 ASSERT(!m_token); 491 DCHECK(!m_token);
505 DCHECK(!m_lastChunkBeforePause); 492 DCHECK(!m_lastChunkBeforePause);
506 493
507 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk)); 494 std::unique_ptr<TokenizedChunk> chunk(std::move(popChunk));
508 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens); 495 std::unique_ptr<CompactHTMLTokenStream> tokens = std::move(chunk->tokens);
509 size_t elementTokenCount = 0; 496 size_t elementTokenCount = 0;
510 497
511 m_loadingTaskRunner->postTask( 498 m_backgroundParser->startedChunkWithCheckpoint(chunk->inputCheckpoint);
512 BLINK_FROM_HERE,
513 WTF::bind(&BackgroundHTMLParser::startedChunkWithCheckpoint,
514 m_backgroundParser, chunk->inputCheckpoint));
515 499
516 for (const auto& xssInfo : chunk->xssInfos) { 500 for (const auto& xssInfo : chunk->xssInfos) {
517 m_textPosition = xssInfo->m_textPosition; 501 m_textPosition = xssInfo->m_textPosition;
518 m_xssAuditorDelegate.didBlockScript(*xssInfo); 502 m_xssAuditorDelegate.didBlockScript(*xssInfo);
519 if (isStopped()) 503 if (isStopped())
520 break; 504 break;
521 } 505 }
522 // XSSAuditorDelegate can detach the parser if it decides to block the entire 506 // XSSAuditorDelegate can detach the parser if it decides to block the entire
523 // current document. 507 // current document.
524 if (isDetached()) 508 if (isDetached())
525 return elementTokenCount; 509 return elementTokenCount;
526 510
527 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); 511 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin();
528 it != tokens->end(); ++it) { 512 it != tokens->end(); ++it) {
529 ASSERT(!isWaitingForScripts()); 513 DCHECK(!isWaitingForScripts());
530 514
531 if (!chunk->startingScript && 515 if (!chunk->startingScript &&
532 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag)) 516 (it->type() == HTMLToken::StartTag || it->type() == HTMLToken::EndTag))
533 elementTokenCount++; 517 elementTokenCount++;
534 518
535 if (document()->frame() && 519 if (document()->frame() &&
536 document()->frame()->navigationScheduler().locationChangePending()) { 520 document()->frame()->navigationScheduler().locationChangePending()) {
537 // To match main-thread parser behavior (which never checks 521 // To match main-thread parser behavior (which never checks
538 // locationChangePending on the EOF path) we peek to see if this chunk has 522 // locationChangePending on the EOF path) we peek to see if this chunk has
539 // an EOF and process it anyway. 523 // an EOF and process it anyway.
540 if (tokens->back().type() == HTMLToken::EndOfFile) { 524 if (tokens->back().type() == HTMLToken::EndOfFile) {
541 ASSERT( 525 DCHECK(
542 m_speculations 526 m_speculations
543 .isEmpty()); // There should never be any chunks after the EOF. 527 .isEmpty()); // There should never be any chunks after the EOF.
544 prepareToStopParsing(); 528 prepareToStopParsing();
545 } 529 }
546 break; 530 break;
547 } 531 }
548 532
549 m_textPosition = it->textPosition(); 533 m_textPosition = it->textPosition();
550 534
551 constructTreeFromCompactHTMLToken(*it); 535 constructTreeFromCompactHTMLToken(*it);
552 536
553 if (isStopped()) 537 if (isStopped())
554 break; 538 break;
555 539
556 // Preloads were queued if there was a <meta> csp token in a tokenized 540 // Preloads were queued if there was a <meta> csp token in a tokenized
557 // chunk. 541 // chunk.
558 if (m_pendingCSPMetaToken && it == m_pendingCSPMetaToken) { 542 if (m_pendingCSPMetaToken && it == m_pendingCSPMetaToken) {
559 m_pendingCSPMetaToken = nullptr; 543 m_pendingCSPMetaToken = nullptr;
560 fetchQueuedPreloads(); 544 fetchQueuedPreloads();
561 } 545 }
562 546
563 if (isPaused()) { 547 if (isPaused()) {
564 // The script or stylesheet should be the last token of this bunch. 548 // The script or stylesheet should be the last token of this bunch.
565 ASSERT(it + 1 == tokens->end()); 549 DCHECK(it + 1 == tokens->end());
566 if (isWaitingForScripts()) 550 if (isWaitingForScripts())
567 runScriptsForPausedTreeBuilder(); 551 runScriptsForPausedTreeBuilder();
568 validateSpeculations(std::move(chunk)); 552 validateSpeculations(std::move(chunk));
569 break; 553 break;
570 } 554 }
571 555
572 if (it->type() == HTMLToken::EndOfFile) { 556 if (it->type() == HTMLToken::EndOfFile) {
573 // The EOF is assumed to be the last token of this bunch. 557 // The EOF is assumed to be the last token of this bunch.
574 ASSERT(it + 1 == tokens->end()); 558 DCHECK(it + 1 == tokens->end());
575 // There should never be any chunks after the EOF. 559 // There should never be any chunks after the EOF.
576 ASSERT(m_speculations.isEmpty()); 560 DCHECK(m_speculations.isEmpty());
577 prepareToStopParsing(); 561 prepareToStopParsing();
578 break; 562 break;
579 } 563 }
580 564
581 ASSERT(!m_tokenizer); 565 DCHECK(!m_tokenizer);
582 ASSERT(!m_token); 566 DCHECK(!m_token);
583 } 567 }
584 568
585 // Make sure all required pending text nodes are emitted before returning. 569 // Make sure all required pending text nodes are emitted before returning.
586 // This leaves "script", "style" and "svg" nodes text nodes intact. 570 // This leaves "script", "style" and "svg" nodes text nodes intact.
587 if (!isStopped()) 571 if (!isStopped())
588 m_treeBuilder->flush(FlushIfAtTextLimit); 572 m_treeBuilder->flush(FlushIfAtTextLimit);
589 573
590 m_isParsingAtLineNumber = false; 574 m_isParsingAtLineNumber = false;
591 575
592 return elementTokenCount; 576 return elementTokenCount;
593 } 577 }
594 578
595 void HTMLDocumentParser::pumpPendingSpeculations() { 579 void HTMLDocumentParser::pumpPendingSpeculations() {
596 // If this assert fails, you need to call validateSpeculations to make sure 580 // If this assert fails, you need to call validateSpeculations to make sure
597 // m_tokenizer and m_token don't have state that invalidates m_speculations. 581 // m_tokenizer and m_token don't have state that invalidates m_speculations.
598 ASSERT(!m_tokenizer); 582 DCHECK(!m_tokenizer);
599 ASSERT(!m_token); 583 DCHECK(!m_token);
600 DCHECK(!m_lastChunkBeforePause); 584 DCHECK(!m_lastChunkBeforePause);
601 DCHECK(!isPaused()); 585 DCHECK(!isPaused());
602 ASSERT(!isStopped()); 586 DCHECK(!isStopped());
603 ASSERT(!isScheduledForResume()); 587 DCHECK(!isScheduledForResume());
604 ASSERT(!inPumpSession()); 588 DCHECK(!inPumpSession());
605 589
606 // FIXME: Here should never be reached when there is a blocking script, 590 // FIXME: Here should never be reached when there is a blocking script,
607 // but it happens in unknown scenarios. See https://crbug.com/440901 591 // but it happens in unknown scenarios. See https://crbug.com/440901
608 if (isWaitingForScripts()) { 592 if (isWaitingForScripts()) {
609 m_parserScheduler->scheduleForResume(); 593 m_parserScheduler->scheduleForResume();
610 return; 594 return;
611 } 595 }
612 596
613 // Do not allow pumping speculations in nested event loops. 597 // Do not allow pumping speculations in nested event loops.
614 if (m_pumpSpeculationsSessionNestingLevel) { 598 if (m_pumpSpeculationsSessionNestingLevel) {
615 m_parserScheduler->scheduleForResume(); 599 m_parserScheduler->scheduleForResume();
616 return; 600 return;
617 } 601 }
618 602
619 // FIXME: Pass in current input length. 603 // FIXME: Pass in current input length.
620 TRACE_EVENT_BEGIN1("devtools.timeline", "ParseHTML", "beginData", 604 TRACE_EVENT_BEGIN1("devtools.timeline", "ParseHTML", "beginData",
621 InspectorParseHtmlEvent::beginData( 605 InspectorParseHtmlEvent::beginData(
622 document(), lineNumber().zeroBasedInt())); 606 document(), lineNumber().zeroBasedInt()));
623 607
624 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel); 608 SpeculationsPumpSession session(m_pumpSpeculationsSessionNestingLevel);
625 while (!m_speculations.isEmpty()) { 609 while (!m_speculations.isEmpty()) {
626 ASSERT(!isScheduledForResume()); 610 DCHECK(!isScheduledForResume());
627 size_t elementTokenCount = 611 size_t elementTokenCount =
628 processTokenizedChunkFromBackgroundParser(m_speculations.takeFirst()); 612 processTokenizedChunkFromBackgroundParser(m_speculations.takeFirst());
629 session.addedElementTokens(elementTokenCount); 613 session.addedElementTokens(elementTokenCount);
630 614
631 // Always check isParsing first as m_document may be null. Surprisingly, 615 // Always check isParsing first as m_document may be null. Surprisingly,
632 // isScheduledForResume() may be set here as a result of 616 // isScheduledForResume() may be set here as a result of
633 // processTokenizedChunkFromBackgroundParser running arbitrary javascript 617 // processTokenizedChunkFromBackgroundParser running arbitrary javascript
634 // which invokes nested event loops. (e.g. inspector breakpoints) 618 // which invokes nested event loops. (e.g. inspector breakpoints)
635 checkIfBodyStlyesheetAdded(); 619 checkIfBodyStlyesheetAdded();
636 if (!isParsing() || isPaused() || isScheduledForResume()) 620 if (!isParsing() || isPaused() || isScheduledForResume())
(...skipping 10 matching lines...) Expand all
647 InspectorParseHtmlEvent::endData(lineNumber().zeroBasedInt() - 1)); 631 InspectorParseHtmlEvent::endData(lineNumber().zeroBasedInt() - 1));
648 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), 632 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
649 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data", 633 "UpdateCounters", TRACE_EVENT_SCOPE_THREAD, "data",
650 InspectorUpdateCountersEvent::data()); 634 InspectorUpdateCountersEvent::data());
651 } 635 }
652 636
653 void HTMLDocumentParser::forcePlaintextForTextDocument() { 637 void HTMLDocumentParser::forcePlaintextForTextDocument() {
654 if (shouldUseThreading()) { 638 if (shouldUseThreading()) {
655 // This method is called before any data is appended, so we have to start 639 // This method is called before any data is appended, so we have to start
656 // the background parser ourselves. 640 // the background parser ourselves.
657 if (!m_haveBackgroundParser) 641 if (!m_backgroundParser)
658 startBackgroundParser(); 642 startBackgroundParser();
659 643
660 // This task should be synchronous, because otherwise synchronous 644 // This task should be synchronous, because otherwise synchronous
661 // tokenizing can happen before plaintext is forced. 645 // tokenizing can happen before plaintext is forced.
662 m_backgroundParser->forcePlaintextForTextDocument(); 646 m_backgroundParser->forcePlaintextForTextDocument();
663 } else 647 } else
664 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); 648 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
665 } 649 }
666 650
667 void HTMLDocumentParser::pumpTokenizer() { 651 void HTMLDocumentParser::pumpTokenizer() {
668 ASSERT(!isStopped()); 652 DCHECK(!isStopped());
669 ASSERT(m_tokenizer); 653 DCHECK(m_tokenizer);
670 ASSERT(m_token); 654 DCHECK(m_token);
671 655
672 PumpSession session(m_pumpSessionNestingLevel); 656 PumpSession session(m_pumpSessionNestingLevel);
673 657
674 // We tell the InspectorInstrumentation about every pump, even if we end up 658 // We tell the InspectorInstrumentation about every pump, even if we end up
675 // pumping nothing. It can filter out empty pumps itself. 659 // pumping nothing. It can filter out empty pumps itself.
676 // FIXME: m_input.current().length() is only accurate if we end up parsing the 660 // FIXME: m_input.current().length() is only accurate if we end up parsing the
677 // whole buffer in this pump. We should pass how much we parsed as part of 661 // whole buffer in this pump. We should pass how much we parsed as part of
678 // didWriteHTML instead of willWriteHTML. 662 // didWriteHTML instead of willWriteHTML.
679 TRACE_EVENT_BEGIN1( 663 TRACE_EVENT_BEGIN1(
680 "devtools.timeline", "ParseHTML", "beginData", 664 "devtools.timeline", "ParseHTML", "beginData",
(...skipping 20 matching lines...) Expand all
701 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) { 685 token(), m_sourceTracker, m_tokenizer->shouldAllowCDATA()))) {
702 m_xssAuditorDelegate.didBlockScript(*xssInfo); 686 m_xssAuditorDelegate.didBlockScript(*xssInfo);
703 // If we're in blocking mode, we might stop the parser in 687 // If we're in blocking mode, we might stop the parser in
704 // 'didBlockScript()'. In that case, exit early. 688 // 'didBlockScript()'. In that case, exit early.
705 if (!isParsing()) 689 if (!isParsing())
706 return; 690 return;
707 } 691 }
708 } 692 }
709 693
710 constructTreeFromHTMLToken(); 694 constructTreeFromHTMLToken();
711 ASSERT(isStopped() || token().isUninitialized()); 695 DCHECK(isStopped() || token().isUninitialized());
712 } 696 }
713 697
714 if (isStopped()) 698 if (isStopped())
715 return; 699 return;
716 700
717 // There should only be PendingText left since the tree-builder always flushes 701 // There should only be PendingText left since the tree-builder always flushes
718 // the task queue before returning. In case that ever changes, crash. 702 // the task queue before returning. In case that ever changes, crash.
719 m_treeBuilder->flush(FlushAlways); 703 m_treeBuilder->flush(FlushAlways);
720 RELEASE_ASSERT(!isStopped()); 704 CHECK(!isStopped());
721 705
722 if (isPaused()) { 706 if (isPaused()) {
723 ASSERT(m_tokenizer->getState() == HTMLTokenizer::DataState); 707 DCHECK(m_tokenizer->getState() == HTMLTokenizer::DataState);
724 708
725 ASSERT(m_preloader); 709 DCHECK(m_preloader);
726 // TODO(kouhei): m_preloader should be always available for synchronous 710 // TODO(kouhei): m_preloader should be always available for synchronous
727 // parsing case, adding paranoia if for speculative crash fix for 711 // parsing case, adding paranoia if for speculative crash fix for
728 // crbug.com/465478 712 // crbug.com/465478
729 if (m_preloader) { 713 if (m_preloader) {
730 if (!m_preloadScanner) { 714 if (!m_preloadScanner) {
731 m_preloadScanner = createPreloadScanner(); 715 m_preloadScanner = createPreloadScanner();
732 m_preloadScanner->appendToEnd(m_input.current()); 716 m_preloadScanner->appendToEnd(m_input.current());
733 } 717 }
734 scanAndPreload(m_preloadScanner.get()); 718 scanAndPreload(m_preloadScanner.get());
735 } 719 }
(...skipping 21 matching lines...) Expand all
757 token().clear(); 741 token().clear();
758 742
759 m_treeBuilder->constructTree(&atomicToken); 743 m_treeBuilder->constructTree(&atomicToken);
760 checkIfBodyStlyesheetAdded(); 744 checkIfBodyStlyesheetAdded();
761 745
762 // FIXME: constructTree may synchronously cause Document to be detached. 746 // FIXME: constructTree may synchronously cause Document to be detached.
763 if (!m_token) 747 if (!m_token)
764 return; 748 return;
765 749
766 if (!token().isUninitialized()) { 750 if (!token().isUninitialized()) {
767 ASSERT(token().type() == HTMLToken::Character); 751 DCHECK(token().type() == HTMLToken::Character);
768 token().clear(); 752 token().clear();
769 } 753 }
770 } 754 }
771 755
772 void HTMLDocumentParser::constructTreeFromCompactHTMLToken( 756 void HTMLDocumentParser::constructTreeFromCompactHTMLToken(
773 const CompactHTMLToken& compactToken) { 757 const CompactHTMLToken& compactToken) {
774 AtomicHTMLToken token(compactToken); 758 AtomicHTMLToken token(compactToken);
775 m_treeBuilder->constructTree(&token); 759 m_treeBuilder->constructTree(&token);
776 checkIfBodyStlyesheetAdded(); 760 checkIfBodyStlyesheetAdded();
777 } 761 }
778 762
779 bool HTMLDocumentParser::hasInsertionPoint() { 763 bool HTMLDocumentParser::hasInsertionPoint() {
780 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our 764 // FIXME: The wasCreatedByScript() branch here might not be fully correct. Our
781 // model of the EOF character differs slightly from the one in the spec 765 // model of the EOF character differs slightly from the one in the spec
782 // because our treatment is uniform between network-sourced and script-sourced 766 // because our treatment is uniform between network-sourced and script-sourced
783 // input streams whereas the spec treats them differently. 767 // input streams whereas the spec treats them differently.
784 return m_input.hasInsertionPoint() || 768 return m_input.hasInsertionPoint() ||
785 (wasCreatedByScript() && !m_input.haveSeenEndOfFile()); 769 (wasCreatedByScript() && !m_input.haveSeenEndOfFile());
786 } 770 }
787 771
788 void HTMLDocumentParser::insert(const SegmentedString& source) { 772 void HTMLDocumentParser::insert(const SegmentedString& source) {
789 if (isStopped()) 773 if (isStopped())
790 return; 774 return;
791 775
792 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length", 776 TRACE_EVENT1("blink", "HTMLDocumentParser::insert", "source_length",
793 source.length()); 777 source.length());
794 778
795 if (!m_tokenizer) { 779 if (!m_tokenizer) {
796 ASSERT(!inPumpSession()); 780 DCHECK(!inPumpSession());
797 ASSERT(m_haveBackgroundParser || wasCreatedByScript()); 781 DCHECK(m_backgroundParser || wasCreatedByScript());
798 m_token = WTF::wrapUnique(new HTMLToken); 782 m_token = WTF::wrapUnique(new HTMLToken);
799 m_tokenizer = HTMLTokenizer::create(m_options); 783 m_tokenizer = HTMLTokenizer::create(m_options);
800 } 784 }
801 785
802 SegmentedString excludedLineNumberSource(source); 786 SegmentedString excludedLineNumberSource(source);
803 excludedLineNumberSource.setExcludeLineNumbers(); 787 excludedLineNumberSource.setExcludeLineNumbers();
804 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource); 788 m_input.insertAtCurrentInsertionPoint(excludedLineNumberSource);
805 pumpTokenizerIfPossible(); 789 pumpTokenizerIfPossible();
806 790
807 if (isPaused()) { 791 if (isPaused()) {
808 // Check the document.write() output with a separate preload scanner as 792 // Check the document.write() output with a separate preload scanner as
809 // the main scanner can't deal with insertions. 793 // the main scanner can't deal with insertions.
810 if (!m_insertionPreloadScanner) 794 if (!m_insertionPreloadScanner)
811 m_insertionPreloadScanner = createPreloadScanner(); 795 m_insertionPreloadScanner = createPreloadScanner();
812 m_insertionPreloadScanner->appendToEnd(source); 796 m_insertionPreloadScanner->appendToEnd(source);
813 scanAndPreload(m_insertionPreloadScanner.get()); 797 scanAndPreload(m_insertionPreloadScanner.get());
814 } 798 }
815 799
816 endIfDelayed(); 800 endIfDelayed();
817 } 801 }
818 802
819 void HTMLDocumentParser::startBackgroundParser() { 803 void HTMLDocumentParser::startBackgroundParser() {
820 ASSERT(!isStopped()); 804 DCHECK(!isStopped());
821 ASSERT(shouldUseThreading()); 805 DCHECK(shouldUseThreading());
822 ASSERT(!m_haveBackgroundParser); 806 DCHECK(!m_backgroundParser);
823 ASSERT(document()); 807 DCHECK(document());
824 m_haveBackgroundParser = true;
825 808
826 // TODO(alexclarke): Remove WebFrameScheduler::setDocumentParsingInBackground 809 // TODO(csharrison): Remove WebFrameScheduler::setDocumentParsingInBackground.
827 // when background parser goes away.
828 if (document()->frame() && document()->frame()->frameScheduler()) 810 if (document()->frame() && document()->frame()->frameScheduler())
829 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true); 811 document()->frame()->frameScheduler()->setDocumentParsingInBackground(true);
830 812
831 // Make sure that a resolver is set up, so that the correct viewport 813 // Make sure that a resolver is set up, so that the correct viewport
832 // dimensions will be fed to the background parser and preload scanner. 814 // dimensions will be fed to the background parser and preload scanner.
833 if (document()->loader()) 815 if (document()->loader())
834 document()->ensureStyleResolver(); 816 document()->ensureStyleResolver();
835 817
836 std::unique_ptr<BackgroundHTMLParser::Configuration> config = 818 std::unique_ptr<BackgroundHTMLParser::Configuration> config =
837 WTF::wrapUnique(new BackgroundHTMLParser::Configuration); 819 WTF::wrapUnique(new BackgroundHTMLParser::Configuration);
838 config->options = m_options; 820 config->options = m_options;
839 config->parser = m_weakFactory.createWeakPtr();
840 config->xssAuditor = WTF::wrapUnique(new XSSAuditor); 821 config->xssAuditor = WTF::wrapUnique(new XSSAuditor);
841 config->xssAuditor->init(document(), &m_xssAuditorDelegate); 822 config->xssAuditor->init(document(), &m_xssAuditorDelegate);
842 823
843 config->decoder = takeDecoder(); 824 config->decoder = takeDecoder();
844 config->tokenizedChunkQueue = m_tokenizedChunkQueue.get(); 825 config->tokenizedChunkQueue = m_tokenizedChunkQueue.get();
845 if (document()->settings()) { 826 if (document()->settings()) {
846 if (document() 827 if (document()
847 ->settings() 828 ->settings()
848 ->getBackgroundHtmlParserOutstandingTokenLimit()) { 829 ->getBackgroundHtmlParserOutstandingTokenLimit()) {
849 config->outstandingTokenLimit = 830 config->outstandingTokenLimit =
850 document() 831 document()
851 ->settings() 832 ->settings()
852 ->getBackgroundHtmlParserOutstandingTokenLimit(); 833 ->getBackgroundHtmlParserOutstandingTokenLimit();
853 } 834 }
854 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) { 835 if (document()->settings()->getBackgroundHtmlParserPendingTokenLimit()) {
855 config->pendingTokenLimit = 836 config->pendingTokenLimit =
856 document()->settings()->getBackgroundHtmlParserPendingTokenLimit(); 837 document()->settings()->getBackgroundHtmlParserPendingTokenLimit();
857 } 838 }
858 } 839 }
859 840
860 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); 841 DCHECK(config->xssAuditor->isSafeToSendToAnotherThread());
861 842
862 // The background parser is created on the main thread, but may otherwise
863 // only be used from the parser thread.
864 m_backgroundParser = 843 m_backgroundParser =
865 BackgroundHTMLParser::create(std::move(config), m_loadingTaskRunner); 844 BackgroundHTMLParser::create(this, *document(), std::move(config));
866 // TODO(csharrison): This is a hack to initialize MediaValuesCached on the
867 // correct thread. We should get rid of it.
868 m_backgroundParser->init(
869 document()->url(), CachedDocumentParameters::create(document()),
870 MediaValuesCached::MediaValuesCachedData(*document()));
871 }
872
873 void HTMLDocumentParser::stopBackgroundParser() {
874 ASSERT(shouldUseThreading());
875 ASSERT(m_haveBackgroundParser);
876
877 if (m_haveBackgroundParser && document()->frame() &&
878 document()->frame()->frameScheduler())
879 document()->frame()->frameScheduler()->setDocumentParsingInBackground(
880 false);
881
882 m_haveBackgroundParser = false;
883
884 // Make this sync, as lsan triggers on some unittests if the task runner is
885 // used.
886 m_backgroundParser->stop();
887 m_weakFactory.revokeAll();
888 } 845 }
889 846
890 void HTMLDocumentParser::append(const String& inputSource) { 847 void HTMLDocumentParser::append(const String& inputSource) {
891 if (isStopped()) 848 if (isStopped())
892 return; 849 return;
893 850
894 // We should never reach this point if we're using a parser thread, as 851 // We should never reach this point if we're using a parser thread, as
895 // appendBytes() will directly ship the data to the thread. 852 // appendBytes() will directly ship the data to the thread.
896 ASSERT(!shouldUseThreading()); 853 DCHECK(!shouldUseThreading());
897 854
898 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), 855 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
899 "HTMLDocumentParser::append", "size", inputSource.length()); 856 "HTMLDocumentParser::append", "size", inputSource.length());
900 const SegmentedString source(inputSource); 857 const SegmentedString source(inputSource);
901 858
902 if (document()->isPrefetchOnly()) { 859 if (document()->isPrefetchOnly()) {
903 if (!m_preloadScanner) 860 if (!m_preloadScanner)
904 m_preloadScanner = createPreloadScanner(); 861 m_preloadScanner = createPreloadScanner();
905 862
906 m_preloadScanner->appendToEnd(source); 863 m_preloadScanner->appendToEnd(source);
(...skipping 24 matching lines...) Expand all
931 // this data in a less-nested write(). 888 // this data in a less-nested write().
932 return; 889 return;
933 } 890 }
934 891
935 pumpTokenizerIfPossible(); 892 pumpTokenizerIfPossible();
936 893
937 endIfDelayed(); 894 endIfDelayed();
938 } 895 }
939 896
940 void HTMLDocumentParser::end() { 897 void HTMLDocumentParser::end() {
941 ASSERT(!isDetached()); 898 DCHECK(!isDetached());
942 ASSERT(!isScheduledForResume()); 899 DCHECK(!isScheduledForResume());
943 900
944 if (m_haveBackgroundParser) 901 m_backgroundParser.clear();
945 stopBackgroundParser();
946 902
947 // Informs the the rest of WebCore that parsing is really finished (and 903 // Informs the the rest of WebCore that parsing is really finished (and
948 // deletes this). 904 // deletes this).
949 m_treeBuilder->finished(); 905 m_treeBuilder->finished();
950 906
951 DocumentParser::stopParsing(); 907 DocumentParser::stopParsing();
952 } 908 }
953 909
954 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() { 910 void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd() {
955 ASSERT(isStopping()); 911 DCHECK(isStopping());
956 // FIXME: It may not be correct to disable this for the background parser. 912 // FIXME: It may not be correct to disable this for the background parser.
957 // That means hasInsertionPoint() may not be correct in some cases. 913 // That means hasInsertionPoint() may not be correct in some cases.
958 ASSERT(!hasInsertionPoint() || m_haveBackgroundParser); 914 DCHECK(!hasInsertionPoint() || m_backgroundParser);
959 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing()) 915 if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing())
960 return; 916 return;
961 end(); 917 end();
962 } 918 }
963 919
964 void HTMLDocumentParser::attemptToEnd() { 920 void HTMLDocumentParser::attemptToEnd() {
965 // finish() indicates we will not receive any more data. If we are waiting on 921 // finish() indicates we will not receive any more data. If we are waiting on
966 // an external script to load, we can't finish parsing quite yet. 922 // an external script to load, we can't finish parsing quite yet.
967 923
968 if (shouldDelayEnd()) { 924 if (shouldDelayEnd()) {
969 m_endWasDelayed = true; 925 m_endWasDelayed = true;
970 return; 926 return;
971 } 927 }
972 prepareToStopParsing(); 928 prepareToStopParsing();
973 } 929 }
974 930
975 void HTMLDocumentParser::endIfDelayed() { 931 void HTMLDocumentParser::endIfDelayed() {
976 // If we've already been detached, don't bother ending. 932 // If we've already been detached, don't bother ending.
977 if (isDetached()) 933 if (isDetached())
978 return; 934 return;
979 935
980 if (!m_endWasDelayed || shouldDelayEnd()) 936 if (!m_endWasDelayed || shouldDelayEnd())
981 return; 937 return;
982 938
983 m_endWasDelayed = false; 939 m_endWasDelayed = false;
984 prepareToStopParsing(); 940 prepareToStopParsing();
985 } 941 }
986 942
987 void HTMLDocumentParser::finish() { 943 void HTMLDocumentParser::finish() {
988 // FIXME: We should ASSERT(!m_parserStopped) here, since it does not makes 944 // FIXME: We should DCHECK(!m_parserStopped) here, since it does not makes
989 // sense to call any methods on DocumentParser once it's been stopped. 945 // sense to call any methods on DocumentParser once it's been stopped.
990 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. 946 // However, FrameLoader::stop calls DocumentParser::finish unconditionally.
991 947
992 flush(); 948 flush();
993 if (isDetached()) 949 if (isDetached())
994 return; 950 return;
995 951
996 // Empty documents never got an append() call, and thus have never started a 952 // Empty documents never got an append() call, and thus have never started a
997 // background parser. In those cases, we ignore shouldUseThreading() and fall 953 // background parser. In those cases, we ignore shouldUseThreading() and fall
998 // through to the non-threading case. 954 // through to the non-threading case.
999 if (m_haveBackgroundParser) { 955 if (m_backgroundParser) {
1000 if (!m_input.haveSeenEndOfFile()) 956 if (!m_input.haveSeenEndOfFile())
1001 m_input.closeWithoutMarkingEndOfFile(); 957 m_input.closeWithoutMarkingEndOfFile();
1002 m_loadingTaskRunner->postTask( 958 m_backgroundParser->finish();
1003 BLINK_FROM_HERE,
1004 WTF::bind(&BackgroundHTMLParser::finish, m_backgroundParser));
1005 return; 959 return;
1006 } 960 }
1007 961
1008 if (!m_tokenizer) { 962 if (!m_tokenizer) {
1009 ASSERT(!m_token); 963 DCHECK(!m_token);
1010 // We're finishing before receiving any data. Rather than booting up the 964 // We're finishing before receiving any data. Rather than booting up the
1011 // background parser just to spin it down, we finish parsing synchronously. 965 // background parser just to spin it down, we finish parsing synchronously.
1012 m_token = WTF::wrapUnique(new HTMLToken); 966 m_token = WTF::wrapUnique(new HTMLToken);
1013 m_tokenizer = HTMLTokenizer::create(m_options); 967 m_tokenizer = HTMLTokenizer::create(m_options);
1014 } 968 }
1015 969
1016 // We're not going to get any more data off the network, so we tell the input 970 // We're not going to get any more data off the network, so we tell the input
1017 // stream we've reached the end of file. finish() can be called more than 971 // stream we've reached the end of file. finish() can be called more than
1018 // once, if the first time does not call end(). 972 // once, if the first time does not call end().
1019 if (!m_input.haveSeenEndOfFile()) 973 if (!m_input.haveSeenEndOfFile())
1020 m_input.markEndOfFile(); 974 m_input.markEndOfFile();
1021 975
1022 attemptToEnd(); 976 attemptToEnd();
1023 } 977 }
1024 978
1025 bool HTMLDocumentParser::isExecutingScript() const { 979 bool HTMLDocumentParser::isExecutingScript() const {
1026 if (!m_scriptRunner) 980 if (!m_scriptRunner)
1027 return false; 981 return false;
1028 return m_scriptRunner->isExecutingScript(); 982 return m_scriptRunner->isExecutingScript();
1029 } 983 }
1030 984
1031 bool HTMLDocumentParser::isParsingAtLineNumber() const { 985 bool HTMLDocumentParser::isParsingAtLineNumber() const {
1032 return m_isParsingAtLineNumber && 986 return m_isParsingAtLineNumber &&
1033 ScriptableDocumentParser::isParsingAtLineNumber(); 987 ScriptableDocumentParser::isParsingAtLineNumber();
1034 } 988 }
1035 989
1036 OrdinalNumber HTMLDocumentParser::lineNumber() const { 990 OrdinalNumber HTMLDocumentParser::lineNumber() const {
1037 if (m_haveBackgroundParser) 991 if (m_backgroundParser)
1038 return m_textPosition.m_line; 992 return m_textPosition.m_line;
1039 993
1040 return m_input.current().currentLine(); 994 return m_input.current().currentLine();
1041 } 995 }
1042 996
1043 TextPosition HTMLDocumentParser::textPosition() const { 997 TextPosition HTMLDocumentParser::textPosition() const {
1044 if (m_haveBackgroundParser) 998 if (m_backgroundParser)
1045 return m_textPosition; 999 return m_textPosition;
1046 1000
1047 const SegmentedString& currentString = m_input.current(); 1001 const SegmentedString& currentString = m_input.current();
1048 OrdinalNumber line = currentString.currentLine(); 1002 OrdinalNumber line = currentString.currentLine();
1049 OrdinalNumber column = currentString.currentColumn(); 1003 OrdinalNumber column = currentString.currentColumn();
1050 1004
1051 return TextPosition(line, column); 1005 return TextPosition(line, column);
1052 } 1006 }
1053 1007
1054 bool HTMLDocumentParser::isWaitingForScripts() const { 1008 bool HTMLDocumentParser::isWaitingForScripts() const {
1055 // When the TreeBuilder encounters a </script> tag, it returns to the 1009 // When the TreeBuilder encounters a </script> tag, it returns to the
1056 // HTMLDocumentParser where the script is transfered from the treebuilder to 1010 // HTMLDocumentParser where the script is transfered from the treebuilder to
1057 // the script runner. The script runner will hold the script until its loaded 1011 // the script runner. The script runner will hold the script until its loaded
1058 // and run. During any of this time, we want to count ourselves as "waiting 1012 // and run. During any of this time, we want to count ourselves as "waiting
1059 // for a script" and thus run the preload scanner, as well as delay completion 1013 // for a script" and thus run the preload scanner, as well as delay completion
1060 // of parsing. 1014 // of parsing.
1061 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript(); 1015 bool treeBuilderHasBlockingScript = m_treeBuilder->hasParserBlockingScript();
1062 bool scriptRunnerHasBlockingScript = 1016 bool scriptRunnerHasBlockingScript =
1063 m_scriptRunner && m_scriptRunner->hasParserBlockingScript(); 1017 m_scriptRunner && m_scriptRunner->hasParserBlockingScript();
1064 // Since the parser is paused while a script runner has a blocking script, it 1018 // Since the parser is paused while a script runner has a blocking script, it
1065 // should never be possible to end up with both objects holding a blocking 1019 // should never be possible to end up with both objects holding a blocking
1066 // script. 1020 // script.
1067 ASSERT(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript)); 1021 DCHECK(!(treeBuilderHasBlockingScript && scriptRunnerHasBlockingScript));
1068 // If either object has a blocking script, the parser should be paused. 1022 // If either object has a blocking script, the parser should be paused.
1069 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript || 1023 return treeBuilderHasBlockingScript || scriptRunnerHasBlockingScript ||
1070 m_reentryPermit->parserPauseFlag(); 1024 m_reentryPermit->parserPauseFlag();
1071 } 1025 }
1072 1026
1073 void HTMLDocumentParser::resumeParsingAfterPause() { 1027 void HTMLDocumentParser::resumeParsingAfterPause() {
1074 ASSERT(!isExecutingScript()); 1028 DCHECK(!isExecutingScript());
1075 DCHECK(!isPaused()); 1029 DCHECK(!isPaused());
1076 1030
1077 checkIfBodyStlyesheetAdded(); 1031 checkIfBodyStlyesheetAdded();
1078 if (isPaused()) 1032 if (isPaused())
1079 return; 1033 return;
1080 1034
1081 if (m_haveBackgroundParser) { 1035 if (m_backgroundParser) {
1082 if (m_lastChunkBeforePause) { 1036 if (m_lastChunkBeforePause) {
1083 validateSpeculations(std::move(m_lastChunkBeforePause)); 1037 validateSpeculations(std::move(m_lastChunkBeforePause));
1084 DCHECK(!m_lastChunkBeforePause); 1038 DCHECK(!m_lastChunkBeforePause);
1085 pumpPendingSpeculations(); 1039 pumpPendingSpeculations();
1086 } 1040 }
1087 return; 1041 return;
1088 } 1042 }
1089 1043
1090 m_insertionPreloadScanner.reset(); 1044 m_insertionPreloadScanner.reset();
1091 if (m_tokenizer) { 1045 if (m_tokenizer) {
1092 pumpTokenizerIfPossible(); 1046 pumpTokenizerIfPossible();
1093 } 1047 }
1094 endIfDelayed(); 1048 endIfDelayed();
1095 } 1049 }
1096 1050
1097 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() { 1051 void HTMLDocumentParser::appendCurrentInputStreamToPreloadScannerAndScan() {
1098 ASSERT(m_preloadScanner); 1052 DCHECK(m_preloadScanner);
1099 m_preloadScanner->appendToEnd(m_input.current()); 1053 m_preloadScanner->appendToEnd(m_input.current());
1100 scanAndPreload(m_preloadScanner.get()); 1054 scanAndPreload(m_preloadScanner.get());
1101 } 1055 }
1102 1056
1103 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) { 1057 void HTMLDocumentParser::notifyScriptLoaded(PendingScript* pendingScript) {
1104 ASSERT(m_scriptRunner); 1058 DCHECK(m_scriptRunner);
1105 ASSERT(!isExecutingScript()); 1059 DCHECK(!isExecutingScript());
1106 1060
1107 if (isStopped()) { 1061 if (isStopped()) {
1108 return; 1062 return;
1109 } 1063 }
1110 1064
1111 if (isStopping()) { 1065 if (isStopping()) {
1112 attemptToRunDeferredScriptsAndEnd(); 1066 attemptToRunDeferredScriptsAndEnd();
1113 return; 1067 return;
1114 } 1068 }
1115 1069
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 ParserContentPolicy parserContentPolicy) { 1119 ParserContentPolicy parserContentPolicy) {
1166 HTMLDocumentParser* parser = 1120 HTMLDocumentParser* parser =
1167 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy); 1121 HTMLDocumentParser::create(fragment, contextElement, parserContentPolicy);
1168 parser->append(source); 1122 parser->append(source);
1169 parser->finish(); 1123 parser->finish();
1170 // Allows ~DocumentParser to assert it was detached before destruction. 1124 // Allows ~DocumentParser to assert it was detached before destruction.
1171 parser->detach(); 1125 parser->detach();
1172 } 1126 }
1173 1127
1174 void HTMLDocumentParser::suspendScheduledTasks() { 1128 void HTMLDocumentParser::suspendScheduledTasks() {
1175 ASSERT(!m_tasksWereSuspended); 1129 DCHECK(!m_tasksWereSuspended);
1176 m_tasksWereSuspended = true; 1130 m_tasksWereSuspended = true;
1177 if (m_parserScheduler) 1131 if (m_parserScheduler)
1178 m_parserScheduler->suspend(); 1132 m_parserScheduler->suspend();
1179 } 1133 }
1180 1134
1181 void HTMLDocumentParser::resumeScheduledTasks() { 1135 void HTMLDocumentParser::resumeScheduledTasks() {
1182 ASSERT(m_tasksWereSuspended); 1136 DCHECK(m_tasksWereSuspended);
1183 m_tasksWereSuspended = false; 1137 m_tasksWereSuspended = false;
1184 if (m_parserScheduler) 1138 if (m_parserScheduler)
1185 m_parserScheduler->resume(); 1139 m_parserScheduler->resume();
1186 } 1140 }
1187 1141
1188 void HTMLDocumentParser::appendBytes(const char* data, size_t length) { 1142 void HTMLDocumentParser::appendBytes(const char* data, size_t length) {
1189 if (!length || isStopped()) 1143 if (!length || isStopped())
1190 return; 1144 return;
1191 1145
1192 if (shouldUseThreading()) { 1146 if (shouldUseThreading()) {
1193 double bytesReceivedTime = monotonicallyIncreasingTimeMS(); 1147 double bytesReceivedTime = monotonicallyIncreasingTimeMS();
1194 if (!m_haveBackgroundParser) 1148 if (!m_backgroundParser)
1195 startBackgroundParser(); 1149 startBackgroundParser();
1196 1150
1197 std::unique_ptr<Vector<char>> buffer = 1151 std::unique_ptr<Vector<char>> buffer =
1198 WTF::makeUnique<Vector<char>>(length); 1152 WTF::makeUnique<Vector<char>>(length);
1199 memcpy(buffer->data(), data, length); 1153 memcpy(buffer->data(), data, length);
1200 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"), 1154 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
1201 "HTMLDocumentParser::appendBytes", "size", (unsigned)length); 1155 "HTMLDocumentParser::appendBytes", "size", (unsigned)length);
1202 1156
1203 m_loadingTaskRunner->postTask( 1157 m_backgroundParser->appendRawBytesFromMainThread(std::move(buffer),
1204 BLINK_FROM_HERE, 1158 bytesReceivedTime);
1205 WTF::bind(&BackgroundHTMLParser::appendRawBytesFromMainThread,
1206 m_backgroundParser, WTF::passed(std::move(buffer)),
1207 bytesReceivedTime));
1208 return; 1159 return;
1209 } 1160 }
1210 1161
1211 DecodedDataDocumentParser::appendBytes(data, length); 1162 DecodedDataDocumentParser::appendBytes(data, length);
1212 } 1163 }
1213 1164
1214 void HTMLDocumentParser::flush() { 1165 void HTMLDocumentParser::flush() {
1215 // If we've got no decoder, we never received any data. 1166 // If we've got no decoder, we never received any data.
1216 if (isDetached() || needsDecoder()) 1167 if (isDetached() || needsDecoder())
1217 return; 1168 return;
1218 1169
1219 if (shouldUseThreading()) { 1170 if (shouldUseThreading()) {
1220 // In some cases, flush() is called without any invocation of appendBytes. 1171 // In some cases, flush() is called without any invocation of appendBytes.
1221 // Fallback to synchronous parsing in that case. 1172 // Fallback to synchronous parsing in that case.
1222 if (!m_haveBackgroundParser) { 1173 if (!m_backgroundParser) {
1223 m_shouldUseThreading = false; 1174 m_shouldUseThreading = false;
1224 m_token = WTF::wrapUnique(new HTMLToken); 1175 m_token = WTF::wrapUnique(new HTMLToken);
1225 m_tokenizer = HTMLTokenizer::create(m_options); 1176 m_tokenizer = HTMLTokenizer::create(m_options);
1226 DecodedDataDocumentParser::flush(); 1177 DecodedDataDocumentParser::flush();
1227 return; 1178 return;
1228 } 1179 }
1229 1180 m_backgroundParser->flush();
1230 m_loadingTaskRunner->postTask(
1231 BLINK_FROM_HERE,
1232 WTF::bind(&BackgroundHTMLParser::flush, m_backgroundParser));
1233 } else { 1181 } else {
1234 DecodedDataDocumentParser::flush(); 1182 DecodedDataDocumentParser::flush();
1235 } 1183 }
1236 } 1184 }
1237 1185
1238 void HTMLDocumentParser::setDecoder( 1186 void HTMLDocumentParser::setDecoder(
1239 std::unique_ptr<TextResourceDecoder> decoder) { 1187 std::unique_ptr<TextResourceDecoder> decoder) {
1240 ASSERT(decoder); 1188 DCHECK(decoder);
1241 DecodedDataDocumentParser::setDecoder(std::move(decoder)); 1189 DecodedDataDocumentParser::setDecoder(std::move(decoder));
1242 1190
1243 if (m_haveBackgroundParser) { 1191 if (m_backgroundParser)
1244 m_loadingTaskRunner->postTask( 1192 m_backgroundParser->setDecoder(takeDecoder());
1245 BLINK_FROM_HERE,
1246 WTF::bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser,
1247 WTF::passed(takeDecoder())));
1248 }
1249 } 1193 }
1250 1194
1251 void HTMLDocumentParser::documentElementAvailable() { 1195 void HTMLDocumentParser::documentElementAvailable() {
1252 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable"); 1196 TRACE_EVENT0("blink,loader", "HTMLDocumentParser::documentElementAvailable");
1253 DCHECK(document()->documentElement()); 1197 DCHECK(document()->documentElement());
1254 fetchQueuedPreloads(); 1198 fetchQueuedPreloads();
1255 } 1199 }
1256 1200
1257 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() { 1201 std::unique_ptr<HTMLPreloadScanner> HTMLDocumentParser::createPreloadScanner() {
1258 return HTMLPreloadScanner::create( 1202 return HTMLPreloadScanner::create(
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 successHistogram.count(duration); 1274 successHistogram.count(duration);
1331 } else { 1275 } else {
1332 DEFINE_STATIC_LOCAL( 1276 DEFINE_STATIC_LOCAL(
1333 CustomCountHistogram, failureHistogram, 1277 CustomCountHistogram, failureHistogram,
1334 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50)); 1278 ("PreloadScanner.DocumentWrite.ExecutionTime.Failure", 1, 10000, 50));
1335 failureHistogram.count(duration); 1279 failureHistogram.count(duration);
1336 } 1280 }
1337 } 1281 }
1338 1282
1339 } // namespace blink 1283 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698