Shrink NodeListsNodeData
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Jun 2012 23:37:56 +0000 (23:37 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Jun 2012 23:37:56 +0000 (23:37 +0000)
https://bugs.webkit.org/show_bug.cgi?id=89036

Reviewed by Andreas Kling.

Replaced 6 hash maps of AtomicString, String, and RefPtr<QualifiedName::QualifiedNameImpl> and a raw pointer
by 3 hash maps of std::pair<unsigned short, AtomicString>, std::pair<unsigned short, String>, and QualifiedName,
to halve the NodeListsNodeData's size (Reduced from 7 pointers to 3 pointers). Made those hash maps private and
added addCacheWith* and removeCacheWith* member functions to reduce the code duplication.

Also got rid of removeCached*NodeList member functions from Node and Document now that DynamicSubtreeNodeList can
simply call nodeLists()->removeCacheWith* on m_node.

* dom/ChildNodeList.cpp:
(WebCore::ChildNodeList::ChildNodeList):
* dom/ClassNodeList.cpp:
(WebCore::ClassNodeList::~ClassNodeList):
* dom/Document.cpp:
(WebCore::Document::getItems): Use addCacheWithName.
* dom/Document.h: Got rid of removeCachedMicroDataItemList.
(Document):
* dom/DynamicNodeList.cpp:
(WebCore): Moved the constructor to the header file.
* dom/DynamicNodeList.h: Added NodeListType and InvalidationType to be used in NodeListsNodeData.
(WebCore::DynamicNodeList::DynamicNodeList): Takes the invalidation type.
(WebCore::DynamicNodeList::document): Added.
(WebCore::DynamicNodeList::shouldInvalidateOnAttributeChange): Added.
(WebCore::DynamicNodeList::Caches::Caches): Added shouldInvalidateOnAttributeChange to retain the invalidation type.
(Caches):
(WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
* dom/MicroDataItemList.cpp:
(WebCore::MicroDataItemList::~MicroDataItemList):
* dom/NameNodeList.cpp:
(WebCore::NameNodeList::NameNodeList):
(WebCore::NameNodeList::~NameNodeList):
(WebCore::NameNodeList::nodeMatches):
* dom/NameNodeList.h:
(WebCore):
(NameNodeList):
(WebCore::NameNodeList::create):
* dom/Node.cpp:
(WebCore::Node::nodeLists): Added so that node lists can directly call removeCacheWith*.
(WebCore::Node::getElementsByTagName):
(WebCore::Node::getElementsByTagNameNS):
(WebCore::Node::getElementsByName):
(WebCore::Node::getElementsByClassName):
(WebCore::Node::radioNodeList):
(WebCore::NodeListsNodeData::invalidateCaches): Merged invalidateCachesThatDependOnAttributes. The function takes
the attribute name to avoid invalidating tag node lists when only attributes are modified. Also, now we have exactly
three hash maps to invalidate: m_atomicNameCaches, m_nameCaches, and m_tagNodeListCacheNS.
(WebCore): NodeListsNodeData::isEmpty is moved to NodeRareData.h.
* dom/Node.h:
(WebCore):
(Node):
* dom/NodeRareData.h:
(NodeListsNodeData):
(WebCore::NodeListsNodeData::addCacheWithAtomicName):
(WebCore::NodeListsNodeData::addCacheWithName):
(WebCore::NodeListsNodeData::addCacheWithQualifiedName):
(WebCore::NodeListsNodeData::removeCacheWithAtomicName):
(WebCore::NodeListsNodeData::removeCacheWithName):
(WebCore::NodeListsNodeData::removeCacheWithQualifiedName):
(WebCore::NodeListsNodeData::isEmpty): Moved from Node.cpp now that this function is much shorter.
(WebCore::NodeListsNodeData::NodeListsNodeData):
(WebCore::NodeListsNodeData::namedNodeListKey): Helper member functions to obtain the key for AtomicString and
String hash maps.
* dom/TagNodeList.cpp:
(WebCore::TagNodeList::TagNodeList):
(WebCore::TagNodeList::~TagNodeList):
(WebCore::HTMLTagNodeList::HTMLTagNodeList): Hard code namespaceURI = starAtom since other values are never used.
(WebCore::HTMLTagNodeList::nodeMatches): Given that, assert m_namespace == starAtom.
* dom/TagNodeList.h:
(WebCore::TagNodeList::create): Add a new version of create that doesn't take namespace (assume starAtom) so that
addCacheWithAtomicName works with this class.
(WebCore::HTMLTagNodeList::create): Removed namespaceURI from the argument list since it's always starAtom.
(HTMLTagNodeList):
* html/LabelableElement.cpp:
(WebCore::LabelableElement::labels):
* html/LabelsNodeList.cpp:
(WebCore::LabelsNodeList::LabelsNodeList): Removed redundant m_forNode (identical to m_node in DynamicNodeList).
(WebCore::LabelsNodeList::~LabelsNodeList):
(WebCore::LabelsNodeList::nodeMatches):
* html/LabelsNodeList.h:
(WebCore::LabelsNodeList::create):
(LabelsNodeList):
* html/RadioNodeList.cpp:
(WebCore::RadioNodeList::RadioNodeList): Removed redundant m_baseElement (identical to m_node in DynamicNodeList).
Also changed the first argument's type from Element* to Node* so that it works better with new template member
functions of NodeListsNodeData.
(WebCore::RadioNodeList::~RadioNodeList):
(WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):
* html/RadioNodeList.h:
(WebCore::RadioNodeList::create):
(RadioNodeList):

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

20 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/ChildNodeList.cpp
Source/WebCore/dom/ClassNodeList.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/DynamicNodeList.cpp
Source/WebCore/dom/DynamicNodeList.h
Source/WebCore/dom/MicroDataItemList.cpp
Source/WebCore/dom/NameNodeList.cpp
Source/WebCore/dom/NameNodeList.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/NodeRareData.h
Source/WebCore/dom/TagNodeList.cpp
Source/WebCore/dom/TagNodeList.h
Source/WebCore/html/LabelableElement.cpp
Source/WebCore/html/LabelsNodeList.cpp
Source/WebCore/html/LabelsNodeList.h
Source/WebCore/html/RadioNodeList.cpp
Source/WebCore/html/RadioNodeList.h

index 6fecaa4..8d2642c 100644 (file)
@@ -1,3 +1,100 @@
+2012-06-20  Ryosuke Niwa  <rniwa@webkit.org>
+
+        Shrink NodeListsNodeData
+        https://bugs.webkit.org/show_bug.cgi?id=89036
+
+        Reviewed by Andreas Kling.
+
+        Replaced 6 hash maps of AtomicString, String, and RefPtr<QualifiedName::QualifiedNameImpl> and a raw pointer
+        by 3 hash maps of std::pair<unsigned short, AtomicString>, std::pair<unsigned short, String>, and QualifiedName,
+        to halve the NodeListsNodeData's size (Reduced from 7 pointers to 3 pointers). Made those hash maps private and
+        added addCacheWith* and removeCacheWith* member functions to reduce the code duplication.
+
+        Also got rid of removeCached*NodeList member functions from Node and Document now that DynamicSubtreeNodeList can
+        simply call nodeLists()->removeCacheWith* on m_node.
+
+        * dom/ChildNodeList.cpp:
+        (WebCore::ChildNodeList::ChildNodeList):
+        * dom/ClassNodeList.cpp:
+        (WebCore::ClassNodeList::~ClassNodeList):
+        * dom/Document.cpp:
+        (WebCore::Document::getItems): Use addCacheWithName.
+        * dom/Document.h: Got rid of removeCachedMicroDataItemList.
+        (Document):
+        * dom/DynamicNodeList.cpp:
+        (WebCore): Moved the constructor to the header file.
+        * dom/DynamicNodeList.h: Added NodeListType and InvalidationType to be used in NodeListsNodeData.
+        (WebCore::DynamicNodeList::DynamicNodeList): Takes the invalidation type.
+        (WebCore::DynamicNodeList::document): Added.
+        (WebCore::DynamicNodeList::shouldInvalidateOnAttributeChange): Added.
+        (WebCore::DynamicNodeList::Caches::Caches): Added shouldInvalidateOnAttributeChange to retain the invalidation type.
+        (Caches):
+        (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList):
+        * dom/MicroDataItemList.cpp:
+        (WebCore::MicroDataItemList::~MicroDataItemList):
+        * dom/NameNodeList.cpp:
+        (WebCore::NameNodeList::NameNodeList):
+        (WebCore::NameNodeList::~NameNodeList):
+        (WebCore::NameNodeList::nodeMatches):
+        * dom/NameNodeList.h:
+        (WebCore):
+        (NameNodeList):
+        (WebCore::NameNodeList::create):
+        * dom/Node.cpp:
+        (WebCore::Node::nodeLists): Added so that node lists can directly call removeCacheWith*.
+        (WebCore::Node::getElementsByTagName):
+        (WebCore::Node::getElementsByTagNameNS):
+        (WebCore::Node::getElementsByName):
+        (WebCore::Node::getElementsByClassName):
+        (WebCore::Node::radioNodeList):
+        (WebCore::NodeListsNodeData::invalidateCaches): Merged invalidateCachesThatDependOnAttributes. The function takes
+        the attribute name to avoid invalidating tag node lists when only attributes are modified. Also, now we have exactly
+        three hash maps to invalidate: m_atomicNameCaches, m_nameCaches, and m_tagNodeListCacheNS.
+        (WebCore): NodeListsNodeData::isEmpty is moved to NodeRareData.h.
+        * dom/Node.h:
+        (WebCore):
+        (Node):
+        * dom/NodeRareData.h:
+        (NodeListsNodeData):
+        (WebCore::NodeListsNodeData::addCacheWithAtomicName):
+        (WebCore::NodeListsNodeData::addCacheWithName):
+        (WebCore::NodeListsNodeData::addCacheWithQualifiedName):
+        (WebCore::NodeListsNodeData::removeCacheWithAtomicName):
+        (WebCore::NodeListsNodeData::removeCacheWithName):
+        (WebCore::NodeListsNodeData::removeCacheWithQualifiedName):
+        (WebCore::NodeListsNodeData::isEmpty): Moved from Node.cpp now that this function is much shorter.
+        (WebCore::NodeListsNodeData::NodeListsNodeData):
+        (WebCore::NodeListsNodeData::namedNodeListKey): Helper member functions to obtain the key for AtomicString and
+        String hash maps.
+        * dom/TagNodeList.cpp:
+        (WebCore::TagNodeList::TagNodeList):
+        (WebCore::TagNodeList::~TagNodeList):
+        (WebCore::HTMLTagNodeList::HTMLTagNodeList): Hard code namespaceURI = starAtom since other values are never used.
+        (WebCore::HTMLTagNodeList::nodeMatches): Given that, assert m_namespace == starAtom.
+        * dom/TagNodeList.h:
+        (WebCore::TagNodeList::create): Add a new version of create that doesn't take namespace (assume starAtom) so that
+        addCacheWithAtomicName works with this class.
+        (WebCore::HTMLTagNodeList::create): Removed namespaceURI from the argument list since it's always starAtom.
+        (HTMLTagNodeList):
+        * html/LabelableElement.cpp:
+        (WebCore::LabelableElement::labels):
+        * html/LabelsNodeList.cpp:
+        (WebCore::LabelsNodeList::LabelsNodeList): Removed redundant m_forNode (identical to m_node in DynamicNodeList).
+        (WebCore::LabelsNodeList::~LabelsNodeList):
+        (WebCore::LabelsNodeList::nodeMatches):
+        * html/LabelsNodeList.h:
+        (WebCore::LabelsNodeList::create):
+        (LabelsNodeList):
+        * html/RadioNodeList.cpp:
+        (WebCore::RadioNodeList::RadioNodeList): Removed redundant m_baseElement (identical to m_node in DynamicNodeList).
+        Also changed the first argument's type from Element* to Node* so that it works better with new template member
+        functions of NodeListsNodeData.
+        (WebCore::RadioNodeList::~RadioNodeList):
+        (WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter):
+        * html/RadioNodeList.h:
+        (WebCore::RadioNodeList::create):
+        (RadioNodeList):
+
 2012-06-21  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r120945.
index 41ae7cc..c225afb 100644 (file)
@@ -28,7 +28,7 @@
 namespace WebCore {
 
 ChildNodeList::ChildNodeList(PassRefPtr<Node> node)
-    : DynamicNodeList(node)
+    : DynamicNodeList(node, RootedAtNode, DoNotInvalidateOnAttributeChange)
 {
 }
 
index f347647..2900215 100644 (file)
@@ -31,6 +31,7 @@
 #include "ClassNodeList.h"
 
 #include "Document.h"
+#include "NodeRareData.h"
 #include "StyledElement.h"
 
 namespace WebCore {
@@ -44,7 +45,7 @@ ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames
 
 ClassNodeList::~ClassNodeList()
 {
-    node()->removeCachedClassNodeList(this, m_originalClassNames);
+    node()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames);
 } 
 
 bool ClassNodeList::nodeMatches(Element* testNode) const
index 83a83ef..132680a 100644 (file)
@@ -5926,31 +5926,11 @@ DocumentLoader* Document::loader() const
 #if ENABLE(MICRODATA)
 PassRefPtr<NodeList> Document::getItems(const String& typeNames)
 {
-    NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);
-
     // Since documet.getItem() is allowed for microdata, typeNames will be null string.
     // In this case we need to create an unique string identifier to map such request in the cache.
     String localTypeNames = typeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : typeNames;
 
-    NodeListsNodeData::MicroDataItemListCache::AddResult result = nodeLists->m_microDataItemListCache.add(localTypeNames, 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<NodeList>(result.iterator->second);
-
-    RefPtr<MicroDataItemList> list = MicroDataItemList::create(this, typeNames);
-    result.iterator->second = list.get();
-    return list.release();
-}
-
-void Document::removeCachedMicroDataItemList(MicroDataItemList* list, const String& typeNames)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-
-    String localTypeNames = typeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : typeNames;
-    ASSERT_UNUSED(list, list == data->m_microDataItemListCache.get(localTypeNames));
-    data->m_microDataItemListCache.remove(localTypeNames);
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithName<MicroDataItemList>(this, DynamicNodeList::MicroDataItemListType, localTypeNames);
 }
 #endif
 
index 056270a..68885fb 100644 (file)
@@ -1108,7 +1108,6 @@ public:
 
 #if ENABLE(MICRODATA)
     PassRefPtr<NodeList> getItems(const String& typeNames);
-    void removeCachedMicroDataItemList(MicroDataItemList*, const String&);
 #endif
     
 #if ENABLE(UNDO_MANAGER)
index 5182cfe..cd1eb56 100644 (file)
 
 namespace WebCore {
 
-DynamicSubtreeNodeList::DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType)
-    : DynamicNodeList(node, rootType)
-{
-}
-
 DynamicSubtreeNodeList::~DynamicSubtreeNodeList()
 {
 }
index fd91366..1d12535 100644 (file)
@@ -36,14 +36,26 @@ class Node;
 
 class DynamicNodeList : public NodeList {
 public:
+    enum NodeListType {
+        ChildNodeListType,
+        ClassNodeListType,
+        NameNodeListType,
+        TagNodeListType,
+        RadioNodeListType,
+        LabelsNodeListType,
+        MicroDataItemListType,
+    };
     enum RootType {
         RootedAtNode,
         RootedAtDocument,
     };
-
-    DynamicNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode)
+    enum InvalidationType {
+        AlwaysInvalidate,
+        DoNotInvalidateOnAttributeChange,
+    };
+    DynamicNodeList(PassRefPtr<Node> node, RootType rootType, InvalidationType invalidationType)
         : m_node(node)
-        , m_caches(rootType)
+        , m_caches(rootType, invalidationType)
     { }
     virtual ~DynamicNodeList() { }
 
@@ -59,6 +71,9 @@ public:
             return m_node->document();
         return m_node.get();
     }
+    Document* document() { return m_node->document(); }
+
+    bool shouldInvalidateOnAttributeChange() const { return m_caches.shouldInvalidateOnAttributeChange; }
 
     void invalidateCache() { m_caches.reset(); }
 
@@ -66,8 +81,9 @@ protected:
     virtual bool nodeMatches(Element*) const = 0;
 
     struct Caches {
-        Caches(RootType rootType)
+        Caches(RootType rootType, InvalidationType invalidationType)
             : rootedAtDocument(rootType == RootedAtDocument)
+            , shouldInvalidateOnAttributeChange(invalidationType == AlwaysInvalidate)
         {
             reset();
         }
@@ -81,10 +97,14 @@ protected:
 
         Node* lastItem;
         unsigned cachedLength;
-        unsigned lastItemOffset : 29; // Borrow 3-bits for bit fields
+        unsigned lastItemOffset;
         unsigned isLengthCacheValid : 1;
         unsigned isItemCacheValid : 1;
+
+        // Following flags should belong in DynamicSubtreeNode but are here for bit-packing.
+        unsigned type : 4;
         unsigned rootedAtDocument : 1;
+        unsigned shouldInvalidateOnAttributeChange : 1;
     };
 
     RefPtr<Node> m_node;
@@ -101,7 +121,9 @@ public:
     virtual Node* item(unsigned index) const OVERRIDE;
 
 protected:
-    DynamicSubtreeNodeList(PassRefPtr<Node>, RootType = RootedAtNode);
+    DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode, InvalidationType invalidationType = AlwaysInvalidate)
+        : DynamicNodeList(node, rootType, invalidationType)
+    { }
 
 private:
     Node* itemForwardsFromCurrent(Node* start, unsigned offset, int remainingOffset) const;
