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

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: 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 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 84c9197c309a3f36d5ee241d57a959ea31b771b2..a87b8f65af0aee6d1efdd991eb1ac31b0d6206e1 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/WebThread.h"
+#include "public/platform/WebThreadedResourceProvider.h"
#include "wtf/Functional.h"
namespace WebCore {
@@ -71,6 +74,25 @@ static HTMLTokenizer::State tokenizerStateForContextElement(Element* contextElem
return HTMLTokenizer::DataState;
}
+class ParserResourceForegroundClient : public blink::WebThreadedResourceForegroundClient {
+public:
+ ParserResourceForegroundClient(WeakPtr<HTMLDocumentParser> parser)
+ : m_parser(parser)
+ {
+ }
+
+ // WebThreadedResourceForegroundClient
+ 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
+ if (m_parser.get())
+ m_parser.get()->didSwitchedToBackgroundClient();
darin (slow to review) 2014/02/16 07:12:27 nit: "didSwitched..." should be "didSwitch..."
+ }
+
+private:
+ WeakPtr<HTMLDocumentParser> m_parser;
+};
+
+blink::WebThread* HTMLDocumentParser::s_parserThread = 0;
+
HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors)
: ScriptableDocumentParser(document)
, m_options(document)
@@ -86,6 +108,7 @@ HTMLDocumentParser::HTMLDocumentParser(HTMLDocument* document, bool reportErrors
, m_endWasDelayed(false)
, m_haveBackgroundParser(false)
, m_pumpSessionNestingLevel(0)
+ , m_parserThreadIsStandalone(false)
{
ASSERT(shouldUseThreading() || (m_token && m_tokenizer));
}
@@ -104,6 +127,7 @@ HTMLDocumentParser::HTMLDocumentParser(DocumentFragment* fragment, Element* cont
, m_endWasDelayed(false)
, m_haveBackgroundParser(false)
, m_pumpSessionNestingLevel(0)
+ , m_parserThreadIsStandalone(false)
{
ASSERT(!shouldUseThreading());
bool reportErrors = false; // For now document fragment parsing never reports errors.
@@ -322,6 +346,11 @@ void HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser(const Docume
document()->setEncodingData(data);
}
+void HTMLDocumentParser::destroyResourceProvider(PassOwnPtr<blink::WebThreadedResourceProvider> resourceProvider)
+{
+ // 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
+}
+
void HTMLDocumentParser::validateSpeculations(PassOwnPtr<ParsedChunk> chunk)
{
ASSERT(chunk);
@@ -377,7 +406,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(s_parserThread);
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::resumeFrom, m_backgroundParser, checkpoint.release())));
}
void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk> popChunk)
@@ -394,13 +424,14 @@ void HTMLDocumentParser::processParsedChunkFromBackgroundParser(PassOwnPtr<Parse
ASSERT(!m_tokenizer);
ASSERT(!m_token);
ASSERT(!m_lastChunkBeforeScript);
+ ASSERT(s_parserThread);
ActiveParserSession session(contextForParsingSession());
OwnPtr<ParsedChunk> chunk(popChunk);
OwnPtr<CompactHTMLTokenStream> tokens = chunk->tokens.release();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::startedChunkWithCheckpoint, m_backgroundParser, chunk->inputCheckpoint));
+ s_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 +522,12 @@ 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();
+ if (shouldUseThreading() && !m_haveBackgroundParser)
+ startBackgroundParser();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser));
- } else
+ if (m_haveBackgroundParser)
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::forcePlaintextForTextDocument, m_backgroundParser)));
+ else
m_tokenizer->setState(HTMLTokenizer::PLAINTEXTState);
}
@@ -662,6 +691,26 @@ void HTMLDocumentParser::startBackgroundParser()
ASSERT(!isStopped());
ASSERT(shouldUseThreading());
ASSERT(!m_haveBackgroundParser);
+
+ OwnPtr<blink::WebThreadedResourceProvider> resourceProvider = document()->loader()->createThreadedResourceProvider();
+ if (resourceProvider) {
+ // The resource provider is responsible for destroying the client we create here.
+ resourceProvider->setForegroundClient(new ParserResourceForegroundClient(m_weakFactory.createWeakPtr()));
+ if (!s_parserThread)
+ s_parserThread = resourceProvider->resourceProviderThread();
darin (slow to review) 2014/02/16 07:12:27 nit: perhaps it would be better to have Blink crea
+ ASSERT(s_parserThread && s_parserThread == resourceProvider->resourceProviderThread());
+ }
+
+ if (!s_parserThread) {
+ // If we don't have a thread object, we can't use threading and must
+ // fall back to singlethreaded mode by having our own tokenizer.
+ if (!m_token)
+ m_token = adoptPtr(new HTMLToken);
+ if (!m_tokenizer)
+ m_tokenizer = HTMLTokenizer::create(m_options);
+ return;
+ }
+
m_haveBackgroundParser = true;
RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<BackgroundHTMLParser>::createUnbound();
@@ -674,19 +723,21 @@ void HTMLDocumentParser::startBackgroundParser()
config->xssAuditor->init(document(), &m_xssAuditorDelegate);
config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy(), document()->devicePixelRatio()));
config->decoder = takeDecoder();
+ config->resourceProvider = resourceProvider.release();
ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::start, reference.release(), config.release()));
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::start, reference.release(), config.release())));
}
void HTMLDocumentParser::stopBackgroundParser()
{
ASSERT(shouldUseThreading());
ASSERT(m_haveBackgroundParser);
+ ASSERT(s_parserThread);
m_haveBackgroundParser = false;
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::stop, m_backgroundParser));
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::stop, m_backgroundParser)));
m_weakFactory.revokeAll();
}
@@ -697,7 +748,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_haveBackgroundParser);
// pumpTokenizer can cause this parser to be detached from the Document,
// but we need to ensure it isn't deleted yet.
@@ -799,7 +850,7 @@ void HTMLDocumentParser::finish()
if (m_haveBackgroundParser) {
if (!m_input.haveSeenEndOfFile())
m_input.closeWithoutMarkingEndOfFile();
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::finish, m_backgroundParser));
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::finish, m_backgroundParser)));
return;
}
@@ -968,21 +1019,38 @@ void HTMLDocumentParser::appendBytes(const char* data, size_t length)
if (!length || isStopped())
return;
- if (shouldUseThreading()) {
- if (!m_haveBackgroundParser)
- startBackgroundParser();
+ if (shouldUseThreading() && !m_haveBackgroundParser)
+ startBackgroundParser();
+
+ if (m_haveBackgroundParser) {
+ 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()));
+ ASSERT(s_parserThread);
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::appendBytes, m_backgroundParser, buffer.release())));
return;
}
DecodedDataDocumentParser::appendBytes(data, length);
}
+void HTMLDocumentParser::didSwitchedToBackgroundClient()
+{
+ if (isDetached())
+ return;
+
+ ASSERT(s_parserThread);
+ ASSERT(m_haveBackgroundParser);
+ // 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;
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::didSwitchedToBackgroundClient, m_backgroundParser)));
+}
+
void HTMLDocumentParser::flush()
{
// If we've got no decoder, we never received any data.
@@ -990,7 +1058,7 @@ void HTMLDocumentParser::flush()
return;
if (m_haveBackgroundParser)
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::flush, m_backgroundParser));
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::flush, m_backgroundParser)));
else
DecodedDataDocumentParser::flush();
}
@@ -1001,7 +1069,7 @@ void HTMLDocumentParser::setDecoder(PassOwnPtr<TextResourceDecoder> decoder)
DecodedDataDocumentParser::setDecoder(decoder);
if (m_haveBackgroundParser)
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, takeDecoder()));
+ s_parserThread->postTask(new Task(bind(&BackgroundHTMLParser::setDecoder, m_backgroundParser, takeDecoder())));
}
}

Powered by Google App Engine
This is Rietveld 408576698