Changeset 122498 in webkit


Ignore:
Timestamp:
Jul 12, 2012 1:31:09 PM (12 years ago)
Author:
rniwa@webkit.org
Message:

invalidateNodeListsCacheAfterAttributeChanged should dynamically figure out which attribute needs invalidation
https://bugs.webkit.org/show_bug.cgi?id=91046

Reviewed by Anders Carlsson.

Added an array of counters (m_nodeListCounts) for each set of attributes (NodeListInvalidationType) node lists care about
to Document, and made DynamicSubtreeNodeList's constructor and destructor increment and decrement these counters via
registerDynamicSubtreeNodeList and unregisterDynamicSubtreeNodeList respectively. shouldInvalidateDynamicSubtreeNodeList,
which is called by invalidateNodeListsCacheAfterAttributeChanged, then use these counters to determine whether a given
attribute change should result in node list invalidations.

Also removed m_numNodeListCaches from TreeScope because this counter has now become redundant with m_nodeListCounts.

  • dom/ChildNodeList.cpp:

(WebCore::ChildNodeList::ChildNodeList): Do not invalidate on attribute changes.

  • dom/ClassNodeList.cpp:

(WebCore::ClassNodeList::ClassNodeList): Invalidate on class attribute changes.

  • dom/Document.cpp:

(WebCore::Document::Document): Initialize m_nodeListCounts.
(WebCore::Document::~Document): Add assertions to make sure m_listsInvalidatedAtDocument, m_nodeListCounts, and
m_collections are all empty.
(WebCore::Document::registerDynamicSubtreeNodeList): This function is now called for all DynamicSubtreeNodeLists supposed
to just ones rooted at the document in order to increment the counter for each invalidation type.
(WebCore::Document::unregisterDynamicSubtreeNodeList): Ditto.
(WebCore::shouldInvalidateDynamicSubtreeNodeListForType): Checks the attribute name against NodeListInvalidationType.
(WebCore::Document::shouldInvalidateDynamicSubtreeNodeList): Returns true if the given attribute name matches the invalidation
type of the existing DynamicSubtreeNodeLists in the document. If the attribute name is not given (used when children change),
then it checks for the existence of any DynamicSubtreeNodeLists. Conceptually, this function can be written as a list of
"if" statements that checks values in m_nodeListCounts and the attribute name. We use "for" loop and switch statement instead
to share logic and detect future addition of values to NodeListInvalidationType.

  • dom/Document.h:

(Document): Moved RootType and InvalidationType from DynamicNodeListCacheBase and renamed them to NodeListRootType and
NodeListInvalidationType respectively in order to reduce the possibility of future name collisions. Also the invalidation type
now contains 6 values instead of 2.

  • dom/DynamicNodeList.cpp:

(WebCore):

  • dom/DynamicNodeList.h:

(WebCore::DynamicNodeListCacheBase::DynamicNodeListCacheBase):
(WebCore::DynamicNodeListCacheBase::shouldInvalidateOnAttributeChange):
(WebCore::DynamicNodeListCacheBase::rootType): Added.
(WebCore::DynamicNodeListCacheBase::invalidationType): Added.
(DynamicNodeListCacheBase): Uses 3 bits to store invalidation type now that the number of values have increased from 2 to 6.
(WebCore::DynamicNodeList::DynamicNodeList):
(WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList): Call unregisterDynamicSubtreeNodeList.
(WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList): Call registerDynamicSubtreeNodeList.

  • dom/MicroDataItemList.cpp:

(WebCore::MicroDataItemList::MicroDataItemList): Invalidate on itemscope, itemprop, and itemtype content attribute changes.

  • dom/NameNodeList.cpp:

(WebCore::NameNodeList::NameNodeList): Invalidate on name attribute changes.

  • dom/Node.cpp:

(WebCore::Node::clearRareData):
(WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged): Replaced the hard coded check list of attributes, by a call
to shouldInvalidateDynamicSubtreeNodeList.
(WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged): Calls shouldInvalidateDynamicSubtreeNodeList.
(WebCore::Node::getElementsByTagName):
(WebCore::Node::getElementsByTagNameNS):
(WebCore::Node::getElementsByName):
(WebCore::Node::getElementsByClassName):
(WebCore::Node::radioNodeList):
(WebCore::NodeRareData::createNodeLists):

  • dom/NodeRareData.h:

(WebCore::NodeListsNodeData::adoptTreeScope): Unregister and register node lists in m_tagNodeListCacheNS since all node lists
need to be accounted in m_nodeListCounts.
(WebCore::NodeRareData::ensureNodeLists):
(NodeRareData):

  • dom/TagNodeList.cpp:

(WebCore::TagNodeList::TagNodeList): Do not invalidate on any attribute changes.

  • dom/TreeScope.cpp:

(WebCore::TreeScope::TreeScope): No longer initializes m_numNodeListCaches since it has been removed.

  • dom/TreeScope.h:

(TreeScope): Removed m_numNodeListCaches.

  • dom/TreeScopeAdopter.cpp:

(WebCore::TreeScopeAdopter::moveTreeToNewScope):

  • html/HTMLCollection.h:

(WebCore::HTMLCollectionCacheBase::HTMLCollectionCacheBase): Just pass in DoNotInvalidateOnAttributeChanges for now since
it's never used in HTMLCollections.

  • html/LabelableElement.cpp:

(WebCore::LabelableElement::labels):

  • html/LabelsNodeList.cpp:

(WebCore::LabelsNodeList::LabelsNodeList): Invalidate on for content attribute changes.
(WebCore::LabelsNodeList::~LabelsNodeList):

  • html/RadioNodeList.cpp:

(WebCore::RadioNodeList::RadioNodeList): Invalidate on id, name, and for content attribute changes.
(WebCore::RadioNodeList::~RadioNodeList):