index b1561a4..7c90dda 100644 (file)
@@ -32,6 +32,7 @@
 #include "Document.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
+#include "NodeRareData.h"
 
 namespace WebCore {
 
@@ -46,7 +47,8 @@ MicroDataItemList::MicroDataItemList(PassRefPtr<Node> rootNode, const String& ty
 
 MicroDataItemList::~MicroDataItemList()
 {
-    rootNode()->document()->removeCachedMicroDataItemList(this, m_originalTypeNames);
+    String localTypeNames = m_originalTypeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : m_originalTypeNames;
+    m_node->nodeLists()->removeCacheWithName(this, DynamicNodeList::MicroDataItemListType, localTypeNames);
 }
 
 bool MicroDataItemList::nodeMatches(Element* testNode) const
index b034e8c..457376a 100644 (file)
 
 #include "Element.h"
 #include "HTMLNames.h"
+#include "NodeRareData.h"
 #include <wtf/Assertions.h>
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
-NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name)
+NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name)
     : DynamicSubtreeNodeList(rootNode)
-    , m_nodeName(name)
+    , m_name(name)
 {
 }
 
 NameNodeList::~NameNodeList()
 {
-    node()->removeCachedNameNodeList(this, m_nodeName);
+    m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name);
 } 
 
 bool NameNodeList::nodeMatches(Element* testNode) const
 {
-    return testNode->getNameAttribute() == m_nodeName;
+    return testNode->getNameAttribute() == m_name;
 }
 
 } // namespace WebCore
