Changeset 143051 in webkit


Ignore:
Timestamp:
Feb 15, 2013 2:14:31 PM (11 years ago)
Author:
abarth@webkit.org
Message:

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):

Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r143048 r143051  
     12013-02-15  Adam Barth  <abarth@webkit.org>
     2
     3        Enable the preload scanner on the background parser thread
     4        https://bugs.webkit.org/show_bug.cgi?id=108027
     5
     6        Reviewed by Tony Gentilcore.
     7
     8        The patch causes us to pass all the fast/preloader tests with the
     9        threaded parser enabled.
     10
     11        This patch wires up the BackgroundHTMLParser to the
     12        TokenPreloadScanner.  Currently, we bail out of preload scanning if we
     13        encounter a document.write becaues we don't know how to rewind the
     14        preload scanner, but that's something we can tune in the future.
     15
     16        The BackgroundHTMLParser delivers the preloads to the
     17        HTMLDocumentParser together with the token stream. If the
     18        HTMLDocumentParser isn't able to use the token stream immediately, it
     19        kicks off the preloads.
     20
     21        * html/parser/BackgroundHTMLParser.cpp:
     22        (WebCore::checkThatPreloadsAreSafeToSendToAnotherThread):
     23        (WebCore::BackgroundHTMLParser::BackgroundHTMLParser):
     24        (WebCore::BackgroundHTMLParser::resumeFrom):
     25        (WebCore::BackgroundHTMLParser::pumpTokenizer):
     26        (WebCore::BackgroundHTMLParser::sendTokensToMainThread):
     27        * html/parser/BackgroundHTMLParser.h:
     28        (Configuration):
     29            - We need to add a struct for the create function because the
     30              number of arguments exceeds the limits of Functional.h.
     31        (BackgroundHTMLParser):
     32        (WebCore::BackgroundHTMLParser::create):
     33        * html/parser/CSSPreloadScanner.cpp:
     34        (WebCore::CSSPreloadScanner::scanCommon):
     35        (WebCore::CSSPreloadScanner::scan):
     36        (WebCore::CSSPreloadScanner::emitRule):
     37            - We need to use a new string here so that the string is safe to
     38              send to another thread.
     39        * html/parser/CSSPreloadScanner.h:
     40        (CSSPreloadScanner):
     41        * html/parser/HTMLDocumentParser.cpp:
     42        (WebCore::HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser):
     43        (WebCore::HTMLDocumentParser::startBackgroundParser):
     44            - Following the example of the XSSAuditor, we create the
     45              TokenPreloadScanner on the main thread and then send it to the
     46              background thread for operation.
     47        * html/parser/HTMLDocumentParser.h:
     48        (WebCore):
     49        (ParsedChunk):
     50        * html/parser/HTMLParserOptions.h:
     51        (HTMLParserOptions):
     52            - We need to add a default constructor so that the
     53              HTMLDocumentParser can create an empty
     54              BackgroundHTMLParser::Configuration struct.
     55        * html/parser/HTMLPreloadScanner.cpp:
     56        (WebCore::TokenPreloadScanner::scan):
     57        (WebCore::TokenPreloadScanner::scanCommon):
     58        (WebCore::HTMLPreloadScanner::scan):
     59        * html/parser/HTMLPreloadScanner.h:
     60        (TokenPreloadScanner):
     61        (WebCore::TokenPreloadScanner::isSafeToSendToAnotherThread):
     62        * html/parser/HTMLResourcePreloader.cpp:
     63        (WebCore::HTMLResourcePreloader::takeAndPreload):
     64        (WebCore):
     65        * html/parser/HTMLResourcePreloader.h:
     66        (WebCore::PreloadRequest::PreloadRequest):
     67        (WebCore):
     68        (HTMLResourcePreloader):
     69
    1702013-02-15  Ryosuke Niwa  <rniwa@webkit.org>
    271
  • trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp

    r142829 r143051  
    5252    for (size_t i = 0; i < tokens->size(); ++i)
    5353        ASSERT(tokens->at(i).isSafeToSendToAnotherThread());
     54}
     55
     56static void checkThatPreloadsAreSafeToSendToAnotherThread(const PreloadRequestStream& preloads)
     57{
     58    for (size_t i = 0; i < preloads.size(); ++i)
     59        ASSERT(preloads[i]->isSafeToSendToAnotherThread());
    5460}
    5561
     
    107113}
    108114
    109 // FIXME: Tune this constant based on a benchmark. The current value was choosen arbitrarily.
     115// FIXME: Tune this constant based on a benchmark. The current value was chosen arbitrarily.
    110116static const size_t pendingTokenLimit = 4000;
    111117
    112 BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
     118BackgroundHTMLParser::BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config)
    113119    : m_weakFactory(reference, this)
    114120    , m_token(adoptPtr(new HTMLToken))
    115     , m_tokenizer(HTMLTokenizer::create(options))
    116     , m_options(options)
    117     , m_parser(parser)
     121    , m_tokenizer(HTMLTokenizer::create(config->options))
     122    , m_options(config->options)
     123    , m_parser(config->parser)
    118124    , m_pendingTokens(adoptPtr(new CompactHTMLTokenStream))
    119     , m_xssAuditor(xssAuditor)
     125    , m_xssAuditor(config->xssAuditor.release())
     126    , m_preloadScanner(config->preloadScanner.release())
    120127{
    121128    m_namespaceStack.append(HTML);
     
    134141    m_tokenizer = checkpoint->tokenizer.release();
    135142    m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput);
     143    m_preloadScanner.clear(); // FIXME: We should rewind the preload scanner rather than clearing it.
    136144    pumpTokenizer();
    137145}
     
    224232            OwnPtr<XSSInfo> xssInfo = m_xssAuditor->filterToken(FilterTokenRequest(*m_token, m_sourceTracker, m_tokenizer->shouldAllowCDATA()));
    225233            CompactHTMLToken token(m_token.get(), TextPosition(m_input.current().currentLine(), m_input.current().currentColumn()));
     234
    226235            if (xssInfo)
    227236                token.setXSSInfo(xssInfo.release());
     237
     238            if (m_preloadScanner)
     239                m_preloadScanner->scan(token, m_pendingPreloads);
     240
    228241            m_pendingTokens->append(token);
    229242        }
     
    245258#ifndef NDEBUG
    246259    checkThatTokensAreSafeToSendToAnotherThread(m_pendingTokens.get());
     260    checkThatPreloadsAreSafeToSendToAnotherThread(m_pendingPreloads);
    247261#endif
    248262
    249263    OwnPtr<HTMLDocumentParser::ParsedChunk> chunk = adoptPtr(new HTMLDocumentParser::ParsedChunk);
    250264    chunk->tokens = m_pendingTokens.release();
     265    chunk->preloads.swap(m_pendingPreloads);
    251266    chunk->checkpoint = m_input.createCheckpoint();
    252267    callOnMainThread(bind(&HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser, m_parser, chunk.release()));
  • trunk/Source/WebCore/html/parser/BackgroundHTMLParser.h

    r142829 r143051  
    3232#include "CompactHTMLToken.h"
    3333#include "HTMLParserOptions.h"
     34#include "HTMLPreloadScanner.h"
    3435#include "HTMLSourceTracker.h"
    3536#include "HTMLToken.h"
     
    4950    WTF_MAKE_FAST_ALLOCATED;
    5051public:
    51     static void create(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, const HTMLParserOptions& options, const WeakPtr<HTMLDocumentParser>& parser, PassOwnPtr<XSSAuditor> xssAuditor)
     52    struct Configuration {
     53        HTMLParserOptions options;
     54        WeakPtr<HTMLDocumentParser> parser;
     55        OwnPtr<XSSAuditor> xssAuditor;
     56        OwnPtr<TokenPreloadScanner> preloadScanner;
     57    };
     58
     59    static void create(PassRefPtr<WeakReference<BackgroundHTMLParser> > reference, PassOwnPtr<Configuration> config)
    5260    {
    53         new BackgroundHTMLParser(reference, options, parser, xssAuditor);
     61        new BackgroundHTMLParser(reference, config);
    5462        // Caller must free by calling stop().
    5563    }
     
    7785    };
    7886
    79     BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> >, const HTMLParserOptions&, const WeakPtr<HTMLDocumentParser>&, PassOwnPtr<XSSAuditor>);
     87    BackgroundHTMLParser(PassRefPtr<WeakReference<BackgroundHTMLParser> >, PassOwnPtr<Configuration>);
    8088
    8189    void markEndOfFile();
     
    94102    HTMLParserOptions m_options;
    95103    WeakPtr<HTMLDocumentParser> m_parser;
     104
    96105    OwnPtr<CompactHTMLTokenStream> m_pendingTokens;
     106    PreloadRequestStream m_pendingPreloads;
     107
    97108    OwnPtr<XSSAuditor> m_xssAuditor;
     109    OwnPtr<TokenPreloadScanner> m_preloadScanner;
    98110};
    99111
  • trunk/Source/WebCore/html/parser/CSSPreloadScanner.cpp

    r143020 r143051  
    5252
    5353template<typename Char>
    54 void CSSPreloadScanner::scanCommon(const Char* begin, const Char* end, Vector<OwnPtr<PreloadRequest> >& requests)
     54void CSSPreloadScanner::scanCommon(const Char* begin, const Char* end, PreloadRequestStream& requests)
    5555{
    5656    m_requests = &requests;
     
    6060}
    6161
    62 void CSSPreloadScanner::scan(const HTMLToken::DataVector& data, Vector<OwnPtr<PreloadRequest> >& requests)
     62void CSSPreloadScanner::scan(const HTMLToken::DataVector& data, PreloadRequestStream& requests)
    6363{
    6464    scanCommon(data.data(), data.data() + data.size(), requests);
    6565}
    6666
    67 void CSSPreloadScanner::scan(const String& data, Vector<OwnPtr<PreloadRequest> >& requests)
     67void CSSPreloadScanner::scan(const String& data, PreloadRequestStream& requests)
    6868{
    6969    if (data.is8Bit()) {
     
    214214        if (!url.isEmpty()) {
    215215            KURL baseElementURL; // FIXME: This should be passed in from the HTMLPreloadScaner via scan()!
    216             OwnPtr<PreloadRequest> request = PreloadRequest::create(
    217                 cachedResourceRequestInitiators().css, url, baseElementURL, CachedResource::CSSStyleSheet);
     216            OwnPtr<PreloadRequest> request = PreloadRequest::create("css", url, baseElementURL, CachedResource::CSSStyleSheet);
    218217            // FIXME: Should this be including the charset in the preload request?
    219218            m_requests->append(request.release());
  • trunk/Source/WebCore/html/parser/CSSPreloadScanner.h

    r143020 r143051  
    4242    void reset();
    4343
    44     void scan(const HTMLToken::DataVector&, Vector<OwnPtr<PreloadRequest> >&);
    45     void scan(const String&, Vector<OwnPtr<PreloadRequest> >&);
     44    void scan(const HTMLToken::DataVector&, PreloadRequestStream&);
     45    void scan(const String&, PreloadRequestStream&);
    4646
    4747private:
     
    6060
    6161    template<typename Char>
    62     void scanCommon(const Char* begin, const Char* end, Vector<OwnPtr<PreloadRequest> >&);
     62    void scanCommon(const Char* begin, const Char* end, PreloadRequestStream&);
    6363
    6464    inline void tokenize(UChar);
     
    7070
    7171    // Only non-zero during scan()
    72     Vector<OwnPtr<PreloadRequest> >* m_requests;
     72    PreloadRequestStream* m_requests;
    7373};
    7474
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp

    r142673 r143051  
    287287{
    288288    if (isWaitingForScripts()) {
     289        m_preloader->takeAndPreload(chunk->preloads);
    289290        m_speculations.append(chunk);
    290291        return;
    291292    }
    292293    ASSERT(m_speculations.isEmpty());
     294    chunk->preloads.clear(); // We don't need to preload because we're going to parse immediately.
    293295    processParsedChunkFromBackgroundParser(chunk);
    294296}
     
    556558    m_backgroundParser = WeakPtr<BackgroundHTMLParser>(reference);
    557559
    558     WeakPtr<HTMLDocumentParser> parser = m_weakFactory.createWeakPtr();
    559     OwnPtr<XSSAuditor> xssAuditor = adoptPtr(new XSSAuditor);
    560     xssAuditor->init(document());
    561     ASSERT(xssAuditor->isSafeToSendToAnotherThread());
    562     HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), m_options, parser, xssAuditor.release()));
     560    OwnPtr<BackgroundHTMLParser::Configuration> config = adoptPtr(new BackgroundHTMLParser::Configuration);
     561    config->options = m_options;
     562    config->parser = m_weakFactory.createWeakPtr();
     563    config->xssAuditor = adoptPtr(new XSSAuditor);
     564    config->xssAuditor->init(document());
     565    config->preloadScanner = adoptPtr(new TokenPreloadScanner(document()->url().copy()));
     566
     567    ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
     568    ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
     569    HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), config.release()));
    563570}
    564571
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.h

    r142641 r143051  
    3333#include "HTMLInputStream.h"
    3434#include "HTMLParserOptions.h"
     35#include "HTMLPreloadScanner.h"
    3536#include "HTMLScriptRunnerHost.h"
    3637#include "HTMLSourceTracker.h"
     
    5758class HTMLScriptRunner;
    5859class HTMLTreeBuilder;
    59 class HTMLPreloadScanner;
    6060class HTMLResourcePreloader;
    6161class ScriptController;
     
    8989    struct ParsedChunk {
    9090        OwnPtr<CompactHTMLTokenStream> tokens;
     91        PreloadRequestStream preloads;
    9192        HTMLInputCheckpoint checkpoint;
    9293    };
  • trunk/Source/WebCore/html/parser/HTMLParserOptions.h

    r139959 r143051  
    3939    unsigned maximumDOMTreeDepth;
    4040
    41     explicit HTMLParserOptions(Document*);
     41    explicit HTMLParserOptions(Document* = 0);
    4242};
    4343
  • trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp

    r143020 r143051  
    355355{
    356356    ASSERT(m_predictedBaseElementURL.isEmpty());
    357     m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(token.getAttributeItem(hrefAttr)->value()));
     357    m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(token.getAttributeItem(hrefAttr)->value())).copy();
    358358}
    359359#endif
     
    382382        m_scanner.setPredictedBaseElementURL(startingBaseElementURL);
    383383
    384     Vector<OwnPtr<PreloadRequest> > requests;
     384    PreloadRequestStream requests;
     385
    385386    while (m_tokenizer->nextToken(m_source, m_token)) {
    386387        if (m_token.type() == HTMLToken::StartTag)
     
    389390        m_token.clear();
    390391    }
    391     for (size_t i = 0; i < requests.size(); i++)
    392         preloader->preload(requests[i].release());
    393 }
    394 
    395 }
     392
     393    preloader->takeAndPreload(requests);
     394}
     395
     396}
  • trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h

    r143020 r143051  
    4545    ~TokenPreloadScanner();
    4646
    47     void scan(const HTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
     47    void scan(const HTMLToken&, PreloadRequestStream& requests);
    4848#if ENABLE(THREADED_HTML_PARSER)
    49     void scan(const CompactHTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
     49    void scan(const CompactHTMLToken&, PreloadRequestStream& requests);
    5050#endif
    5151
    5252    void setPredictedBaseElementURL(const KURL& url) { m_predictedBaseElementURL = url; }
     53
     54    bool isSafeToSendToAnotherThread()
     55    {
     56        return m_documentURL.isSafeToSendToAnotherThread()
     57            && m_predictedBaseElementURL.isSafeToSendToAnotherThread();
     58    }
    5359
    5460private:
     
    7076
    7177    template<typename Token>
    72     inline void scanCommon(const Token&, Vector<OwnPtr<PreloadRequest> >& requests);
     78    inline void scanCommon(const Token&, PreloadRequestStream& requests);
    7379
    7480    static TagId tagIdFor(const HTMLToken::DataVector&);
  • trunk/Source/WebCore/html/parser/HTMLResourcePreloader.cpp

    r142796 r143051  
    5757}
    5858
     59void HTMLResourcePreloader::takeAndPreload(PreloadRequestStream& r)
     60{
     61    PreloadRequestStream requests;
     62    requests.swap(r);
     63
     64    for (PreloadRequestStream::iterator it = requests.begin(); it != requests.end(); ++it)
     65        preload(it->release());
     66}
     67
    5968void HTMLResourcePreloader::preload(PassOwnPtr<PreloadRequest> preload)
    6069{
  • trunk/Source/WebCore/html/parser/HTMLResourcePreloader.h

    r142796 r143051  
    5151    PreloadRequest(const String& initiator, const String& resourceURL, const KURL& baseURL, CachedResource::Type resourceType)
    5252        : m_initiator(initiator)
    53         , m_resourceURL(resourceURL)
    54         , m_baseURL(baseURL)
     53        , m_resourceURL(resourceURL.isolatedCopy())
     54        , m_baseURL(baseURL.copy())
    5555        , m_resourceType(resourceType)
    5656        , m_crossOriginModeAllowsCookies(false)
     
    6868};
    6969
     70typedef Vector<OwnPtr<PreloadRequest> > PreloadRequestStream;
     71
    7072class HTMLResourcePreloader {
    7173    WTF_MAKE_NONCOPYABLE(HTMLResourcePreloader); WTF_MAKE_FAST_ALLOCATED;
     
    7779    }
    7880
     81    void takeAndPreload(PreloadRequestStream&);
    7982    void preload(PassOwnPtr<PreloadRequest>);
    8083
Note: See TracChangeset for help on using the changeset viewer.