Changeset 144010 in webkit


Ignore:
Timestamp:
Feb 25, 2013 11:21:52 PM (11 years ago)
Author:
abarth@webkit.org
Message:

6% regression in intl1 page cycler on chromium-mac
https://bugs.webkit.org/show_bug.cgi?id=110784

Unreviewed.

This patch restores the code that I rolled out in
http://trac.webkit.org/changeset/143960 and
http://trac.webkit.org/changeset/143983. Rolling out those patches did
not heal the bot.

  • dom/Element.cpp:

(WebCore::Element::addAttributeInternal):
(WebCore::ShareableElementData::ShareableElementData):
(WebCore::UniqueElementData::makeShareableCopy):
(WebCore::UniqueElementData::addAttribute):
(WebCore::UniqueElementData::removeAttribute):
(WebCore::ElementData::reportMemoryUsage):
(WebCore::UniqueElementData::getAttributeItem):
(WebCore):
(WebCore::UniqueElementData::attributeItem):

  • dom/Element.h:

(ElementData):
(UniqueElementData):
(WebCore::isShadowHost):
(WebCore::ElementData::length):
(WebCore::ElementData::attributeItem):

  • html/parser/BackgroundHTMLParser.cpp:

(WebCore::BackgroundHTMLParser::resumeFrom):
(WebCore::BackgroundHTMLParser::pumpTokenizer):
(WebCore::BackgroundHTMLParser::sendTokensToMainThread):

  • html/parser/CSSPreloadScanner.cpp:

(WebCore):
(WebCore::CSSPreloadScanner::scanCommon):
(WebCore::CSSPreloadScanner::scan):
(WebCore::CSSPreloadScanner::emitRule):

  • html/parser/CSSPreloadScanner.h:

(CSSPreloadScanner):

  • html/parser/HTMLDocumentParser.cpp:

(WebCore::HTMLDocumentParser::startBackgroundParser):

  • html/parser/HTMLPreloadScanner.cpp:

(WebCore::TokenPreloadScanner::tagIdFor):
(WebCore):
(WebCore::TokenPreloadScanner::initiatorFor):
(WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
(TokenPreloadScanner::StartTagScanner):
(WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest):
(WebCore::TokenPreloadScanner::createCheckpoint):
(WebCore::TokenPreloadScanner::rewindTo):
(WebCore::TokenPreloadScanner::scan):
(WebCore::TokenPreloadScanner::scanCommon):
(WebCore::TokenPreloadScanner::updatePredictedBaseURL):
(WebCore::HTMLPreloadScanner::scan):

  • html/parser/HTMLPreloadScanner.h:

(TokenPreloadScanner):
(WebCore::TokenPreloadScanner::isSafeToSendToAnotherThread):
(WebCore::TokenPreloadScanner::Checkpoint::Checkpoint):
(Checkpoint):

Location:
trunk/Source/WebCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r144007 r144010  
     12013-02-25  Adam Barth  <abarth@webkit.org>
     2
     3        6% regression in intl1 page cycler on chromium-mac
     4        https://bugs.webkit.org/show_bug.cgi?id=110784
     5
     6        Unreviewed.
     7
     8        This patch restores the code that I rolled out in
     9        http://trac.webkit.org/changeset/143960 and
     10        http://trac.webkit.org/changeset/143983. Rolling out those patches did
     11        not heal the bot.
     12
     13        * dom/Element.cpp:
     14        (WebCore::Element::addAttributeInternal):
     15        (WebCore::ShareableElementData::ShareableElementData):
     16        (WebCore::UniqueElementData::makeShareableCopy):
     17        (WebCore::UniqueElementData::addAttribute):
     18        (WebCore::UniqueElementData::removeAttribute):
     19        (WebCore::ElementData::reportMemoryUsage):
     20        (WebCore::UniqueElementData::getAttributeItem):
     21        (WebCore):
     22        (WebCore::UniqueElementData::attributeItem):
     23        * dom/Element.h:
     24        (ElementData):
     25        (UniqueElementData):
     26        (WebCore::isShadowHost):
     27        (WebCore::ElementData::length):
     28        (WebCore::ElementData::attributeItem):
     29        * html/parser/BackgroundHTMLParser.cpp:
     30        (WebCore::BackgroundHTMLParser::resumeFrom):
     31        (WebCore::BackgroundHTMLParser::pumpTokenizer):
     32        (WebCore::BackgroundHTMLParser::sendTokensToMainThread):
     33        * html/parser/CSSPreloadScanner.cpp:
     34        (WebCore):
     35        (WebCore::CSSPreloadScanner::scanCommon):
     36        (WebCore::CSSPreloadScanner::scan):
     37        (WebCore::CSSPreloadScanner::emitRule):
     38        * html/parser/CSSPreloadScanner.h:
     39        (CSSPreloadScanner):
     40        * html/parser/HTMLDocumentParser.cpp:
     41        (WebCore::HTMLDocumentParser::startBackgroundParser):
     42        * html/parser/HTMLPreloadScanner.cpp:
     43        (WebCore::TokenPreloadScanner::tagIdFor):
     44        (WebCore):
     45        (WebCore::TokenPreloadScanner::initiatorFor):
     46        (WebCore::TokenPreloadScanner::StartTagScanner::processAttributes):
     47        (TokenPreloadScanner::StartTagScanner):
     48        (WebCore::TokenPreloadScanner::StartTagScanner::createPreloadRequest):
     49        (WebCore::TokenPreloadScanner::createCheckpoint):
     50        (WebCore::TokenPreloadScanner::rewindTo):
     51        (WebCore::TokenPreloadScanner::scan):
     52        (WebCore::TokenPreloadScanner::scanCommon):
     53        (WebCore::TokenPreloadScanner::updatePredictedBaseURL):
     54        (WebCore::HTMLPreloadScanner::scan):
     55        * html/parser/HTMLPreloadScanner.h:
     56        (TokenPreloadScanner):
     57        (WebCore::TokenPreloadScanner::isSafeToSendToAnotherThread):
     58        (WebCore::TokenPreloadScanner::Checkpoint::Checkpoint):
     59        (Checkpoint):
     60
    1612013-02-25  Chris Rogers  <crogers@google.com>
    262
  • trunk/Source/WebCore/dom/Element.cpp

    r143983 r144010  
    18211821    if (!inSynchronizationOfLazyAttribute)
    18221822        willModifyAttribute(name, nullAtom, value);
    1823     ensureUniqueElementData()->addAttribute(Attribute(name, value));
     1823    ensureUniqueElementData()->addAttribute(name, value);
    18241824    if (!inSynchronizationOfLazyAttribute)
    18251825        didAddAttribute(name, value);
     
    29702970
    29712971    for (unsigned i = 0; i < m_arraySize; ++i)
    2972         new (&reinterpret_cast<Attribute*>(&m_attributeArray)[i]) Attribute(*other.attributeItem(i));
     2972        new (&m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
    29732973}
    29742974
     
    30203020PassRefPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
    30213021{
    3022     void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(mutableAttributeVector().size()));
     3022    void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
    30233023    return adoptRef(new (slot) ShareableElementData(*this));
    30243024}
    30253025
    3026 void ElementData::addAttribute(const Attribute& attribute)
    3027 {
    3028     ASSERT(isUnique());
    3029     mutableAttributeVector().append(attribute);
    3030 }
    3031 
    3032 void ElementData::removeAttribute(size_t index)
    3033 {
    3034     ASSERT(isUnique());
     3026void UniqueElementData::addAttribute(const QualifiedName& attributeName, const AtomicString& value)
     3027{
     3028    m_attributeVector.append(Attribute(attributeName, value));
     3029}
     3030
     3031void UniqueElementData::removeAttribute(size_t index)
     3032{
    30353033    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
    3036     mutableAttributeVector().remove(index);
     3034    m_attributeVector.remove(index);
    30373035}
    30383036
     
    30643062    info.addMember(m_idForStyleResolution, "idForStyleResolution");
    30653063    if (m_isUnique) {
    3066         info.addMember(presentationAttributeStyle(), "presentationAttributeStyle()");
    3067         info.addMember(mutableAttributeVector(), "mutableAttributeVector");
     3064        const UniqueElementData* uniqueThis = static_cast<const UniqueElementData*>(this);
     3065        info.addMember(uniqueThis->m_presentationAttributeStyle, "presentationAttributeStyle");
     3066        info.addMember(uniqueThis->m_attributeVector, "attributeVector");
    30683067    }
    30693068    for (unsigned i = 0, len = length(); i < len; i++)
     
    30903089}
    30913090
     3091Attribute* UniqueElementData::getAttributeItem(const QualifiedName& name)
     3092{
     3093    for (unsigned i = 0; i < length(); ++i) {
     3094        if (m_attributeVector.at(i).name().matches(name))
     3095            return &m_attributeVector.at(i);
     3096    }
     3097    return 0;
     3098}
     3099
     3100Attribute* UniqueElementData::attributeItem(unsigned index)
     3101{
     3102    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
     3103    return &m_attributeVector.at(index);
     3104}
     3105
    30923106} // namespace WebCore
  • trunk/Source/WebCore/dom/Element.h

    r143983 r144010  
    7676    const Attribute* attributeItem(unsigned index) const;
    7777    const Attribute* getAttributeItem(const QualifiedName&) const;
    78     Attribute* attributeItem(unsigned index);
    79     Attribute* getAttributeItem(const QualifiedName&);
    8078    size_t getAttributeItemIndex(const QualifiedName&) const;
    8179    size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    8280
    83     // These functions do no error checking.
    84     void addAttribute(const Attribute&);
    85     void removeAttribute(size_t index);
    86 
    8781    bool hasID() const { return !m_idForStyleResolution.isNull(); }
    8882    bool hasClass() const { return !m_classNames.isNull(); }
     
    9387
    9488    bool isUnique() const { return m_isUnique; }
    95     const Attribute* immutableAttributeArray() const;
    9689
    9790protected:
     
    121114#endif
    122115
    123     Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase);
    124116    const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    125117    size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    126118
    127119    PassRefPtr<UniqueElementData> makeUniqueCopy() const;
    128 
    129     Vector<Attribute, 4>& mutableAttributeVector();
    130     const Vector<Attribute, 4>& mutableAttributeVector() const;
    131120};
    132121
     
    155144    static PassRefPtr<UniqueElementData> create();
    156145    PassRefPtr<ShareableElementData> makeShareableCopy() const;
     146
     147    // These functions do no error/duplicate checking.
     148    void addAttribute(const QualifiedName&, const AtomicString&);
     149    void removeAttribute(size_t index);
     150
     151    Attribute* attributeItem(unsigned index);
     152    Attribute* getAttributeItem(const QualifiedName&);
    157153
    158154    UniqueElementData();
     
    903899    return node && node->isElementNode() && toElement(node)->shadow();
    904900}
    905 inline Vector<Attribute, 4>& ElementData::mutableAttributeVector()
    906 {
    907     ASSERT(m_isUnique);
    908     return static_cast<UniqueElementData*>(this)->m_attributeVector;
    909 }
    910 
    911 inline const Vector<Attribute, 4>& ElementData::mutableAttributeVector() const
    912 {
    913     ASSERT(m_isUnique);
    914     return static_cast<const UniqueElementData*>(this)->m_attributeVector;
    915 }
    916 
    917 inline const Attribute* ElementData::immutableAttributeArray() const
    918 {
    919     ASSERT(!m_isUnique);
    920     return reinterpret_cast<const Attribute*>(&static_cast<const ShareableElementData*>(this)->m_attributeArray);
    921 }
    922901
    923902inline size_t ElementData::length() const
    924903{
    925904    if (isUnique())
    926         return mutableAttributeVector().size();
     905        return static_cast<const UniqueElementData*>(this)->m_attributeVector.size();
    927906    return m_arraySize;
    928907}
     
    933912        return 0;
    934913    return static_cast<const UniqueElementData*>(this)->m_presentationAttributeStyle.get();
    935 }
    936 
    937 inline Attribute* ElementData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase)
    938 {
    939     size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
    940     if (index != notFound)
    941         return attributeItem(index);
    942     return 0;
    943914}
    944915
     
    991962}
    992963
    993 inline Attribute* ElementData::getAttributeItem(const QualifiedName& name)
    994 {
    995     for (unsigned i = 0; i < length(); ++i) {
    996         if (attributeItem(i)->name().matches(name))
    997             return attributeItem(i);
    998     }
    999     return 0;
    1000 }
    1001 
    1002964inline const Attribute* ElementData::attributeItem(unsigned index) const
    1003965{
    1004966    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
    1005967    if (m_isUnique)
    1006         return &mutableAttributeVector().at(index);
    1007     return &immutableAttributeArray()[index];
    1008 }
    1009 
    1010 inline Attribute* ElementData::attributeItem(unsigned index)
    1011 {
    1012     ASSERT_WITH_SECURITY_IMPLICATION(index < length());
    1013     return &mutableAttributeVector().at(index);
     968        return &static_cast<const UniqueElementData*>(this)->m_attributeVector.at(index);
     969    return &static_cast<const ShareableElementData*>(this)->m_attributeArray[index];
    1014970}
    1015971
  • trunk/Source/WebCore/html/parser/BackgroundHTMLParser.cpp

    r143960 r144010  
    157157    m_tokenizer = checkpoint->tokenizer.release();
    158158    m_input.rewindTo(checkpoint->inputCheckpoint, checkpoint->unparsedInput);
     159    m_preloadScanner->rewindTo(checkpoint->preloadScannerCheckpoint);
    159160    pumpTokenizer();
    160161}
     
    252253                token.setXSSInfo(xssInfo.release());
    253254
     255            m_preloadScanner->scan(token, m_pendingPreloads);
     256
    254257            m_pendingTokens->append(token);
    255258        }
     
    278281    chunk->preloads.swap(m_pendingPreloads);
    279282    chunk->inputCheckpoint = m_input.createCheckpoint();
     283    chunk->preloadScannerCheckpoint = m_preloadScanner->createCheckpoint();
    280284    callOnMainThread(bind(&HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser, m_parser, chunk.release()));
    281285
  • trunk/Source/WebCore/html/parser/CSSPreloadScanner.cpp

    r143960 r144010  
    5151}
    5252
    53 void CSSPreloadScanner::scan(const UChar* begin, const UChar* end, Vector<OwnPtr<PreloadRequest> >& requests)
     53template<typename Char>
     54void CSSPreloadScanner::scanCommon(const Char* begin, const Char* end, PreloadRequestStream& requests)
    5455{
    5556    m_requests = &requests;
    56     for (const UChar* it = begin; it != end && m_state != DoneParsingImportRules; ++it)
     57    for (const Char* it = begin; it != end && m_state != DoneParsingImportRules; ++it)
    5758        tokenize(*it);
    5859    m_requests = 0;
    5960}
    6061
    61 void CSSPreloadScanner::scan(const LChar* begin, const LChar* end, Vector<OwnPtr<PreloadRequest> >& requests)
    62 {
    63     m_requests = &requests;
    64     for (const LChar* it = begin; it != end && m_state != DoneParsingImportRules; ++it)
    65         tokenize(*it);
    66     m_requests = 0;
     62void CSSPreloadScanner::scan(const HTMLToken::DataVector& data, PreloadRequestStream& requests)
     63{
     64    scanCommon(data.data(), data.data() + data.size(), requests);
     65}
     66
     67void CSSPreloadScanner::scan(const String& data, PreloadRequestStream& requests)
     68{
     69    if (data.is8Bit()) {
     70        const LChar* begin = data.characters8();
     71        scanCommon(begin, begin + data.length(), requests);
     72        return;
     73    }
     74    const UChar* begin = data.characters16();
     75    scanCommon(begin, begin + data.length(), requests);
    6776}
    6877
     
    205214        if (!url.isEmpty()) {
    206215            KURL baseElementURL; // FIXME: This should be passed in from the HTMLPreloadScaner via scan()!
    207             OwnPtr<PreloadRequest> request = PreloadRequest::create(
    208                 cachedResourceRequestInitiators().css, url, baseElementURL, CachedResource::CSSStyleSheet);
     216            OwnPtr<PreloadRequest> request = PreloadRequest::create("css", url, baseElementURL, CachedResource::CSSStyleSheet);
    209217            // FIXME: Should this be including the charset in the preload request?
    210218            m_requests->append(request.release());
  • trunk/Source/WebCore/html/parser/CSSPreloadScanner.h

    r143960 r144010  
    2929
    3030#include "HTMLResourcePreloader.h"
     31#include "HTMLToken.h"
    3132#include <wtf/text/StringBuilder.h>
    3233
     
    4142    void reset();
    4243
    43     void scan(const UChar* begin, const UChar* end, Vector<OwnPtr<PreloadRequest> >&);
    44     void scan(const LChar* begin, const LChar* end, Vector<OwnPtr<PreloadRequest> >&);
     44    void scan(const HTMLToken::DataVector&, PreloadRequestStream&);
     45    void scan(const String&, PreloadRequestStream&);
    4546
    4647private:
     
    5859    };
    5960
     61    template<typename Char>
     62    void scanCommon(const Char* begin, const Char* end, PreloadRequestStream&);
     63
    6064    inline void tokenize(UChar);
    6165    void emitRule();
     
    6670
    6771    // Only non-zero during scan()
    68     Vector<OwnPtr<PreloadRequest> >* m_requests;
     72    PreloadRequestStream* m_requests;
    6973};
    7074
  • trunk/Source/WebCore/html/parser/HTMLDocumentParser.cpp

    r144000 r144010  
    625625
    626626    ASSERT(config->xssAuditor->isSafeToSendToAnotherThread());
     627    ASSERT(config->preloadScanner->isSafeToSendToAnotherThread());
    627628    HTMLParserThread::shared()->postTask(bind(&BackgroundHTMLParser::create, reference.release(), config.release()));
    628629}
  • trunk/Source/WebCore/html/parser/HTMLPreloadScanner.cpp

    r143960 r144010  
    4444using namespace HTMLNames;
    4545
    46 static bool isStartTag(HTMLToken::Type type)
    47 {
    48     return type == HTMLToken::StartTag;
    49 }
    50 
    51 static bool isStartOrEndTag(HTMLToken::Type type)
    52 {
    53     return type == HTMLToken::EndTag || isStartTag(type);
    54 }
    55 
    56 TokenPreloadScanner::TagId TokenPreloadScanner::identifierFor(const AtomicString& tagName)
    57 {
     46TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVector& data)
     47{
     48    AtomicString tagName(data);
    5849    if (tagName == imgTag)
    5950        return ImgTagId;
     
    7364}
    7465
    75 String TokenPreloadScanner::inititatorFor(TagId tagId)
     66TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const String& tagName)
     67{
     68    if (threadSafeMatch(tagName, imgTag))
     69        return ImgTagId;
     70    if (threadSafeMatch(tagName, inputTag))
     71        return InputTagId;
     72    if (threadSafeMatch(tagName, linkTag))
     73        return LinkTagId;
     74    if (threadSafeMatch(tagName, scriptTag))
     75        return ScriptTagId;
     76    if (threadSafeMatch(tagName, styleTag))
     77        return StyleTagId;
     78    if (threadSafeMatch(tagName, baseTag))
     79        return BaseTagId;
     80    if (threadSafeMatch(tagName, templateTag))
     81        return TemplateTagId;
     82    return UnknownTagId;
     83}
     84
     85String TokenPreloadScanner::initiatorFor(TagId tagId)
    7686{
    7787    switch (tagId) {
     
    108118    {
    109119        ASSERT(isMainThread());
    110 
    111120        if (m_tagId >= UnknownTagId)
    112121            return;
    113 
    114122        for (HTMLToken::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
    115123            AtomicString attributeName(iter->name);
     
    119127    }
    120128
     129#if ENABLE(THREADED_HTML_PARSER)
     130    void processAttributes(const Vector<CompactHTMLToken::Attribute>& attributes)
     131    {
     132        if (m_tagId >= UnknownTagId)
     133            return;
     134        for (Vector<CompactHTMLToken::Attribute>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
     135            processAttribute(iter->name, iter->value);
     136    }
     137#endif
     138
    121139    PassOwnPtr<PreloadRequest> createPreloadRequest(const KURL& predictedBaseURL)
    122140    {
     
    124142            return nullptr;
    125143
    126         OwnPtr<PreloadRequest> request = PreloadRequest::create(inititatorFor(m_tagId), m_urlToLoad, predictedBaseURL, resourceType());
     144        OwnPtr<PreloadRequest> request = PreloadRequest::create(initiatorFor(m_tagId), m_urlToLoad, predictedBaseURL, resourceType());
    127145        request->setCrossOriginModeAllowsCookies(crossOriginModeAllowsCookies());
    128146        request->setCharset(charset());
     
    245263}
    246264
    247 #if ENABLE(TEMPLATE_ELEMENT)
    248 bool TokenPreloadScanner::processPossibleTemplateTag(TagId tagId, HTMLToken::Type type)
    249 {
    250     if (isStartOrEndTag(type) && tagId == TemplateTagId) {
    251         if (isStartTag(type))
    252             m_templateCount++;
    253         else
    254             m_templateCount--;
    255         return true; // Twas our token.
    256     }
    257     // If we're in a template we "consume" all tokens.
    258     return m_templateCount > 0;
    259 }
    260 #endif
    261 
    262 bool TokenPreloadScanner::processPossibleStyleTag(TagId tagId, HTMLToken::Type type)
    263 {
    264     ASSERT(isStartOrEndTag(type));
    265     if (tagId != StyleTagId)
    266         return false;
    267 
    268     m_inStyle = isStartTag(type);
    269 
    270     if (!m_inStyle)
    271         m_cssScanner.reset();
    272 
    273     return true;
    274 }
    275 
    276 bool TokenPreloadScanner::processPossibleBaseTag(TagId tagId, const HTMLToken& token)
    277 {
    278     ASSERT(isStartTag(token.type()));
    279     if (tagId != BaseTagId)
    280         return false;
    281 
    282     // The first <base> element is the one that wins.
    283     if (!m_predictedBaseElementURL.isEmpty())
    284         return true;
    285 
    286     for (HTMLToken::AttributeList::const_iterator iter = token.attributes().begin(); iter != token.attributes().end(); ++iter) {
    287         AtomicString attributeName(iter->name);
    288         if (attributeName == hrefAttr) {
    289             String hrefValue = StringImpl::create8BitIfPossible(iter->value);
    290             m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefValue));
    291             break;
    292         }
    293     }
    294     return true;
     265TokenPreloadScannerCheckpoint TokenPreloadScanner::createCheckpoint()
     266{
     267    TokenPreloadScannerCheckpoint checkpoint = m_checkpoints.size();
     268    m_checkpoints.append(Checkpoint(m_predictedBaseElementURL, m_inStyle
     269#if ENABLE(TEMPLATE_ELEMENT)
     270                                    , m_templateCount
     271#endif
     272                                    ));
     273    return checkpoint;
     274}
     275
     276void TokenPreloadScanner::rewindTo(TokenPreloadScannerCheckpoint checkpointIndex)
     277{
     278    ASSERT(checkpointIndex < m_checkpoints.size()); // If this ASSERT fires, checkpointIndex is invalid.
     279    const Checkpoint& checkpoint = m_checkpoints[checkpointIndex];
     280    m_predictedBaseElementURL = checkpoint.predictedBaseElementURL;
     281    m_inStyle = checkpoint.inStyle;
     282#if ENABLE(TEMPLATE_ELEMENT)
     283    m_templateCount = checkpoint.templateCount;
     284#endif
     285    m_cssScanner.reset();
     286    m_checkpoints.clear();
    295287}
    296288
    297289void TokenPreloadScanner::scan(const HTMLToken& token, Vector<OwnPtr<PreloadRequest> >& requests)
    298290{
    299     // <style> is the only place we search for urls in non-start/end-tag tokens.
    300     if (m_inStyle) {
    301         if (token.type() != HTMLToken::Character)
    302             return;
    303         const HTMLToken::DataVector& characters = token.characters();
    304         return m_cssScanner.scan(characters.begin(), characters.end(), requests);
    305     }
    306 
    307     if (!isStartOrEndTag(token.type()))
     291    scanCommon(token, requests);
     292}
     293
     294#if ENABLE(THREADED_HTML_PARSER)
     295void TokenPreloadScanner::scan(const CompactHTMLToken& token, Vector<OwnPtr<PreloadRequest> >& requests)
     296{
     297    scanCommon(token, requests);
     298}
     299#endif
     300
     301template<typename Token>
     302void TokenPreloadScanner::scanCommon(const Token& token, Vector<OwnPtr<PreloadRequest> >& requests)
     303{
     304    switch (token.type()) {
     305    case HTMLToken::Character: {
     306        if (!m_inStyle)
     307            return;
     308        m_cssScanner.scan(token.data(), requests);
    308309        return;
    309 
    310     AtomicString tagName(token.name());
    311     TagId tagId = identifierFor(tagName);
    312 
    313 #if ENABLE(TEMPLATE_ELEMENT)
    314     if (processPossibleTemplateTag(tagId, token.type()))
     310    }
     311    case HTMLToken::EndTag: {
     312        TagId tagId = tagIdFor(token.data());
     313#if ENABLE(TEMPLATE_ELEMENT)
     314        if (tagId == TemplateTagId) {
     315            if (m_templateCount)
     316                --m_templateCount;
     317            return;
     318        }
     319#endif
     320        if (tagId == StyleTagId) {
     321            if (m_inStyle)
     322                m_cssScanner.reset();
     323            m_inStyle = false;
     324        }
    315325        return;
    316 #endif
    317     if (processPossibleStyleTag(tagId, token.type()))
     326    }
     327    case HTMLToken::StartTag: {
     328#if ENABLE(TEMPLATE_ELEMENT)
     329        if (m_templateCount)
     330            return;
     331#endif
     332        TagId tagId = tagIdFor(token.data());
     333#if ENABLE(TEMPLATE_ELEMENT)
     334        if (tagId == TemplateTagId) {
     335            ++m_templateCount;
     336            return;
     337        }
     338#endif
     339        if (tagId == StyleTagId) {
     340            m_inStyle = true;
     341            return;
     342        }
     343        if (tagId == BaseTagId) {
     344            // The first <base> element is the one that wins.
     345            if (!m_predictedBaseElementURL.isEmpty())
     346                return;
     347            updatePredictedBaseURL(token);
     348            return;
     349        }
     350
     351        StartTagScanner scanner(tagId);
     352        scanner.processAttributes(token.attributes());
     353        OwnPtr<PreloadRequest> request = scanner.createPreloadRequest(m_predictedBaseElementURL);
     354        if (request)
     355            requests.append(request.release());
    318356        return;
    319     if (!isStartTag(token.type()))
     357    }
     358    default: {
    320359        return;
    321     if (processPossibleBaseTag(tagId, token))
    322         return;
    323 
    324     StartTagScanner scanner(tagId);
    325     scanner.processAttributes(token.attributes());
    326     OwnPtr<PreloadRequest> request =  scanner.createPreloadRequest(m_predictedBaseElementURL);
    327     if (request)
    328         requests.append(request.release());
     360    }
     361    }
     362}
     363
     364template<typename Token>
     365void TokenPreloadScanner::updatePredictedBaseURL(const Token& token)
     366{
     367    ASSERT(m_predictedBaseElementURL.isEmpty());
     368    if (const typename Token::Attribute* hrefAttribute = token.getAttributeItem(hrefAttr))
     369        m_predictedBaseElementURL = KURL(m_documentURL, stripLeadingAndTrailingHTMLSpaces(hrefAttribute->value)).copy();
    329370}
    330371
     
    352393        m_scanner.setPredictedBaseElementURL(startingBaseElementURL);
    353394
    354     Vector<OwnPtr<PreloadRequest> > requests;
     395    PreloadRequestStream requests;
     396
    355397    while (m_tokenizer->nextToken(m_source, m_token)) {
    356         if (isStartTag(m_token.type()))
     398        if (m_token.type() == HTMLToken::StartTag)
    357399            m_tokenizer->updateStateFor(AtomicString(m_token.name()));
    358400        m_scanner.scan(m_token, requests);
    359401        m_token.clear();
    360402    }
    361     for (size_t i = 0; i < requests.size(); i++)
    362         preloader->preload(requests[i].release());
    363 }
    364 
    365 }
     403
     404    preloader->takeAndPreload(requests);
     405}
     406
     407}
  • trunk/Source/WebCore/html/parser/HTMLPreloadScanner.h

    r143960 r144010  
    2929
    3030#include "CSSPreloadScanner.h"
     31#include "CompactHTMLToken.h"
    3132#include "HTMLToken.h"
    3233#include "SegmentedString.h"
     34#include <wtf/Vector.h>
    3335
    3436namespace WebCore {
     
    4648    ~TokenPreloadScanner();
    4749
    48     void scan(const HTMLToken&, Vector<OwnPtr<PreloadRequest> >& requests);
     50    void scan(const HTMLToken&, PreloadRequestStream& requests);
     51#if ENABLE(THREADED_HTML_PARSER)
     52    void scan(const CompactHTMLToken&, PreloadRequestStream& requests);
     53#endif
    4954
    5055    void setPredictedBaseElementURL(const KURL& url) { m_predictedBaseElementURL = url; }
     56
     57    // A TokenPreloadScannerCheckpoint is valid until the next call to rewindTo,
     58    // at which point all outstanding checkpoints are invalidated.
     59    TokenPreloadScannerCheckpoint createCheckpoint();
     60    void rewindTo(TokenPreloadScannerCheckpoint);
     61
     62    bool isSafeToSendToAnotherThread()
     63    {
     64        return m_documentURL.isSafeToSendToAnotherThread()
     65            && m_predictedBaseElementURL.isSafeToSendToAnotherThread();
     66    }
    5167
    5268private:
     
    6783    class StartTagScanner;
    6884
    69     static TagId identifierFor(const AtomicString& tagName);
    70     static String inititatorFor(TagId);
     85    template<typename Token>
     86    inline void scanCommon(const Token&, PreloadRequestStream& requests);
    7187
     88    static TagId tagIdFor(const HTMLToken::DataVector&);
     89    static TagId tagIdFor(const String&);
     90
     91    static String initiatorFor(TagId);
     92
     93    template<typename Token>
     94    void updatePredictedBaseURL(const Token&);
     95
     96    struct Checkpoint {
     97        Checkpoint(const KURL& predictedBaseElementURL, bool inStyle
    7298#if ENABLE(TEMPLATE_ELEMENT)
    73     bool processPossibleTemplateTag(TagId, HTMLToken::Type);
     99            , size_t templateCount
    74100#endif
     101            )
     102            : predictedBaseElementURL(predictedBaseElementURL)
     103            , inStyle(inStyle)
     104#if ENABLE(TEMPLATE_ELEMENT)
     105            , templateCount(templateCount)
     106#endif
     107        {
     108        }
    75109
    76     bool processPossibleStyleTag(TagId, HTMLToken::Type);
    77     bool processPossibleBaseTag(TagId, const HTMLToken&);
     110        KURL predictedBaseElementURL;
     111        bool inStyle;
     112#if ENABLE(TEMPLATE_ELEMENT)
     113        size_t templateCount;
     114#endif
     115    };
    78116
    79117    CSSPreloadScanner m_cssScanner;
    80     KURL m_documentURL;
     118    const KURL m_documentURL;
    81119    KURL m_predictedBaseElementURL;
    82120    bool m_inStyle;
     
    85123    size_t m_templateCount;
    86124#endif
     125
     126    Vector<Checkpoint> m_checkpoints;
    87127};
    88128
Note: See TracChangeset for help on using the changeset viewer.