index fa664ba..b030a1f 100644 (file)
 
 namespace WebCore {
 
-    // NodeList which lists all Nodes in a Element with a given "name" attribute
-    class NameNodeList : public DynamicSubtreeNodeList {
-    public:
-        static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name)
-        {
-            return adoptRef(new NameNodeList(rootNode, name));
-        }
+// NodeList which lists all Nodes in a Element with a given "name" attribute
+class NameNodeList : public DynamicSubtreeNodeList {
+public:
+    static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& name)
+    {
+        return adoptRef(new NameNodeList(rootNode, name));
+    }
 
-        virtual ~NameNodeList();
+    virtual ~NameNodeList();
 
-    private:
-        NameNodeList(PassRefPtr<Node> rootNode, const String& name);
+private:
+    NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name);
 
-        virtual bool nodeMatches(Element*) const;
+    virtual bool nodeMatches(Element*) const;
 
-        AtomicString m_nodeName;
-    };
+    AtomicString m_name;
+};
 
 } // namespace WebCore
 
index c9be657..24c6158 100644 (file)
@@ -980,7 +980,7 @@ void Node::invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName& at
         if (!data->nodeLists())
             continue;
 
-        data->nodeLists()->invalidateCachesThatDependOnAttributes();
+        data->nodeLists()->invalidateCaches(&attrName);
     }
 }
 
