Diff
Modified: trunk/Source/WebCore/ChangeLog (143050 => 143051)
--- trunk/Source/WebCore/ChangeLog 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/ChangeLog 2013-02-15 22:14:31 UTC (rev 143051)
@@ -1,3 +1,72 @@
+2013-02-15 Adam Barth <aba...@webkit.org>
+
+ Enable the preload scanner on the background parser thread
+ https://bugs.webkit.org/show_bug.cgi?id=108027
+
+ Reviewed by Tony Gentilcore.
+
+ The patch causes us to pass all the fast/preloader tests with the
+ threaded parser enabled.
+
+ This patch wires up the BackgroundHTMLParser to the
+ TokenPreloadScanner. Currently, we bail out of preload scanning if we
+ encounter a document.write becaues we don't know how to rewind the
+ preload scanner, but that's something we can tune in the future.
+
+ The BackgroundHTMLParser delivers the preloads to the
+ HTMLDocumentParser together with the token stream. If the
+ HTMLDocumentParser isn't able to use the token stream immediately, it
+ kicks off the preloads.
+
+ * html/parser/BackgroundHTMLParser.cpp:
+ (WebCore::checkThatPreloadsAreSafeToSendToAnotherThread):
+ (WebCore::BackgroundHTMLParser::BackgroundHTMLParser):
+ (WebCore::BackgroundHTMLParser::resumeFrom):
+ (WebCore::BackgroundHTMLParser::pumpTokenizer):
+ (WebCore::BackgroundHTMLParser::sendTokensToMainThread):
+ * html/parser/BackgroundHTMLParser.h:
+ (Configuration):
+ - We need to add a struct for the create function because the
+ number of arguments exceeds the limits of Functional.h.
+ (BackgroundHTMLParser):
+ (WebCore::BackgroundHTMLParser::create):
+ * html/parser/CSSPreloadScanner.cpp:
+ (WebCore::CSSPreloadScanner::scanCommon):
+ (WebCore::CSSPreloadScanner::scan):
+ (WebCore::CSSPreloadScanner::emitRule):
+ - We need to use a new string here so that the string is safe to
+ send to another thread.
+ * html/parser/CSSPreloadScanner.h:
+ (CSSPreloadScanner):
+ * html/parser/HTMLDocumentParser.cpp:
+ (WebCore::HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser):
+ (WebCore::HTMLDocumentParser::startBackgroundParser):
+ - Following the example of the XSSAuditor, we create the
+ TokenPreloadScanner on the main thread and then send it to the
+ background thread for operation.
+ * html/parser/HTMLDocumentParser.h:
+ (WebCore):
+ (ParsedChunk):
+ * html/parser/HTMLParserOptions.h:
+ (HTMLParserOptions):
+ - We need to add a default constructor so that the
+ HTMLDocumentParser can create an empty
+ BackgroundHTMLParser::Configuration struct.
+ * html/parser/HTMLPreloadScanner.cpp:
+ (WebCore::TokenPreloadScanner::scan):
+ (WebCore::TokenPreloadScanner::scanCommon):
+ (WebCore::HTMLPreloadScanner::scan):
+ * html/parser/HTMLPreloadScanner.h:
+ (TokenPreloadScanner):
+ (WebCore::TokenPreloadScanner::isSafeToSendToAnotherThread):
+ * html/parser/HTMLResourcePreloader.cpp:
+ (WebCore::HTMLResourcePreloader::takeAndPreload):
+ (WebCore):
+ * html/parser/HTMLResourcePreloader.h:
+ (WebCore::PreloadRequest::PreloadRequest):
+ (WebCore):
+ (HTMLResourcePreloader):
+
2013-02-15 Ryosuke Niwa <rn...@webkit.org>
Build fix after r143030. We need to keep updatedRange around until createMarkupInternal returns.
Modified: trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp (143050 => 143051)
--- trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp 2013-02-15 22:14:31 UTC (rev 143051)
@@ -53,6 +53,12 @@
ASSERT(tokens->at(i).isSafeToSendToAnotherThread());
}
+static void checkThatPreloadsAreSafeToSendToAnotherThread(const PreloadRequestStream& preloads)
+{
+ for (size_t i = 0; i < preloads.size(); ++i)
+ ASSERT(preloads[i]->isSafeToSendToAnotherThread());
+}
+
#endif
static inline bool tokenExitsForeignContent(const CompactHTMLToken& token)
@@ -106,17 +112,18 @@
|| (threadSafeMatch(tagName, fontTag) && (token.getAttributeItem(colorAttr) || token.getAttributeItem(faceAttr) || token.getAttributeItem(sizeAttr)));
}
-// FIXME: Tune this constant based on a benchmark. The current value was choosen arbitrarily.
+// FIXME: Tune this constant based on a benchmark. The current value was chosen arbitrarily.
static const size_t pendingTokenLimit = 4000;
-BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
+BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config)
: m_weakFactory(reference, this)
, m_token(adoptPtr(new HTMLToken))
- , m_tokenizer(HTMLTokenizer::create(options))
- , m_options(options)
- , m_parser(parser)
+ , m_tokenizer(HTMLTokenizer::create(config->options))
+ , m_options(config->options)
+ , m_parser(config->parser)
, m_pendingTokens(adoptPtr(new CompactHTMLTokenStream))
- , m_xssAuditor(xssAuditor)
+ , m_xssAuditor(config->xssAuditor.release())
+ , m_preloadScanner(config->preloadScanner.release())
{
m_namespaceStack.append(HTML);
}
@@ -133,6 +140,7 @@
m_token = checkpoint->token.release();
m_tokenizer = checkpoint->tokenizer.release();
m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput);
+ m_preloadScanner.clear(); // FIXME: We should rewind the preload scanner rather than clearing it.
pumpTokenizer();
}
@@ -223,8 +231,13 @@
{
OwnPtr<XSSInfo> xssInfo = m_xssAuditor->filterToken(FilterTokenRequest(*m_token, m_sourceTracker, m_tokenizer->shouldAllowCDATA()));
CompactHTMLToken token(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn()));
+
if (xssInfo)
token.setXSSInfo(xssInfo.release());
+
+ if (m_preloadScanner)
+ m_preloadScanner->scan(token, m_pendingPreloads);
+
m_pendingTokens->append(token);
}
@@ -244,10 +257,12 @@
#ifndef NDEBUG
checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get());
+ checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads);
#endif
OwnPtr<HTMLDocumentParser::ParsedChunk> chunk = adoptPtr(new HTMLDocumentParser::ParsedChunk);
chunk->tokens = m_pendingTokens.release();
+ chunk->preloads.swap(m_pendingPreloads);
chunk->checkpoint = m_input.createCheckpoint();
callOnMainThread(bind(&HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser, m_parser, chunk.release()));
Modified: trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -31,6 +31,7 @@
#include "BackgroundHTMLInputStream.h"
#include "CompactHTMLToken.h"
#include "HTMLParserOptions.h"
+#include "HTMLPreloadScanner.h"
#include "HTMLSourceTracker.h"
#include "HTMLToken.h"
#include "HTMLTokenizer.h"
@@ -48,9 +49,16 @@
class BackgroundHTMLParser {
WTF_MAKE_FAST_ALLOCATED;
public:
- static void create(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
+ struct Configuration {
+ HTMLParserOptions options;
+ WeakPtr<HTMLDocumentParser> parser;
+ OwnPtr<XSSAuditor> xssAuditor;
+ OwnPtr<TokenPreloadScanner> preloadScanner;
+ };
+
+ static void create(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config)
{
- new BackgroundHTMLParser(reference, options, parser, xssAuditor);
+ new BackgroundHTMLParser(reference, config);
// Caller must free by calling stop().
}
@@ -76,7 +84,7 @@
MathML
};
- BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> >, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>);
+ BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> >, PassOwnPtr<Configuration>);
void markEndOfFile();
void pumpTokenizer();
@@ -93,8 +101,12 @@
OwnPtr<HTMLTokenizer> m_tokenizer;
HTMLParserOptions m_options;
WeakPtr<HTMLDocumentParser> m_parser;
+
OwnPtr<CompactHTMLTokenStream> m_pendingTokens;
+ PreloadRequestStream m_pendingPreloads;
+
OwnPtr<XSSAuditor> m_xssAuditor;
+ OwnPtr<TokenPreloadScanner> m_preloadScanner;
};
}
Modified: trunk/Source/WebCore/html/parser/CSSPreloadScanner.cpp (143050 => 143051)
--- trunk/Source/WebCore/html/parser/CSSPreloadScanner.cpp 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/CSSPreloadScanner.cpp 2013-02-15 22:14:31 UTC (rev 143051)
@@ -51,7 +51,7 @@
}
template<typename Char>
-void CSSPreloadScanner::scanCommon(const Char* begin, const Char* end, Vector<OwnPtr<PreloadRequest> >& requests)
+void CSSPreloadScanner::scanCommon(const Char* begin, const Char* end, PreloadRequestStream& requests)
{
m_requests = &requests;
for (const Char* it = begin; it != end && m_state != DoneParsingImportRules; ++it)
@@ -59,12 +59,12 @@
m_requests = 0;
}
-void CSSPreloadScanner::scan(const HTMLToken::DataVector& data, Vector<OwnPtr<PreloadRequest> >& requests)
+void CSSPreloadScanner::scan(const HTMLToken::DataVector& data, PreloadRequestStream& requests)
{
scanCommon(data.data(), data.data() + data.size(), requests);
}
-void CSSPreloadScanner::scan(const String& data, Vector<OwnPtr<PreloadRequest> >& requests)
+void CSSPreloadScanner::scan(const String& data, PreloadRequestStream& requests)
{
if (data.is8Bit()) {
const LChar* begin = data.characters8();
@@ -213,8 +213,7 @@
String url = "" m_ruleValue.length());
if (!url.isEmpty()) {
KURL baseElementURL; // FIXME: This should be passed in from the HTMLPreloadScaner via scan()!
- OwnPtr<PreloadRequest> request = PreloadRequest::create(
- cachedResourceRequestInitiators().css, url, baseElementURL, CachedResource::CSSStyleSheet);
+ OwnPtr<PreloadRequest> request = PreloadRequest::create("css", url, baseElementURL, CachedResource::CSSStyleSheet);
// FIXME: Should this be including the charset in the preload request?
m_requests->append(request.release());
}
Modified: trunk/Source/WebCore/html/parser/CSSPreloadScanner.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/CSSPreloadScanner.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/CSSPreloadScanner.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -41,8 +41,8 @@
void reset();
- void scan(const HTMLToken::DataVector&, Vector<OwnPtr<PreloadRequest> >&);
- void scan(const String&, Vector<OwnPtr<PreloadRequest> >&);
+ void scan(const HTMLToken::DataVector&, PreloadRequestStream&);
+ void scan(const String&, PreloadRequestStream&);
private:
enum State {
@@ -59,7 +59,7 @@
};
template<typename Char>
- void scanCommon(const Char* begin, const Char* end, Vector<OwnPtr<PreloadRequest> >&);
+ void scanCommon(const Char* begin, const Char* end, PreloadRequestStream&);
inline void tokenize(UChar);
void emitRule();
@@ -69,7 +69,7 @@
StringBuilder m_ruleValue;
// Only non-zero during scan()
- Vector<OwnPtr<PreloadRequest> >* m_requests;
+ PreloadRequestStream* m_requests;
};
}
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp 2013-02-15 22:14:31 UTC (rev 143051)
@@ -286,10 +286,12 @@
void HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk> chunk)
{
if (isWaitingForScripts()) {
+ m_preloader->takeAndPreload(chunk->preloads);
m_speculations.append(chunk);
return;
}
ASSERT(m_speculations.isEmpty());
+ chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately.
processParsedChunkFromBackgroundParser(chunk);
}
@@ -555,11 +557,16 @@
RefPtr<WeakReference<BackgroundHTMLParser> > reference = WeakReference<BackgroundHTMLParser>::createUnbound();
m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference);
- WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr();
- OwnPtr<XSSAuditor> xssAuditor = adoptPtr(new XSSAuditor);
- xssAuditor->init(document());
- ASSERT(xssAuditor->isSafeToSendToAnotherThread());
- HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), m_options, parser, xssAuditor.release()));
+ OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new BackgroundHTMLParser::Configuration);
+ config->options = m_options;
+ config->parser = m_weakFactory.createWeakPtr();
+ config->xssAuditor = adoptPtr(new XSSAuditor);
+ config->xssAuditor->init(document());
+ config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy()));
+
+ ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
+ ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
+ HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), config.release()));
}
void HTMLDocumentParser::stopBackgroundParser()
Modified: trunk/Source/WebCore/html/parser/HTMLDocumentParser.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLDocumentParser.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLDocumentParser.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -32,6 +32,7 @@
#include "FragmentScriptingPermission.h"
#include "HTMLInputStream.h"
#include "HTMLParserOptions.h"
+#include "HTMLPreloadScanner.h"
#include "HTMLScriptRunnerHost.h"
#include "HTMLSourceTracker.h"
#include "HTMLToken.h"
@@ -56,7 +57,6 @@
class HTMLTokenizer;
class HTMLScriptRunner;
class HTMLTreeBuilder;
-class HTMLPreloadScanner;
class HTMLResourcePreloader;
class ScriptController;
class ScriptSourceCode;
@@ -88,6 +88,7 @@
#if ENABLE(THREADED_HTML_PARSER)
struct ParsedChunk {
OwnPtr<CompactHTMLTokenStream> tokens;
+ PreloadRequestStream preloads;
HTMLInputCheckpoint checkpoint;
};
void didReceiveParsedChunkFromBackgroundParser(PassOwnPtr<ParsedChunk>);
Modified: trunk/Source/WebCore/html/parser/HTMLParserOptions.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLParserOptions.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLParserOptions.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -38,7 +38,7 @@
bool useThreading;
unsigned maximumDOMTreeDepth;
- explicit HTMLParserOptions(Document*);
+ explicit HTMLParserOptions(Document* = 0);
};
}
Modified: trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp 2013-02-15 22:14:31 UTC (rev 143051)
@@ -354,7 +354,7 @@
void TokenPreloadScanner::updatePredictedBaseURL(const CompactHTMLToken& token)
{
ASSERT(m_predictedBaseElementURL.isEmpty());
- m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(token.getAttributeItem(hrefAttr)->value()));
+ m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(token.getAttributeItem(hrefAttr)->value())).copy();
}
#endif
@@ -381,15 +381,16 @@
if (!startingBaseElementURL.isEmpty())
m_scanner.setPredictedBaseElementURL(startingBaseElementURL);
- Vector<OwnPtr<PreloadRequest> > requests;
+ PreloadRequestStream requests;
+
while (m_tokenizer->nextToken(m_source, m_token)) {
if (m_token.type() == HTMLToken::StartTag)
m_tokenizer->updateStateFor(AtomicString(m_token.name()));
m_scanner.scan(m_token, requests);
m_token.clear();
}
- for (size_t i = 0; i < requests.size(); i++)
- preloader->preload(requests[i].release());
+
+ preloader->takeAndPreload(requests);
}
}
Modified: trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -44,13 +44,19 @@
explicit TokenPreloadScanner(const KURL& documentURL);
~TokenPreloadScanner();
- void scan(const HTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
+ void scan(const HTMLToken&, PreloadRequestStream& requests);
#if ENABLE(THREADED_HTML_PARSER)
- void scan(const CompactHTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
+ void scan(const CompactHTMLToken&, PreloadRequestStream& requests);
#endif
void setPredictedBaseElementURL(const KURL& url) { m_predictedBaseElementURL = url; }
+ bool isSafeToSendToAnotherThread()
+ {
+ return m_documentURL.isSafeToSendToAnotherThread()
+ && m_predictedBaseElementURL.isSafeToSendToAnotherThread();
+ }
+
private:
enum TagId {
// These tags are scanned by the StartTagScanner.
@@ -69,7 +75,7 @@
class StartTagScanner;
template<typename Token>
- inline void scanCommon(const Token&, Vector<OwnPtr<PreloadRequest> >& requests);
+ inline void scanCommon(const Token&, PreloadRequestStream& requests);
static TagId tagIdFor(const HTMLToken::DataVector&);
static TagId tagIdFor(const String&);
Modified: trunk/Source/WebCore/html/parser/HTMLResourcePreloader.cpp (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLResourcePreloader.cpp 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLResourcePreloader.cpp 2013-02-15 22:14:31 UTC (rev 143051)
@@ -56,6 +56,15 @@
return request;
}
+void HTMLResourcePreloader::takeAndPreload(PreloadRequestStream& r)
+{
+ PreloadRequestStream requests;
+ requests.swap(r);
+
+ for (PreloadRequestStream::iterator it = requests.begin(); it != requests.end(); ++it)
+ preload(it->release());
+}
+
void HTMLResourcePreloader::preload(PassOwnPtr<PreloadRequest> preload)
{
CachedResourceRequest request = preload->resourceRequest(m_document);
Modified: trunk/Source/WebCore/html/parser/HTMLResourcePreloader.h (143050 => 143051)
--- trunk/Source/WebCore/html/parser/HTMLResourcePreloader.h 2013-02-15 22:01:04 UTC (rev 143050)
+++ trunk/Source/WebCore/html/parser/HTMLResourcePreloader.h 2013-02-15 22:14:31 UTC (rev 143051)
@@ -50,8 +50,8 @@
private:
PreloadRequest(const String& initiator, const String& resourceURL, const KURL& baseURL, CachedResource::Type resourceType)
: m_initiator(initiator)
- , m_resourceURL(resourceURL)
- , m_baseURL(baseURL)
+ , m_resourceURL(resourceURL.isolatedCopy())
+ , m_baseURL(baseURL.copy())
, m_resourceType(resourceType)
, m_crossOriginModeAllowsCookies(false)
{
@@ -67,6 +67,8 @@
bool m_crossOriginModeAllowsCookies;
};
+typedef Vector<OwnPtr<PreloadRequest> > PreloadRequestStream;
+
class HTMLResourcePreloader {
WTF_MAKE_NONCOPYABLE(HTMLResourcePreloader); WTF_MAKE_FAST_ALLOCATED;
public:
@@ -76,6 +78,7 @@
{
}
+ void takeAndPreload(PreloadRequestStream&);
void preload(PassOwnPtr<PreloadRequest>);
WeakPtr<HTMLResourcePreloader> createWeakPtr() { return m_weakFactory.createWeakPtr(); }