Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: Source/core/dom/LiveNodeList.h

Issue 134193005: Move caching out of LiveNodeListBase and into a new CollectionIndexCache class (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | Source/core/dom/LiveNodeList.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details. 15 * Library General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Library General Public License 17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to 18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA. 20 * Boston, MA 02110-1301, USA.
21 * 21 *
22 */ 22 */
23 23
24 #ifndef LiveNodeList_h 24 #ifndef LiveNodeList_h
25 #define LiveNodeList_h 25 #define LiveNodeList_h
26 26
27 #include "HTMLNames.h" 27 #include "HTMLNames.h"
28 #include "core/dom/Document.h" 28 #include "core/dom/Document.h"
29 #include "core/dom/NodeList.h" 29 #include "core/dom/NodeList.h"
30 #include "core/html/CollectionIndexCache.h"
30 #include "core/html/CollectionType.h" 31 #include "core/html/CollectionType.h"
31 #include "wtf/Forward.h" 32 #include "wtf/Forward.h"
32 #include "wtf/RefPtr.h" 33 #include "wtf/RefPtr.h"
33 34
34 namespace WebCore { 35 namespace WebCore {
35 36
36 class Element; 37 class Element;
37 38
38 enum NodeListRootType { 39 enum NodeListRootType {
39 NodeListIsRootedAtNode, 40 NodeListIsRootedAtNode,
40 NodeListIsRootedAtDocument, 41 NodeListIsRootedAtDocument,
41 NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr, 42 NodeListIsRootedAtDocumentIfOwnerHasItemrefAttr,
42 }; 43 };
43 44
44 class LiveNodeListBase { 45 class LiveNodeListBase {
45 public: 46 public:
46 enum ItemAfterOverrideType { 47 enum ItemAfterOverrideType {
47 OverridesItemAfter, 48 OverridesItemAfter,
48 DoesNotOverrideItemAfter, 49 DoesNotOverrideItemAfter,
49 }; 50 };
50 51
51 LiveNodeListBase(ContainerNode* ownerNode, NodeListRootType rootType, NodeLi stInvalidationType invalidationType, 52 LiveNodeListBase(ContainerNode* ownerNode, NodeListRootType rootType, NodeLi stInvalidationType invalidationType,
52 bool shouldOnlyIncludeDirectChildren, CollectionType collectionType, Ite mAfterOverrideType itemAfterOverrideType) 53 bool shouldOnlyIncludeDirectChildren, CollectionType collectionType, Ite mAfterOverrideType itemAfterOverrideType)
53 : m_ownerNode(ownerNode) 54 : m_ownerNode(ownerNode)
54 , m_cachedItem(0)
55 , m_isLengthCacheValid(false)
56 , m_rootType(rootType) 55 , m_rootType(rootType)
57 , m_invalidationType(invalidationType) 56 , m_invalidationType(invalidationType)
58 , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren) 57 , m_shouldOnlyIncludeDirectChildren(shouldOnlyIncludeDirectChildren)
59 , m_collectionType(collectionType) 58 , m_collectionType(collectionType)
60 , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter) 59 , m_overridesItemAfter(itemAfterOverrideType == OverridesItemAfter)
61 { 60 {
62 ASSERT(m_ownerNode); 61 ASSERT(m_ownerNode);
63 ASSERT(m_rootType == static_cast<unsigned>(rootType)); 62 ASSERT(m_rootType == static_cast<unsigned>(rootType));
64 ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType)); 63 ASSERT(m_invalidationType == static_cast<unsigned>(invalidationType));
65 ASSERT(m_collectionType == static_cast<unsigned>(collectionType)); 64 ASSERT(m_collectionType == static_cast<unsigned>(collectionType));
66 ASSERT(!m_overridesItemAfter || !isLiveNodeListType(collectionType)); 65 ASSERT(!m_overridesItemAfter || !isLiveNodeListType(collectionType));
67 66
68 if (collectionType != ChildNodeListType) 67 if (collectionType != ChildNodeListType)
69 document().registerNodeList(this); 68 document().registerNodeList(this);
70 } 69 }
71 70
72 virtual ~LiveNodeListBase() 71 virtual ~LiveNodeListBase()
73 { 72 {
74 if (type() != ChildNodeListType) 73 if (type() != ChildNodeListType)
75 document().unregisterNodeList(this); 74 document().unregisterNodeList(this);
76 } 75 }
77 76
78 unsigned length() const; 77 ContainerNode& rootNode() const;
79 Node* item(unsigned offset) const; 78 bool overridesItemAfter() const { return m_overridesItemAfter; }
79 Node* itemBefore(const Node* previousItem) const;
80 80
81 ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type( )); } 81 ALWAYS_INLINE bool hasIdNameCache() const { return !isLiveNodeListType(type( )); }
82 ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeLis tIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemref Attr; } 82 ALWAYS_INLINE bool isRootedAtDocument() const { return m_rootType == NodeLis tIsRootedAtDocument || m_rootType == NodeListIsRootedAtDocumentIfOwnerHasItemref Attr; }
83 ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return sta tic_cast<NodeListInvalidationType>(m_invalidationType); } 83 ALWAYS_INLINE NodeListInvalidationType invalidationType() const { return sta tic_cast<NodeListInvalidationType>(m_invalidationType); }
84 ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionTyp e>(m_collectionType); } 84 ALWAYS_INLINE CollectionType type() const { return static_cast<CollectionTyp e>(m_collectionType); }
85 ContainerNode* ownerNode() const { return m_ownerNode.get(); } 85 ContainerNode* ownerNode() const { return m_ownerNode.get(); }
86 ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const 86 ALWAYS_INLINE void invalidateCache(const QualifiedName* attrName) const
87 { 87 {
88 if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType( ), *attrName)) 88 if (!attrName || shouldInvalidateTypeOnAttributeChange(invalidationType( ), *attrName))
89 invalidateCache(); 89 invalidateCache();
90 else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrNam e == HTMLNames::nameAttr)) 90 else if (hasIdNameCache() && (*attrName == HTMLNames::idAttr || *attrNam e == HTMLNames::nameAttr))
91 invalidateIdNameCacheMaps(); 91 invalidateIdNameCacheMaps();
92 } 92 }
93 virtual void invalidateCache() const; 93 virtual void invalidateCache() const = 0;
94 94
95 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&); 95 static bool shouldInvalidateTypeOnAttributeChange(NodeListInvalidationType, const QualifiedName&);
96 96
97 protected: 97 protected:
98 Document& document() const { return m_ownerNode->document(); } 98 Document& document() const { return m_ownerNode->document(); }
99 ContainerNode& rootNode() const;
100 bool overridesItemAfter() const { return m_overridesItemAfter; }
101
102 ALWAYS_INLINE Node* cachedItem() const { return m_cachedItem; }
103 ALWAYS_INLINE unsigned cachedItemOffset() const { ASSERT(cachedItem()); retu rn m_cachedItemOffset; }
104
105 ALWAYS_INLINE bool isLengthCacheValid() const { return m_isLengthCacheValid; }
106 ALWAYS_INLINE unsigned cachedLength() const { return m_cachedLength; }
107 ALWAYS_INLINE void setLengthCache(unsigned length) const
108 {
109 m_cachedLength = length;
110 m_isLengthCacheValid = true;
111 }
112 ALWAYS_INLINE void setItemCache(Node* item, unsigned offset) const
113 {
114 ASSERT(item);
115 m_cachedItem = item;
116 m_cachedItemOffset = offset;
117 }
118 99
119 ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeLis tRootType>(m_rootType); } 100 ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeLis tRootType>(m_rootType); }
120 bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDir ectChildren; } 101 bool shouldOnlyIncludeDirectChildren() const { return m_shouldOnlyIncludeDir ectChildren; }
121 102
122 private: 103 private:
123 Node* itemBeforeOrAfterCachedItem(unsigned offset, const ContainerNode& root ) const;
124 bool isLastItemCloserThanLastOrCachedItem(unsigned offset) const;
125 bool isFirstItemCloserThanCachedItem(unsigned offset) const;
126 Node* iterateForPreviousNode(Node* current) const; 104 Node* iterateForPreviousNode(Node* current) const;
127 Node* itemBefore(const Node* previousItem) const;
128 void invalidateIdNameCacheMaps() const; 105 void invalidateIdNameCacheMaps() const;
129 106
130 RefPtr<ContainerNode> m_ownerNode; // Cannot be null. 107 RefPtr<ContainerNode> m_ownerNode; // Cannot be null.
131 mutable Node* m_cachedItem;
132 mutable unsigned m_cachedLength;
133 mutable unsigned m_cachedItemOffset;
134 mutable unsigned m_isLengthCacheValid : 1;
135 const unsigned m_rootType : 2; 108 const unsigned m_rootType : 2;
136 const unsigned m_invalidationType : 4; 109 const unsigned m_invalidationType : 4;
137 const unsigned m_shouldOnlyIncludeDirectChildren : 1; 110 const unsigned m_shouldOnlyIncludeDirectChildren : 1;
138 const unsigned m_collectionType : 5; 111 const unsigned m_collectionType : 5;
139 112
140 // From HTMLCollection 113 // From HTMLCollection
141 const unsigned m_overridesItemAfter : 1; 114 const unsigned m_overridesItemAfter : 1;
142 }; 115 };
143 116
144 ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL istInvalidationType type, const QualifiedName& attrName) 117 ALWAYS_INLINE bool LiveNodeListBase::shouldInvalidateTypeOnAttributeChange(NodeL istInvalidationType type, const QualifiedName& attrName)
(...skipping 21 matching lines...) Expand all
166 return false; 139 return false;
167 } 140 }
168 141
169 class LiveNodeList : public NodeList, public LiveNodeListBase { 142 class LiveNodeList : public NodeList, public LiveNodeListBase {
170 public: 143 public:
171 LiveNodeList(PassRefPtr<ContainerNode> ownerNode, CollectionType collectionT ype, NodeListInvalidationType invalidationType, NodeListRootType rootType = Node ListIsRootedAtNode) 144 LiveNodeList(PassRefPtr<ContainerNode> ownerNode, CollectionType collectionT ype, NodeListInvalidationType invalidationType, NodeListRootType rootType = Node ListIsRootedAtNode)
172 : LiveNodeListBase(ownerNode.get(), rootType, invalidationType, collecti onType == ChildNodeListType, 145 : LiveNodeListBase(ownerNode.get(), rootType, invalidationType, collecti onType == ChildNodeListType,
173 collectionType, DoesNotOverrideItemAfter) 146 collectionType, DoesNotOverrideItemAfter)
174 { } 147 { }
175 148
176 virtual unsigned length() const OVERRIDE FINAL { return LiveNodeListBase::le ngth(); } 149 virtual unsigned length() const OVERRIDE FINAL { return m_collectionIndexCac he.nodeCount(*this); }
177 virtual Node* item(unsigned offset) const OVERRIDE FINAL { return LiveNodeLi stBase::item(offset); } 150 virtual Node* item(unsigned offset) const OVERRIDE FINAL { return m_collecti onIndexCache.nodeAt(*this, offset); }
178 virtual Node* namedItem(const AtomicString&) const OVERRIDE FINAL; 151 virtual Node* namedItem(const AtomicString&) const OVERRIDE FINAL;
179 virtual bool nodeMatches(const Element&) const = 0; 152 virtual bool nodeMatches(const Element&) const = 0;
180 // Avoid ambiguity since both NodeList and LiveNodeListBase have an ownerNod e() method. 153 // Avoid ambiguity since both NodeList and LiveNodeListBase have an ownerNod e() method.
181 using LiveNodeListBase::ownerNode; 154 using LiveNodeListBase::ownerNode;
182 155
156 virtual void invalidateCache() const OVERRIDE FINAL;
157
158 // Collection IndexCache API.
183 Node* traverseToFirstElement(const ContainerNode& root) const; 159 Node* traverseToFirstElement(const ContainerNode& root) const;
184 Node* traverseForwardToOffset(unsigned offset, Node& currentNode, unsigned& currentOffset, const ContainerNode& root) const; 160 Node* traverseForwardToOffset(unsigned offset, Node& currentNode, unsigned& currentOffset, const ContainerNode& root) const;
185 161
186 private: 162 private:
187 virtual bool isLiveNodeList() const OVERRIDE FINAL { return true; } 163 virtual bool isLiveNodeList() const OVERRIDE FINAL { return true; }
164
165 mutable CollectionIndexCache<LiveNodeList> m_collectionIndexCache;
188 }; 166 };
189 167
190 } // namespace WebCore 168 } // namespace WebCore
191 169
192 #endif // LiveNodeList_h 170 #endif // LiveNodeList_h
OLDNEW
« no previous file with comments | « no previous file | Source/core/dom/LiveNodeList.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698