@@ -1005,54 +1005,9 @@ void Node::invalidateNodeListsCacheAfterChildrenChanged()
     }
 }
 
-void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className)
+NodeListsNodeData* Node::nodeLists()
 {
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_classNodeListCache.get(className));
-    data->m_classNodeListCache.remove(className);
-}
-
-void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_nameNodeListCache.get(nodeName));
-    data->m_nameNodeListCache.remove(nodeName);
-}
-
-void Node::removeCachedTagNodeList(TagNodeList* list, const AtomicString& name)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_tagNodeListCache.get(name.impl()));
-    data->m_tagNodeListCache.remove(name.impl());
-}
-
-void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_tagNodeListCacheNS.get(name.impl()));
-    data->m_tagNodeListCacheNS.remove(name.impl());
-}
-
-void Node::removeCachedLabelsNodeList(DynamicSubtreeNodeList* list)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_labelsNodeListCache);
-    data->m_labelsNodeListCache = 0;
+    return hasRareData() ? rareData()->nodeLists() : 0;
 }
 
 void Node::removeCachedChildNodeList()
@@ -1592,19 +1547,9 @@ PassRefPtr<NodeList> Node::getElementsByTagName(const AtomicString& localName)
     if (localName.isNull())
         return 0;
 
-    AtomicString localNameAtom = localName;
-
-    NodeListsNodeData::TagNodeListCache::AddResult result = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCache.add(localNameAtom, 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<TagNodeList>(result.iterator->second);
-
-    RefPtr<TagNodeList> list;
     if (document()->isHTMLDocument())
-        list = HTMLTagNodeList::create(this, starAtom, localNameAtom);
-    else
-        list = TagNodeList::create(this, starAtom, localNameAtom);
-    result.iterator->second = list.get();
-    return list.release();   
+        return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName);
 }
 
 PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName)
