Changeset 58526 in webkit
- Timestamp:
- Apr 29, 2010 11:02:47 AM (14 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r58524 r58526 1 2010-04-29 Anton Muhin <antonm@chromium.org> 2 3 Reviewed by Darin Adler. 4 5 Let's cache nodelists instead of DynamicNodeList::Caches 6 https://bugs.webkit.org/show_bug.cgi?id=33696 7 8 * fast/dom/Element/node-list-identity-expected.txt: Added to verify that node lists are indeed cached 9 * fast/dom/Element/node-list-identity.html: Added to verify that node lists are indeed cached 10 * fast/dom/gc-9-expected.txt: Updated to follow changed semantics of caching 11 * fast/dom/gc-9.html: Updated to follow changed semantics of caching 12 1 13 2010-04-29 Marcus Bulach <bulach@chromium.org> 2 14 -
trunk/LayoutTests/fast/dom/gc-9-expected.txt
r47165 r58526 10 10 PASS: document.body.myCustomProperty should be 1 and is. 11 11 PASS: document.body.attributes.myCustomProperty should be 1 and is. 12 PASS: document.getElementsByTagName('body').myCustomProperty should be undefinedand is.12 PASS: document.getElementsByTagName('body').myCustomProperty should be 1 and is. 13 13 PASS: document.getElementsByTagName('canvas')[0].getContext('2d').myCustomProperty should be 1 and is. 14 14 PASS: document.getElementsByTagName('canvas')[0].getContext('2d').createLinearGradient(0, 0, 0, 0).myCustomProperty should be undefined and is. … … 46 46 PASS: document.body.myCustomProperty should be 1 and is. 47 47 PASS: document.body.attributes.myCustomProperty should be 1 and is. 48 PASS: document.getElementsByTagName('body').myCustomProperty should be undefinedand is.48 PASS: document.getElementsByTagName('body').myCustomProperty should be 1 and is. 49 49 PASS: document.getElementsByTagName('canvas')[0].getContext('2d').myCustomProperty should be 1 and is. 50 50 PASS: document.getElementsByTagName('canvas')[0].getContext('2d').createLinearGradient(0, 0, 0, 0).myCustomProperty should be undefined and is. -
trunk/LayoutTests/fast/dom/gc-9.html
r47165 r58526 111 111 [ "document.body", "allow custom" ], 112 112 [ "document.body.attributes", "allow custom" ], // NamedNodeMap 113 [ "document.getElementsByTagName('body')" ], // NodeList113 [ "document.getElementsByTagName('body')", "allow custom" ], // NodeList 114 114 [ "document.getElementsByTagName('canvas')[0].getContext('2d')", "allow custom" ], // CanvasRenderingContext2D 115 115 [ "document.getElementsByTagName('canvas')[0].getContext('2d').createLinearGradient(0, 0, 0, 0)" ], // CanvasGradient -
trunk/WebCore/ChangeLog
r58525 r58526 1 2010-04-29 Anton Muhin <antonm@chromium.org> 2 3 Reviewed by Darin Adler. 4 5 Let's cache nodelists instead of DynamicNodeList::Caches 6 https://bugs.webkit.org/show_bug.cgi?id=33696 7 8 Test: fast/dom/Element/node-list-identity.html 9 10 * bindings/js/JSNodeCustom.cpp: 11 (WebCore::JSNode::markChildren): Mark all cached node lists as well 12 * dom/ClassNodeList.cpp: 13 (WebCore::ClassNodeList::ClassNodeList): Don't need DynamicNodeList::Caches argument any more 14 (WebCore::ClassNodeList::~ClassNodeList): Remove from the cache 15 * dom/ClassNodeList.h: Added a field with original class names to be used as a key for removal from the cache 16 (WebCore::ClassNodeList::create): Don't need DynamicNodeList::Caches argument any more 17 * dom/NameNodeList.cpp: 18 (WebCore::NameNodeList::NameNodeList): Don't need DynamicNodeList::Caches argument any more 19 (WebCore::NameNodeList::~NameNodeList): Remove from the cache 20 * dom/NameNodeList.h: 21 (WebCore::NameNodeList::create): Don't need DynamicNodeList::Caches argument any more 22 * dom/Node.cpp: 23 (WebCore::Node::removeCachedClassNodeList): Remove ClassNodeList from the cache 24 (WebCore::Node::removeCachedNameNodeList): Remove NameNodeList from the cache 25 (WebCore::Node::removeCachedTagNodeList): Remove TagNodeList from the cache 26 (WebCore::Node::getElementsByTagNameNS): Switch to caching node lists themselves, not the data 27 (WebCore::Node::getElementsByName): Switch to caching node lists themselves, not the data 28 (WebCore::Node::getElementsByClassName): Switch to caching node lists themselves, not the data 29 (WebCore::NodeListsNodeData::invalidateCaches): Switch to caching node lists themselves, not the data 30 (WebCore::NodeListsNodeData::invalidateCachesThatDependOnAttributes): Switch to caching node lists themselves, not the data 31 (WebCore::NodeListsNodeData::isEmpty): Switch to caching node lists themselves, not the data 32 (WebCore::markNodeLists): Helper to mark all the node lists in the cache 33 (WebCore::Node::markCachedNodeListsSlow): Mark all the cached node lists if any could be present 34 * dom/Node.h: 35 (WebCore::Node::markCachedNodeLists): Fast-path marking of cached node lists---bails out if there is no rare data 36 * dom/NodeRareData.h: Changed type of caches to hold raw pointers to node lists, not RefPtr's to data 37 * dom/TagNodeList.cpp: 38 (WebCore::TagNodeList::TagNodeList): Don't need DynamicNodeList::Caches argument any more 39 (WebCore::TagNodeList::~TagNodeList): Remove from the cache 40 * dom/TagNodeList.h: 41 (WebCore::TagNodeList::create): Don't need DynamicNodeList::Caches argument any more 42 1 43 2010-04-29 Mikhail Naganov <mnaganov@chromium.org> 2 44 -
trunk/WebCore/bindings/js/JSNodeCustom.cpp
r58330 r58526 180 180 Node* node = m_impl.get(); 181 181 node->markJSEventListeners(markStack); 182 node->markCachedNodeLists(markStack, *Heap::heap(this)->globalData()); 182 183 183 184 // Nodes in the document are kept alive by JSDocument::mark, so, if we're in -
trunk/WebCore/dom/ClassNodeList.cpp
r37037 r58526 36 36 namespace WebCore { 37 37 38 ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames , DynamicNodeList::Caches* caches)39 : DynamicNodeList(rootNode , caches)38 ClassNodeList::ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames) 39 : DynamicNodeList(rootNode) 40 40 , m_classNames(classNames, m_rootNode->document()->inCompatMode()) 41 , m_originalClassNames(classNames) 41 42 { 42 43 } 44 45 ClassNodeList::~ClassNodeList() 46 { 47 m_rootNode->removeCachedClassNodeList(this, m_originalClassNames); 48 } 43 49 44 50 bool ClassNodeList::nodeMatches(Element* testNode) const -
trunk/WebCore/dom/ClassNodeList.h
r51902 r58526 38 38 class ClassNodeList : public DynamicNodeList { 39 39 public: 40 static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames , Caches* caches)40 static PassRefPtr<ClassNodeList> create(PassRefPtr<Node> rootNode, const String& classNames) 41 41 { 42 return adoptRef(new ClassNodeList(rootNode, classNames , caches));42 return adoptRef(new ClassNodeList(rootNode, classNames)); 43 43 } 44 44 45 virtual ~ClassNodeList(); 46 45 47 private: 46 ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames , Caches*);48 ClassNodeList(PassRefPtr<Node> rootNode, const String& classNames); 47 49 48 50 virtual bool nodeMatches(Element*) const; 49 51 50 52 SpaceSplitString m_classNames; 53 String m_originalClassNames; 51 54 }; 52 55 -
trunk/WebCore/dom/NameNodeList.cpp
r37037 r58526 32 32 using namespace HTMLNames; 33 33 34 NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name , DynamicNodeList::Caches* caches)35 : DynamicNodeList(rootNode , caches)34 NameNodeList::NameNodeList(PassRefPtr<Node> rootNode, const String& name) 35 : DynamicNodeList(rootNode) 36 36 , m_nodeName(name) 37 37 { 38 38 } 39 40 NameNodeList::~NameNodeList() 41 { 42 m_rootNode->removeCachedNameNodeList(this, m_nodeName); 43 } 39 44 40 45 bool NameNodeList::nodeMatches(Element* testNode) const -
trunk/WebCore/dom/NameNodeList.h
r37037 r58526 35 35 class NameNodeList : public DynamicNodeList { 36 36 public: 37 static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name , Caches* caches)37 static PassRefPtr<NameNodeList> create(PassRefPtr<Node> rootNode, const String& name) 38 38 { 39 return adoptRef(new NameNodeList(rootNode, name , caches));39 return adoptRef(new NameNodeList(rootNode, name)); 40 40 } 41 41 42 virtual ~NameNodeList(); 43 42 44 private: 43 NameNodeList(PassRefPtr<Node> rootNode, const String& name , Caches*);45 NameNodeList(PassRefPtr<Node> rootNode, const String& name); 44 46 45 47 virtual bool nodeMatches(Element*) const; -
trunk/WebCore/dom/Node.cpp
r58362 r58526 97 97 #if ENABLE(XHTMLMP) 98 98 #include "HTMLNoScriptElement.h" 99 #endif 100 101 #if USE(JSC) 102 #include <runtime/JSGlobalData.h> 99 103 #endif 100 104 … … 978 982 } 979 983 984 void Node::removeCachedClassNodeList(ClassNodeList* list, const String& className) 985 { 986 ASSERT(rareData()); 987 ASSERT(rareData()->nodeLists()); 988 ASSERT_UNUSED(list, list->hasOwnCaches()); 989 990 NodeListsNodeData* data = rareData()->nodeLists(); 991 ASSERT_UNUSED(list, list == data->m_classNodeListCache.get(className)); 992 data->m_classNodeListCache.remove(className); 993 } 994 995 void Node::removeCachedNameNodeList(NameNodeList* list, const String& nodeName) 996 { 997 ASSERT(rareData()); 998 ASSERT(rareData()->nodeLists()); 999 ASSERT_UNUSED(list, list->hasOwnCaches()); 1000 1001 NodeListsNodeData* data = rareData()->nodeLists(); 1002 ASSERT_UNUSED(list, list == data->m_nameNodeListCache.get(nodeName)); 1003 data->m_nameNodeListCache.remove(nodeName); 1004 } 1005 1006 void Node::removeCachedTagNodeList(TagNodeList* list, const QualifiedName& name) 1007 { 1008 ASSERT(rareData()); 1009 ASSERT(rareData()->nodeLists()); 1010 ASSERT_UNUSED(list, list->hasOwnCaches()); 1011 1012 NodeListsNodeData* data = rareData()->nodeLists(); 1013 ASSERT_UNUSED(list, list == data->m_tagNodeListCache.get(name)); 1014 data->m_tagNodeListCache.remove(name); 1015 } 1016 980 1017 Node *Node::traverseNextNode(const Node *stayWithin) const 981 1018 { … … 1608 1645 AtomicString localNameAtom = name; 1609 1646 1610 pair<NodeListsNodeData::TagCacheMap::iterator, bool> result = data->nodeLists()->m_tagNodeListCaches.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0); 1611 if (result.second) 1612 result.first->second = DynamicNodeList::Caches::create(); 1613 1614 return TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom, result.first->second.get()); 1647 pair<NodeListsNodeData::TagNodeListCache::iterator, bool> result = data->nodeLists()->m_tagNodeListCache.add(QualifiedName(nullAtom, localNameAtom, namespaceURI), 0); 1648 if (!result.second) 1649 return PassRefPtr<TagNodeList>(result.first->second); 1650 1651 RefPtr<TagNodeList> list = TagNodeList::create(this, namespaceURI.isEmpty() ? nullAtom : namespaceURI, localNameAtom); 1652 result.first->second = list.get(); 1653 return list.release(); 1615 1654 } 1616 1655 … … 1623 1662 } 1624 1663 1625 pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_nameNodeListCaches.add(elementName, 0); 1626 if (result.second) 1627 result.first->second = DynamicNodeList::Caches::create(); 1628 1629 return NameNodeList::create(this, elementName, result.first->second.get()); 1664 pair<NodeListsNodeData::NameNodeListCache::iterator, bool> result = data->nodeLists()->m_nameNodeListCache.add(elementName, 0); 1665 if (!result.second) 1666 return PassRefPtr<NodeList>(result.first->second); 1667 1668 RefPtr<NameNodeList> list = NameNodeList::create(this, elementName); 1669 result.first->second = list.get(); 1670 return list.release(); 1630 1671 } 1631 1672 … … 1638 1679 } 1639 1680 1640 pair<NodeListsNodeData::CacheMap::iterator, bool> result = data->nodeLists()->m_classNodeListCaches.add(classNames, 0); 1641 if (result.second) 1642 result.first->second = DynamicNodeList::Caches::create(); 1643 1644 return ClassNodeList::create(this, classNames, result.first->second.get()); 1681 pair<NodeListsNodeData::ClassNodeListCache::iterator, bool> result = data->nodeLists()->m_classNodeListCache.add(classNames, 0); 1682 if (!result.second) 1683 return PassRefPtr<NodeList>(result.first->second); 1684 1685 RefPtr<ClassNodeList> list = ClassNodeList::create(this, classNames); 1686 result.first->second = list.get(); 1687 return list.release(); 1645 1688 } 1646 1689 … … 2248 2291 { 2249 2292 m_childNodeListCaches->reset(); 2250 Tag CacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end();2251 for (Tag CacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it)2252 it->second-> reset();2293 TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end(); 2294 for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) 2295 it->second->invalidateCache(); 2253 2296 invalidateCachesThatDependOnAttributes(); 2254 2297 } … … 2256 2299 void NodeListsNodeData::invalidateCachesThatDependOnAttributes() 2257 2300 { 2258 C acheMap::iterator classCachesEnd = m_classNodeListCaches.end();2259 for (C acheMap::iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it)2260 it->second-> reset();2261 2262 CacheMap::iterator nameCachesEnd = m_nameNodeListCaches.end();2263 for ( CacheMap::iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it)2264 it->second-> reset();2301 ClassNodeListCache::iterator classCacheEnd = m_classNodeListCache.end(); 2302 for (ClassNodeListCache::iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it) 2303 it->second->invalidateCache(); 2304 2305 NameNodeListCache::iterator nameCacheEnd = m_nameNodeListCache.end(); 2306 for (NameNodeListCache::iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it) 2307 it->second->invalidateCache(); 2265 2308 } 2266 2309 … … 2273 2316 return false; 2274 2317 2275 Tag CacheMap::const_iterator tagCachesEnd = m_tagNodeListCaches.end();2276 for (Tag CacheMap::const_iterator it = m_tagNodeListCaches.begin(); it != tagCachesEnd; ++it) {2318 TagNodeListCache::const_iterator tagCacheEnd = m_tagNodeListCache.end(); 2319 for (TagNodeListCache::const_iterator it = m_tagNodeListCache.begin(); it != tagCacheEnd; ++it) { 2277 2320 if (it->second->refCount()) 2278 2321 return false; 2279 2322 } 2280 2323 2281 C acheMap::const_iterator classCachesEnd = m_classNodeListCaches.end();2282 for (C acheMap::const_iterator it = m_classNodeListCaches.begin(); it != classCachesEnd; ++it) {2324 ClassNodeListCache::const_iterator classCacheEnd = m_classNodeListCache.end(); 2325 for (ClassNodeListCache::const_iterator it = m_classNodeListCache.begin(); it != classCacheEnd; ++it) { 2283 2326 if (it->second->refCount()) 2284 2327 return false; 2285 2328 } 2286 2329 2287 CacheMap::const_iterator nameCachesEnd = m_nameNodeListCaches.end();2288 for ( CacheMap::const_iterator it = m_nameNodeListCaches.begin(); it != nameCachesEnd; ++it) {2330 NameNodeListCache::const_iterator nameCacheEnd = m_nameNodeListCache.end(); 2331 for (NameNodeListCache::const_iterator it = m_nameNodeListCache.begin(); it != nameCacheEnd; ++it) { 2289 2332 if (it->second->refCount()) 2290 2333 return false; … … 2512 2555 return ensureRareData()->ensureEventTargetData(); 2513 2556 } 2557 2558 #if USE(JSC) 2559 2560 template <class NodeListMap> 2561 void markNodeLists(const NodeListMap& map, JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) 2562 { 2563 for (typename NodeListMap::const_iterator it = map.begin(); it != map.end(); ++it) 2564 markDOMObjectWrapper(markStack, globalData, it->second); 2565 } 2566 2567 void Node::markCachedNodeListsSlow(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) 2568 { 2569 NodeListsNodeData* nodeLists = rareData()->nodeLists(); 2570 if (!nodeLists) 2571 return; 2572 2573 markNodeLists(nodeLists->m_classNodeListCache, markStack, globalData); 2574 markNodeLists(nodeLists->m_nameNodeListCache, markStack, globalData); 2575 markNodeLists(nodeLists->m_tagNodeListCache, markStack, globalData); 2576 } 2577 2578 #endif 2514 2579 2515 2580 void Node::handleLocalEvents(Event* event) -
trunk/WebCore/dom/Node.h
r58362 r58526 33 33 #include <wtf/ListHashSet.h> 34 34 35 #if USE(JSC) 36 namespace JSC { 37 38 class JSGlobalData; 39 class MarkStack; 40 41 } 42 #endif 43 35 44 namespace WebCore { 36 45 37 46 class AtomicString; 38 47 class Attribute; 48 class ClassNodeList; 39 49 class ContainerNode; 40 50 class Document; … … 49 59 class NSResolver; 50 60 class NamedNodeMap; 61 class NameNodeList; 51 62 class NodeList; 52 63 class NodeRareData; … … 62 73 class RenderStyle; 63 74 class StringBuilder; 75 class TagNodeList; 64 76 65 77 typedef int ExceptionCode; … … 503 515 void notifyNodeListsAttributeChanged(); 504 516 void notifyLocalNodeListsAttributeChanged(); 517 void removeCachedClassNodeList(ClassNodeList*, const String&); 518 void removeCachedNameNodeList(NameNodeList*, const String&); 519 void removeCachedTagNodeList(TagNodeList*, const QualifiedName&); 505 520 506 521 PassRefPtr<NodeList> getElementsByTagName(const String&); … … 565 580 virtual EventTargetData* ensureEventTargetData(); 566 581 582 #if USE(JSC) 583 void markCachedNodeLists(JSC::MarkStack& markStack, JSC::JSGlobalData& globalData) 584 { 585 // NodeLists may be present. If so, they need to be marked. 586 if (!hasRareData()) 587 return; 588 589 markCachedNodeListsSlow(markStack, globalData); 590 } 591 #endif 592 567 593 protected: 568 594 // CreateElementZeroRefCount is deprecated and can be removed once we convert all element … … 586 612 587 613 private: 614 #if USE(JSC) 615 void markCachedNodeListsSlow(JSC::MarkStack&, JSC::JSGlobalData&); 616 #endif 617 588 618 static bool initialRefCount(ConstructionType); 589 619 static bool isContainer(ConstructionType); -
trunk/WebCore/dom/NodeRareData.h
r50464 r58526 23 23 #define NodeRareData_h 24 24 25 #include "ClassNodeList.h" 25 26 #include "DynamicNodeList.h" 26 27 #include "EventListener.h" 28 #include "NameNodeList.h" 29 #include "QualifiedName.h" 27 30 #include "RegisteredEventListener.h" 28 31 #include "StringHash.h" 29 #include " QualifiedName.h"32 #include "TagNodeList.h" 30 33 #include <wtf/HashSet.h> 31 34 #include <wtf/PassOwnPtr.h> … … 40 43 RefPtr<DynamicNodeList::Caches> m_childNodeListCaches; 41 44 42 typedef HashMap<String, RefPtr<DynamicNodeList::Caches> > CacheMap; 43 CacheMap m_classNodeListCaches; 44 CacheMap m_nameNodeListCaches; 45 typedef HashMap<String, ClassNodeList*> ClassNodeListCache; 46 ClassNodeListCache m_classNodeListCache; 47 48 typedef HashMap<String, NameNodeList*> NameNodeListCache; 49 NameNodeListCache m_nameNodeListCache; 45 50 46 typedef HashMap<QualifiedName, RefPtr<DynamicNodeList::Caches> > TagCacheMap;47 Tag CacheMap m_tagNodeListCaches;51 typedef HashMap<QualifiedName, TagNodeList*> TagNodeListCache; 52 TagNodeListCache m_tagNodeListCache; 48 53 49 54 static PassOwnPtr<NodeListsNodeData> create() -
trunk/WebCore/dom/TagNodeList.cpp
r39563 r58526 30 30 namespace WebCore { 31 31 32 TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName , DynamicNodeList::Caches* caches)33 : DynamicNodeList(rootNode , caches)32 TagNodeList::TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) 33 : DynamicNodeList(rootNode) 34 34 , m_namespaceURI(namespaceURI) 35 35 , m_localName(localName) … … 37 37 ASSERT(m_namespaceURI.isNull() || !m_namespaceURI.isEmpty()); 38 38 } 39 40 TagNodeList::~TagNodeList() 41 { 42 m_rootNode->removeCachedTagNodeList(this, QualifiedName(nullAtom, m_localName, m_namespaceURI)); 43 } 39 44 40 45 bool TagNodeList::nodeMatches(Element* testNode) const -
trunk/WebCore/dom/TagNodeList.h
r39563 r58526 33 33 class TagNodeList : public DynamicNodeList { 34 34 public: 35 static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName , DynamicNodeList::Caches* caches)35 static PassRefPtr<TagNodeList> create(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName) 36 36 { 37 return adoptRef(new TagNodeList(rootNode, namespaceURI, localName , caches));37 return adoptRef(new TagNodeList(rootNode, namespaceURI, localName)); 38 38 } 39 39 40 virtual ~TagNodeList(); 41 40 42 private: 41 TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName , DynamicNodeList::Caches* caches);43 TagNodeList(PassRefPtr<Node> rootNode, const AtomicString& namespaceURI, const AtomicString& localName); 42 44 43 45 virtual bool nodeMatches(Element*) const;
Note: See TracChangeset
for help on using the changeset viewer.