Unreviewed, rolling out r104084.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jan 2012 04:59:10 +0000 (04:59 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Jan 2012 04:59:10 +0000 (04:59 +0000)
http://trac.webkit.org/changeset/104084
https://bugs.webkit.org/show_bug.cgi?id=75600

Likely kills dom-perf benchmark in chromium
http://build.chromium.org/f/chromium/perf/linux-
release/dom_perf/report.html?history=150&rev=116444 (Requested
by dslomov on #webkit).

Patch by Sheriff Bot <webkit.review.bot@gmail.com> on 2012-01-04

* 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::setTreeScopeRecursively):
(WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
(WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
(WebCore::Node::notifyLocalNodeListsLabelChanged):
(WebCore::Node::itemTypeAttributeChanged):
(WebCore::NodeListsNodeData::invalidateCaches):
(WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes):
* dom/Node.h:
* 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@104116 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/Node.h
Source/WebCore/dom/NodeRareData.h
Source/WebCore/html/HTMLElement.cpp
Source/WebCore/html/HTMLLabelElement.cpp
Source/WebCore/html/HTMLLabelElement.h

index 63dfbdba2c27f341b239b1cd35d93faf319ca0de..7b66ac8a31dca8bf49e40ab38526187149a09a83 100644 (file)
@@ -1,3 +1,45 @@
+2012-01-04  Sheriff Bot  <webkit.review.bot@gmail.com>
+
+        Unreviewed, rolling out r104084.
+        http://trac.webkit.org/changeset/104084
+        https://bugs.webkit.org/show_bug.cgi?id=75600
+
+        Likely kills dom-perf benchmark in chromium
+        http://build.chromium.org/f/chromium/perf/linux-
+        release/dom_perf/report.html?history=150&rev=116444 (Requested
+        by dslomov on #webkit).
+
+        * 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::setTreeScopeRecursively):
+        (WebCore::Node::invalidateNodeListsCacheAfterAttributeChanged):
+        (WebCore::Node::invalidateNodeListsCacheAfterChildrenChanged):
+        (WebCore::Node::notifyLocalNodeListsLabelChanged):
+        (WebCore::Node::itemTypeAttributeChanged):
+        (WebCore::NodeListsNodeData::invalidateCaches):
+        (WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes):
+        * dom/Node.h:
+        * dom/NodeRareData.h:
+        * html/HTMLElement.cpp:
+        (WebCore::HTMLElement::parseMappedAttribute):
+        * html/HTMLLabelElement.cpp:
+        (WebCore::HTMLLabelElement::parseMappedAttribute):
+        * html/HTMLLabelElement.h:
+
 2012-01-04  James Robinson  <jamesr@chromium.org>
 
         [chromium] Remove chromium compositor support for unused zoomAnimatorTransform
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 cda89ba0da604f08d68c65c5e7520bc10de68a24..788ab6ef6809e6b40cd4d357b71e50880e342790 100644 (file)
 
 namespace WebCore {
 
-DynamicSubtreeNodeList::SubtreeCaches::SubtreeCaches()
-    : m_cachedItem(0)
-    , m_isLengthCacheValid(false)
-    , m_isItemCacheValid(false)
-    , m_DOMVersionAtTimeOfCaching(0)
-{
-}
-
-inline void DynamicSubtreeNodeList::SubtreeCaches::setLengthCache(Node* node, unsigned length)
-{
-    if (m_isItemCacheValid && !domVersionIsConsistent()) {
-        m_cachedItem = node;
-        m_isItemCacheValid = false;
-    }
-    m_cachedLength = length;
-    m_isLengthCacheValid = true;
-}
-
-inline void DynamicSubtreeNodeList::SubtreeCaches::setItemCache(Node* item, unsigned offset)
-{
-    if (m_isLengthCacheValid && !domVersionIsConsistent())
-        m_isLengthCacheValid = false;
-    m_cachedItem = item;
-    m_cachedItemOffset = offset;
-    m_isLengthCacheValid = true;
-}
-
-inline 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);
 }
@@ -75,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;
 }
@@ -94,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;
@@ -110,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;
@@ -124,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;
         }
     }
 