@@ -1615,39 +1560,23 @@ PassRefPtr<NodeList> Node::getElementsByTagNameNS(const AtomicString& namespaceU
     if (namespaceURI == starAtom)
         return getElementsByTagName(localName);
 
-    AtomicString localNameAtom = localName;
-
-    NodeListsNodeData::TagNodeListCacheNS::AddResult result
-        = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCacheNS.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<TagNodeList>(result.iterator->second);
-
-    RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom);
-    result.iterator->second = list.get();
-    return list.release();
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName);
 }
 
 PassRefPtr<NodeList> Node::getElementsByName(const String& elementName)
 {
-    NodeListsNodeData::NameNodeListCache::AddResult result = ensureRareData()->ensureNodeLists(this)->m_nameNodeListCache.add(elementName, 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<NodeList>(result.iterator->second);
-
-    RefPtr<NameNodeList> list = NameNodeList::create(this, elementName);
-    result.iterator->second = list.get();
-    return list.release();
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName);
 }
 
 PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames)
 {
-    NodeListsNodeData::ClassNodeListCache::AddResult result
-        = ensureRareData()->ensureNodeLists(this)->m_classNodeListCache.add(classNames, 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<NodeList>(result.iterator->second);
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames);
+}
 
-    RefPtr<ClassNodeList> list = ClassNodeList::create(this, classNames);
-    result.iterator->second = list.get();
-    return list.release();
+PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)
+{
+    ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
+    return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name);
 }
 
 PassRefPtr<Element> Node::querySelector(const AtomicString& selectors, ExceptionCode& ec)
@@ -2309,58 +2238,26 @@ void Node::showTreeForThisAcrossFrame() const
 
 // --------
 
-void NodeListsNodeData::invalidateCaches()
+void NodeListsNodeData::invalidateCaches(const QualifiedName* attrName)
 {
-    TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end();
-    for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it)
-        it->second->invalidateCache();
-    TagNodeListCacheNS::const_iterator tagCacheNSEnd = m_tagNodeListCacheNS.end();
-    for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheNSEnd; ++it)
-        it->second->invalidateCache();
-    invalidateCachesThatDependOnAttributes();
-}
+    NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end();
+    for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) {
+        if (!attrName || it->second->shouldInvalidateOnAttributeChange())
+            it->second->invalidateCache();
+    }
 
-void NodeListsNodeData::invalidateCachesThatDependOnAttributes()
-{
-    ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end();
-    for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it)
-        it->second->invalidateCache();
+    NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end();
+    for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) {
+        if (!attrName || it->second->shouldInvalidateOnAttributeChange())
+            it->second->invalidateCache();
+    }
 
-    NameNodeListCache::iterator nameCacheEnd = m_nameNodeListCache.end();
-    for (NameNodeListCache::iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it)
-        it->second->invalidateCache();
-    if (m_labelsNodeListCache)
-        m_labelsNodeListCache->invalidateCache();
+    if (!attrName)
+        return;
 
-#if ENABLE(MICRODATA)
-    MicroDataItemListCache::iterator itemListCacheEnd = m_microDataItemListCache.end();
-    for (MicroDataItemListCache::iterator it = m_microDataItemListCache.begin(); it != itemListCacheEnd; ++it)
+    TagNodeListCacheNS::iterator tagCacheEnd = m_tagNodeListCacheNS.end();
+    for (TagNodeListCacheNS::iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEnd; ++it)
         it->second->invalidateCache();
-#endif
-}
-
-bool NodeListsNodeData::isEmpty() const
-{
-    if (!m_tagNodeListCache.isEmpty())
-        return false;
-    if (!m_tagNodeListCacheNS.isEmpty())
-        return false;
-    if (!m_classNodeListCache.isEmpty())
-        return false;
-    if (!m_nameNodeListCache.isEmpty())
-        return false;
-#if ENABLE(MICRODATA)
-    if (!m_microDataItemListCache.isEmpty())
-        return false;
-#endif
-
-    if (m_labelsNodeListCache)
-        return false;
-
-    if (!m_radioNodeListCache.isEmpty())
-        return false;
-
-    return true;
 }
 
 void Node::getSubresourceURLs(ListHashSet<KURL>& urls) const
@@ -2871,31 +2768,6 @@ void NodeRareData::clearChildNodeListCache()
         m_childNodeList->invalidateCache();
 }
 
-PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)
-{
-    ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));
-
-    NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);
-
-    NodeListsNodeData::RadioNodeListCache::AddResult result = nodeLists->m_radioNodeListCache.add(name, 0);
-    if (!result.isNewEntry)
-        return PassRefPtr<RadioNodeList>(result.iterator->second);
-
-    RefPtr<RadioNodeList> list = RadioNodeList::create(toElement(this), name);
-    result.iterator->second = list.get();
-    return list.release();
-}
-
-void Node::removeCachedRadioNodeList(RadioNodeList* list, const AtomicString& name)
-{
-    ASSERT(rareData());
-    ASSERT(rareData()->nodeLists());
-
-    NodeListsNodeData* data = rareData()->nodeLists();
-    ASSERT_UNUSED(list, list == data->m_radioNodeListCache.get(name));
-    data->m_radioNodeListCache.remove(name);
-}
-
 // It's important not to inline removedLastRef, because we don't want to inline the code to
 // delete a Node at each deref call site.
 void Node::removedLastRef()
index 265912d..e8fde30 100644 (file)
@@ -69,6 +69,7 @@ class NSResolver;
 class NamedNodeMap;
 class NameNodeList;
 class NodeList;
+class NodeListsNodeData;
 class NodeRareData;
 class NodeRenderingContext;
 class PlatformKeyboardEvent;
@@ -558,23 +559,14 @@ public:
 
     void invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName&, Element* attributeOwnerElement);
     void invalidateNodeListsCacheAfterChildrenChanged();
-    void removeCachedClassNodeList(ClassNodeList*, const String&);
-
-    void removeCachedNameNodeList(NameNodeList*, const String&);
-    void removeCachedTagNodeList(TagNodeList*, const AtomicString&);
-    void removeCachedTagNodeList(TagNodeList*, const QualifiedName&);
-    void removeCachedLabelsNodeList(DynamicSubtreeNodeList*);
-
+    NodeListsNodeData* nodeLists();
     void removeCachedChildNodeList();
 
-    PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
-    void removeCachedRadioNodeList(RadioNodeList*, const AtomicString&);
-    void resetCachedRadioNodeListRootNode();
-
     PassRefPtr<NodeList> getElementsByTagName(const AtomicString&);
     PassRefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
     PassRefPtr<NodeList> getElementsByName(const String& elementName);
     PassRefPtr<NodeList> getElementsByClassName(const String& classNames);
+    PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);
 
     PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionCode&);
     PassRefPtr<NodeList> querySelectorAll(const AtomicString& selectors, ExceptionCode&);
index 9f2ad4c..f774f83 100644 (file)
 #define NodeRareData_h
 
 #include "ChildNodeList.h"
-#include "ClassNodeList.h"
 #include "DOMSettableTokenList.h"
 #include "DynamicNodeList.h"
 #include "MutationObserverRegistration.h"
-#include "NameNodeList.h"
 #include "QualifiedName.h"
 #include "TagNodeList.h"
 #include "WebKitMutationObserver.h"
@@ -51,40 +49,92 @@ class TreeScope;
 struct NodeListsNodeData {
     WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED;
 public:
-    typedef HashMap<String, ClassNodeList*> ClassNodeListCache;
-    ClassNodeListCache m_classNodeListCache;
+    typedef HashMap<std::pair<unsigned short, AtomicString>, DynamicSubtreeNodeList*> NodeListAtomicNameCacheMap;
+    typedef HashMap<std::pair<unsigned short, String>, DynamicSubtreeNodeList*> NodeListNameCacheMap;
+    typedef HashMap<QualifiedName, TagNodeList*> TagNodeListCacheNS;
 
-    typedef HashMap<String, NameNodeList*> NameNodeListCache;
-    NameNodeListCache m_nameNodeListCache;
-    typedef HashMap<AtomicString, TagNodeList*> TagNodeListCache;
-    TagNodeListCache m_tagNodeListCache;
+    template<typename T>
+    PassRefPtr<T> addCacheWithAtomicName(Node* node, DynamicNodeList::NodeListType listType, const AtomicString& name)
+    {
+        NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(listType, name), 0);
+        if (!result.isNewEntry)
+            return static_cast<T*>(result.iterator->second);
 
-    typedef HashMap<RefPtr<QualifiedName::QualifiedNameImpl>, TagNodeList*> TagNodeListCacheNS;
-    TagNodeListCacheNS m_tagNodeListCacheNS;
+        RefPtr<T> list = T::create(node, name);
+        result.iterator->second = list.get();
+        return list.release();
+    }
 
-#if ENABLE(MICRODATA)
-    typedef HashMap<String, MicroDataItemList*> MicroDataItemListCache;
-    MicroDataItemListCache m_microDataItemListCache;
-#endif
+    template<typename T>
+    PassRefPtr<T> addCacheWithName(Node* node, DynamicNodeList::NodeListType listType, const String& name)
+    {
+        NodeListNameCacheMap::AddResult result = m_nameCaches.add(namedNodeListKey(listType, name), 0);
+        if (!result.isNewEntry)
+            return static_cast<T*>(result.iterator->second);
 
-    LabelsNodeList* m_labelsNodeListCache;
+        RefPtr<T> list = T::create(node, name);
+        result.iterator->second = list.get();
+        return list.release();
+    }
 
