Changeset 120979 in webkit
- Timestamp:
- Jun 21, 2012 4:37:56 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r120978 r120979 1 2012-06-20 Ryosuke Niwa <rniwa@webkit.org> 2 3 Shrink NodeListsNodeData 4 https://bugs.webkit.org/show_bug.cgi?id=89036 5 6 Reviewed by Andreas Kling. 7 8 Replaced 6 hash maps of AtomicString, String, and RefPtr<QualifiedName::QualifiedNameImpl> and a raw pointer 9 by 3 hash maps of std::pair<unsigned short, AtomicString>, std::pair<unsigned short, String>, and QualifiedName, 10 to halve the NodeListsNodeData's size (Reduced from 7 pointers to 3 pointers). Made those hash maps private and 11 added addCacheWith* and removeCacheWith* member functions to reduce the code duplication. 12 13 Also got rid of removeCached*NodeList member functions from Node and Document now that DynamicSubtreeNodeList can 14 simply call nodeLists()->removeCacheWith* on m_node. 15 16 * dom/ChildNodeList.cpp: 17 (WebCore::ChildNodeList::ChildNodeList): 18 * dom/ClassNodeList.cpp: 19 (WebCore::ClassNodeList::~ClassNodeList): 20 * dom/Document.cpp: 21 (WebCore::Document::getItems): Use addCacheWithName. 22 * dom/Document.h: Got rid of removeCachedMicroDataItemList. 23 (Document): 24 * dom/DynamicNodeList.cpp: 25 (WebCore): Moved the constructor to the header file. 26 * dom/DynamicNodeList.h: Added NodeListType and InvalidationType to be used in NodeListsNodeData. 27 (WebCore::DynamicNodeList::DynamicNodeList): Takes the invalidation type. 28 (WebCore::DynamicNodeList::document): Added. 29 (WebCore::DynamicNodeList::shouldInvalidateOnAttributeChange): Added. 30 (WebCore::DynamicNodeList::Caches::Caches): Added shouldInvalidateOnAttributeChange to retain the invalidation type. 31 (Caches): 32 (WebCore::DynamicSubtreeNodeList::DynamicSubtreeNodeList): 33 * dom/MicroDataItemList.cpp: 34 (WebCore::MicroDataItemList::~MicroDataItemList): 35 * dom/NameNodeList.cpp: 36 (WebCore::NameNodeList::NameNodeList): 37 (WebCore::NameNodeList::~NameNodeList): 38 (WebCore::NameNodeList::nodeMatches): 39 * dom/NameNodeList.h: 40 (WebCore): 41 (NameNodeList): 42 (WebCore::NameNodeList::create): 43 * dom/Node.cpp: 44 (WebCore::Node::nodeLists): Added so that node lists can directly call removeCacheWith*. 45 (WebCore::Node::getElementsByTagName): 46 (WebCore::Node::getElementsByTagNameNS): 47 (WebCore::Node::getElementsByName): 48 (WebCore::Node::getElementsByClassName): 49 (WebCore::Node::radioNodeList): 50 (WebCore::NodeListsNodeData::invalidateCaches): Merged invalidateCachesThatDependOnAttributes. The function takes 51 the attribute name to avoid invalidating tag node lists when only attributes are modified. Also, now we have exactly 52 three hash maps to invalidate: m_atomicNameCaches, m_nameCaches, and m_tagNodeListCacheNS. 53 (WebCore): NodeListsNodeData::isEmpty is moved to NodeRareData.h. 54 * dom/Node.h: 55 (WebCore): 56 (Node): 57 * dom/NodeRareData.h: 58 (NodeListsNodeData): 59 (WebCore::NodeListsNodeData::addCacheWithAtomicName): 60 (WebCore::NodeListsNodeData::addCacheWithName): 61 (WebCore::NodeListsNodeData::addCacheWithQualifiedName): 62 (WebCore::NodeListsNodeData::removeCacheWithAtomicName): 63 (WebCore::NodeListsNodeData::removeCacheWithName): 64 (WebCore::NodeListsNodeData::removeCacheWithQualifiedName): 65 (WebCore::NodeListsNodeData::isEmpty): Moved from Node.cpp now that this function is much shorter. 66 (WebCore::NodeListsNodeData::NodeListsNodeData): 67 (WebCore::NodeListsNodeData::namedNodeListKey): Helper member functions to obtain the key for AtomicString and 68 String hash maps. 69 * dom/TagNodeList.cpp: 70 (WebCore::TagNodeList::TagNodeList): 71 (WebCore::TagNodeList::~TagNodeList): 72 (WebCore::HTMLTagNodeList::HTMLTagNodeList): Hard code namespaceURI = starAtom since other values are never used. 73 (WebCore::HTMLTagNodeList::nodeMatches): Given that, assert m_namespace == starAtom. 74 * dom/TagNodeList.h: 75 (WebCore::TagNodeList::create): Add a new version of create that doesn't take namespace (assume starAtom) so that 76 addCacheWithAtomicName works with this class. 77 (WebCore::HTMLTagNodeList::create): Removed namespaceURI from the argument list since it's always starAtom. 78 (HTMLTagNodeList): 79 * html/LabelableElement.cpp: 80 (WebCore::LabelableElement::labels): 81 * html/LabelsNodeList.cpp: 82 (WebCore::LabelsNodeList::LabelsNodeList): Removed redundant m_forNode (identical to m_node in DynamicNodeList). 83 (WebCore::LabelsNodeList::~LabelsNodeList): 84 (WebCore::LabelsNodeList::nodeMatches): 85 * html/LabelsNodeList.h: 86 (WebCore::LabelsNodeList::create): 87 (LabelsNodeList): 88 * html/RadioNodeList.cpp: 89 (WebCore::RadioNodeList::RadioNodeList): Removed redundant m_baseElement (identical to m_node in DynamicNodeList). 90 Also changed the first argument's type from Element* to Node* so that it works better with new template member 91 functions of NodeListsNodeData. 92 (WebCore::RadioNodeList::~RadioNodeList): 93 (WebCore::RadioNodeList::checkElementMatchesRadioNodeListFilter): 94 * html/RadioNodeList.h: 95 (WebCore::RadioNodeList::create): 96 (RadioNodeList): 97 1 98 2012-06-21 Sheriff Bot <webkit.review.bot@gmail.com> 2 99 -
trunk/Source/WebCore/dom/ChildNodeList.cpp
r105408 r120979 29 29 30 30 ChildNodeList::ChildNodeList(PassRefPtr<Node> node) 31 : DynamicNodeList(node )31 : DynamicNodeList(node, RootedAtNode, DoNotInvalidateOnAttributeChange) 32 32 { 33 33 } -
trunk/Source/WebCore/dom/ClassNodeList.cpp
r120367 r120979 32 32 33 33 #include "Document.h" 34 #include "NodeRareData.h" 34 35 #include "StyledElement.h" 35 36 … … 45 46 ClassNodeList::~ClassNodeList() 46 47 { 47 node()-> removeCachedClassNodeList(this, m_originalClassNames);48 node()->nodeLists()->removeCacheWithName(this, DynamicNodeList::ClassNodeListType, m_originalClassNames); 48 49 } 49 50 -
trunk/Source/WebCore/dom/Document.cpp
r120885 r120979 5927 5927 PassRefPtr<NodeList> Document::getItems(const String& typeNames) 5928 5928 { 5929 NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);5930 5931 5929 // Since documet.getItem() is allowed for microdata, typeNames will be null string. 5932 5930 // In this case we need to create an unique string identifier to map such request in the cache. 5933 5931 String localTypeNames = typeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : typeNames; 5934 5932 5935 NodeListsNodeData::MicroDataItemListCache::AddResult result = nodeLists->m_microDataItemListCache.add(localTypeNames, 0); 5936 if (!result.isNewEntry) 5937 return PassRefPtr<NodeList>(result.iterator->second); 5938 5939 RefPtr<MicroDataItemList> list = MicroDataItemList::create(this, typeNames); 5940 result.iterator->second = list.get(); 5941 return list.release(); 5942 } 5943 5944 void Document::removeCachedMicroDataItemList(MicroDataItemList* list, const String& typeNames) 5945 { 5946 ASSERT(rareData()); 5947 ASSERT(rareData()->nodeLists()); 5948 5949 NodeListsNodeData* data = rareData()->nodeLists(); 5950 5951 String localTypeNames = typeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : typeNames; 5952 ASSERT_UNUSED(list, list == data->m_microDataItemListCache.get(localTypeNames)); 5953 data->m_microDataItemListCache.remove(localTypeNames); 5933 return ensureRareData()->ensureNodeLists(this)->addCacheWithName<MicroDataItemList>(this, DynamicNodeList::MicroDataItemListType, localTypeNames); 5954 5934 } 5955 5935 #endif -
trunk/Source/WebCore/dom/Document.h
r120868 r120979 1109 1109 #if ENABLE(MICRODATA) 1110 1110 PassRefPtr<NodeList> getItems(const String& typeNames); 1111 void removeCachedMicroDataItemList(MicroDataItemList*, const String&);1112 1111 #endif 1113 1112 -
trunk/Source/WebCore/dom/DynamicNodeList.cpp
r120367 r120979 28 28 29 29 namespace WebCore { 30 31 DynamicSubtreeNodeList::DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType)32 : DynamicNodeList(node, rootType)33 {34 }35 30 36 31 DynamicSubtreeNodeList::~DynamicSubtreeNodeList() -
trunk/Source/WebCore/dom/DynamicNodeList.h
r120868 r120979 37 37 class DynamicNodeList : public NodeList { 38 38 public: 39 enum NodeListType { 40 ChildNodeListType, 41 ClassNodeListType, 42 NameNodeListType, 43 TagNodeListType, 44 RadioNodeListType, 45 LabelsNodeListType, 46 MicroDataItemListType, 47 }; 39 48 enum RootType { 40 49 RootedAtNode, 41 50 RootedAtDocument, 42 51 }; 43 44 DynamicNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode) 52 enum InvalidationType { 53 AlwaysInvalidate, 54 DoNotInvalidateOnAttributeChange, 55 }; 56 DynamicNodeList(PassRefPtr<Node> node, RootType rootType, InvalidationType invalidationType) 45 57 : m_node(node) 46 , m_caches(rootType )58 , m_caches(rootType, invalidationType) 47 59 { } 48 60 virtual ~DynamicNodeList() { } … … 60 72 return m_node.get(); 61 73 } 74 Document* document() { return m_node->document(); } 75 76 bool shouldInvalidateOnAttributeChange() const { return m_caches.shouldInvalidateOnAttributeChange; } 62 77 63 78 void invalidateCache() { m_caches.reset(); } … … 67 82 68 83 struct Caches { 69 Caches(RootType rootType )84 Caches(RootType rootType, InvalidationType invalidationType) 70 85 : rootedAtDocument(rootType == RootedAtDocument) 86 , shouldInvalidateOnAttributeChange(invalidationType == AlwaysInvalidate) 71 87 { 72 88 reset(); … … 82 98 Node* lastItem; 83 99 unsigned cachedLength; 84 unsigned lastItemOffset : 29; // Borrow 3-bits for bit fields100 unsigned lastItemOffset; 85 101 unsigned isLengthCacheValid : 1; 86 102 unsigned isItemCacheValid : 1; 103 104 // Following flags should belong in DynamicSubtreeNode but are here for bit-packing. 105 unsigned type : 4; 87 106 unsigned rootedAtDocument : 1; 107 unsigned shouldInvalidateOnAttributeChange : 1; 88 108 }; 89 109 … … 102 122 103 123 protected: 104 DynamicSubtreeNodeList(PassRefPtr<Node>, RootType = RootedAtNode); 124 DynamicSubtreeNodeList(PassRefPtr<Node> node, RootType rootType = RootedAtNode, InvalidationType invalidationType = AlwaysInvalidate) 125 : DynamicNodeList(node, rootType, invalidationType) 126 { } 105 127 106 128 private: -
trunk/Source/WebCore/dom/MicroDataItemList.cpp
r105655 r120979 33 33 #include "HTMLElement.h" 34 34 #include "HTMLNames.h" 35 #include "NodeRareData.h" 35 36 36 37 namespace WebCore { … … 47 48 MicroDataItemList::~MicroDataItemList() 48 49 { 49 rootNode()->document()->removeCachedMicroDataItemList(this, m_originalTypeNames); 50 String localTypeNames = m_originalTypeNames.isNull() ? String("http://webkit.org/microdata/undefinedItemType") : m_originalTypeNames; 51 m_node->nodeLists()->removeCacheWithName(this, DynamicNodeList::MicroDataItemListType, localTypeNames); 50 52 } 51 53 -
trunk/Source/WebCore/dom/NameNodeList.cpp
r120367 r120979 26 26 #include "Element.h" 27 27 #include "HTMLNames.h" 28 #include "NodeRareData.h" 28 29 #include <wtf/Assertions.h> 29 30 … … 32 33 using namespace HTMLNames; 33 34 34 NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name)35 NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name) 35 36 : DynamicSubtreeNodeList(rootNode) 36 , m_n odeName(name)37 , m_name(name) 37 38 { 38 39 } … … 40 41 NameNodeList::~NameNodeList() 41 42 { 42 node()->removeCachedNameNodeList(this, m_nodeName);43 m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::NameNodeListType, m_name); 43 44 } 44 45 45 46 bool NameNodeList::nodeMatches(Element* testNode) const 46 47 { 47 return testNode->getNameAttribute() == m_n odeName;48 return testNode->getNameAttribute() == m_name; 48 49 } 49 50 -
trunk/Source/WebCore/dom/NameNodeList.h
r102834 r120979 31 31 namespace WebCore { 32 32 33 34 35 36 static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, constString& name)37 38 39 33 // NodeList which lists all Nodes in a Element with a given "name" attribute 34 class NameNodeList : public DynamicSubtreeNodeList { 35 public: 36 static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& name) 37 { 38 return adoptRef(new NameNodeList(rootNode, name)); 39 } 40 40 41 41 virtual ~NameNodeList(); 42 42 43 44 NameNodeList(PassRefPtr<Node> rootNode, constString& name);43 private: 44 NameNodeList(PassRefPtr<Node> rootNode, const AtomicString& name); 45 45 46 46 virtual bool nodeMatches(Element*) const; 47 47 48 AtomicString m_nodeName;49 48 AtomicString m_name; 49 }; 50 50 51 51 } // namespace WebCore -
trunk/Source/WebCore/dom/Node.cpp
r120868 r120979 981 981 continue; 982 982 983 data->nodeLists()->invalidateCaches ThatDependOnAttributes();983 data->nodeLists()->invalidateCaches(&attrName); 984 984 } 985 985 } … … 1006 1006 } 1007 1007 1008 void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className) 1009 { 1010 ASSERT(rareData()); 1011 ASSERT(rareData()->nodeLists()); 1012 1013 NodeListsNodeData* data = rareData()->nodeLists(); 1014 ASSERT_UNUSED(list, list == data->m_classNodeListCache.get(className)); 1015 data->m_classNodeListCache.remove(className); 1016 } 1017 1018 void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName) 1019 { 1020 ASSERT(rareData()); 1021 ASSERT(rareData()->nodeLists()); 1022 1023 NodeListsNodeData* data = rareData()->nodeLists(); 1024 ASSERT_UNUSED(list, list == data->m_nameNodeListCache.get(nodeName)); 1025 data->m_nameNodeListCache.remove(nodeName); 1026 } 1027 1028 void Node::removeCachedTagNodeList(TagNodeList* list, const AtomicString& name) 1029 { 1030 ASSERT(rareData()); 1031 ASSERT(rareData()->nodeLists()); 1032 1033 NodeListsNodeData* data = rareData()->nodeLists(); 1034 ASSERT_UNUSED(list, list == data->m_tagNodeListCache.get(name.impl())); 1035 data->m_tagNodeListCache.remove(name.impl()); 1036 } 1037 1038 void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name) 1039 { 1040 ASSERT(rareData()); 1041 ASSERT(rareData()->nodeLists()); 1042 1043 NodeListsNodeData* data = rareData()->nodeLists(); 1044 ASSERT_UNUSED(list, list == data->m_tagNodeListCacheNS.get(name.impl())); 1045 data->m_tagNodeListCacheNS.remove(name.impl()); 1046 } 1047 1048 void Node::removeCachedLabelsNodeList(DynamicSubtreeNodeList* list) 1049 { 1050 ASSERT(rareData()); 1051 ASSERT(rareData()->nodeLists()); 1052 1053 NodeListsNodeData* data = rareData()->nodeLists(); 1054 ASSERT_UNUSED(list, list == data->m_labelsNodeListCache); 1055 data->m_labelsNodeListCache = 0; 1008 NodeListsNodeData* Node::nodeLists() 1009 { 1010 return hasRareData() ? rareData()->nodeLists() : 0; 1056 1011 } 1057 1012 … … 1593 1548 return 0; 1594 1549 1595 AtomicString localNameAtom = localName;1596 1597 NodeListsNodeData::TagNodeListCache::AddResult result = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCache.add(localNameAtom, 0);1598 if (!result.isNewEntry)1599 return PassRefPtr<TagNodeList>(result.iterator->second);1600 1601 RefPtr<TagNodeList> list;1602 1550 if (document()->isHTMLDocument()) 1603 list = HTMLTagNodeList::create(this, starAtom, localNameAtom); 1604 else 1605 list = TagNodeList::create(this, starAtom, localNameAtom); 1606 result.iterator->second = list.get(); 1607 return list.release(); 1551 return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<HTMLTagNodeList>(this, DynamicNodeList::TagNodeListType, localName); 1552 return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<TagNodeList>(this, DynamicNodeList::TagNodeListType, localName); 1608 1553 } 1609 1554 … … 1616 1561 return getElementsByTagName(localName); 1617 1562 1618 AtomicString localNameAtom = localName; 1619 1620 NodeListsNodeData::TagNodeListCacheNS::AddResult result 1621 = ensureRareData()->ensureNodeLists(this)->m_tagNodeListCacheNS.add(QualifiedName(nullAtom, localNameAtom, namespaceURI).impl(), 0); 1622 if (!result.isNewEntry) 1623 return PassRefPtr<TagNodeList>(result.iterator->second); 1624 1625 RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom); 1626 result.iterator->second = list.get(); 1627 return list.release(); 1563 return ensureRareData()->ensureNodeLists(this)->addCacheWithQualifiedName(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localName); 1628 1564 } 1629 1565 1630 1566 PassRefPtr<NodeList> Node::getElementsByName(const String& elementName) 1631 1567 { 1632 NodeListsNodeData::NameNodeListCache::AddResult result = ensureRareData()->ensureNodeLists(this)->m_nameNodeListCache.add(elementName, 0); 1633 if (!result.isNewEntry) 1634 return PassRefPtr<NodeList>(result.iterator->second); 1635 1636 RefPtr<NameNodeList> list = NameNodeList::create(this, elementName); 1637 result.iterator->second = list.get(); 1638 return list.release(); 1568 return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<NameNodeList>(this, DynamicNodeList::NameNodeListType, elementName); 1639 1569 } 1640 1570 1641 1571 PassRefPtr<NodeList> Node::getElementsByClassName(const String& classNames) 1642 1572 { 1643 NodeListsNodeData::ClassNodeListCache::AddResult result 1644 = ensureRareData()->ensureNodeLists(this)->m_classNodeListCache.add(classNames, 0); 1645 if (!result.isNewEntry) 1646 return PassRefPtr<NodeList>(result.iterator->second); 1647 1648 RefPtr<ClassNodeList> list = ClassNodeList::create(this, classNames); 1649 result.iterator->second = list.get(); 1650 return list.release(); 1573 return ensureRareData()->ensureNodeLists(this)->addCacheWithName<ClassNodeList>(this, DynamicNodeList::ClassNodeListType, classNames); 1574 } 1575 1576 PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name) 1577 { 1578 ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag)); 1579 return ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<RadioNodeList>(this, DynamicNodeList::RadioNodeListType, name); 1651 1580 } 1652 1581 … … 2310 2239 // -------- 2311 2240 2312 void NodeListsNodeData::invalidateCaches() 2313 { 2314 TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end(); 2315 for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) 2241 void NodeListsNodeData::invalidateCaches(const QualifiedName* attrName) 2242 { 2243 NodeListAtomicNameCacheMap::const_iterator atomicNameCacheEnd = m_atomicNameCaches.end(); 2244 for (NodeListAtomicNameCacheMap::const_iterator it = m_atomicNameCaches.begin(); it != atomicNameCacheEnd; ++it) { 2245 if (!attrName || it->second->shouldInvalidateOnAttributeChange()) 2246 it->second->invalidateCache(); 2247 } 2248 2249 NodeListNameCacheMap::const_iterator nameCacheEnd = m_nameCaches.end(); 2250 for (NodeListNameCacheMap::const_iterator it = m_nameCaches.begin(); it != nameCacheEnd; ++it) { 2251 if (!attrName || it->second->shouldInvalidateOnAttributeChange()) 2252 it->second->invalidateCache(); 2253 } 2254 2255 if (!attrName) 2256 return; 2257 2258 TagNodeListCacheNS::iterator tagCacheEnd = m_tagNodeListCacheNS.end(); 2259 for (TagNodeListCacheNS::iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheEnd; ++it) 2316 2260 it->second->invalidateCache(); 2317 TagNodeListCacheNS::const_iterator tagCacheNSEnd = m_tagNodeListCacheNS.end();2318 for (TagNodeListCacheNS::const_iterator it = m_tagNodeListCacheNS.begin(); it != tagCacheNSEnd; ++it)2319 it->second->invalidateCache();2320 invalidateCachesThatDependOnAttributes();2321 }2322 2323 void NodeListsNodeData::invalidateCachesThatDependOnAttributes()2324 {2325 ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end();2326 for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it)2327 it->second->invalidateCache();2328 2329 NameNodeListCache::iterator nameCacheEnd = m_nameNodeListCache.end();2330 for (NameNodeListCache::iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it)2331 it->second->invalidateCache();2332 if (m_labelsNodeListCache)2333 m_labelsNodeListCache->invalidateCache();2334 2335 #if ENABLE(MICRODATA)2336 MicroDataItemListCache::iterator itemListCacheEnd = m_microDataItemListCache.end();2337 for (MicroDataItemListCache::iterator it = m_microDataItemListCache.begin(); it != itemListCacheEnd; ++it)2338 it->second->invalidateCache();2339 #endif2340 }2341 2342 bool NodeListsNodeData::isEmpty() const2343 {2344 if (!m_tagNodeListCache.isEmpty())2345 return false;2346 if (!m_tagNodeListCacheNS.isEmpty())2347 return false;2348 if (!m_classNodeListCache.isEmpty())2349 return false;2350 if (!m_nameNodeListCache.isEmpty())2351 return false;2352 #if ENABLE(MICRODATA)2353 if (!m_microDataItemListCache.isEmpty())2354 return false;2355 #endif2356 2357 if (m_labelsNodeListCache)2358 return false;2359 2360 if (!m_radioNodeListCache.isEmpty())2361 return false;2362 2363 return true;2364 2261 } 2365 2262 … … 2872 2769 } 2873 2770 2874 PassRefPtr<RadioNodeList> Node::radioNodeList(const AtomicString& name)2875 {2876 ASSERT(hasTagName(formTag) || hasTagName(fieldsetTag));2877 2878 NodeListsNodeData* nodeLists = ensureRareData()->ensureNodeLists(this);2879 2880 NodeListsNodeData::RadioNodeListCache::AddResult result = nodeLists->m_radioNodeListCache.add(name, 0);2881 if (!result.isNewEntry)2882 return PassRefPtr<RadioNodeList>(result.iterator->second);2883 2884 RefPtr<RadioNodeList> list = RadioNodeList::create(toElement(this), name);2885 result.iterator->second = list.get();2886 return list.release();2887 }2888 2889 void Node::removeCachedRadioNodeList(RadioNodeList* list, const AtomicString& name)2890 {2891 ASSERT(rareData());2892 ASSERT(rareData()->nodeLists());2893 2894 NodeListsNodeData* data = rareData()->nodeLists();2895 ASSERT_UNUSED(list, list == data->m_radioNodeListCache.get(name));2896 data->m_radioNodeListCache.remove(name);2897 }2898 2899 2771 // It's important not to inline removedLastRef, because we don't want to inline the code to 2900 2772 // delete a Node at each deref call site. -
trunk/Source/WebCore/dom/Node.h
r120367 r120979 70 70 class NameNodeList; 71 71 class NodeList; 72 class NodeListsNodeData; 72 73 class NodeRareData; 73 74 class NodeRenderingContext; … … 559 560 void invalidateNodeListsCacheAfterAttributeChanged(const QualifiedName&, Element* attributeOwnerElement); 560 561 void invalidateNodeListsCacheAfterChildrenChanged(); 561 void removeCachedClassNodeList(ClassNodeList*, const String&); 562 563 void removeCachedNameNodeList(NameNodeList*, const String&); 564 void removeCachedTagNodeList(TagNodeList*, const AtomicString&); 565 void removeCachedTagNodeList(TagNodeList*, const QualifiedName&); 566 void removeCachedLabelsNodeList(DynamicSubtreeNodeList*); 567 562 NodeListsNodeData* nodeLists(); 568 563 void removeCachedChildNodeList(); 569 570 PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&);571 void removeCachedRadioNodeList(RadioNodeList*, const AtomicString&);572 void resetCachedRadioNodeListRootNode();573 564 574 565 PassRefPtr<NodeList> getElementsByTagName(const AtomicString&); … … 576 567 PassRefPtr<NodeList> getElementsByName(const String& elementName); 577 568 PassRefPtr<NodeList> getElementsByClassName(const String& classNames); 569 PassRefPtr<RadioNodeList> radioNodeList(const AtomicString&); 578 570 579 571 PassRefPtr<Element> querySelector(const AtomicString& selectors, ExceptionCode&); -
trunk/Source/WebCore/dom/NodeRareData.h
r120868 r120979 24 24 25 25 #include "ChildNodeList.h" 26 #include "ClassNodeList.h"27 26 #include "DOMSettableTokenList.h" 28 27 #include "DynamicNodeList.h" 29 28 #include "MutationObserverRegistration.h" 30 #include "NameNodeList.h"31 29 #include "QualifiedName.h" 32 30 #include "TagNodeList.h" … … 52 50 WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED; 53 51 public: 54 typedef HashMap<String, ClassNodeList*> ClassNodeListCache; 55 ClassNodeListCache m_classNodeListCache; 56 57 typedef HashMap<String, NameNodeList*> NameNodeListCache; 58 NameNodeListCache m_nameNodeListCache; 59 60 typedef HashMap<AtomicString, TagNodeList*> TagNodeListCache; 61 TagNodeListCache m_tagNodeListCache; 62 63 typedef HashMap<RefPtr<QualifiedName::QualifiedNameImpl>, TagNodeList*> TagNodeListCacheNS; 52 typedef HashMap<std::pair<unsigned short, AtomicString>, DynamicSubtreeNodeList*> NodeListAtomicNameCacheMap; 53 typedef HashMap<std::pair<unsigned short, String>, DynamicSubtreeNodeList*> NodeListNameCacheMap; 54 typedef HashMap<QualifiedName, TagNodeList*> TagNodeListCacheNS; 55 56 template<typename T> 57 PassRefPtr<T> addCacheWithAtomicName(Node* node, DynamicNodeList::NodeListType listType, const AtomicString& name) 58 { 59 NodeListAtomicNameCacheMap::AddResult result = m_atomicNameCaches.add(namedNodeListKey(listType, name), 0); 60 if (!result.isNewEntry) 61 return static_cast<T*>(result.iterator->second); 62 63 RefPtr<T> list = T::create(node, name); 64 result.iterator->second = list.get(); 65 return list.release(); 66 } 67 68 template<typename T> 69 PassRefPtr<T> addCacheWithName(Node* node, DynamicNodeList::NodeListType listType, const String& name) 70 { 71 NodeListNameCacheMap::AddResult result = m_nameCaches.add(namedNodeListKey(listType, name), 0); 72 if (!result.isNewEntry) 73 return static_cast<T*>(result.iterator->second); 74 75 RefPtr<T> list = T::create(node, name); 76 result.iterator->second = list.get(); 77 return list.release(); 78 } 79 80 PassRefPtr<TagNodeList> addCacheWithQualifiedName(Node* node, const AtomicString& namespaceURI, const AtomicString& localName) 81 { 82 QualifiedName name(nullAtom, localName, namespaceURI); 83 TagNodeListCacheNS::AddResult result = m_tagNodeListCacheNS.add(name, 0); 84 if (!result.isNewEntry) 85 return result.iterator->second; 86 87 RefPtr<TagNodeList> list = TagNodeList::create(node, namespaceURI, localName); 88 result.iterator->second = list.get(); 89 return list.release(); 90 } 91 92 void removeCacheWithAtomicName(DynamicSubtreeNodeList* list, DynamicNodeList::NodeListType listType, const AtomicString& name) 93 { 94 ASSERT_UNUSED(list, list == m_atomicNameCaches.get(namedNodeListKey(listType, name))); 95 m_atomicNameCaches.remove(namedNodeListKey(listType, name)); 96 } 97 98 void removeCacheWithName(DynamicSubtreeNodeList* list, DynamicNodeList::NodeListType listType, const String& name) 99 { 100 ASSERT_UNUSED(list, list == m_nameCaches.get(namedNodeListKey(listType, name))); 101 m_nameCaches.remove(namedNodeListKey(listType, name)); 102 } 103 104 void removeCacheWithQualifiedName(DynamicSubtreeNodeList* list, const AtomicString& namespaceURI, const AtomicString& localName) 105 { 106 QualifiedName name(nullAtom, localName, namespaceURI); 107 ASSERT_UNUSED(list, list == m_tagNodeListCacheNS.get(name)); 108 m_tagNodeListCacheNS.remove(name); 109 } 110 111 static PassOwnPtr<NodeListsNodeData> create() 112 { 113 return adoptPtr(new NodeListsNodeData); 114 } 115 116 void invalidateCaches(const QualifiedName* attrName = 0); 117 bool isEmpty() const 118 { 119 return m_atomicNameCaches.isEmpty() && m_nameCaches.isEmpty() && m_tagNodeListCacheNS.isEmpty(); 120 } 121 122 private: 123 NodeListsNodeData() { } 124 125 std::pair<unsigned short, AtomicString> namedNodeListKey(DynamicNodeList::NodeListType listType, const AtomicString& name) 126 { 127 return std::pair<unsigned short, AtomicString>(listType, name); 128 } 129 130 std::pair<unsigned short, String> namedNodeListKey(DynamicNodeList::NodeListType listType, const String& name) 131 { 132 return std::pair<unsigned short, String>(listType, name); 133 } 134 135 NodeListAtomicNameCacheMap m_atomicNameCaches; 136 NodeListNameCacheMap m_nameCaches; 64 137 TagNodeListCacheNS m_tagNodeListCacheNS; 65 66 #if ENABLE(MICRODATA)67 typedef HashMap<String, MicroDataItemList*> MicroDataItemListCache;68 MicroDataItemListCache m_microDataItemListCache;69 #endif70 71 LabelsNodeList* m_labelsNodeListCache;72 73 typedef HashMap<String, RadioNodeList*> RadioNodeListCache;74 RadioNodeListCache m_radioNodeListCache;75 76 static PassOwnPtr<NodeListsNodeData> create()77 {78 return adoptPtr(new NodeListsNodeData);79 }80 81 void invalidateCaches();82 void invalidateCachesThatDependOnAttributes();83 84 bool isEmpty() const;85 86 private:87 NodeListsNodeData() : m_labelsNodeListCache(0) {}88 138 }; 89 139 -
trunk/Source/WebCore/dom/TagNodeList.cpp
r120367 r120979 26 26 27 27 #include "Element.h" 28 #include "NodeRareData.h" 28 29 #include <wtf/Assertions.h> 29 30 … … 31 32 32 33 TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) 33 : DynamicSubtreeNodeList(rootNode )34 : DynamicSubtreeNodeList(rootNode, RootedAtNode, DoNotInvalidateOnAttributeChange) 34 35 , m_namespaceURI(namespaceURI) 35 36 , m_localName(localName) … … 41 42 { 42 43 if (m_namespaceURI == starAtom) 43 node()->removeCachedTagNodeList(this, m_localName);44 m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::TagNodeListType, m_localName); 44 45 else 45 node()->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI));46 m_node->nodeLists()->removeCacheWithQualifiedName(this, m_namespaceURI, m_localName); 46 47 } 47 48 … … 55 56 } 56 57 57 HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString&localName)58 : TagNodeList(rootNode, namespaceURI, localName)58 HTMLTagNodeList::HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName) 59 : TagNodeList(rootNode, starAtom, localName) 59 60 , m_loweredLocalName(localName.lower()) 60 61 { … … 70 71 } 71 72 72 return m_namespaceURI == starAtom || m_namespaceURI == testNode->namespaceURI(); 73 ASSERT(m_namespaceURI == starAtom); 74 return true; 73 75 } 74 76 -
trunk/Source/WebCore/dom/TagNodeList.h
r113710 r120979 35 35 static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) 36 36 { 37 ASSERT(namespaceURI != starAtom); 37 38 return adoptRef(new TagNodeList(rootNode, namespaceURI, localName)); 39 } 40 41 static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& localName) 42 { 43 return adoptRef(new TagNodeList(rootNode, starAtom, localName)); 38 44 } 39 45 … … 51 57 class HTMLTagNodeList : public TagNodeList { 52 58 public: 53 static PassRefPtr< TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName)59 static PassRefPtr<HTMLTagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& localName) 54 60 { 55 return adoptRef(new HTMLTagNodeList(rootNode, namespaceURI,localName));61 return adoptRef(new HTMLTagNodeList(rootNode, localName)); 56 62 } 57 63 58 64 private: 59 HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString&localName);65 HTMLTagNodeList(PassRefPtr<Node> rootNode, const AtomicString& localName); 60 66 61 67 virtual bool nodeMatches(Element*) const; -
trunk/Source/WebCore/html/LabelableElement.cpp
r110927 r120979 48 48 return 0; 49 49 50 NodeListsNodeData* nodeLists = Node::ensureRareData()->ensureNodeLists(this); 51 if (nodeLists->m_labelsNodeListCache) 52 return nodeLists->m_labelsNodeListCache; 53 54 RefPtr<LabelsNodeList> list = LabelsNodeList::create(this); 55 nodeLists->m_labelsNodeListCache = list.get(); 56 return list.release(); 50 return Node::ensureRareData()->ensureNodeLists(this)->addCacheWithAtomicName<LabelsNodeList>(this, DynamicNodeList::LabelsNodeListType, starAtom); 57 51 } 58 52 -
trunk/Source/WebCore/html/LabelsNodeList.cpp
r120367 r120979 28 28 #include "HTMLLabelElement.h" 29 29 #include "HTMLNames.h" 30 #include "NodeRareData.h" 30 31 31 32 namespace WebCore { … … 35 36 LabelsNodeList::LabelsNodeList(Node* forNode) 36 37 : DynamicSubtreeNodeList(forNode, RootedAtDocument) 37 , m_forNode(forNode)38 38 { 39 m_forNode->document()->registerDynamicSubtreeNodeList(this);39 document()->registerDynamicSubtreeNodeList(this); 40 40 } 41 41 42 42 LabelsNodeList::~LabelsNodeList() 43 43 { 44 m_ forNode->removeCachedLabelsNodeList(this);45 m_forNode->document()->unregisterDynamicSubtreeNodeList(this);44 m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::LabelsNodeListType, starAtom); 45 document()->unregisterDynamicSubtreeNodeList(this); 46 46 } 47 47 48 48 bool LabelsNodeList::nodeMatches(Element* testNode) const 49 49 { 50 return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_ forNode;50 return testNode->hasTagName(labelTag) && static_cast<HTMLLabelElement*>(testNode)->control() == m_node; 51 51 } 52 52 -
trunk/Source/WebCore/html/LabelsNodeList.h
r102834 r120979 33 33 class LabelsNodeList : public DynamicSubtreeNodeList { 34 34 public: 35 static PassRefPtr<LabelsNodeList> create(Node* forNode )35 static PassRefPtr<LabelsNodeList> create(Node* forNode, const AtomicString&) 36 36 { 37 37 return adoptRef(new LabelsNodeList(forNode)); … … 43 43 44 44 virtual bool nodeMatches(Element*) const; 45 46 private:47 RefPtr<Node> m_forNode;48 45 }; 49 46 -
trunk/Source/WebCore/html/RadioNodeList.cpp
r120367 r120979 32 32 #include "HTMLNames.h" 33 33 #include "HTMLObjectElement.h" 34 #include "NodeRareData.h" 34 35 35 36 namespace WebCore { … … 37 38 using namespace HTMLNames; 38 39 39 RadioNodeList::RadioNodeList( Element* baseElement, const AtomicString& name)40 : DynamicSubtreeNodeList( baseElement, baseElement->hasTagName(formTag) ? RootedAtDocument : RootedAtNode)40 RadioNodeList::RadioNodeList(Node* rootNode, const AtomicString& name) 41 : DynamicSubtreeNodeList(rootNode, rootNode->hasTagName(formTag) ? RootedAtDocument : RootedAtNode) 41 42 , m_name(name) 42 , m_baseElement(baseElement)43 43 { 44 m_baseElement->document()->registerDynamicSubtreeNodeList(this);44 document()->registerDynamicSubtreeNodeList(this); 45 45 } 46 46 47 47 RadioNodeList::~RadioNodeList() 48 48 { 49 m_ baseElement->removeCachedRadioNodeList(this, m_name);50 m_baseElement->document()->unregisterDynamicSubtreeNodeList(this);49 m_node->nodeLists()->removeCacheWithAtomicName(this, DynamicNodeList::RadioNodeListType, m_name); 50 document()->unregisterDynamicSubtreeNodeList(this); 51 51 } 52 52 … … 87 87 { 88 88 ASSERT(testElement->hasTagName(objectTag) || testElement->isFormControlElement()); 89 if (m_ baseElement->hasTagName(formTag)) {89 if (m_node->hasTagName(formTag)) { 90 90 HTMLFormElement* formElement = 0; 91 91 if (testElement->hasTagName(objectTag)) … … 93 93 else 94 94 formElement = static_cast<HTMLFormControlElement*>(testElement)->form(); 95 if (!formElement || formElement != m_ baseElement)95 if (!formElement || formElement != m_node) 96 96 return false; 97 97 } -
trunk/Source/WebCore/html/RadioNodeList.h
r120367 r120979 37 37 class RadioNodeList : public DynamicSubtreeNodeList { 38 38 public: 39 static PassRefPtr<RadioNodeList> create( Element* baseElement, const AtomicString& name)39 static PassRefPtr<RadioNodeList> create(Node* rootNode, const AtomicString& name) 40 40 { 41 return adoptRef(new RadioNodeList( baseElement, name));41 return adoptRef(new RadioNodeList(rootNode, name)); 42 42 } 43 43 … … 51 51 52 52 private: 53 RadioNodeList( Element*, const AtomicString& name);53 RadioNodeList(Node*, const AtomicString& name); 54 54 bool checkElementMatchesRadioNodeListFilter(Element*) const; 55 55 56 56 AtomicString m_name; 57 RefPtr<Element> m_baseElement;58 57 }; 59 58
Note: See TracChangeset
for help on using the changeset viewer.