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

Unified 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: Missing include Created 7 years 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 side-by-side diff with in-line comments
Download patch
Index: Source/core/html/parser/HTMLDocumentParser.cpp
diff --git a/Source/core/html/parser/HTMLDocumentParser.cpp b/Source/core/html/parser/HTMLDocumentParser.cpp
index ff73092b2cbfbcead0f72a109aa85434652e03d4..6f6c39eaa888aa910d8f8075367232651601d07d 100644
--- a/Source/core/html/parser/HTMLDocumentParser.cpp
+++ b/Source/core/html/parser/HTMLDocumentParser.cpp
@@ -33,13 +33,16 @@
#include "core/html/parser/AtomicHTMLToken.h"
#include "core/html/parser/BackgroundHTMLParser.h"
#include "core/html/parser/HTMLParserScheduler.h"
-#include "core/html/parser/HTMLParserThread.h"
#include "core/html/parser/HTMLScriptRunner.h"
#include "core/html/parser/HTMLTreeBuilder.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/frame/Frame.h"
+#include "core/loader/DocumentLoader.h"
#include "platform/SharedBuffer.h"
+#include "platform/Task.h"
#include "platform/TraceEvent.h"
+#include "public/platform/WebParserResourceBridge.h"
+#include "public/platform/WebThread.h"
#include "wtf/Functional.h"
namespace WebCore {
@@ -74,8 +77,6 @@ static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors)
: ScriptableDocumentParser(document)
, m_options(document)
- , m_token(m_options.useThreading ? nullptr : adoptPtr(new HTMLToken))
- , m_tokenizer(m_options.useThreading ? nullptr : HTMLTokenizer::create(m_options))
, m_scriptRunner(HTMLScriptRunner::create(document, this))
, m_treeBuilder(HTMLTreeBuilder::create(this, document, parserContentPolicy(), reportErrors, m_options))
, m_parserScheduler(HTMLParserScheduler::create(this))
@@ -84,10 +85,17 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
, m_preloader(adoptPtr(new HTMLResourcePreloader(document)))
, m_isPinnedToMainThread(false)
, m_endWasDelayed(false)
- , m_haveBackgroundParser(false)
, m_pumpSessionNestingLevel(0)
+ , m_parserThread(0)
+ , m_parserThreadIsStandalone(false)
{
- ASSERT(shouldUseThreading() || (m_token && m_tokenizer));
+ if (shouldUseThreading())
+ startBackgroundParser();
abarth-chromium 2013/12/18 18:28:49 Does this integrate correctly with m_isPinnedToMai
oystein (OOO til 10th of July) 2014/01/13 23:19:50 As far as I can tell so far, parsers which aren't
+
+ if (!m_parserThread) {
+ m_token = adoptPtr(new HTMLToken);
+ m_tokenizer = HTMLTokenizer::create(m_options);
+ }
}
// FIXME: Member variables should be grouped into self-initializing structs to
@@ -102,8 +110,9 @@ HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont
, m_weakFactory(this)
, m_isPinnedToMainThread(true)
, m_endWasDelayed(false)
- , m_haveBackgroundParser(false)
, m_pumpSessionNestingLevel(0)
+ , m_parserThread(0)
+ , m_parserThreadIsStandalone(false)
{
ASSERT(!shouldUseThreading());
bool reportErrors = false; // For now document fragment parsing never reports errors.
@@ -117,7 +126,7 @@ HTMLDocumentParser::~HTMLDocumentParser()
ASSERT(!m_pumpSessionNestingLevel);
ASSERT(!m_preloadScanner);
ASSERT(!m_insertionPreloadScanner);
- ASSERT(!m_haveBackgroundParser);
+ ASSERT(!m_parserThread);
// FIXME: We should be able to ASSERT(m_speculations.isEmpty()),
// but there are cases where that's not true currently. For example,
// we we're told to stop parsing before we've consumed all the input.
@@ -125,7 +134,7 @@ HTMLDocumentParser::~HTMLDocumentParser()
void HTMLDocumentParser::pinToMainThread()
{
- ASSERT(!m_haveBackgroundParser);
+ ASSERT(!m_parserThread);
ASSERT(!m_isPinnedToMainThread);
m_isPinnedToMainThread = true;
if (!m_tokenizer) {
@@ -137,7 +146,7 @@ void HTMLDocumentParser::pinToMainThread()
void HTMLDocumentParser::detach()
{
- if (m_haveBackgroundParser)
+ if (m_parserThread)
stopBackgroundParser();
DocumentParser::detach();
if (m_scriptRunner)
@@ -154,7 +163,7 @@ void HTMLDocumentParser::stopParsing()
{
DocumentParser::stopParsing();
m_parserScheduler.clear(); // Deleting the scheduler will clear any timers.
- if (m_haveBackgroundParser)
+ if (m_parserThread)
stopBackgroundParser();
}
@@ -164,7 +173,7 @@ void HTMLDocumentParser::prepareToStopParsing()
{
// FIXME: It may not be correct to disable this for the background parser.
// That means hasInsertionPoint() may not be correct in some cases.
- ASSERT(!hasInsertionPoint() || m_haveBackgroundParser);
+ ASSERT(!hasInsertionPoint() || m_parserThread);
// pumpTokenizer can cause this parser to be detached from the Document,
// but we need to ensure it isn't deleted yet.
@@ -173,7 +182,7 @@ void HTMLDocumentParser::prepareToStopParsing()
// NOTE: This pump should only ever emit buffered character tokens,
// so ForceSynchronous vs. AllowYield should be meaningless.
if (m_tokenizer) {
- ASSERT(!m_haveBackgroundParser);
+ ASSERT(!m_parserThread);
pumpTokenizerIfPossible(ForceSynchronous);
}
@@ -201,7 +210,7 @@ bool HTMLDocumentParser::isParsingFragment() const
bool HTMLDocumentParser::processingData() const
{
- return isScheduledForResume() || inPumpSession() || m_haveBackgroundParser;
+ return isScheduledForResume() || inPumpSession() || m_parserThread;
}
void HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode)
@@ -233,7 +242,7 @@ void HTMLDocumentParser::resumeParsingAfterYield()
// but we need to ensure it isn't deleted yet.
RefPtr<HTMLDocumentParser> protect(this);
- if (m_haveBackgroundParser) {
+ if (m_parserThread) {
pumpPendingSpeculations();
return;
}
@@ -260,7 +269,7 @@ bool HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& ses
if (isStopped())
return false;
- ASSERT(!m_haveBackgroundParser || mode == ForceSynchronous);
+ ASSERT(!m_parserThread || mode == ForceSynchronous);
if (isWaitingForScripts()) {
if (mode == AllowYield)
@@ -322,6 +331,11 @@ void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume
document()->setEncodingData(data);
}
+void HTMLDocumentParser::destructResourceBridge(PassOwnPtr<blink::WebParserResourceBridge> resourceBridge)
+{
+ // Here to let the resource bridge be destructed on the main thread.
+}
+
void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk)
{
ASSERT(chunk);
@@ -377,7 +391,8 @@ void HTMLDocumentParser::discardSpeculationsAndResumeFrom(PassOwnPtr<ParsedChunk
m_input.current().clear(); // FIXME: This should be passed in instead of cleared.
ASSERT(checkpoint->unparsedInput.isSafeToSendToAnotherThread());
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, checkpoint.release()));
+ ASSERT(m_parserThread);
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, checkpoint.release())));
}
void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk> popChunk)
@@ -394,13 +409,14 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
ASSERT(!m_tokenizer);
ASSERT(!m_token);
ASSERT(!m_lastChunkBeforeScript);
+ ASSERT(m_parserThread);
ActiveParserSession session(contextForParsingSession());
OwnPtr<ParsedChunk> chunk(popChunk);
OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint));
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint)));
for (XSSInfoStream::const_iterator it = chunk->xssInfos.begin(); it != chunk->xssInfos.end(); ++it) {
m_textPosition = (*it)->m_textPosition;
@@ -491,14 +507,9 @@ void HTMLDocumentParser::pumpPendingSpeculations()
void HTMLDocumentParser::forcePlaintextForTextDocument()
{
- if (shouldUseThreading()) {
- // This method is called before any data is appended, so we have to start
- // the background parser ourselves.
- if (!m_haveBackgroundParser)
- startBackgroundParser();
-
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser));
- } else
+ if (m_parserThread)
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser)));
+ else
m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
}
@@ -519,7 +530,7 @@ void HTMLDocumentParser::pumpTokenizer(SynchronousMode mode)
ASSERT(refCount() >= 2);
ASSERT(m_tokenizer);
ASSERT(m_token);
- ASSERT(!m_haveBackgroundParser || mode == ForceSynchronous);
+ ASSERT(!m_parserThread || mode == ForceSynchronous);
PumpSession session(m_pumpSessionNestingLevel, contextForParsingSession());
@@ -634,7 +645,7 @@ void HTMLDocumentParser::insert(const SegmentedString& source)
if (!m_tokenizer) {
ASSERT(!inPumpSession());
- ASSERT(m_haveBackgroundParser || wasCreatedByScript());
+ ASSERT(m_parserThread || wasCreatedByScript());
m_token = adoptPtr(new HTMLToken);
m_tokenizer = HTMLTokenizer::create(m_options);
}
@@ -660,8 +671,14 @@ void HTMLDocumentParser::insert(const SegmentedString& source)
void HTMLDocumentParser::startBackgroundParser()
{
ASSERT(shouldUseThreading());
- ASSERT(!m_haveBackgroundParser);
- m_haveBackgroundParser = true;
+ ASSERT(!m_parserThread);
+
+ OwnPtr<blink::WebParserResourceBridge> resourceBridge = document()->loader()->constructParserResourceBridge();
+ if (!resourceBridge)
+ return;
+
+ m_parserThread = resourceBridge->getParserThread();
abarth-chromium 2013/12/18 18:28:49 getParserThread -> parserThread
+ ASSERT(m_parserThread);
RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<BackgroundHTMLParser>::createUnbound();
m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference);
@@ -673,19 +690,20 @@ void HTMLDocumentParser::startBackgroundParser()
config->xssAuditor->init(document(), &m_xssAuditorDelegate);
config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy(), document()->devicePixelRatio()));
config->decoder = takeDecoder();
+ config->resourceBridge = resourceBridge.release();
ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, reference.release(), config.release()));
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::start, reference.release(), config.release())));
}
void HTMLDocumentParser::stopBackgroundParser()
{
ASSERT(shouldUseThreading());
- ASSERT(m_haveBackgroundParser);
- m_haveBackgroundParser = false;
+ ASSERT(m_parserThread);
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_backgroundParser));
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::stop, m_backgroundParser)));
+ m_parserThread = 0;
m_weakFactory.revokeAll();
}
@@ -696,7 +714,7 @@ void HTMLDocumentParser::append(PassRefPtr<StringImpl> inputSource)
// We should never reach this point if we're using a parser thread,
// as appendBytes() will directly ship the data to the thread.
- ASSERT(!shouldUseThreading());
+ ASSERT(!m_parserThread);
// pumpTokenizer can cause this parser to be detached from the Document,
// but we need to ensure it isn't deleted yet.
@@ -743,7 +761,7 @@ void HTMLDocumentParser::end()
ASSERT(!isDetached());
ASSERT(!isScheduledForResume());
- if (m_haveBackgroundParser)
+ if (m_parserThread)
stopBackgroundParser();
// Informs the the rest of WebCore that parsing is really finished (and deletes this).
@@ -755,7 +773,7 @@ void HTMLDocumentParser::attemptToRunDeferredScriptsAndEnd()
ASSERT(isStopping());
// FIXME: It may not be correct to disable this for the background parser.
// That means hasInsertionPoint() may not be correct in some cases.
- ASSERT(!hasInsertionPoint() || m_haveBackgroundParser);
+ ASSERT(!hasInsertionPoint() || m_parserThread);
if (m_scriptRunner && !m_scriptRunner->executeScriptsWaitingForParsing())
return;
end();
@@ -795,10 +813,10 @@ void HTMLDocumentParser::finish()
// Empty documents never got an append() call, and thus have never started
// a background parser. In those cases, we ignore shouldUseThreading()
// and fall through to the non-threading case.
- if (m_haveBackgroundParser) {
+ if (m_parserThread) {
if (!m_input.haveSeenEndOfFile())
m_input.closeWithoutMarkingEndOfFile();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::finish, m_backgroundParser));
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::finish, m_backgroundParser)));
return;
}
@@ -829,7 +847,7 @@ bool HTMLDocumentParser::isExecutingScript() const
OrdinalNumber HTMLDocumentParser::lineNumber() const
{
- if (m_haveBackgroundParser)
+ if (m_parserThread)
return m_textPosition.m_line;
return m_input.current().currentLine();
@@ -837,7 +855,7 @@ OrdinalNumber HTMLDocumentParser::lineNumber() const
TextPosition HTMLDocumentParser::textPosition() const
{
- if (m_haveBackgroundParser)
+ if (m_parserThread)
return m_textPosition;
const SegmentedString& currentString = m_input.current();
@@ -868,7 +886,7 @@ void HTMLDocumentParser::resumeParsingAfterScriptExecution()
ASSERT(!isExecutingScript());
ASSERT(!isWaitingForScripts());
- if (m_haveBackgroundParser) {
+ if (m_parserThread) {
validateSpeculations(m_lastChunkBeforeScript.release());
ASSERT(!m_lastChunkBeforeScript);
// processParsedChunkFromBackgroundParser can cause this parser to be detached from the Document,
@@ -967,29 +985,41 @@ void HTMLDocumentParser::appendBytes(const char* data, size_t length)
if (!length || isDetached())
return;
- if (shouldUseThreading()) {
- if (!m_haveBackgroundParser)
- startBackgroundParser();
+ if (m_parserThread) {
+ if (m_parserThreadIsStandalone)
+ return; // If this is set, the parser thread will receive the data directly.
OwnPtr<Vector<char> > buffer = adoptPtr(new Vector<char>(length));
memcpy(buffer->data(), data, length);
TRACE_EVENT1("net", "HTMLDocumentParser::appendBytes", "size", (unsigned)length);
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::appendBytes, m_backgroundParser, buffer.release()));
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::appendBytes, m_backgroundParser, buffer.release())));
return;
}
DecodedDataDocumentParser::appendBytes(data, length);
}
+void HTMLDocumentParser::parserResourceMessageFilterAdded()
+{
+ if (isDetached())
+ return;
+
+ ASSERT(m_parserThread && !needsDecoder());
+ // At this point the background parser will start receiving data chunks directly
+ // from the I/O thread and we no longer need to pass it any data.
+ m_parserThreadIsStandalone = true;
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::resourceFilterAdded, m_backgroundParser)));
+}
+
void HTMLDocumentParser::flush()
{
// If we've got no decoder, we never received any data.
if (isDetached() || needsDecoder())
return;
- if (m_haveBackgroundParser)
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush, m_backgroundParser));
+ if (m_parserThread)
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::flush, m_backgroundParser)));
else
DecodedDataDocumentParser::flush();
}
@@ -998,8 +1028,8 @@ void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder)
{
DecodedDataDocumentParser::setDecoder(decoder);
- if (m_haveBackgroundParser)
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, takeDecoder()));
+ if (m_parserThread)
+ m_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, takeDecoder())));
}
}

Powered by Google App Engine
This is Rietveld 408576698