@@ -167,7 +139,7 @@ bool DynamicSubtreeNodeList::isDynamicNodeList() const
 
 void DynamicSubtreeNodeList::invalidateCache()
 {
-    m_caches.reset();
+    m_caches->reset();
 }
 
 DynamicSubtreeNodeList::Caches::Caches()
@@ -177,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 13ef6bbe4c19d5324a12c3870b06b8c57519fe0a..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* node, unsigned length);
-        void setItemCache(Node* item, unsigned offset);
-        void reset();
-
-    private:
-        Node* m_cachedItem;
-        unsigned m_cachedItemOffset;
-        unsigned m_cachedLength : 30;
-        unsigned m_isLengthCacheValid : 1;
-        unsigned m_isItemCacheValid : 1;
-
-        bool domVersionIsConsistent() const
-        {
-            return m_cachedItem && m_cachedItem->document()->domTreeVersion() == m_DOMVersionAtTimeOfCaching;
-        }
-        uint64_t m_DOMVersionAtTimeOfCaching;
-    };
-
-    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 365243c8bbae463539910b3f4707a4ef80cc622a..9679b1229fd12a57a8d4f6e2f0268fc637d7bef1 100644 (file)
@@ -674,7 +674,7 @@ void Element::attributeChanged(Attribute* attr, bool)
 
 void Element::updateAfterAttributeChanged(Attribute* attr)
 {
-    invalidateNodeListsCacheAfterAttributeChanged();
+    invalidateNodeListsCacheAfterAttributeChanged(attr->name());
 
     if (!AXObjectCache::accessibilityEnabled())
         return;
index 1a9dcf70da5e76bb536fd856ee248bf69cda5205..9e6dd5fac6fdee0fe0c6cc3a7d249a2a5fa96c49 100644 (file)
@@ -489,7 +489,6 @@ void Node::setTreeScopeRecursively(TreeScope* newTreeScope)
             node->ensureRareData()->setTreeScope(newTreeScope);
 
         if (node->hasRareData() && node->rareData()->nodeLists()) {
-            node->rareData()->nodeLists()->invalidateCaches();
             if (currentTreeScope)
                 currentTreeScope->removeNodeListCache();
             newTreeScope->addNodeListCache();
@@ -1003,19 +1002,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)
@@ -2190,6 +2243,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)
@@ -2318,7 +2388,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();
@@ -2332,7 +2406,6 @@ void NodeListsNodeData::invalidateCaches()
 #if ENABLE(MICRODATA)
     invalidateMicrodataItemListCaches();
 #endif
-    
 }
 
 #if ENABLE(MICRODATA)
index ea49f60f55e60b83dddcc3dfb90b3ed3ab370e37..fa69b75940b3d4187bc97453563da9cabd1b596f 100644 (file)
@@ -521,8 +521,9 @@ public:
 
     void registerDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
     void unregisterDynamicSubtreeNodeList(DynamicSubtreeNodeList*);
-    void invalidateNodeListsCacheAfterAttributeChanged();
+    void invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName&);
     void invalidateNodeListsCacheAfterChildrenChanged();
+    void notifyLocalNodeListsLabelChanged();
     void removeCachedClassNodeList(ClassNodeList*, const String&);
 
     void removeCachedNameNodeList(NameNodeList*, const String&);
@@ -590,6 +591,8 @@ public:
     virtual EventTargetData* ensureEventTargetData();
 
 #if ENABLE(MICRODATA)
+    void itemTypeAttributeChanged();
+
     DOMSettableTokenList* itemProp();
     DOMSettableTokenList* itemRef();
     DOMSettableTokenList* itemType();
index 2249e526b96d0596f6276b067376a392093a6ce2..fb0f76f85c8a6905f8d5a6989e4d4d97a2bce3e3 100644 (file)
@@ -78,6 +78,7 @@ public:
     }
     
     void invalidateCaches();
+    void invalidateCachesThatDependOnAttributes();
 
 #if ENABLE(MICRODATA)
     void invalidateMicrodataItemListCaches();
index 573d581d42d8f91e17caa198854702b9b54a4fce..bacd44f7e8492e5ee77636ea182381914ee06bf6 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