Revert r104210. It turned out that this patch makes improving the node list caches...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jan 2012 07:03:04 +0000 (07:03 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Jan 2012 07:03:04 +0000 (07:03 +0000)
* dom/Attr.cpp:
(WebCore::Attr::setValue):
(WebCore::Attr::childrenChanged):
* dom/DynamicNodeList.cpp:
(WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
(WebCore::DynamicSubtreeNodeList::length):
(WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
(WebCore::DynamicSubtreeNodeList::item):
(WebCore::DynamicSubtreeNodeList::invalidateCache):
(WebCore::DynamicSubtreeNodeList::Caches::create):
(WebCore::DynamicSubtreeNodeList::Caches::reset):
* dom/DynamicNodeList.h:
* dom/Element.cpp:
(WebCore::Element::updateAfterAttributeChanged):
* dom/Node.cpp:
(WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
(WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
(WebCore::Node::notifyLocalNodeListsLabelChanged):
(WebCore::Node::itemTypeAttributeChanged):
(WebCore::NodeListsNodeData::invalidateCaches):
(WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes):
* dom/NodeRareData.h:
* html/HTMLElement.cpp:
(WebCore::HTMLElement::parseMappedAttribute):
* html/HTMLLabelElement.cpp:
(WebCore::HTMLLabelElement::parseMappedAttribute):
* html/HTMLLabelElement.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@104674 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/dom/Attr.cpp
Source/WebCore/dom/DynamicNodeList.cpp
Source/WebCore/dom/DynamicNodeList.h
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/NodeRareData.h
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLLabelElement.h

index 46fc53fb1caacf3938f6410821e62344d3635eed..b05202e9bb2e3701a13f4e68caefaa800b86860f 100644 (file)
@@ -1,3 +1,36 @@
+2012-01-10  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Revert r104210. It turned out that this patch makes improving the node list caches harder.
+
+        * dom/Attr.cpp:
+        (WebCore::Attr::setValue):
+        (WebCore::Attr::childrenChanged):
+        * dom/DynamicNodeList.cpp:
+        (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
+        (WebCore::DynamicSubtreeNodeList::length):
+        (WebCore::DynamicSubtreeNodeList::itemForwardsFromCurrent):
+        (WebCore::DynamicSubtreeNodeList::itemBackwardsFromCurrent):
+        (WebCore::DynamicSubtreeNodeList::item):
+        (WebCore::DynamicSubtreeNodeList::invalidateCache):
+        (WebCore::DynamicSubtreeNodeList::Caches::create):
+        (WebCore::DynamicSubtreeNodeList::Caches::reset):
+        * dom/DynamicNodeList.h:
+        * dom/Element.cpp:
+        (WebCore::Element::updateAfterAttributeChanged):
+        * dom/Node.cpp:
+        (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
+        (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
+        (WebCore::Node::notifyLocalNodeListsLabelChanged):
+        (WebCore::Node::itemTypeAttributeChanged):
+        (WebCore::NodeListsNodeData::invalidateCaches):
+        (WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes):
+        * dom/NodeRareData.h:
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::parseMappedAttribute):
+        * html/HTMLLabelElement.cpp:
+        (WebCore::HTMLLabelElement::parseMappedAttribute):
+        * html/HTMLLabelElement.h:
+
 2012-01-10  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r104263 and r104381.
index cf2111ff2f0434f8bccf18d58ff99cd04e29b5a5..6930fa1dc0605068ce554fc12503e2fb775ead5b 100644 (file)
@@ -129,7 +129,7 @@ void Attr::setValue(const AtomicString& value)
     createTextChild();
     m_ignoreChildrenChanged--;
 
-    invalidateNodeListsCacheAfterAttributeChanged();
+    invalidateNodeListsCacheAfterAttributeChanged(m_attribute->name());
 }
 
 void Attr::setValue(const AtomicString& value, ExceptionCode&)
@@ -174,7 +174,7 @@ void Attr::childrenChanged(bool changedByParser, Node* beforeChange, Node* after
 
     Node::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
 
-    invalidateNodeListsCacheAfterAttributeChanged();
+    invalidateNodeListsCacheAfterAttributeChanged(m_attribute->name());
 
     // FIXME: We should include entity references in the value
 
index c234512874fcd09325f7c2a98754fd5b215cd35b..788ab6ef6809e6b40cd4d357b71e50880e342790 100644 (file)
 
 namespace WebCore {
 
-DynamicSubtreeNodeList::SubtreeCaches::SubtreeCaches()
-    : m_cachedItem(0)
-    , m_isLengthCacheValid(false)
-    , m_isItemCacheValid(false)
-    , m_domTreeVersionAtTimeOfCaching(0)
-{
-}
-
-void DynamicSubtreeNodeList::SubtreeCaches::setLengthCache(Node* node, unsigned length)
-{
-    if (m_isItemCacheValid && !domVersionIsConsistent()) {
-        m_cachedItem = node;
-        m_isItemCacheValid = false;
-    }
-    m_cachedLength = length;
-    m_isLengthCacheValid = true;
-    m_domTreeVersionAtTimeOfCaching = node->document()->domTreeVersion();
-}
-
-void DynamicSubtreeNodeList::SubtreeCaches::setItemCache(Node* item, unsigned offset)
-{
-    if (m_isLengthCacheValid && !domVersionIsConsistent())
-        m_isLengthCacheValid = false;
-    m_cachedItem = item;
-    m_cachedItemOffset = offset;
-    m_isItemCacheValid = true;
-    m_domTreeVersionAtTimeOfCaching = item->document()->domTreeVersion();
-}
-
-void DynamicSubtreeNodeList::SubtreeCaches::reset()
-{
-    m_cachedItem = 0;
-    m_isLengthCacheValid = false;
-    m_isItemCacheValid = false;
-}
-
 DynamicSubtreeNodeList::DynamicSubtreeNodeList(PassRefPtr<Node> node)
     : DynamicNodeList(node)
+    , m_caches(Caches::create())
 {
     rootNode()->registerDynamicSubtreeNodeList(this);
 }
@@ -77,15 +42,16 @@ DynamicSubtreeNodeList::~DynamicSubtreeNodeList()
 
 unsigned DynamicSubtreeNodeList::length() const
 {
-    if (m_caches.isLengthCacheValid())
-        return m_caches.cachedLength();
+    if (m_caches->isLengthCacheValid)
+        return m_caches->cachedLength;
 
     unsigned length = 0;
 
     for (Node* n = node()->firstChild(); n; n = n->traverseNextNode(rootNode()))
         length += n->isElementNode() && nodeMatches(static_cast<Element*>(n));
 
-    m_caches.setLengthCache(node(), length);
+    m_caches->cachedLength = length;
+    m_caches->isLengthCacheValid = true;
 
     return length;
 }
@@ -96,7 +62,9 @@ Node* DynamicSubtreeNodeList::itemForwardsFromCurrent(Node* start, unsigned offs
     for (Node* n = start; n; n = n->traverseNextNode(rootNode())) {
         if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
             if (!remainingOffset) {
-                m_caches.setItemCache(n, offset);
+                m_caches->lastItem = n;
+                m_caches->lastItemOffset = offset;
+                m_caches->isItemCacheValid = true;
                 return n;
             }
             --remainingOffset;
@@ -112,7 +80,9 @@ Node* DynamicSubtreeNodeList::itemBackwardsFromCurrent(Node* start, unsigned off
     for (Node* n = start; n; n = n->traversePreviousNode(rootNode())) {
         if (n->isElementNode() && nodeMatches(static_cast<Element*>(n))) {
             if (!remainingOffset) {
-                m_caches.setItemCache(n, offset);
+                m_caches->lastItem = n;
+                m_caches->lastItemOffset = offset;
+                m_caches->isItemCacheValid = true;
                 return n;
             }
             ++remainingOffset;
@@ -126,12 +96,12 @@ Node* DynamicSubtreeNodeList::item(unsigned offset) const
 {
     int remainingOffset = offset;
     Node* start = node()->firstChild();
-    if (m_caches.isItemCacheValid()) {
-        if (offset == m_caches.cachedItemOffset())
-            return m_caches.cachedItem();
-        if (offset > m_caches.cachedItemOffset() || m_caches.cachedItemOffset() - offset < offset) {
-            start = m_caches.cachedItem();
-            remainingOffset -= m_caches.cachedItemOffset();
+    if (m_caches->isItemCacheValid) {
+        if (offset == m_caches->lastItemOffset)
+            return m_caches->lastItem;
+        else if (offset > m_caches->lastItemOffset || m_caches->lastItemOffset - offset < offset) {
+            start = m_caches->lastItem;
+            remainingOffset -= m_caches->lastItemOffset;
         }
     }
 
@@ -169,7 +139,7 @@ bool DynamicSubtreeNodeList::isDynamicNodeList() const
 
 void DynamicSubtreeNodeList::invalidateCache()
 {
-    m_caches.reset();
+    m_caches->reset();
 }
 
 DynamicSubtreeNodeList::Caches::Caches()
@@ -179,12 +149,12 @@ DynamicSubtreeNodeList::Caches::Caches()
 {
 }
 
-PassRefPtr<DynamicNodeList::Caches> DynamicNodeList::Caches::create()
+PassRefPtr<DynamicSubtreeNodeList::Caches> DynamicSubtreeNodeList::Caches::create()
 {
     return adoptRef(new Caches());
 }
 
-void DynamicNodeList::Caches::reset()
+void DynamicSubtreeNodeList::Caches::reset()
 {
     lastItem = 0;
     isLengthCacheValid = false;
index 7f36e8190ad061016a5751a8e54a600db526eaa4..606fc64bf99a96e375b9d4d538b97e4fe21d4a3a 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef DynamicNodeList_h
 #define DynamicNodeList_h
 
-#include "Document.h"
 #include "NodeList.h"
 #include <wtf/RefCounted.h>
 #include <wtf/Forward.h>
@@ -46,11 +45,9 @@ public:
         unsigned lastItemOffset;
         bool isLengthCacheValid : 1;
         bool isItemCacheValid : 1;
-
     protected:
         Caches();
     };
-
     DynamicNodeList(PassRefPtr<Node> node)
         : m_node(node)
     { }
@@ -79,40 +76,9 @@ public:
 
 protected:
     DynamicSubtreeNodeList(PassRefPtr<Node> rootNode);
+    mutable RefPtr<Caches> m_caches;
 
 private:
-
-    class SubtreeCaches {
-    public:
-        SubtreeCaches();
-
-        bool isLengthCacheValid() const { return m_isLengthCacheValid && domVersionIsConsistent(); }
-        bool isItemCacheValid() const { return m_isItemCacheValid && domVersionIsConsistent(); }
-
-        unsigned cachedLength() const { return m_cachedLength; }
-        Node* cachedItem() const { return m_cachedItem; }
-        unsigned cachedItemOffset() const { return m_cachedItemOffset; }
-
-        void setLengthCache(Node* nodeForDocumentVersion, unsigned length);
-        void setItemCache(Node*, unsigned offset);
-        void reset();
-
-    private:
-        Node* m_cachedItem;
-        unsigned m_cachedItemOffset;
-        unsigned m_cachedLength;
-        bool m_isLengthCacheValid : 1;
-        bool m_isItemCacheValid : 1;
-
-        bool domVersionIsConsistent() const
-        {
-            return m_cachedItem && m_cachedItem->document()->domTreeVersion() == m_domTreeVersionAtTimeOfCaching;
-        }
-        uint64_t m_domTreeVersionAtTimeOfCaching;
-    };
-
-    mutable SubtreeCaches m_caches;
-
     virtual bool isDynamicNodeList() const;
     Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
     Node* itemBackwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
index 9b5bf2f584acf6c50fcbb88b7743f183b6624a0b..24486d7bef3b445016a3152fa904fc2f390f48cc 100644 (file)
@@ -664,7 +664,7 @@ void Element::attributeChanged(Attribute* attr, bool)
 
 void Element::updateAfterAttributeChanged(Attribute* attr)
 {
-    invalidateNodeListsCacheAfterAttributeChanged();
+    invalidateNodeListsCacheAfterAttributeChanged(attr->name());
 
     if (!AXObjectCache::accessibilityEnabled())
         return;
index 2af546f81bf888cd1541eee4d2a73efef7f3cf49..a1c76246d36e2846eba3eb1c1612568966cf5eac 100644 (file)
@@ -955,19 +955,73 @@ void Node::unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList* list)
     removeNodeListCacheIfPossible(this, data);
 }
 
-void Node::invalidateNodeListsCacheAfterAttributeChanged()
+void Node::invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName& attrName)
 {
     if (hasRareData() && isAttributeNode()) {
         NodeRareData* data = rareData();
         ASSERT(!data->nodeLists());
         data->clearChildNodeListCache();
     }
+
+    // This list should be sync'ed with NodeListsNodeData.
+    if (attrName != classAttr
+#if ENABLE(MICRODATA)
+        && attrName != itemscopeAttr
+        && attrName != itempropAttr
+#endif
+        && attrName != nameAttr)
+        return;
+
+    if (!treeScope()->hasNodeListCaches())
+        return;
+
+    for (Node* node = this; node; node = node->parentNode()) {
+        ASSERT(this == node || !node->isAttributeNode());
+        if (!node->hasRareData())
+            continue;
+        NodeRareData* data = node->rareData();
+        if (!data->nodeLists())
+            continue;
+
+        data->nodeLists()->invalidateCachesThatDependOnAttributes();
+        removeNodeListCacheIfPossible(node, data);
+    }
 }
 
 void Node::invalidateNodeListsCacheAfterChildrenChanged()
 {
     if (hasRareData())
         rareData()->clearChildNodeListCache();
+
+    if (!treeScope()->hasNodeListCaches())
+        return;
+    for (Node* node = this; node; node = node->parentNode()) {
+        if (!node->hasRareData())
+            continue;
+        NodeRareData* data = node->rareData();
+        if (!data->nodeLists())
+            continue;
+
+        data->nodeLists()->invalidateCaches();
+
+        NodeListsNodeData::NodeListSet::iterator end = data->nodeLists()->m_listsWithCaches.end();
+        for (NodeListsNodeData::NodeListSet::iterator it = data->nodeLists()->m_listsWithCaches.begin(); it != end; ++it)
+            (*it)->invalidateCache();
+
+        removeNodeListCacheIfPossible(node, data);
+    }
+}
+
+void Node::notifyLocalNodeListsLabelChanged()
+{
+    if (!hasRareData())
+        return;
+    NodeRareData* data = rareData();
+    if (!data->nodeLists())
+        return;
+
+    if (data->nodeLists()->m_labelsNodeListCache)
+        data->nodeLists()->m_labelsNodeListCache->invalidateCache();
 }
 
 void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className)
@@ -2150,6 +2204,23 @@ FloatPoint Node::convertFromPage(const FloatPoint& p) const
     return p;
 }
 
+#if ENABLE(MICRODATA)
+void Node::itemTypeAttributeChanged()
+{
+    Node * rootNode = document();
+
+    if (!rootNode->hasRareData())
+        return;
+
+    NodeRareData* data = rootNode->rareData();
+
+    if (!data->nodeLists())
+        return;
+
+    data->nodeLists()->invalidateMicrodataItemListCaches();
+}
+#endif
+
 #ifndef NDEBUG
 
 static void appendAttributeDesc(const Node* node, String& string, const QualifiedName& name, const char* attrDesc)
@@ -2278,7 +2349,11 @@ void NodeListsNodeData::invalidateCaches()
     TagNodeListCacheNS::const_iterator tagCacheNSEnd = m_tagNodeListCacheNS.end();
     for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheNSEnd; ++it)
         it->second->invalidateCache();
+    invalidateCachesThatDependOnAttributes();
+}
 
+void NodeListsNodeData::invalidateCachesThatDependOnAttributes()
+{
     ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end();
     for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it)
         it->second->invalidateCache();
@@ -2292,7 +2367,6 @@ void NodeListsNodeData::invalidateCaches()
 #if ENABLE(MICRODATA)
     invalidateMicrodataItemListCaches();
 #endif
-    
 }
 
 #if ENABLE(MICRODATA)
index 9bb73eba897482cabc4b66f2e7413e5f69275a42..362135c99cf926abfa1621ccbeb5059b252fddc1 100644 (file)
@@ -78,6 +78,7 @@ public:
     }
     
     void invalidateCaches();
+    void invalidateCachesThatDependOnAttributes();
 
 #if ENABLE(MICRODATA)
     void invalidateMicrodataItemListCaches();
index 2e20daf895a2bf602ce5e549ab0849df8ee5fba7..a78f4d05728c8dfd53e304014d17fd02ee53e224 100644 (file)
@@ -237,6 +237,7 @@ void HTMLElement::parseMappedAttribute(Attribute* attr)
         setItemRef(attr->value());
     } else if (attr->name() == itemtypeAttr) {
         setItemType(attr->value());
+        itemTypeAttributeChanged();
 #endif
     }
 // standard events
index 6cbd21900b03e79c6f003f0d14593468b4f39a03..318fe88da2cb3ac1905c9b83fa51e1c9c7cad9aa 100644 (file)
@@ -154,4 +154,15 @@ void HTMLLabelElement::accessKeyAction(bool sendMouseEvents)
         HTMLElement::accessKeyAction(sendMouseEvents);
 }
 
+void HTMLLabelElement::parseMappedAttribute(Attribute* attribute)
+{
+    if (attribute->name() == forAttr) {
+        // htmlFor attribute change affects other nodes than this.
+        // Clear the caches to ensure that the labels caches are cleared.
+        if (document())
+            document()->notifyLocalNodeListsLabelChanged();
+    } else
+        HTMLElement::parseMappedAttribute(attribute);
+}
+                
 } // namespace
index 32a55e449668fedd4d55d4b74ab60196df8b7428..2f8497839278c45eff34be383c97a09cbd444201 100644 (file)
@@ -50,6 +50,8 @@ private:
     virtual void defaultEventHandler(Event*);
 
     void focus(bool restorePreviousSelection = true);
+
+    virtual void parseMappedAttribute(Attribute*);
 };
 
 } //namespace