-    typedef HashMap<String, RadioNodeList*> RadioNodeListCache;
-    RadioNodeListCache m_radioNodeListCache;
+    PassRefPtr<TagNodeList> addCacheWithQualifiedName(Node* node, const AtomicString& namespaceURI, const AtomicString& localName)
+    {
+        QualifiedName name(nullAtom, localName, namespaceURI);
+        TagNodeListCacheNS::AddResult result = m_tagNodeListCacheNS.add(name, 0);
+        if (!result.isNewEntry)
+            return result.iterator->second;
+
+        RefPtr<TagNodeList> list = TagNodeList::create(node, namespaceURI, localName);
+        result.iterator->second = list.get();
+        return list.release();
+    }
+
+    void removeCacheWithAtomicName(DynamicSubtreeNodeList* list, DynamicNodeList::NodeListType listType, const AtomicString& name)
+    {
+        ASSERT_UNUSED(list, list == m_atomicNameCaches.get(namedNodeListKey(listType, name)));
+        m_atomicNameCaches.remove(namedNodeListKey(listType, name));
+    }
+
+    void removeCacheWithName(DynamicSubtreeNodeList* list, DynamicNodeList::NodeListType listType, const String& name)
+    {
+        ASSERT_UNUSED(list, list == m_nameCaches.get(namedNodeListKey(listType, name)));
+        m_nameCaches.remove(namedNodeListKey(listType, name));
+    }
+
+    void removeCacheWithQualifiedName(DynamicSubtreeNodeList* list, const AtomicString& namespaceURI, const AtomicString& localName)
+    {
+        QualifiedName name(nullAtom, localName, namespaceURI);
+        ASSERT_UNUSED(list, list == m_tagNodeListCacheNS.get(name));
+        m_tagNodeListCacheNS.remove(name);
+    }
 
     static PassOwnPtr<NodeListsNodeData> create()
     {
         return adoptPtr(new NodeListsNodeData);
     }
 
-    void invalidateCaches();
-    void invalidateCachesThatDependOnAttributes();
-
-    bool isEmpty() const;
+    void invalidateCaches(const QualifiedName* attrName = 0);
+    bool isEmpty() const
+    {
+        return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagNodeListCacheNS.isEmpty();
+    }
 
 private:
-    NodeListsNodeData() : m_labelsNodeListCache(0) {}
+    NodeListsNodeData() { }
+
+    std::pair<unsigned short, AtomicString> namedNodeListKey(DynamicNodeList::NodeListType listType, const AtomicString& name)
+    {
+        return std::pair<unsigned short, AtomicString>(listType, name);
+    }
+
+    std::pair<unsigned short, String> namedNodeListKey(DynamicNodeList::NodeListType listType, const String& name)
+    {
+        return std::pair<unsigned short, String>(listType, name);
+    }
+
+    NodeListAtomicNameCacheMap m_atomicNameCaches;
+    NodeListNameCacheMap m_nameCaches;
+    TagNodeListCacheNS m_tagNodeListCacheNS;
 };
 
 class NodeRareData {
index 8c93d90..d65b810 100644 (file)
 #include "TagNodeList.h"
 
 #include "Element.h"
+#include "NodeRareData.h"
 #include <wtf/Assertions.h>
 
 namespace WebCore {
 
 TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
-    : DynamicSubtreeNodeList(rootNode)
+    : DynamicSubtreeNodeList(rootNode, RootedAtNode, DoNotInvalidateOnAttributeChange)
     , m_namespaceURI(namespaceURI)
     , m_localName(localName)
 {
@@ -40,9 +41,9 @@ TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespac
 TagNodeList::~TagNodeList()
 {
     if (m_namespaceURI == starAtom)
-        node()->removeCachedTagNodeList(this, m_localName);
+        m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName);
     else
-        node()->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));
+        m_node->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName);
 }
 
 bool TagNodeList::nodeMatches(Element* testNode) const
@@ -54,8 +55,8 @@ bool TagNodeList::nodeMatches(Element* testNode) const
     return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI();
 }
 
-HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
-    : TagNodeList(rootNode, namespaceURI, localName)
+HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName)
+    : TagNodeList(rootNode, starAtom, localName)
     , m_loweredLocalName(localName.lower())
 {
 }
@@ -69,7 +70,8 @@ bool HTMLTagNodeList::nodeMatches(Element* testNode) const
             return false;
     }
 
-    return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI();
+    ASSERT(m_namespaceURI == starAtom);
+    return true;
 }
 
 } // namespace WebCore
index b8ccefe..251a86d 100644 (file)
@@ -34,9 +34,15 @@ namespace WebCore {
     public:
         static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
         {
+            ASSERT(namespaceURI != starAtom);
             return adoptRef(new TagNodeList(rootNode, namespaceURI, localName));
         }
 
+        static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& localName)
+        {
+            return adoptRef(new TagNodeList(rootNode, starAtom, localName));
+        }
+
         virtual ~TagNodeList();
 
     protected:
@@ -50,13 +56,13 @@ namespace WebCore {
 
     class HTMLTagNodeList : public TagNodeList {
     public:
-        static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)
+        static PassRefPtr<HTMLTagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& localName)
         {
-            return adoptRef(new HTMLTagNodeList(rootNode, namespaceURI, localName));
+            return adoptRef(new HTMLTagNodeList(rootNode, localName));
         }
 
     private:
-        HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName);
+        HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName);
 
         virtual bool nodeMatches(Element*) const;
 