Location:
trunk/Source/WebCore
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r122494 r122498  
     12012-07-11  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        invalidateNodeListsCacheAfterAttributeChanged should dynamically figure out which attribute needs invalidation
     4        https://bugs.webkit.org/show_bug.cgi?id=91046
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Added an array of counters (m_nodeListCounts) for each set of attributes (NodeListInvalidationType) node lists care about
     9        to Document, and made DynamicSubtreeNodeList's constructor and destructor increment and decrement these counters via
     10        registerDynamicSubtreeNodeList and unregisterDynamicSubtreeNodeList respectively. shouldInvalidateDynamicSubtreeNodeList,
     11        which is called by invalidateNodeListsCacheAfterAttributeChanged, then use these counters to determine whether a given
     12        attribute change should result in node list invalidations.
     13
     14        Also removed m_numNodeListCaches from TreeScope because this counter has now become redundant with m_nodeListCounts.
     15
     16        * dom/ChildNodeList.cpp:
     17        (WebCore::ChildNodeList::ChildNodeList): Do not invalidate on attribute changes.
     18        * dom/ClassNodeList.cpp:
     19        (WebCore::ClassNodeList::ClassNodeList): Invalidate on class attribute changes.
     20        * dom/Document.cpp:
     21        (WebCore::Document::Document): Initialize m_nodeListCounts.
     22        (WebCore::Document::~Document): Add assertions to make sure m_listsInvalidatedAtDocument, m_nodeListCounts, and
     23        m_collections are all empty.
     24        (WebCore::Document::registerDynamicSubtreeNodeList): This function is now called for all DynamicSubtreeNodeLists supposed
     25        to just ones rooted at the document in order to increment the counter for each invalidation type.
     26        (WebCore::Document::unregisterDynamicSubtreeNodeList): Ditto.
     27        (WebCore::shouldInvalidateDynamicSubtreeNodeListForType): Checks the attribute name against NodeListInvalidationType.
     28        (WebCore::Document::shouldInvalidateDynamicSubtreeNodeList): Returns true if the given attribute name matches the invalidation
     29        type of the existing DynamicSubtreeNodeLists in the document. If the attribute name is not given (used when children change),
     30        then it checks for the existence of any DynamicSubtreeNodeLists. Conceptually, this function can be written as a list of
     31        "if" statements that checks values in m_nodeListCounts and the attribute name. We use "for" loop and switch statement instead
     32        to share logic and detect future addition of values to NodeListInvalidationType.
     33        * dom/Document.h:
     34        (Document): Moved RootType and InvalidationType from DynamicNodeListCacheBase and renamed them to NodeListRootType and
     35        NodeListInvalidationType respectively in order to reduce the possibility of future name collisions. Also the invalidation type
     36        now contains 6 values instead of 2.
     37        * dom/DynamicNodeList.cpp:
     38        (WebCore):
     39        * dom/DynamicNodeList.h:
     40        (WebCore::DynamicNodeListCacheBase::DynamicNodeListCacheBase):
     41        (WebCore::DynamicNodeListCacheBase::shouldInvalidateOnAttributeChange):
     42        (WebCore::DynamicNodeListCacheBase::rootType): Added.
     43        (WebCore::DynamicNodeListCacheBase::invalidationType): Added.
     44        (DynamicNodeListCacheBase): Uses 3 bits to store invalidation type now that the number of values have increased from 2 to 6.
     45        (WebCore::DynamicNodeList::DynamicNodeList):
     46        (WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList): Call unregisterDynamicSubtreeNodeList.
     47        (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList): Call registerDynamicSubtreeNodeList.
     48        * dom/MicroDataItemList.cpp:
     49        (WebCore::MicroDataItemList::MicroDataItemList): Invalidate on itemscope, itemprop, and itemtype content attribute changes.
     50        * dom/NameNodeList.cpp:
     51        (WebCore::NameNodeList::NameNodeList): Invalidate on name attribute changes.
     52        * dom/Node.cpp:
     53        (WebCore::Node::clearRareData):
     54        (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged): Replaced the hard coded check list of attributes, by a call
     55        to shouldInvalidateDynamicSubtreeNodeList.
     56        (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged): Calls shouldInvalidateDynamicSubtreeNodeList.
     57        (WebCore::Node::getElementsByTagName):
     58        (WebCore::Node::getElementsByTagNameNS):
     59        (WebCore::Node::getElementsByName):
     60        (WebCore::Node::getElementsByClassName):
     61        (WebCore::Node::radioNodeList):
     62        (WebCore::NodeRareData::createNodeLists):
     63        * dom/NodeRareData.h:
     64        (WebCore::NodeListsNodeData::adoptTreeScope): Unregister and register node lists in m_tagNodeListCacheNS since all node lists
     65        need to be accounted in m_nodeListCounts.
     66        (WebCore::NodeRareData::ensureNodeLists):
     67        (NodeRareData):
     68        * dom/TagNodeList.cpp:
     69        (WebCore::TagNodeList::TagNodeList): Do not invalidate on any attribute changes.
     70        * dom/TreeScope.cpp:
     71        (WebCore::TreeScope::TreeScope): No longer initializes m_numNodeListCaches since it has been removed.
     72        * dom/TreeScope.h:
     73        (TreeScope): Removed m_numNodeListCaches.
     74        * dom/TreeScopeAdopter.cpp:
     75        (WebCore::TreeScopeAdopter::moveTreeToNewScope):
     76        * html/HTMLCollection.h:
     77        (WebCore::HTMLCollectionCacheBase::HTMLCollectionCacheBase): Just pass in DoNotInvalidateOnAttributeChanges for now since
     78        it's never used in HTMLCollections.
     79        * html/LabelableElement.cpp:
     80        (WebCore::LabelableElement::labels):
     81        * html/LabelsNodeList.cpp:
     82        (WebCore::LabelsNodeList::LabelsNodeList): Invalidate on for content attribute changes.
     83        (WebCore::LabelsNodeList::~LabelsNodeList):
     84        * html/RadioNodeList.cpp:
     85        (WebCore::RadioNodeList::RadioNodeList): Invalidate on id, name, and for content attribute changes.
     86        (WebCore::RadioNodeList::~RadioNodeList):
     87
    1882012-07-12  Gavin Barraclough  <barraclough@apple.com>
    289
  • trunk/Source/WebCore/dom/ChildNodeList.cpp

    r121580 r122498  
    2929
    3030ChildNodeList::ChildNodeList(PassRefPtr<Node> node)
    31     : DynamicNodeList(node, RootedAtNode, DoNotInvalidateOnAttributeChange)
     31    : DynamicNodeList(node, NodeListIsRootedAtNode, DoNotInvalidateOnAttributeChanges)
    3232{
    3333}
  • trunk/Source/WebCore/dom/ClassNodeList.cpp

    r121003 r122498  
    3838
    3939ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames)
    40     : DynamicSubtreeNodeList(rootNode)
     40    : DynamicSubtreeNodeList(rootNode, InvalidateOnClassAttrChange)
    4141    , m_classNames(classNames, document()->inQuirksMode())
    4242    , m_originalClassNames(classNames)
  • trunk/Source/WebCore/dom/Document.cpp

    r122205 r122498  
    565565    static int docID = 0;
    566566    m_docID = docID++;
    567    
     567
     568    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
     569        m_nodeListCounts[i] = 0;
     570
    568571    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
    569572        m_collections[i] = 0;
     
    648651    if (hasRareData())
    649652        clearRareData();
     653
     654    ASSERT(!m_listsInvalidatedAtDocument.size());
     655
     656    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListCounts); i++)
     657        ASSERT(!m_nodeListCounts[i]);
     658
     659    for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_collections); i++)
     660        ASSERT(!m_collections[i]);
    650661
    651662    m_document = 0;
     
    38663877}
    38673878
    3868 void Document::registerDynamicSubtreeNodeList(DynamicSubtreeNodeList* list)
    3869 {
    3870     m_listsInvalidatedAtDocument.add(list);
    3871 }
    3872 
    3873 void Document::unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList* list)
    3874 {
    3875     m_listsInvalidatedAtDocument.remove(list);
     3879void Document::registerDynamicSubtreeNodeList(DynamicSubtreeNodeList* list, NodeListRootType rootType, NodeListInvalidationType invalidationType)
     3880{
     3881    m_nodeListCounts[invalidationType]++;
     3882    if (rootType == NodeListIsRootedAtDocument)
     3883        m_listsInvalidatedAtDocument.add(list);
     3884}
     3885
     3886void Document::unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList* list, NodeListRootType rootType, NodeListInvalidationType invalidationType)
     3887{
     3888    m_nodeListCounts[invalidationType]--;
     3889    if (rootType == NodeListIsRootedAtDocument) {
     3890        ASSERT(m_listsInvalidatedAtDocument.contains(list));
     3891        m_listsInvalidatedAtDocument.remove(list);
     3892    }
     3893}
     3894
     3895static ALWAYS_INLINE bool shouldInvalidateNodeListForType(NodeListInvalidationType type, const QualifiedName& attrName)
     3896{
     3897    switch (type) {
     3898    case InvalidateOnClassAttrChange:
     3899        return attrName == classAttr;
     3900    case InvalidateOnNameAttrChange:
     3901        return attrName == nameAttr;
     3902    case InvalidateOnForAttrChange:
     3903        return attrName == forAttr;
     3904    case InvalidateOnIdNameForAttrChange:
     3905        return attrName == nameAttr || attrName == idAttr || attrName == forAttr;
     3906    case InvalidateOnItemAttrChange:
     3907#if ENABLE(MICRODATA)
     3908        return attrName == itemscopeAttr || attrName == itempropAttr || attrName == itemtypeAttr;
     3909#endif // Intentionally fall through
     3910    case DoNotInvalidateOnAttributeChanges:
     3911        ASSERT_NOT_REACHED();
     3912        return false;
     3913    }
     3914    return false;
     3915}
     3916
     3917bool Document::shouldInvalidateDynamicSubtreeNodeList(const QualifiedName* attrName) const
     3918{
     3919    if (attrName) {
     3920        for (int type = DoNotInvalidateOnAttributeChanges + 1; type < numNodeListInvalidationTypes; type++) {
     3921            if (m_nodeListCounts[type] && shouldInvalidateNodeListForType(static_cast<NodeListInvalidationType>(type), *attrName))
     3922                return true;
     3923        }
     3924        return false;
     3925    }
     3926
     3927    for (int type = 0; type < numNodeListInvalidationTypes; type++) {
     3928        if (m_nodeListCounts[type])
     3929            return true;
     3930    }
     3931
     3932    return false;
    38763933}
    38773934
     
    59666023    String localTypeNames = typeNames.isNull() ? MicroDataItemList::undefinedItemType() : typeNames;
    59676024
    5968     return ensureRareData()->ensureNodeLists(this)->addCacheWithName<MicroDataItemList>(this, DynamicNodeList::MicroDataItemListType, localTypeNames);
     6025    return ensureRareData()->ensureNodeLists()->addCacheWithName<MicroDataItemList>(this, DynamicNodeList::MicroDataItemListType, localTypeNames);
    59696026}
    59706027#endif
  • trunk/Source/WebCore/dom/Document.h

    r122205 r122498  
    187187enum StyleResolverUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded };
    188188
     189enum NodeListRootType {
     190    NodeListIsRootedAtNode,
     191    NodeListIsRootedAtDocument,
     192};
     193
     194enum NodeListInvalidationType {
     195    DoNotInvalidateOnAttributeChanges = 0,
     196    InvalidateOnClassAttrChange,
     197    InvalidateOnNameAttrChange,
     198    InvalidateOnForAttrChange,
     199    InvalidateOnIdNameForAttrChange,
     200    InvalidateOnItemAttrChange,
     201};
     202const int numNodeListInvalidationTypes = InvalidateOnItemAttrChange + 1;
     203
    189204class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
    190205public:
     
    724739    void styleRecalcTimerFired(Timer<Document>*);
    725740
    726     void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
    727     void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
     741    void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*, NodeListRootType, NodeListInvalidationType);
     742    void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*, NodeListRootType, NodeListInvalidationType);
     743    bool shouldInvalidateDynamicSubtreeNodeList(const QualifiedName* attrName = 0) const;
    728744    void clearNodeListCaches();
    729745
     
    14101426
    14111427    HashSet<DynamicSubtreeNodeList*> m_listsInvalidatedAtDocument;
     1428    unsigned m_nodeListCounts[numNodeListInvalidationTypes];
    14121429
    14131430    HTMLCollection* m_collections[NumUnnamedDocumentCachedTypes];
  • trunk/Source/WebCore/dom/DynamicNodeList.cpp

    r121580 r122498  
    2828
    2929namespace WebCore {
    30 
    31 DynamicSubtreeNodeList::~DynamicSubtreeNodeList()
    32 {
    33 }
    3430
    3531unsigned DynamicSubtreeNodeList::length() const
  • trunk/Source/WebCore/dom/DynamicNodeList.h

    r121580 r122498  
    3737class DynamicNodeListCacheBase {
    3838public:
    39     enum RootType {
    40         RootedAtNode,
    41         RootedAtDocument,
    42     };
    43 
    44     enum InvalidationType {
    45         AlwaysInvalidate,
    46         DoNotInvalidateOnAttributeChange,
    47     };
    48 
    49     DynamicNodeListCacheBase(RootType rootType, InvalidationType invalidationType)
    50         : m_rootedAtDocument(rootType == RootedAtDocument)
    51         , m_shouldInvalidateOnAttributeChange(invalidationType == AlwaysInvalidate)
     39    DynamicNodeListCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType)
     40        : m_rootedAtDocument(rootType == NodeListIsRootedAtDocument)
     41        , m_invalidationType(invalidationType)
    5242    {
     43        ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
    5344        clearCache();
    5445    }
     
    5647public:
    5748    ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootedAtDocument; }
    58     ALWAYS_INLINE bool shouldInvalidateOnAttributeChange() const { return m_shouldInvalidateOnAttributeChange; }
     49    ALWAYS_INLINE bool shouldInvalidateOnAttributeChange() const { return m_invalidationType != DoNotInvalidateOnAttributeChanges; }
     50    ALWAYS_INLINE NodeListRootType rootType() { return m_rootedAtDocument ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode; }
     51    ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
    5952
    6053protected:
     
    9386    // From DynamicNodeList
    9487    const unsigned m_rootedAtDocument : 1;
    95     const unsigned m_shouldInvalidateOnAttributeChange : 1;
     88    const unsigned m_invalidationType : 3;
    9689};
    9790
     
    107100        MicroDataItemListType,
    108101    };
    109     DynamicNodeList(PassRefPtr<Node> ownerNode, RootType rootType, InvalidationType invalidationType)
     102    DynamicNodeList(PassRefPtr<Node> ownerNode, NodeListRootType rootType, NodeListInvalidationType invalidationType)
    110103        : DynamicNodeListCacheBase(rootType, invalidationType)
    111104        , m_ownerNode(ownerNode)
     
    139132class DynamicSubtreeNodeList : public DynamicNodeList {
    140133public:
    141     virtual ~DynamicSubtreeNodeList();
     134    virtual ~DynamicSubtreeNodeList()
     135    {
     136        document()->unregisterDynamicSubtreeNodeList(this, rootType(), invalidationType());
     137    }
    142138    virtual unsigned length() const OVERRIDE;
    143139    virtual Node* item(unsigned index) const OVERRIDE;
    144140
    145141protected:
    146     DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode, InvalidationType invalidationType = AlwaysInvalidate)
     142    DynamicSubtreeNodeList(PassRefPtr<Node> node, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode)
    147143        : DynamicNodeList(node, rootType, invalidationType)
    148     { }
     144    {
     145        document()->registerDynamicSubtreeNodeList(this, rootType, invalidationType);
     146    }
    149147
    150148private:
  • trunk/Source/WebCore/dom/MicroDataItemList.cpp

    r121149 r122498  
    4646
    4747MicroDataItemList::MicroDataItemList(PassRefPtr<Node> rootNode, const String& typeNames)
    48     : DynamicSubtreeNodeList(rootNode)
     48    : DynamicSubtreeNodeList(rootNode, InvalidateOnItemAttrChange)
    4949    , m_typeNames(typeNames, document()->inQuirksMode())
    5050    , m_originalTypeNames(typeNames)
  • trunk/Source/WebCore/dom/NameNodeList.cpp

    r121003 r122498  
    3434
    3535NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name)
    36     : DynamicSubtreeNodeList(rootNode)
     36    : DynamicSubtreeNodeList(rootNode, InvalidateOnNameAttrChange)
    3737    , m_name(name)
    3838{
  • trunk/Source/WebCore/dom/Node.cpp

    r122159 r122498  
    490490{
    491491    ASSERT(hasRareData());
    492     if (treeScope() && rareData()->nodeLists())
    493         treeScope()->removeNodeListCache();
    494492
    495493#if ENABLE(MUTATION_OBSERVERS)
     
    966964        return;
    967965
    968     // FIXME: Move the list of attributes each NodeList type cares about to be a static on the
    969     // appropriate NodeList class. Then use those lists here and in invalidateCachesThatDependOnAttributes
    970     // to only invalidate the cache types that depend on the attribute that changed.
    971     // FIXME: Keep track of when we have no caches of a given type so that we can avoid the for-loop
    972     // below even if a related attribute changed (e.g. if we have no RadioNodeLists, we don't need
    973     // to invalidate any caches when id attributes change.)
    974     if (attrName != classAttr
    975 #if ENABLE(MICRODATA)
    976         && attrName != itemscopeAttr
    977         && attrName != itempropAttr
    978         && attrName != itemtypeAttr
    979 #endif
    980         && attrName != nameAttr
    981         && attrName != forAttr
    982         && (attrName != idAttr || !attributeOwnerElement->isFormControlElement()))
     966    if (!document()->shouldInvalidateDynamicSubtreeNodeList(&attrName))
    983967        return;
    984968
    985969    document()->clearNodeListCaches();
    986 
    987     if (!treeScope()->hasNodeListCaches())
    988         return;
    989970
    990971    for (Node* node = this; node; node = node->parentNode()) {
     
    1005986        rareData()->clearChildNodeListCache();
    1006987
     988    if (!document()->shouldInvalidateDynamicSubtreeNodeList())
     989        return;
     990
    1007991    document()->clearNodeListCaches();
    1008 
    1009     if (!treeScope()->hasNodeListCaches())
    1010         return;
    1011992
    1012993    for (Node* node = this; node; node = node->parentNode()) {
     
    15641545
    15651546    if (document()->isHTMLDocument())
    1566         return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
    1567     return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
     1547        return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
     1548    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
    15681549}
    15691550
     
    15761557        return getElementsByTagName(localName);
    15771558
    1578     return ensureRareData()->ensureNodeLists(this)->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
     1559    return ensureRareData()->ensureNodeLists()->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
    15791560}
    15801561
    15811562PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
    15821563{
    1583     return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName);
     1564    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName);
    15841565}
    15851566
    15861567PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
    15871568{
    1588     return ensureRareData()->ensureNodeLists(this)->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames);
     1569    return ensureRareData()->ensureNodeLists()->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames);
    15891570}
    15901571
     
    15921573{
    15931574    ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
    1594     return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name);
     1575    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name);
    15951576}
    15961577
     
    27812762#endif
    27822763
    2783 void NodeRareData::createNodeLists(Node* node)
    2784 {
    2785     ASSERT(node);
     2764void NodeRareData::createNodeLists()
     2765{
    27862766    setNodeLists(NodeListsNodeData::create());
    2787     if (TreeScope* treeScope = node->treeScope())
    2788         treeScope->addNodeListCache();
    27892767}
    27902768
  • trunk/Source/WebCore/dom/NodeRareData.h

    r122159 r122498  
    130130    }
    131131
    132     void adoptTreeScope(TreeScope* oldTreeScope, TreeScope* newTreeScope, Document* oldDocument, Document* newDocument)
     132    void adoptTreeScope(Document* oldDocument, Document* newDocument)
    133133    {
    134134        invalidateCaches();
     
    139139                DynamicSubtreeNodeList* list = it->second;
    140140                if (list->isRootedAtDocument()) {
    141                     oldDocument->unregisterDynamicSubtreeNodeList(list);
    142                     newDocument->registerDynamicSubtreeNodeList(list);
     141                    oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     142                    newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
    143143                }
    144144            }
     
    148148                DynamicSubtreeNodeList* list = it->second;
    149149                if (list->isRootedAtDocument()) {
    150                     oldDocument->unregisterDynamicSubtreeNodeList(list);
    151                     newDocument->registerDynamicSubtreeNodeList(list);
     150                    oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     151                    newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
    152152                }
    153153            }
     154
     155            TagNodeListCacheNS::const_iterator tagEnd = m_tagNodeListCacheNS.end();
     156            for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagEnd; ++it) {
     157                DynamicSubtreeNodeList* list = it->second;
     158                ASSERT(!list->isRootedAtDocument());
     159                oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     160                newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     161            }
    154162        }
    155 
    156         if (oldTreeScope)
    157             oldTreeScope->removeNodeListCache();
    158         newTreeScope->addNodeListCache();
    159163    }
    160164
     
    216220    void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
    217221    NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }
    218     NodeListsNodeData* ensureNodeLists(Node* node)
     222    NodeListsNodeData* ensureNodeLists()
    219223    {
    220224        if (!m_nodeLists)
    221             createNodeLists(node);
     225            createNodeLists();
    222226        return m_nodeLists.get();
    223227    }
     
    341345
    342346private:
    343     void createNodeLists(Node*);
     347    void createNodeLists();
    344348
    345349    TreeScope* m_treeScope;
  • trunk/Source/WebCore/dom/TagNodeList.cpp

    r121003 r122498  
    3232
    3333TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
    34     : DynamicSubtreeNodeList(rootNode, RootedAtNode, DoNotInvalidateOnAttributeChange)
     34    : DynamicSubtreeNodeList(rootNode, DoNotInvalidateOnAttributeChanges)
    3535    , m_namespaceURI(namespaceURI)
    3636    , m_localName(localName)
  • trunk/Source/WebCore/dom/TreeScope.cpp

    r121126 r122498  
    5555    : m_rootNode(rootNode)
    5656    , m_parentTreeScope(0)
    57     , m_numNodeListCaches(0)
    5857{
    5958    ASSERT(rootNode);
  • trunk/Source/WebCore/dom/TreeScope.h

    r121126 r122498  
    6262    HTMLMapElement* getImageMap(const String& url) const;
    6363
    64     void addNodeListCache() { ++m_numNodeListCaches; }
    65     void removeNodeListCache() { ASSERT(m_numNodeListCaches > 0); --m_numNodeListCaches; }
    66     bool hasNodeListCaches() const { return m_numNodeListCaches; }
    67 
    6864    DOMSelection* getSelection() const;
    6965
     
    9692    DocumentOrderedMap m_imageMapsByName;
    9793
    98     unsigned m_numNodeListCaches;
    99 
    10094    mutable RefPtr<DOMSelection> m_selection;
    10195};
  • trunk/Source/WebCore/dom/TreeScopeAdopter.cpp

    r121174 r122498  
    5050        NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
    5151        if (rareData && rareData->nodeLists())
    52             rareData->nodeLists()->adoptTreeScope(m_oldScope, m_newScope, oldDocument, newDocument);
     52            rareData->nodeLists()->adoptTreeScope(oldDocument, newDocument);
    5353
    5454        if (willMoveToNewDocument)
  • trunk/Source/WebCore/html/HTMLCollection.h

    r122353 r122498  
    4141public:
    4242    HTMLCollectionCacheBase(CollectionType type, bool includeChildren)
    43         : DynamicNodeListCacheBase(RootedAtNode, AlwaysInvalidate) // These two flags are never used
     43        : DynamicNodeListCacheBase(NodeListIsRootedAtNode, DoNotInvalidateOnAttributeChanges) // These two flags are never used
    4444        , m_cachedElementsArrayOffset(0)
    4545        , m_cacheTreeVersion(0)
  • trunk/Source/WebCore/html/HTMLPropertiesCollection.cpp

    r122353 r122498  
    154154}
    155155
    156 void HTMLPropertiesCollection::cacheFirstItem() const
    157 {
    158     for (unsigned i = 0; i < m_itemRefElements.size(); ++i) {
    159         if (HTMLElement* element = itemAfter(m_itemRefElements[i], 0))
    160             return setItemCache(element, 0, i);
    161     }
    162     setItemCache(0, 0, 0);
    163 }
    164 
    165156void HTMLPropertiesCollection::updateNameCache() const
    166157{
  • trunk/Source/WebCore/html/LabelableElement.cpp

    r121335 r122498  
    4848        return 0;
    4949
    50     return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom);
     50    return ensureRareData()->ensureNodeLists()->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom);
    5151}
    5252
  • trunk/Source/WebCore/html/LabelsNodeList.cpp

    r121126 r122498  
    3535
    3636LabelsNodeList::LabelsNodeList(Node* forNode)
    37     : DynamicSubtreeNodeList(forNode, RootedAtDocument)
     37    : DynamicSubtreeNodeList(forNode, InvalidateOnForAttrChange, NodeListIsRootedAtDocument)
    3838{
    39     document()->registerDynamicSubtreeNodeList(this);
    4039}
    4140
     
    4342{
    4443    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
    45     document()->unregisterDynamicSubtreeNodeList(this);
    4644}
    4745   
  • trunk/Source/WebCore/html/RadioNodeList.cpp

    r121126 r122498  
    3939
    4040RadioNodeList::RadioNodeList(Node* rootNode, const AtomicString& name)
    41     : DynamicSubtreeNodeList(rootNode, rootNode->hasTagName(formTag) ? RootedAtDocument : RootedAtNode)
     41    : DynamicSubtreeNodeList(rootNode, InvalidateOnIdNameForAttrChange, rootNode->hasTagName(formTag) ? NodeListIsRootedAtDocument : NodeListIsRootedAtNode)
    4242    , m_name(name)
    4343{
    44     document()->registerDynamicSubtreeNodeList(this);
    4544}
    4645
     
    4847{
    4948    ownerNode()->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
    50     document()->unregisterDynamicSubtreeNodeList(this);
    5149}
    5250
Note: See TracChangeset for help on using the changeset viewer.