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

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

Issue 100563004: Redirect HTML resource bytes directly to parser thread (Blink side CL) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@parserthread_decodermove
Patch Set: Created 6 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
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
(...skipping 15 matching lines...) Expand all
26 #include "config.h" 26 #include "config.h"
27 #include "core/html/parser/HTMLDocumentParser.h" 27 #include "core/html/parser/HTMLDocumentParser.h"
28 28
29 #include "HTMLNames.h" 29 #include "HTMLNames.h"
30 #include "core/dom/DocumentFragment.h" 30 #include "core/dom/DocumentFragment.h"
31 #include "core/dom/Element.h" 31 #include "core/dom/Element.h"
32 #include "core/html/HTMLDocument.h" 32 #include "core/html/HTMLDocument.h"
33 #include "core/html/parser/AtomicHTMLToken.h" 33 #include "core/html/parser/AtomicHTMLToken.h"
34 #include "core/html/parser/BackgroundHTMLParser.h" 34 #include "core/html/parser/BackgroundHTMLParser.h"
35 #include "core/html/parser/HTMLParserScheduler.h" 35 #include "core/html/parser/HTMLParserScheduler.h"
36 #include "core/html/parser/HTMLParserThread.h"
37 #include "core/html/parser/HTMLScriptRunner.h" 36 #include "core/html/parser/HTMLScriptRunner.h"
38 #include "core/html/parser/HTMLTreeBuilder.h" 37 #include "core/html/parser/HTMLTreeBuilder.h"
39 #include "core/inspector/InspectorInstrumentation.h" 38 #include "core/inspector/InspectorInstrumentation.h"
40 #include "core/frame/Frame.h" 39 #include "core/frame/Frame.h"
40 #include "core/loader/DocumentLoader.h"
41 #include "platform/SharedBuffer.h" 41 #include "platform/SharedBuffer.h"
42 #include "platform/Task.h"
42 #include "platform/TraceEvent.h" 43 #include "platform/TraceEvent.h"
44 #include "public/platform/WebThread.h"
45 #include "public/platform/WebThreadedResourceProvider.h"
43 #include "wtf/Functional.h" 46 #include "wtf/Functional.h"
44 47
45 namespace WebCore { 48 namespace WebCore {
46 49
47 using namespace HTMLNames; 50 using namespace HTMLNames;
48 51
49 // This is a direct transcription of step 4 from: 52 // This is a direct transcription of step 4 from:
50 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case 53 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#frag ment-case
51 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem ent, bool reportErrors, const HTMLParserOptions& options) 54 static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem ent, bool reportErrors, const HTMLParserOptions& options)
52 { 55 {
(...skipping 11 matching lines...) Expand all
64 || (contextTag.matches(noscriptTag) && options.scriptEnabled) 67 || (contextTag.matches(noscriptTag) && options.scriptEnabled)
65 || contextTag.matches(noframesTag)) 68 || contextTag.matches(noframesTag))
66 return reportErrors ? HTMLTokenizer::RAWTEXTState : HTMLTokenizer::PLAIN TEXTState; 69 return reportErrors ? HTMLTokenizer::RAWTEXTState : HTMLTokenizer::PLAIN TEXTState;
67 if (contextTag.matches(scriptTag)) 70 if (contextTag.matches(scriptTag))
68 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL AINTEXTState; 71 return reportErrors ? HTMLTokenizer::ScriptDataState : HTMLTokenizer::PL AINTEXTState;
69 if (contextTag.matches(plaintextTag)) 72 if (contextTag.matches(plaintextTag))
70 return HTMLTokenizer::PLAINTEXTState; 73 return HTMLTokenizer::PLAINTEXTState;
71 return HTMLTokenizer::DataState; 74 return HTMLTokenizer::DataState;
72 } 75 }
73 76
77 class ParserResourceForegroundClient : public blink::WebThreadedResourceForegrou ndClient {
78 public:
79 ParserResourceForegroundClient(WeakPtr<HTMLDocumentParser> parser)
80 : m_parser(parser)
81 {
82 }
83
84 // WebThreadedResourceForegroundClient
85 virtual void didSwitchedToBackgroundClient() OVERRIDE FINAL {
darin (slow to review) 2014/02/16 07:12:27 nit: opening paren should be on the next line per
86 if (m_parser.get())
87 m_parser.get()->didSwitchedToBackgroundClient();
darin (slow to review) 2014/02/16 07:12:27 nit: "didSwitched..." should be "didSwitch..."
88 }
89
90 private:
91 WeakPtr<HTMLDocumentParser> m_parser;
92 };
93
94 blink::WebThread* HTMLDocumentParser::s_parserThread = 0;
95
74 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors ) 96 HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors )
75 : ScriptableDocumentParser(document) 97 : ScriptableDocumentParser(document)
76 , m_options(document) 98 , m_options(document)
77 , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken)) 99 , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken))
78 , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_opt ions)) 100 , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_opt ions))
79 , m_scriptRunner(HTMLScriptRunner::create(document, this)) 101 , m_scriptRunner(HTMLScriptRunner::create(document, this))
80 , m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy( ), reportErrors, m_options)) 102 , m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy( ), reportErrors, m_options))
81 , m_parserScheduler(HTMLParserScheduler::create(this)) 103 , m_parserScheduler(HTMLParserScheduler::create(this))
82 , m_xssAuditorDelegate(document) 104 , m_xssAuditorDelegate(document)
83 , m_weakFactory(this) 105 , m_weakFactory(this)
84 , m_preloader(adoptPtr(new HTMLResourcePreloader(document))) 106 , m_preloader(adoptPtr(new HTMLResourcePreloader(document)))
85 , m_isPinnedToMainThread(false) 107 , m_isPinnedToMainThread(false)
86 , m_endWasDelayed(false) 108 , m_endWasDelayed(false)
87 , m_haveBackgroundParser(false) 109 , m_haveBackgroundParser(false)
88 , m_pumpSessionNestingLevel(0) 110 , m_pumpSessionNestingLevel(0)
111 , m_parserThreadIsStandalone(false)
89 { 112 {
90 ASSERT(shouldUseThreading() || (m_token && m_tokenizer)); 113 ASSERT(shouldUseThreading() || (m_token && m_tokenizer));
91 } 114 }
92 115
93 // FIXME: Member variables should be grouped into self-initializing structs to 116 // FIXME: Member variables should be grouped into self-initializing structs to
94 // minimize code duplication between these constructors. 117 // minimize code duplication between these constructors.
95 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont extElement, ParserContentPolicy parserContentPolicy) 118 HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont extElement, ParserContentPolicy parserContentPolicy)
96 : ScriptableDocumentParser(&fragment->document(), parserContentPolicy) 119 : ScriptableDocumentParser(&fragment->document(), parserContentPolicy)
97 , m_options(&fragment->document()) 120 , m_options(&fragment->document())
98 , m_token(adoptPtr(new HTMLToken)) 121 , m_token(adoptPtr(new HTMLToken))
99 , m_tokenizer(HTMLTokenizer::create(m_options)) 122 , m_tokenizer(HTMLTokenizer::create(m_options))
100 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this ->parserContentPolicy(), m_options)) 123 , m_treeBuilder(HTMLTreeBuilder::create(this, fragment, contextElement, this ->parserContentPolicy(), m_options))
101 , m_xssAuditorDelegate(&fragment->document()) 124 , m_xssAuditorDelegate(&fragment->document())
102 , m_weakFactory(this) 125 , m_weakFactory(this)
103 , m_isPinnedToMainThread(true) 126 , m_isPinnedToMainThread(true)
104 , m_endWasDelayed(false) 127 , m_endWasDelayed(false)
105 , m_haveBackgroundParser(false) 128 , m_haveBackgroundParser(false)
106 , m_pumpSessionNestingLevel(0) 129 , m_pumpSessionNestingLevel(0)
130 , m_parserThreadIsStandalone(false)
107 { 131 {
108 ASSERT(!shouldUseThreading()); 132 ASSERT(!shouldUseThreading());
109 bool reportErrors = false; // For now document fragment parsing never report s errors. 133 bool reportErrors = false; // For now document fragment parsing never report s errors.
110 m_tokenizer->setState(tokenizerStateForContextElement(contextElement, report Errors, m_options)); 134 m_tokenizer->setState(tokenizerStateForContextElement(contextElement, report Errors, m_options));
111 m_xssAuditor.initForFragment(); 135 m_xssAuditor.initForFragment();
112 } 136 }
113 137
114 HTMLDocumentParser::~HTMLDocumentParser() 138 HTMLDocumentParser::~HTMLDocumentParser()
115 { 139 {
116 ASSERT(!m_parserScheduler); 140 ASSERT(!m_parserScheduler);
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately. 339 chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately.
316 m_speculations.append(chunk); 340 m_speculations.append(chunk);
317 pumpPendingSpeculations(); 341 pumpPendingSpeculations();
318 } 342 }
319 343
320 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data) 344 void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume ntEncodingData& data)
321 { 345 {
322 document()->setEncodingData(data); 346 document()->setEncodingData(data);
323 } 347 }
324 348
349 void HTMLDocumentParser::destroyResourceProvider(PassOwnPtr<blink::WebThreadedRe sourceProvider> resourceProvider)
350 {
351 // Here to let the resource bridge be destructed on the main thread.
darin (slow to review) 2014/02/16 07:12:27 nit: I think this is a reference to ResourceLoader
352 }
353
325 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk) 354 void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk)
326 { 355 {
327 ASSERT(chunk); 356 ASSERT(chunk);
328 if (isWaitingForScripts()) { 357 if (isWaitingForScripts()) {
329 // We're waiting on a network script, just save the chunk, we'll get 358 // We're waiting on a network script, just save the chunk, we'll get
330 // a second validateSpeculations call after the script completes. 359 // a second validateSpeculations call after the script completes.
331 // This call should have been made immediately after runScriptsForPaused TreeBuilder 360 // This call should have been made immediately after runScriptsForPaused TreeBuilder
332 // which may have started a network load and left us waiting. 361 // which may have started a network load and left us waiting.
333 ASSERT(!m_lastChunkBeforeScript); 362 ASSERT(!m_lastChunkBeforeScript);
334 m_lastChunkBeforeScript = chunk; 363 m_lastChunkBeforeScript = chunk;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 checkpoint->parser = m_weakFactory.createWeakPtr(); 399 checkpoint->parser = m_weakFactory.createWeakPtr();
371 checkpoint->token = token; 400 checkpoint->token = token;
372 checkpoint->tokenizer = tokenizer; 401 checkpoint->tokenizer = tokenizer;
373 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get()); 402 checkpoint->treeBuilderState = HTMLTreeBuilderSimulator::stateFor(m_treeBuil der.get());
374 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint; 403 checkpoint->inputCheckpoint = lastChunkBeforeScript->inputCheckpoint;
375 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint; 404 checkpoint->preloadScannerCheckpoint = lastChunkBeforeScript->preloadScanner Checkpoint;
376 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy(); 405 checkpoint->unparsedInput = m_input.current().toString().isolatedCopy();
377 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared. 406 m_input.current().clear(); // FIXME: This should be passed in instead of cle ared.
378 407
379 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread()); 408 ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread());
380 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, checkpoint.release())); 409 ASSERT(s_parserThread);
410 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::resumeFrom, m_ backgroundParser, checkpoint.release())));
381 } 411 }
382 412
383 void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse dChunk> popChunk) 413 void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse dChunk> popChunk)
384 { 414 {
385 TRACE_EVENT0("webkit", "HTMLDocumentParser::processParsedChunkFromBackground Parser"); 415 TRACE_EVENT0("webkit", "HTMLDocumentParser::processParsedChunkFromBackground Parser");
386 416
387 ASSERT_WITH_SECURITY_IMPLICATION(!document()->activeParserCount()); 417 ASSERT_WITH_SECURITY_IMPLICATION(!document()->activeParserCount());
388 ASSERT(!isParsingFragment()); 418 ASSERT(!isParsingFragment());
389 ASSERT(!isWaitingForScripts()); 419 ASSERT(!isWaitingForScripts());
390 ASSERT(!isStopped()); 420 ASSERT(!isStopped());
391 // ASSERT that this object is both attached to the Document and protected. 421 // ASSERT that this object is both attached to the Document and protected.
392 ASSERT(refCount() >= 2); 422 ASSERT(refCount() >= 2);
393 ASSERT(shouldUseThreading()); 423 ASSERT(shouldUseThreading());
394 ASSERT(!m_tokenizer); 424 ASSERT(!m_tokenizer);
395 ASSERT(!m_token); 425 ASSERT(!m_token);
396 ASSERT(!m_lastChunkBeforeScript); 426 ASSERT(!m_lastChunkBeforeScript);
427 ASSERT(s_parserThread);
397 428
398 ActiveParserSession session(contextForParsingSession()); 429 ActiveParserSession session(contextForParsingSession());
399 430
400 OwnPtr<ParsedChunk> chunk(popChunk); 431 OwnPtr<ParsedChunk> chunk(popChunk);
401 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release(); 432 OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release();
402 433
403 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::startedChun kWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)); 434 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::startedChunkWi thCheckpoint, m_backgroundParser, chunk->inputCheckpoint)));
404 435
405 for (XSSInfoStream::const_iterator it = chunk->xssInfos.begin(); it != chunk ->xssInfos.end(); ++it) { 436 for (XSSInfoStream::const_iterator it = chunk->xssInfos.begin(); it != chunk ->xssInfos.end(); ++it) {
406 m_textPosition = (*it)->m_textPosition; 437 m_textPosition = (*it)->m_textPosition;
407 m_xssAuditorDelegate.didBlockScript(**it); 438 m_xssAuditorDelegate.didBlockScript(**it);
408 if (isStopped()) 439 if (isStopped())
409 break; 440 break;
410 } 441 }
411 442
412 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) { 443 for (Vector<CompactHTMLToken>::const_iterator it = tokens->begin(); it != to kens->end(); ++it) {
413 ASSERT(!isWaitingForScripts()); 444 ASSERT(!isWaitingForScripts());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 m_parserScheduler->scheduleForResume(); 515 m_parserScheduler->scheduleForResume();
485 break; 516 break;
486 } 517 }
487 } 518 }
488 519
489 InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt()); 520 InspectorInstrumentation::didWriteHTML(cookie, lineNumber().zeroBasedInt());
490 } 521 }
491 522
492 void HTMLDocumentParser::forcePlaintextForTextDocument() 523 void HTMLDocumentParser::forcePlaintextForTextDocument()
493 { 524 {
494 if (shouldUseThreading()) { 525 if (shouldUseThreading() && !m_haveBackgroundParser)
495 // This method is called before any data is appended, so we have to star t 526 startBackgroundParser();
496 // the background parser ourselves.
497 if (!m_haveBackgroundParser)
498 startBackgroundParser();
499 527
500 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::forcePl aintextForTextDocument, m_backgroundParser)); 528 if (m_haveBackgroundParser)
501 } else 529 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::forcePlain textForTextDocument, m_backgroundParser)));
530 else
502 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState); 531 m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
503 } 532 }
504 533
505 Document* HTMLDocumentParser::contextForParsingSession() 534 Document* HTMLDocumentParser::contextForParsingSession()
506 { 535 {
507 // The parsing session should interact with the document only when parsing 536 // The parsing session should interact with the document only when parsing
508 // non-fragments. Otherwise, we might delay the load event mistakenly. 537 // non-fragments. Otherwise, we might delay the load event mistakenly.
509 if (isParsingFragment()) 538 if (isParsingFragment())
510 return 0; 539 return 0;
511 return document(); 540 return document();
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 } 684 }
656 685
657 endIfDelayed(); 686 endIfDelayed();
658 } 687 }
659 688
660 void HTMLDocumentParser::startBackgroundParser() 689 void HTMLDocumentParser::startBackgroundParser()
661 { 690 {
662 ASSERT(!isStopped()); 691 ASSERT(!isStopped());
663 ASSERT(shouldUseThreading()); 692 ASSERT(shouldUseThreading());
664 ASSERT(!m_haveBackgroundParser); 693 ASSERT(!m_haveBackgroundParser);
694
695 OwnPtr<blink::WebThreadedResourceProvider> resourceProvider = document()->lo ader()->createThreadedResourceProvider();
696 if (resourceProvider) {
697 // The resource provider is responsible for destroying the client we cre ate here.
698 resourceProvider->setForegroundClient(new ParserResourceForegroundClient (m_weakFactory.createWeakPtr()));
699 if (!s_parserThread)
700 s_parserThread = resourceProvider->resourceProviderThread();
darin (slow to review) 2014/02/16 07:12:27 nit: perhaps it would be better to have Blink crea
701 ASSERT(s_parserThread && s_parserThread == resourceProvider->resourcePro viderThread());
702 }
703
704 if (!s_parserThread) {
705 // If we don't have a thread object, we can't use threading and must
706 // fall back to singlethreaded mode by having our own tokenizer.
707 if (!m_token)
708 m_token = adoptPtr(new HTMLToken);
709 if (!m_tokenizer)
710 m_tokenizer = HTMLTokenizer::create(m_options);
711 return;
712 }
713
665 m_haveBackgroundParser = true; 714 m_haveBackgroundParser = true;
666 715
667 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg roundHTMLParser>::createUnbound(); 716 RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<Backg roundHTMLParser>::createUnbound();
668 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference); 717 m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference);
669 718
670 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background HTMLParser::Configuration); 719 OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new Background HTMLParser::Configuration);
671 config->options = m_options; 720 config->options = m_options;
672 config->parser = m_weakFactory.createWeakPtr(); 721 config->parser = m_weakFactory.createWeakPtr();
673 config->xssAuditor = adoptPtr(new XSSAuditor); 722 config->xssAuditor = adoptPtr(new XSSAuditor);
674 config->xssAuditor->init(document(), &m_xssAuditorDelegate); 723 config->xssAuditor->init(document(), &m_xssAuditorDelegate);
675 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url(). copy(), document()->devicePixelRatio())); 724 config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url(). copy(), document()->devicePixelRatio()));
676 config->decoder = takeDecoder(); 725 config->decoder = takeDecoder();
726 config->resourceProvider = resourceProvider.release();
677 727
678 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread()); 728 ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
679 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread()); 729 ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
680 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, refe rence.release(), config.release())); 730 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::start, referen ce.release(), config.release())));
681 } 731 }
682 732
683 void HTMLDocumentParser::stopBackgroundParser() 733 void HTMLDocumentParser::stopBackgroundParser()
684 { 734 {
685 ASSERT(shouldUseThreading()); 735 ASSERT(shouldUseThreading());
686 ASSERT(m_haveBackgroundParser); 736 ASSERT(m_haveBackgroundParser);
737 ASSERT(s_parserThread);
687 m_haveBackgroundParser = false; 738 m_haveBackgroundParser = false;
688 739
689 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_bac kgroundParser)); 740 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::stop, m_backgr oundParser)));
690 m_weakFactory.revokeAll(); 741 m_weakFactory.revokeAll();
691 } 742 }
692 743
693 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource) 744 void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource)
694 { 745 {
695 if (isStopped()) 746 if (isStopped())
696 return; 747 return;
697 748
698 // We should never reach this point if we're using a parser thread, 749 // We should never reach this point if we're using a parser thread,
699 // as appendBytes() will directly ship the data to the thread. 750 // as appendBytes() will directly ship the data to the thread.
700 ASSERT(!shouldUseThreading()); 751 ASSERT(!m_haveBackgroundParser);
701 752
702 // pumpTokenizer can cause this parser to be detached from the Document, 753 // pumpTokenizer can cause this parser to be detached from the Document,
703 // but we need to ensure it isn't deleted yet. 754 // but we need to ensure it isn't deleted yet.
704 RefPtr<HTMLDocumentParser> protect(this); 755 RefPtr<HTMLDocumentParser> protect(this);
705 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt h()); 756 TRACE_EVENT1("net", "HTMLDocumentParser::append", "size", inputSource->lengt h());
706 String source(inputSource); 757 String source(inputSource);
707 758
708 if (m_preloadScanner) { 759 if (m_preloadScanner) {
709 if (m_input.current().isEmpty() && !isWaitingForScripts()) { 760 if (m_input.current().isEmpty() && !isWaitingForScripts()) {
710 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner. 761 // We have parsed until the end of the current input and so are now moving ahead of the preload scanner.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 // FIXME: We should ASSERT(!m_parserStopped) here, since it does not 843 // FIXME: We should ASSERT(!m_parserStopped) here, since it does not
793 // makes sense to call any methods on DocumentParser once it's been stopped. 844 // makes sense to call any methods on DocumentParser once it's been stopped.
794 // However, FrameLoader::stop calls DocumentParser::finish unconditionally. 845 // However, FrameLoader::stop calls DocumentParser::finish unconditionally.
795 846
796 // Empty documents never got an append() call, and thus have never started 847 // Empty documents never got an append() call, and thus have never started
797 // a background parser. In those cases, we ignore shouldUseThreading() 848 // a background parser. In those cases, we ignore shouldUseThreading()
798 // and fall through to the non-threading case. 849 // and fall through to the non-threading case.
799 if (m_haveBackgroundParser) { 850 if (m_haveBackgroundParser) {
800 if (!m_input.haveSeenEndOfFile()) 851 if (!m_input.haveSeenEndOfFile())
801 m_input.closeWithoutMarkingEndOfFile(); 852 m_input.closeWithoutMarkingEndOfFile();
802 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::finish, m_backgroundParser)); 853 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::finish, m_ backgroundParser)));
803 return; 854 return;
804 } 855 }
805 856
806 if (!m_tokenizer) { 857 if (!m_tokenizer) {
807 ASSERT(!m_token); 858 ASSERT(!m_token);
808 // We're finishing before receiving any data. Rather than booting up 859 // We're finishing before receiving any data. Rather than booting up
809 // the background parser just to spin it down, we finish parsing 860 // the background parser just to spin it down, we finish parsing
810 // synchronously. 861 // synchronously.
811 m_token = adoptPtr(new HTMLToken); 862 m_token = adoptPtr(new HTMLToken);
812 m_tokenizer = HTMLTokenizer::create(m_options); 863 m_tokenizer = HTMLTokenizer::create(m_options);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 { 1012 {
962 if (m_parserScheduler) 1013 if (m_parserScheduler)
963 m_parserScheduler->resume(); 1014 m_parserScheduler->resume();
964 } 1015 }
965 1016
966 void HTMLDocumentParser::appendBytes(const char* data, size_t length) 1017 void HTMLDocumentParser::appendBytes(const char* data, size_t length)
967 { 1018 {
968 if (!length || isStopped()) 1019 if (!length || isStopped())
969 return; 1020 return;
970 1021
971 if (shouldUseThreading()) { 1022 if (shouldUseThreading() && !m_haveBackgroundParser)
972 if (!m_haveBackgroundParser) 1023 startBackgroundParser();
973 startBackgroundParser(); 1024
1025 if (m_haveBackgroundParser) {
1026 if (m_parserThreadIsStandalone)
1027 return; // If this is set, the parser thread will receive the data d irectly.
974 1028
975 OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length)); 1029 OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length));
976 memcpy(buffer->data(), data, length); 1030 memcpy(buffer->data(), data, length);
977 TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned )length); 1031 TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned )length);
978 1032
979 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::appendB ytes, m_backgroundParser, buffer.release())); 1033 ASSERT(s_parserThread);
1034 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::appendByte s, m_backgroundParser, buffer.release())));
980 return; 1035 return;
981 } 1036 }
982 1037
983 DecodedDataDocumentParser::appendBytes(data, length); 1038 DecodedDataDocumentParser::appendBytes(data, length);
984 } 1039 }
985 1040
1041 void HTMLDocumentParser::didSwitchedToBackgroundClient()
1042 {
1043 if (isDetached())
1044 return;
1045
1046 ASSERT(s_parserThread);
1047 ASSERT(m_haveBackgroundParser);
1048 // At this point the background parser will start receiving data chunks dire ctly
1049 // from the I/O thread and we no longer need to pass it any data.
1050 m_parserThreadIsStandalone = true;
1051 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::didSwitchedToB ackgroundClient, m_backgroundParser)));
1052 }
1053
986 void HTMLDocumentParser::flush() 1054 void HTMLDocumentParser::flush()
987 { 1055 {
988 // If we've got no decoder, we never received any data. 1056 // If we've got no decoder, we never received any data.
989 if (isDetached() || needsDecoder()) 1057 if (isDetached() || needsDecoder())
990 return; 1058 return;
991 1059
992 if (m_haveBackgroundParser) 1060 if (m_haveBackgroundParser)
993 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush, m_backgroundParser)); 1061 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::flush, m_b ackgroundParser)));
994 else 1062 else
995 DecodedDataDocumentParser::flush(); 1063 DecodedDataDocumentParser::flush();
996 } 1064 }
997 1065
998 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder) 1066 void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder)
999 { 1067 {
1000 ASSERT(decoder); 1068 ASSERT(decoder);
1001 DecodedDataDocumentParser::setDecoder(decoder); 1069 DecodedDataDocumentParser::setDecoder(decoder);
1002 1070
1003 if (m_haveBackgroundParser) 1071 if (m_haveBackgroundParser)
1004 HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDeco der, m_backgroundParser, takeDecoder())); 1072 s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::setDecoder , m_backgroundParser, takeDecoder())));
1005 } 1073 }
1006 1074
1007 } 1075 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698