index e8247b9..1d59936 100644 (file)
@@ -47,13 +47,7 @@ PassRefPtr<NodeList> LabelableElement::labels()
     if (!document())
         return 0;
 
-    NodeListsNodeData* nodeLists = Node::ensureRareData()->ensureNodeLists(this);
-    if (nodeLists->m_labelsNodeListCache)
-        return nodeLists->m_labelsNodeListCache;
-
-    RefPtr<LabelsNodeList> list = LabelsNodeList::create(this);
-    nodeLists->m_labelsNodeListCache = list.get();
-    return list.release();
+    return Node::ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom);
 }
 
 } // namespace Webcore
index fb3442b..67ff78f 100644 (file)
@@ -27,6 +27,7 @@
 #include "Element.h"
 #include "HTMLLabelElement.h"
 #include "HTMLNames.h"
+#include "NodeRareData.h"
 
 namespace WebCore {
 
@@ -34,20 +35,19 @@ using namespace HTMLNames;
 
 LabelsNodeList::LabelsNodeList(Node* forNode)
     : DynamicSubtreeNodeList(forNode, RootedAtDocument)
-    , m_forNode(forNode)
 {
-    m_forNode->document()->registerDynamicSubtreeNodeList(this);
+    document()->registerDynamicSubtreeNodeList(this);
 }
 
 LabelsNodeList::~LabelsNodeList()
 {
-    m_forNode->removeCachedLabelsNodeList(this);
-    m_forNode->document()->unregisterDynamicSubtreeNodeList(this);
+    m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom);
+    document()->unregisterDynamicSubtreeNodeList(this);
 } 
     
 bool LabelsNodeList::nodeMatches(Element* testNode) const
 {
-    return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_forNode;
+    return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_node;
 }
 
 } // namespace WebCore
index b89b208..5879f92 100644 (file)
@@ -32,7 +32,7 @@ namespace WebCore {
 
 class LabelsNodeList : public DynamicSubtreeNodeList {
 public:
-    static PassRefPtr<LabelsNodeList> create(Node* forNode)
+    static PassRefPtr<LabelsNodeList> create(Node* forNode, const AtomicString&)
     {
         return adoptRef(new LabelsNodeList(forNode));
     }
@@ -42,9 +42,6 @@ protected:
     LabelsNodeList(Node* forNode);
 
     virtual bool nodeMatches(Element*) const;
-
-private:
-    RefPtr<Node> m_forNode;
 };
 
 } // namespace WebCore
index 3c3a618..0f0aeaf 100644 (file)
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "HTMLObjectElement.h"
+#include "NodeRareData.h"
 
 namespace WebCore {
 
 using namespace HTMLNames;
 
-RadioNodeList::RadioNodeList(Element* baseElement, const AtomicString& name)
-    : DynamicSubtreeNodeList(baseElement, baseElement->hasTagName(formTag) ? RootedAtDocument : RootedAtNode)
+RadioNodeList::RadioNodeList(Node* rootNode, const AtomicString& name)
+    : DynamicSubtreeNodeList(rootNode, rootNode->hasTagName(formTag) ? RootedAtDocument : RootedAtNode)
     , m_name(name)
-    , m_baseElement(baseElement)
 {
-    m_baseElement->document()->registerDynamicSubtreeNodeList(this);
+    document()->registerDynamicSubtreeNodeList(this);
 }
 
 RadioNodeList::~RadioNodeList()
 {
-    m_baseElement->removeCachedRadioNodeList(this, m_name);
-    m_baseElement->document()->unregisterDynamicSubtreeNodeList(this);
+    m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name);
+    document()->unregisterDynamicSubtreeNodeList(this);
 }
 
 static inline HTMLInputElement* toRadioButtonInputElement(Node* node)
@@ -86,13 +86,13 @@ void RadioNodeList::setValue(const String& value)
 bool RadioNodeList::checkElementMatchesRadioNodeListFilter(Element* testElement) const
 {
     ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement());
-    if (m_baseElement->hasTagName(formTag)) {
+    if (m_node->hasTagName(formTag)) {
         HTMLFormElement* formElement = 0;
         if (testElement->hasTagName(objectTag))
             formElement = static_cast<HTMLObjectElement*>(testElement)->form();
         else
             formElement = static_cast<HTMLFormControlElement*>(testElement)->form();
-        if (!formElement || formElement != m_baseElement)
+        if (!formElement || formElement != m_node)
             return false;
     }
 
index 46065b3..18eb288 100644 (file)
@@ -36,9 +36,9 @@ namespace WebCore {
 
 class RadioNodeList : public DynamicSubtreeNodeList {
 public:
-    static PassRefPtr<RadioNodeList> create(Element* baseElement, const AtomicString& name)
+    static PassRefPtr<RadioNodeList> create(Node* rootNode, const AtomicString& name)
     {
-        return adoptRef(new RadioNodeList(baseElement, name));
+        return adoptRef(new RadioNodeList(rootNode, name));
     }
 
     ~RadioNodeList();
@@ -50,11 +50,10 @@ protected:
     virtual bool nodeMatches(Element*) const;
 
 private:
-    RadioNodeList(Element*, const AtomicString& name);
+    RadioNodeList(Node*, const AtomicString& name);
     bool checkElementMatchesRadioNodeListFilter(Element*) const;
 
     AtomicString m_name;
-    RefPtr<Element> m_baseElement;
 };
 
 } // namepsace