Changeset 122621 in webkit


Ignore:
Timestamp:
Jul 13, 2012 12:48:40 PM (12 years ago)
Author:
rniwa@webkit.org
Message:

HTMLCollection should use DynamicNodeList's invalidation model
https://bugs.webkit.org/show_bug.cgi?id=90326

Reviewed by Anders Carlsson.

Make HTMLCollection invalidated upon attribute and children changes instead of invalidating it on demand
by comparing DOM tree versions. Node that HTMLCollections owned by Document are invalidated with other
document-rooted node lists in m_listsInvalidatedAtDocument for simplicity although this mechanism is
normally used for node lists owned by a non-Document node that contains nodes outside of its subtree.
ItemProperties and FormControls are more "traditional" users of the mechanism.

Also, merged DynamicNodeList::invalidateCache and HTMLCollection::invalidateCache.

  • dom/Document.cpp:

(WebCore::Document::registerNodeListCache): Renamed. No longer takes NodeListInvalidationType or
NodeListRootType since they can be obtained from the cache base. Increment the node list counter for
InvalidateOnIdNameAttrChange when a HTMLCollection is passed in since all HTMLCollections need to be
invalidated on id or name content attribute changes due to named getters.
(WebCore::Document::unregisterNodeListCache): Ditto.
(WebCore::shouldInvalidateNodeListForType):
(WebCore::Document::shouldInvalidateNodeListCaches):
(WebCore::Document::clearNodeListCaches):

  • dom/Document.h:

(WebCore): Added InvalidateOnIdNameAttrChange, InvalidateOnHRefAttrChange, and InvalidateOnAnyAttrChange.
(Document):

  • dom/DynamicNodeList.cpp:

(WebCore::DynamicNodeListCacheBase::invalidateCache): Added. Invalidates caches of both DynamicNodeList
and HTMLCollection. We can't afford to use virtual function calls here because this function is called on
all node lists and HTML collections owned by ancestors of an element under which a node is added, removed,
or its attributes are changed.
(WebCore):

  • dom/DynamicNodeList.h:

(WebCore::DynamicNodeListCacheBase::DynamicNodeListCacheBase): Initializes member variables directly
instead of calling clearCache now that DynamicNodeListCacheBase::invalidateCache has become polymorphic.
(DynamicNodeListCacheBase): Increased the number of bits for m_invalidationType since we now have 9
invalidation types.
(WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList):
(WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):

  • dom/ElementRareData.h:

(ElementRareData):
(WebCore::ElementRareData::clearHTMLCollectionCaches): Added.
(WebCore::ElementRareData::adoptTreeScope): Added; similar to NodeRareData::adoptTreeScope.

  • dom/Node.cpp:

(WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged): Clears HTML collection caches as well as
node list caches.
(WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged): Ditto.

  • dom/NodeRareData.h:

(WebCore::NodeListsNodeData::adoptTreeScope):

  • dom/TreeScopeAdopter.cpp:

(WebCore::TreeScopeAdopter::moveTreeToNewScope): Calls ElementRareData's adoptTreeScope as well as
NodeRareData's.

  • html/HTMLAllCollection.cpp:

(WebCore::HTMLAllCollection::namedItemWithIndex):

  • html/HTMLCollection.cpp:

(WebCore::rootTypeFromCollectionType): Added. As mentioned above, treat all Document-owned HTML collection
as if rooted at document for convenience.
(WebCore::invalidationTypeExcludingIdAndNameAttributes): Added. Since all HTML collection requires
invalidation on id and name content attribute changes, which is taken care by the special logic in
Document::registerNodeListCache, exclude those two attributes from consideration.
(WebCore::HTMLCollection::HTMLCollection): Calls Document::registerNodeListCache.
(WebCore::HTMLCollection::~HTMLCollection): Calls Document::unregisterNodeListCache.
(WebCore::HTMLCollection::length):
(WebCore::HTMLCollection::item):
(WebCore::HTMLCollection::namedItem):
(WebCore::HTMLCollection::updateNameCache):

  • html/HTMLCollection.h:

(WebCore::HTMLCollectionCacheBase::HTMLCollectionCacheBase):
(HTMLCollectionCacheBase): Removed m_cacheTreeVersion and clearCache since they're no longer used.
(HTMLCollection):

  • html/HTMLFormCollection.cpp:

(WebCore::HTMLFormCollection::namedItem):
(WebCore::HTMLFormCollection::updateNameCache):

  • html/HTMLOptionsCollection.h:

(HTMLOptionsCollection):

  • html/HTMLPropertiesCollection.cpp:

(WebCore::HTMLPropertiesCollection::updateNameCache):

  • html/HTMLPropertiesCollection.h:

(WebCore::HTMLPropertiesCollection::invalidateCache):

Location:
trunk/Source/WebCore
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r122619 r122621  
     12012-07-13  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        HTMLCollection should use DynamicNodeList's invalidation model
     4        https://bugs.webkit.org/show_bug.cgi?id=90326
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Make HTMLCollection invalidated upon attribute and children changes instead of invalidating it on demand
     9        by comparing DOM tree versions. Node that HTMLCollections owned by Document are invalidated with other
     10        document-rooted node lists in m_listsInvalidatedAtDocument for simplicity although this mechanism is
     11        normally used for node lists owned by a non-Document node that contains nodes outside of its subtree.
     12        ItemProperties and FormControls are more "traditional" users of the mechanism.
     13
     14        Also, merged DynamicNodeList::invalidateCache and HTMLCollection::invalidateCache.
     15
     16        * dom/Document.cpp:
     17        (WebCore::Document::registerNodeListCache): Renamed. No longer takes NodeListInvalidationType or
     18        NodeListRootType since they can be obtained from the cache base. Increment the node list counter for
     19        InvalidateOnIdNameAttrChange when a HTMLCollection is passed in since all HTMLCollections need to be
     20        invalidated on id or name content attribute changes due to named getters.
     21        (WebCore::Document::unregisterNodeListCache): Ditto.
     22        (WebCore::shouldInvalidateNodeListForType):
     23        (WebCore::Document::shouldInvalidateNodeListCaches):
     24        (WebCore::Document::clearNodeListCaches):
     25        * dom/Document.h:
     26        (WebCore): Added InvalidateOnIdNameAttrChange, InvalidateOnHRefAttrChange, and InvalidateOnAnyAttrChange.
     27        (Document):
     28        * dom/DynamicNodeList.cpp:
     29        (WebCore::DynamicNodeListCacheBase::invalidateCache): Added. Invalidates caches of both DynamicNodeList
     30        and HTMLCollection. We can't afford to use virtual function calls here because this function is called on
     31        all node lists and HTML collections owned by ancestors of an element under which a node is added, removed,
     32        or its attributes are changed.
     33        (WebCore):
     34        * dom/DynamicNodeList.h:
     35        (WebCore::DynamicNodeListCacheBase::DynamicNodeListCacheBase): Initializes member variables directly
     36        instead of calling clearCache now that DynamicNodeListCacheBase::invalidateCache has become polymorphic.
     37        (DynamicNodeListCacheBase): Increased the number of bits for m_invalidationType since we now have 9
     38        invalidation types.
     39        (WebCore::DynamicSubtreeNodeList::~DynamicSubtreeNodeList):
     40        (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
     41        * dom/ElementRareData.h:
     42        (ElementRareData):
     43        (WebCore::ElementRareData::clearHTMLCollectionCaches): Added.
     44        (WebCore::ElementRareData::adoptTreeScope): Added; similar to NodeRareData::adoptTreeScope.
     45        * dom/Node.cpp:
     46        (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged): Clears HTML collection caches as well as
     47        node list caches.
     48        (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged): Ditto.
     49        * dom/NodeRareData.h:
     50        (WebCore::NodeListsNodeData::adoptTreeScope):
     51        * dom/TreeScopeAdopter.cpp:
     52        (WebCore::TreeScopeAdopter::moveTreeToNewScope): Calls ElementRareData's adoptTreeScope as well as
     53        NodeRareData's.
     54        * html/HTMLAllCollection.cpp:
     55        (WebCore::HTMLAllCollection::namedItemWithIndex):
     56        * html/HTMLCollection.cpp:
     57        (WebCore::rootTypeFromCollectionType): Added. As mentioned above, treat all Document-owned HTML collection
     58        as if rooted at document for convenience.
     59        (WebCore::invalidationTypeExcludingIdAndNameAttributes): Added. Since all HTML collection requires
     60        invalidation on id and name content attribute changes, which is taken care by the special logic in
     61        Document::registerNodeListCache, exclude those two attributes from consideration.
     62        (WebCore::HTMLCollection::HTMLCollection): Calls Document::registerNodeListCache.
     63        (WebCore::HTMLCollection::~HTMLCollection): Calls Document::unregisterNodeListCache.
     64        (WebCore::HTMLCollection::length):
     65        (WebCore::HTMLCollection::item):
     66        (WebCore::HTMLCollection::namedItem):
     67        (WebCore::HTMLCollection::updateNameCache):
     68        * html/HTMLCollection.h:
     69        (WebCore::HTMLCollectionCacheBase::HTMLCollectionCacheBase):
     70        (HTMLCollectionCacheBase): Removed m_cacheTreeVersion and clearCache since they're no longer used.
     71        (HTMLCollection):
     72        * html/HTMLFormCollection.cpp:
     73        (WebCore::HTMLFormCollection::namedItem):
     74        (WebCore::HTMLFormCollection::updateNameCache):
     75        * html/HTMLOptionsCollection.h:
     76        (HTMLOptionsCollection):
     77        * html/HTMLPropertiesCollection.cpp:
     78        (WebCore::HTMLPropertiesCollection::updateNameCache):
     79        * html/HTMLPropertiesCollection.h:
     80        (WebCore::HTMLPropertiesCollection::invalidateCache):
     81
    1822012-07-13  Shawn Singh  <shawnsingh@chromium.org>
    283
  • trunk/Source/WebCore/dom/Document.cpp

    r122600 r122621  
    38623862}
    38633863
    3864 void Document::registerDynamicSubtreeNodeList(DynamicSubtreeNodeList* list, NodeListRootType rootType, NodeListInvalidationType invalidationType)
    3865 {
    3866     m_nodeListCounts[invalidationType]++;
    3867     if (rootType == NodeListIsRootedAtDocument)
     3864void Document::registerNodeListCache(DynamicNodeListCacheBase* list)
     3865{
     3866    if (list->type() != InvalidCollectionType)
     3867        m_nodeListCounts[InvalidateOnIdNameAttrChange]++;
     3868    m_nodeListCounts[list->invalidationType()]++;
     3869    if (list->rootType() == NodeListIsRootedAtDocument)
    38683870        m_listsInvalidatedAtDocument.add(list);
    38693871}
    38703872
    3871 void Document::unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList* list, NodeListRootType rootType, NodeListInvalidationType invalidationType)
    3872 {
    3873     m_nodeListCounts[invalidationType]--;
    3874     if (rootType == NodeListIsRootedAtDocument) {
     3873void Document::unregisterNodeListCache(DynamicNodeListCacheBase* list)
     3874{
     3875    if (list->type() != InvalidCollectionType)
     3876        m_nodeListCounts[InvalidateOnIdNameAttrChange]--;
     3877    m_nodeListCounts[list->invalidationType()]--;
     3878    if (list->rootType() == NodeListIsRootedAtDocument) {
    38753879        ASSERT(m_listsInvalidatedAtDocument.contains(list));
    38763880        m_listsInvalidatedAtDocument.remove(list);
     
    38853889    case InvalidateOnNameAttrChange:
    38863890        return attrName == nameAttr;
     3891    case InvalidateOnIdNameAttrChange:
     3892        return attrName == idAttr || attrName == nameAttr;
    38873893    case InvalidateOnForAttrChange:
    38883894        return attrName == forAttr;
    38893895    case InvalidateForFormControls:
    38903896        return attrName == nameAttr || attrName == idAttr || attrName == forAttr || attrName == typeAttr;
     3897    case InvalidateOnHRefAttrChange:
     3898        return attrName == hrefAttr;
    38913899    case InvalidateOnItemAttrChange:
    38923900#if ENABLE(MICRODATA)
     
    38963904        ASSERT_NOT_REACHED();
    38973905        return false;
     3906    case InvalidateOnAnyAttrChange:
     3907        return true;
    38983908    }
    38993909    return false;
    39003910}
    39013911
    3902 bool Document::shouldInvalidateDynamicSubtreeNodeList(const QualifiedName* attrName) const
     3912bool Document::shouldInvalidateNodeListCaches(const QualifiedName* attrName) const
    39033913{
    39043914    if (attrName) {
     
    39203930void Document::clearNodeListCaches()
    39213931{
    3922     HashSet<DynamicSubtreeNodeList*>::iterator end = m_listsInvalidatedAtDocument.end();
    3923     for (HashSet<DynamicSubtreeNodeList*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
     3932    HashSet<DynamicNodeListCacheBase*>::iterator end = m_listsInvalidatedAtDocument.end();
     3933    for (HashSet<DynamicNodeListCacheBase*>::iterator it = m_listsInvalidatedAtDocument.begin(); it != end; ++it)
    39243934        (*it)->invalidateCache();
    39253935}
  • trunk/Source/WebCore/dom/Document.h

    r122556 r122621  
    8080class DocumentType;
    8181class DocumentWeakReference;
     82class DynamicNodeListCacheBase;
    8283class EditingText;
    8384class Element;
     
    188189enum StyleResolverUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded };
    189190
    190 enum NodeListRootType {
    191     NodeListIsRootedAtNode,
    192     NodeListIsRootedAtDocument,
    193 };
    194 
    195191enum NodeListInvalidationType {
    196192    DoNotInvalidateOnAttributeChanges = 0,
    197193    InvalidateOnClassAttrChange,
     194    InvalidateOnIdNameAttrChange,
    198195    InvalidateOnNameAttrChange,
    199196    InvalidateOnForAttrChange,
    200197    InvalidateForFormControls,
     198    InvalidateOnHRefAttrChange,
    201199    InvalidateOnItemAttrChange,
     200    InvalidateOnAnyAttrChange,
    202201};
    203 const int numNodeListInvalidationTypes = InvalidateOnItemAttrChange + 1;
     202const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1;
    204203
    205204class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext {
     
    737736    void styleRecalcTimerFired(Timer<Document>*);
    738737
    739     void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*, NodeListRootType, NodeListInvalidationType);
    740     void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*, NodeListRootType, NodeListInvalidationType);
    741     bool shouldInvalidateDynamicSubtreeNodeList(const QualifiedName* attrName = 0) const;
     738    void registerNodeListCache(DynamicNodeListCacheBase*);
     739    void unregisterNodeListCache(DynamicNodeListCacheBase*);
     740    bool shouldInvalidateNodeListCaches(const QualifiedName* attrName = 0) const;
    742741    void clearNodeListCaches();
    743742
     
    14231422    InheritedBool m_designMode;
    14241423
    1425     HashSet<DynamicSubtreeNodeList*> m_listsInvalidatedAtDocument;
     1424    HashSet<DynamicNodeListCacheBase*> m_listsInvalidatedAtDocument;
    14261425    unsigned m_nodeListCounts[numNodeListInvalidationTypes];
    14271426
  • trunk/Source/WebCore/dom/DynamicNodeList.cpp

    r122498 r122621  
    2626#include "Document.h"
    2727#include "Element.h"
     28#include "HTMLCollection.h"
     29#include "HTMLPropertiesCollection.h"
    2830
    2931namespace WebCore {
     32
     33void DynamicNodeListCacheBase::invalidateCache() const
     34{
     35    m_cachedItem = 0;
     36    m_isLengthCacheValid = false;
     37    m_isItemCacheValid = false;
     38    m_isNameCacheValid = false;
     39    if (type() == InvalidCollectionType)
     40        return;
     41
     42    const HTMLCollectionCacheBase* cacheBase = static_cast<const HTMLCollectionCacheBase*>(this);
     43    cacheBase->m_idCache.clear();
     44    cacheBase->m_nameCache.clear();
     45    cacheBase->m_cachedElementsArrayOffset = 0;
     46
     47#if ENABLE(MICRODATA)
     48    // FIXME: There should be more generic mechanism to clear caches in subclasses.
     49    if (type() == ItemProperties)
     50        static_cast<const HTMLPropertiesCollection*>(this)->invalidateCache();
     51#endif
     52}
    3053
    3154unsigned DynamicSubtreeNodeList::length() const
  • trunk/Source/WebCore/dom/DynamicNodeList.h

    r122533 r122621  
    3636class Node;
    3737
     38enum NodeListRootType {
     39    NodeListIsRootedAtNode,
     40    NodeListIsRootedAtDocument,
     41};
     42
    3843class DynamicNodeListCacheBase {
    3944public:
    40     DynamicNodeListCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType)
    41         : m_rootedAtDocument(rootType == NodeListIsRootedAtDocument)
     45    DynamicNodeListCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType, CollectionType collectionType = InvalidCollectionType)
     46        : m_cachedItem(0)
     47        , m_isLengthCacheValid(false)
     48        , m_isItemCacheValid(false)
     49        , m_rootedAtDocument(rootType == NodeListIsRootedAtDocument)
    4250        , m_invalidationType(invalidationType)
    43         , m_collectionType(InvalidCollectionType)
     51        , m_isNameCacheValid(false)
     52        , m_collectionType(collectionType)
    4453    {
    4554        ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
    46         clearCache();
    47     }
    48 
    49     DynamicNodeListCacheBase(CollectionType collectionType)
    50         : m_rootedAtDocument(false) // Ignored
    51         , m_invalidationType(DoNotInvalidateOnAttributeChanges) // Ignored
    52         , m_collectionType(collectionType)
    53     {
    5455        ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
    55         clearCache();
    5656    }
    5757
     
    6262    ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return static_cast<NodeListInvalidationType>(m_invalidationType); }
    6363    ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionType>(m_collectionType); }
     64
     65    void invalidateCache() const;
    6466
    6567protected:
     
    8688    void setHasNameCache() const { m_isNameCacheValid = true; }
    8789
    88     void clearCache() const
    89     {
    90         m_cachedItem = 0;
    91         m_isLengthCacheValid = false;
    92         m_isItemCacheValid = false;
    93         m_isNameCacheValid = false;
    94     }
    95 
    9690private:
    9791    mutable Node* m_cachedItem;
     
    10094    mutable unsigned m_isLengthCacheValid : 1;
    10195    mutable unsigned m_isItemCacheValid : 1;
    102 
    103     // From DynamicNodeList
    10496    const unsigned m_rootedAtDocument : 1;
    105     const unsigned m_invalidationType : 3;
     97    const unsigned m_invalidationType : 4;
    10698
    10799    // From HTMLCollection
     
    134126    // Other methods (not part of DOM)
    135127    Node* ownerNode() const { return m_ownerNode.get(); }
    136     void invalidateCache() { clearCache(); }
    137128
    138129protected:
     
    155146    virtual ~DynamicSubtreeNodeList()
    156147    {
    157         document()->unregisterDynamicSubtreeNodeList(this, rootType(), invalidationType());
     148        document()->unregisterNodeListCache(this);
    158149    }
    159150    virtual unsigned length() const OVERRIDE;
     
    164155        : DynamicNodeList(node, rootType, invalidationType)
    165156    {
    166         document()->registerDynamicSubtreeNodeList(this, rootType, invalidationType);
     157        document()->registerNodeListCache(this);
    167158    }
    168159
  • trunk/Source/WebCore/dom/ElementRareData.h

    r122550 r122621  
    2727#include "Element.h"
    2828#include "ElementShadow.h"
     29#include "HTMLCollection.h"
    2930#include "NamedNodeMap.h"
    3031#include "NodeRareData.h"
     
    5859        return (*m_cachedCollections)[type - FirstNodeCollectionType];
    5960    }
     61
    6062    void removeCachedHTMLCollection(HTMLCollection* collection, CollectionType type)
    6163    {
     
    6365        ASSERT_UNUSED(collection, (*m_cachedCollections)[type - FirstNodeCollectionType] == collection);
    6466        (*m_cachedCollections)[type - FirstNodeCollectionType] = 0;
     67    }
     68
     69    void clearHTMLCollectionCaches()
     70    {
     71        if (!m_cachedCollections)
     72            return;
     73
     74        for (unsigned i = 0; i < (*m_cachedCollections).size(); i++) {
     75            if ((*m_cachedCollections)[i])
     76                (*m_cachedCollections)[i]->invalidateCache();
     77        }
     78    }
     79
     80    void adoptTreeScope(Document* oldDocument, Document* newDocument)
     81    {
     82        if (!m_cachedCollections)
     83            return;
     84
     85        for (unsigned i = 0; i < (*m_cachedCollections).size(); i++) {
     86            HTMLCollection* collection = (*m_cachedCollections)[i];
     87            if (!collection)
     88                continue;
     89            collection->invalidateCache();
     90            if (oldDocument != newDocument) {
     91                oldDocument->unregisterNodeListCache(collection);
     92                newDocument->registerNodeListCache(collection);
     93            }
     94        }
    6595    }
    6696
  • trunk/Source/WebCore/dom/Node.cpp

    r122600 r122621  
    4848#include "DynamicNodeList.h"
    4949#include "Element.h"
     50#include "ElementRareData.h"
    5051#include "ElementShadow.h"
    5152#include "Event.h"
     
    974975        return;
    975976
    976     if (!document()->shouldInvalidateDynamicSubtreeNodeList(&attrName))
     977    if (!document()->shouldInvalidateNodeListCaches(&attrName))
    977978        return;
    978979
     
    984985            continue;
    985986        NodeRareData* data = node->rareData();
    986         if (!data->nodeLists())
    987             continue;
    988 
    989         data->nodeLists()->invalidateCaches(&attrName);
     987        if (data->nodeLists())
     988            data->nodeLists()->invalidateCaches(&attrName);
     989        if (node->isElementNode())
     990            static_cast<ElementRareData*>(data)->clearHTMLCollectionCaches();
    990991    }
    991992}
     
    996997        rareData()->clearChildNodeListCache();
    997998
    998     if (!document()->shouldInvalidateDynamicSubtreeNodeList())
     999    if (!document()->shouldInvalidateNodeListCaches())
    9991000        return;
    10001001
     
    10051006            continue;
    10061007        NodeRareData* data = node->rareData();
    1007         if (!data->nodeLists())
    1008             continue;
    1009 
    1010         data->nodeLists()->invalidateCaches();
     1008        if (data->nodeLists())
     1009            data->nodeLists()->invalidateCaches();
     1010        if (node->isElementNode())
     1011            static_cast<ElementRareData*>(data)->clearHTMLCollectionCaches();
    10111012    }
    10121013}
  • trunk/Source/WebCore/dom/NodeRareData.h

    r122498 r122621  
    139139                DynamicSubtreeNodeList* list = it->second;
    140140                if (list->isRootedAtDocument()) {
    141                     oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
    142                     newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     141                    oldDocument->unregisterNodeListCache(list);
     142                    newDocument->registerNodeListCache(list);
    143143                }
    144144            }
     
    148148                DynamicSubtreeNodeList* list = it->second;
    149149                if (list->isRootedAtDocument()) {
    150                     oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
    151                     newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     150                    oldDocument->unregisterNodeListCache(list);
     151                    newDocument->registerNodeListCache(list);
    152152                }
    153153            }
     
    157157                DynamicSubtreeNodeList* list = it->second;
    158158                ASSERT(!list->isRootedAtDocument());
    159                 oldDocument->unregisterDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
    160                 newDocument->registerDynamicSubtreeNodeList(list, list->rootType(), list->invalidationType());
     159                oldDocument->unregisterNodeListCache(list);
     160                newDocument->registerNodeListCache(list);
    161161            }
    162162        }
  • trunk/Source/WebCore/dom/TreeScopeAdopter.cpp

    r122498 r122621  
    2727
    2828#include "Document.h"
     29#include "ElementRareData.h"
    2930#include "ElementShadow.h"
    3031#include "NodeRareData.h"
     32#include "RenderStyle.h"
    3133#include "ShadowRoot.h"
    3234
     
    4850
    4951    for (Node* node = root; node; node = node->traverseNextNode(root)) {
    50         NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
    51         if (rareData && rareData->nodeLists())
    52             rareData->nodeLists()->adoptTreeScope(oldDocument, newDocument);
     52        if (NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope)) {
     53            if (rareData->nodeLists())
     54                rareData->nodeLists()->adoptTreeScope(oldDocument, newDocument);
     55            if (node->isElementNode())
     56                static_cast<ElementRareData*>(rareData)->adoptTreeScope(oldDocument, newDocument);
     57        }
    5358
    5459        if (willMoveToNewDocument)
  • trunk/Source/WebCore/html/HTMLAllCollection.cpp

    r122115 r122621  
    4747Node* HTMLAllCollection::namedItemWithIndex(const AtomicString& name, unsigned index) const
    4848{
    49     invalidateCacheIfNeeded();
    5049    updateNameCache();
    5150
  • trunk/Source/WebCore/html/HTMLCollection.cpp

    r122531 r122621  
    7777}
    7878
     79static NodeListRootType rootTypeFromCollectionType(CollectionType type)
     80{
     81    switch (type) {
     82    case DocImages:
     83    case DocApplets:
     84    case DocEmbeds:
     85    case DocObjects:
     86    case DocForms:
     87    case DocLinks:
     88    case DocAnchors:
     89    case DocScripts:
     90    case DocAll:
     91    case WindowNamedItems:
     92    case DocumentNamedItems:
     93#if ENABLE(MICRODATA)
     94    case ItemProperties:
     95#endif
     96    case FormControls:
     97        return NodeListIsRootedAtDocument;
     98    case NodeChildren:
     99    case TableTBodies:
     100    case TSectionRows:
     101    case TableRows:
     102    case TRCells:
     103    case SelectOptions:
     104    case SelectedOptions:
     105    case DataListOptions:
     106    case MapAreas:
     107    case InvalidCollectionType:
     108        return NodeListIsRootedAtNode;
     109    }
     110    ASSERT_NOT_REACHED();
     111    return NodeListIsRootedAtNode;
     112}
     113
     114static NodeListInvalidationType invalidationTypeExcludingIdAndNameAttributes(CollectionType type)
     115{
     116    switch (type) {
     117    case DocImages:
     118    case DocEmbeds:
     119    case DocObjects:
     120    case DocForms:
     121    case DocAnchors: // Depends on name attribute.
     122    case DocScripts:
     123    case DocAll:
     124    case WindowNamedItems: // Depends on id and name attributes.
     125    case DocumentNamedItems: // Ditto.
     126    case NodeChildren:
     127    case TableTBodies:
     128    case TSectionRows:
     129    case TableRows:
     130    case TRCells:
     131    case SelectOptions:
     132    case MapAreas:
     133        return DoNotInvalidateOnAttributeChanges;
     134    case DocApplets:
     135    case SelectedOptions:
     136    case DataListOptions:
     137        // FIXME: We can do better some day.
     138        return InvalidateOnAnyAttrChange;
     139    case DocLinks:
     140        return InvalidateOnHRefAttrChange;
     141#if ENABLE(MICRODATA)
     142    case ItemProperties:
     143        return InvalidateOnItemAttrChange;
     144#endif
     145    case FormControls:
     146        return InvalidateForFormControls;
     147    case InvalidCollectionType:
     148        break;
     149    }
     150    ASSERT_NOT_REACHED();
     151    return DoNotInvalidateOnAttributeChanges;
     152}
     153   
     154
    79155HTMLCollection::HTMLCollection(Node* base, CollectionType type)
    80     : HTMLCollectionCacheBase(type)
     156    : HTMLCollectionCacheBase(rootTypeFromCollectionType(type), invalidationTypeExcludingIdAndNameAttributes(type), type)
    81157    , m_base(base)
    82158{
    83159    ASSERT(m_base);
     160    m_base->document()->registerNodeListCache(this);
    84161}
    85162
     
    99176    } else // HTMLNameCollection removes cache by itself.
    100177        ASSERT(type() == WindowNamedItems || type() == DocumentNamedItems);
    101 }
    102 
    103 void HTMLCollection::invalidateCacheIfNeeded() const
    104 {
    105     uint64_t docversion = static_cast<HTMLDocument*>(m_base->document())->domTreeVersion();
    106 
    107     if (cacheTreeVersion() == docversion)
    108         return;
    109 
    110     invalidateCache();
    111 }
    112 
    113 void HTMLCollection::invalidateCache() const
    114 {
    115 #if ENABLE(MICRODATA)
    116     // FIXME: There should be more generic mechanism to clear caches in subclasses.
    117     if (type() == ItemProperties)
    118         static_cast<const HTMLPropertiesCollection*>(this)->clearCache();
    119 #endif
    120     clearCache(static_cast<HTMLDocument*>(m_base->document())->domTreeVersion());
     178
     179    m_base->document()->unregisterNodeListCache(this);
    121180}
    122181
     
    201260unsigned HTMLCollection::length() const
    202261{
    203     invalidateCacheIfNeeded();
    204262    if (isLengthCacheValid())
    205263        return cachedLength();
     
    223281Node* HTMLCollection::item(unsigned index) const
    224282{
    225     invalidateCacheIfNeeded();
    226283    if (isItemCacheValid() && cachedItemOffset() == index)
    227284        return cachedItem();
     
    307364    // object with a matching name attribute, but only on those elements
    308365    // that are allowed a name attribute.
    309     invalidateCacheIfNeeded();
    310366
    311367    unsigned arrayOffset = 0;
     
    333389void HTMLCollection::updateNameCache() const
    334390{
    335     invalidateCacheIfNeeded();
    336391    if (hasNameCache())
    337392        return;
  • trunk/Source/WebCore/html/HTMLCollection.h

    r122531 r122621  
    4040class HTMLCollectionCacheBase : public DynamicNodeListCacheBase {
    4141public:
    42     HTMLCollectionCacheBase(CollectionType type)
    43         : DynamicNodeListCacheBase(type)
     42    HTMLCollectionCacheBase(NodeListRootType rootType, NodeListInvalidationType invalidationType, CollectionType collectionType)
     43        : DynamicNodeListCacheBase(rootType, invalidationType, collectionType)
    4444        , m_cachedElementsArrayOffset(0)
    45         , m_cacheTreeVersion(0)
    4645    {
    4746    }
    4847
    4948protected:
    50     void clearCache(uint64_t currentDomTreeVersion) const
    51     {
    52         DynamicNodeListCacheBase::clearCache();
    53         m_idCache.clear();
    54         m_nameCache.clear();
    55         m_cachedElementsArrayOffset = 0;
    56         m_cacheTreeVersion = currentDomTreeVersion;
    57     }
    58 
    5949    void setItemCache(Node* item, unsigned offset, unsigned elementsArrayOffset) const
    6050    {
     
    6353    }
    6454    unsigned cachedElementsArrayOffset() const { return m_cachedElementsArrayOffset; }
    65 
    66     uint64_t cacheTreeVersion() const { return m_cacheTreeVersion; }
    6755
    6856    typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<Element*> > > NodeCacheMap;
     
    7765    using DynamicNodeListCacheBase::isRootedAtDocument;
    7866    using DynamicNodeListCacheBase::shouldInvalidateOnAttributeChange;
    79     using DynamicNodeListCacheBase::clearCache;
    8067    using DynamicNodeListCacheBase::setItemCache;
    8168
     
    8370    mutable NodeCacheMap m_nameCache;
    8471    mutable unsigned m_cachedElementsArrayOffset;
    85     mutable uint64_t m_cacheTreeVersion;
     72
     73    friend void DynamicNodeListCacheBase::invalidateCache() const;
    8674};
    8775
     
    10290    bool isEmpty() const
    10391    {
    104         invalidateCacheIfNeeded();
    10592        if (isLengthCacheValid())
    10693            return !cachedLength();
     
    11198    bool hasExactlyOneItem() const
    11299    {
    113         invalidateCacheIfNeeded();
    114100        if (isLengthCacheValid())
    115101            return cachedLength() == 1;
     
    120106
    121107    Node* base() const { return m_base.get(); }
    122 
    123     void invalidateCache() const;
    124     void invalidateCacheIfNeeded() const;
    125108
    126109protected:
  • trunk/Source/WebCore/html/HTMLFormCollection.cpp

    r122518 r122621  
    112112    // object with a matching name attribute, but only on those elements
    113113    // that are allowed a name attribute.
    114     invalidateCacheIfNeeded();
    115114    const Vector<HTMLImageElement*>* imagesElements = base()->hasTagName(fieldsetTag) ? 0 : &formImageElements();
    116115    if (HTMLElement* item = firstNamedItem(formControlElements(), imagesElements, idAttr, name))
     
    122121void HTMLFormCollection::updateNameCache() const
    123122{
    124     invalidateCacheIfNeeded();
    125123    if (hasNameCache())
    126124        return;
  • trunk/Source/WebCore/html/HTMLOptionsCollection.h

    r122115 r122621  
    4747    void setLength(unsigned, ExceptionCode&);
    4848
    49     using HTMLCollection::invalidateCacheIfNeeded;
    50 
    5149private:
    5250    HTMLOptionsCollection(Element*);
  • trunk/Source/WebCore/html/HTMLPropertiesCollection.cpp

    r122518 r122621  
    143143void HTMLPropertiesCollection::updateNameCache() const
    144144{
    145     invalidateCacheIfNeeded();
    146145    if (m_hasPropertyNameCache)
    147146        return;
  • trunk/Source/WebCore/html/HTMLPropertiesCollection.h

    r122518 r122621  
    5252    virtual bool hasNamedItem(const AtomicString&) const OVERRIDE;
    5353
    54     void clearCache() const
     54    void invalidateCache() const
    5555    {
    5656        m_itemRefElements.clear();
Note: See TracChangeset for help on using the changeset viewer.