Changeset 158698 in webkit
- Timestamp:
- Nov 5, 2013, 3:45:43 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 1 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/Source/WebCore/ChangeLog ¶
r158697 r158698 1 2013-11-05 Antti Koivisto <antti@apple.com> 2 3 Factor index cache for NodeLists and HTMLCollections to a class 4 https://bugs.webkit.org/show_bug.cgi?id=123823 5 6 Reviewed by Ryosuke Niwa. 7 8 Implement index cache class that can used by NodeLists and HTMLCollections that currently 9 each have implementations of their own. 10 11 This patch also implements ChildNodeList and LiveNodeList using CollectionIndexCache. 12 HTMLCollection is will be transitioned later. 13 14 * GNUmakefile.list.am: 15 * WebCore.vcxproj/WebCore.vcxproj: 16 * WebCore.xcodeproj/project.pbxproj: 17 * dom/ChildNodeList.cpp: 18 (WebCore::ChildNodeList::ChildNodeList): 19 (WebCore::ChildNodeList::length): 20 (WebCore::ChildNodeList::item): 21 22 The client calls to cache to for indexed and size access. 23 24 (WebCore::ChildNodeList::collectionFirst): 25 (WebCore::ChildNodeList::collectionLast): 26 (WebCore::ChildNodeList::collectionTraverseForward): 27 (WebCore::ChildNodeList::collectionTraverseBackward): 28 29 Cache calls back to these as needed to do the actual traversal. 30 31 (WebCore::ChildNodeList::invalidateCache): 32 * dom/ChildNodeList.h: 33 * dom/CollectionIndexCache.h: Added. 34 35 Templated cache class itself. 36 37 (WebCore::::CollectionIndexCache): 38 (WebCore::::nodeCount): 39 (WebCore::::nodeBeforeCached): 40 (WebCore::::nodeAfterCached): 41 (WebCore::::nodeAt): 42 (WebCore::::invalidate): 43 * dom/LiveNodeList.cpp: 44 (WebCore::firstMatchingElement): 45 (WebCore::nextMatchingElement): 46 (WebCore::traverseMatchingElementsForward): 47 (WebCore::LiveNodeList::collectionFirst): 48 (WebCore::LiveNodeList::collectionLast): 49 (WebCore::LiveNodeList::collectionTraverseForward): 50 (WebCore::LiveNodeList::collectionTraverseBackward): 51 (WebCore::LiveNodeList::length): 52 (WebCore::LiveNodeList::item): 53 (WebCore::LiveNodeList::invalidateCache): 54 * dom/LiveNodeList.h: 55 (WebCore::LiveNodeList::LiveNodeList): 56 1 57 2013-11-05 Enrica Casucci <enrica@apple.com> 2 58 -
TabularUnified trunk/Source/WebCore/GNUmakefile.list.am ¶
r158656 r158698 2738 2738 Source/WebCore/dom/ClipboardEvent.h \ 2739 2739 Source/WebCore/dom/Clipboard.h \ 2740 Source/WebCore/dom/CollectionIndexCache.h \ 2740 2741 Source/WebCore/dom/Comment.cpp \ 2741 2742 Source/WebCore/dom/Comment.h \ -
TabularUnified trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj ¶
r158626 r158698 1 <?xml version="1.0" encoding="utf-8"?>1 <?xml version="1.0" encoding="utf-8"?> 2 2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 3 <ItemGroup Label="ProjectConfigurations"> … … 19841 19841 <ClInclude Include="..\dom\ClipboardAccessPolicy.h" /> 19842 19842 <ClInclude Include="..\dom\ClipboardEvent.h" /> 19843 <ClInclude Include="..\dom\CollectionIndexCache.h" /> 19843 19844 <ClInclude Include="..\dom\Comment.h" /> 19844 19845 <ClInclude Include="..\dom\CompositionEvent.h" /> -
TabularUnified trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj ¶
r158654 r158698 5690 5690 E1FF8F6D180DB5BE00132674 /* CryptoAlgorithmRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */; }; 5691 5691 E401C27517CE53EC00C41A35 /* ElementIteratorAssertions.h in Headers */ = {isa = PBXBuildFile; fileRef = E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */; }; 5692 E425A49A18292B840020CFCF /* CollectionIndexCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E425A49918292B840020CFCF /* CollectionIndexCache.h */; }; 5692 5693 E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5693 5694 E43105B816750F0C00DB2FB8 /* NodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */; }; … … 12750 12751 E41EA038119836DB00710BC5 /* CSSPropertyNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyNames.cpp; sourceTree = "<group>"; }; 12751 12752 E41EA0391198374900710BC5 /* CSSValueKeywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSValueKeywords.cpp; sourceTree = "<group>"; }; 12753 E425A49918292B840020CFCF /* CollectionIndexCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionIndexCache.h; sourceTree = "<group>"; }; 12752 12754 E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadPriority.h; sourceTree = "<group>"; }; 12753 12755 E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodeTraversal.cpp; sourceTree = "<group>"; }; … … 21058 21060 85031B2A0A44EFC700F992E0 /* ClipboardEvent.h */, 21059 21061 2D90660C0665D937006B6F1A /* ClipboardMac.mm */, 21062 E425A49918292B840020CFCF /* CollectionIndexCache.h */, 21060 21063 6550B697099DF0270090D781 /* Comment.cpp */, 21061 21064 6550B698099DF0270090D781 /* Comment.h */, … … 23307 23310 A80E7B0E0A19D606007FB8C5 /* JSHTMLStyleElement.h in Headers */, 23308 23311 BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */, 23312 E425A49A18292B840020CFCF /* CollectionIndexCache.h in Headers */, 23309 23313 BC06EDE40BFD6D0D00856E9D /* JSHTMLTableCellElement.h in Headers */, 23310 23314 BC06ED9E0BFD660600856E9D /* JSHTMLTableColElement.h in Headers */, -
TabularUnified trunk/Source/WebCore/dom/ChildNodeList.cpp ¶
r158569 r158698 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2007, 2008 Apple Inc. All rights reserved.5 * Copyright (C) 2004, 2007, 2008, 2013 Apple Inc. All rights reserved. 6 6 * 7 7 * This library is free software; you can redistribute it and/or … … 36 36 ChildNodeList::ChildNodeList(ContainerNode& parent) 37 37 : m_parent(parent) 38 , m_cachedLength(0)39 , m_cachedLengthValid(false)40 , m_cachedCurrentPosition(0)41 , m_cachedCurrentNode(nullptr)42 38 { 43 39 } … … 50 46 unsigned ChildNodeList::length() const 51 47 { 52 if (!m_cachedLengthValid) { 53 m_cachedLength = m_parent->childNodeCount(); 54 m_cachedLengthValid = true; 55 } 56 return m_cachedLength; 57 } 58 59 static Node* childFromFirst(const ContainerNode& parent, unsigned delta) 60 { 61 Node* child = parent.firstChild(); 62 for (; delta && child; --delta) 63 child = child->nextSibling(); 64 return child; 65 } 66 67 static Node* childFromLast(const ContainerNode& parent, unsigned delta) 68 { 69 Node* child = parent.lastChild(); 70 for (; delta; --delta) 71 child = child->previousSibling(); 72 ASSERT(child); 73 return child; 74 } 75 76 Node* ChildNodeList::nodeBeforeCached(unsigned index) const 77 { 78 ASSERT(m_cachedCurrentNode); 79 ASSERT(index < m_cachedCurrentPosition); 80 if (index < m_cachedCurrentPosition - index) { 81 m_cachedCurrentNode = childFromFirst(m_parent.get(), index); 82 m_cachedCurrentPosition = index; 83 return m_cachedCurrentNode; 84 } 85 while (m_cachedCurrentNode && m_cachedCurrentPosition > index) { 86 m_cachedCurrentNode = m_cachedCurrentNode->previousSibling(); 87 --m_cachedCurrentPosition; 88 } 89 return m_cachedCurrentNode; 90 } 91 92 Node* ChildNodeList::nodeAfterCached(unsigned index) const 93 { 94 ASSERT(m_cachedCurrentNode); 95 ASSERT(index > m_cachedCurrentPosition); 96 ASSERT(!m_cachedLengthValid || index < m_cachedLength); 97 if (m_cachedLengthValid && m_cachedLength - index < index - m_cachedCurrentPosition) { 98 m_cachedCurrentNode = childFromLast(m_parent.get(), m_cachedLength - index - 1); 99 m_cachedCurrentPosition = index; 100 return m_cachedCurrentNode; 101 } 102 while (m_cachedCurrentNode && m_cachedCurrentPosition < index) { 103 m_cachedCurrentNode = m_cachedCurrentNode->nextSibling(); 104 ++m_cachedCurrentPosition; 105 } 106 if (!m_cachedCurrentNode && !m_cachedLengthValid) { 107 m_cachedLength = m_cachedCurrentPosition; 108 m_cachedLengthValid = true; 109 } 110 return m_cachedCurrentNode; 48 return m_indexCache.nodeCount(*this); 111 49 } 112 50 113 51 Node* ChildNodeList::item(unsigned index) const 114 52 { 115 if (m_cachedLengthValid && index >= m_cachedLength) 116 return nullptr; 117 if (m_cachedCurrentNode) { 118 if (index > m_cachedCurrentPosition) 119 return nodeAfterCached(index); 120 if (index < m_cachedCurrentPosition) 121 return nodeBeforeCached(index); 122 return m_cachedCurrentNode; 53 return m_indexCache.nodeAt(*this, index); 54 } 55 56 Node* ChildNodeList::collectionFirst() const 57 { 58 return m_parent->firstChild(); 59 } 60 61 Node* ChildNodeList::collectionLast() const 62 { 63 return m_parent->lastChild(); 64 } 65 66 Node* ChildNodeList::collectionTraverseForward(Node& current, unsigned count, unsigned& traversedCount) const 67 { 68 ASSERT(count); 69 Node* child = ¤t; 70 for (traversedCount = 0; traversedCount < count; ++traversedCount) { 71 child = child->nextSibling(); 72 if (!child) 73 return nullptr; 123 74 } 124 if (m_cachedLengthValid && m_cachedLength - index < index) 125 m_cachedCurrentNode = childFromLast(m_parent.get(), m_cachedLength - index - 1); 126 else 127 m_cachedCurrentNode = childFromFirst(m_parent.get(), index); 128 m_cachedCurrentPosition = index; 129 return m_cachedCurrentNode; 75 return child; 76 } 77 78 Node* ChildNodeList::collectionTraverseBackward(Node& current, unsigned count) const 79 { 80 ASSERT(count); 81 Node* child = ¤t; 82 for (; count && child ; --count) 83 child = child->previousSibling(); 84 return child; 130 85 } 131 86 … … 151 106 void ChildNodeList::invalidateCache() 152 107 { 153 m_cachedCurrentNode = nullptr; 154 m_cachedLengthValid = false; 108 m_indexCache.invalidate(); 155 109 } 156 110 -
TabularUnified trunk/Source/WebCore/dom/ChildNodeList.h ¶
r158536 r158698 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2007 Apple Inc. All rights reserved.5 * Copyright (C) 2004, 2007, 2013 Apple Inc. All rights reserved. 6 6 * 7 7 * This library is free software; you can redistribute it and/or … … 25 25 #define ChildNodeList_h 26 26 27 #include "CollectionIndexCache.h" 27 28 #include "NodeList.h" 28 29 #include <wtf/Ref.h> … … 68 69 void invalidateCache(); 69 70 71 // For CollectionIndexCache 72 Node* collectionFirst() const; 73 Node* collectionLast() const; 74 Node* collectionTraverseForward(Node&, unsigned count, unsigned& traversedCount) const; 75 Node* collectionTraverseBackward(Node&, unsigned count) const; 76 70 77 private: 71 78 explicit ChildNodeList(ContainerNode& parent); … … 77 84 virtual bool isChildNodeList() const OVERRIDE { return true; } 78 85 79 Node* nodeBeforeCached(unsigned) const;80 Node* nodeAfterCached(unsigned) const;81 82 86 Ref<ContainerNode> m_parent; 83 mutable unsigned m_cachedLength : 31; 84 mutable unsigned m_cachedLengthValid : 1; 85 mutable unsigned m_cachedCurrentPosition; 86 mutable Node* m_cachedCurrentNode; 87 mutable CollectionIndexCache<ChildNodeList, Node> m_indexCache; 87 88 }; 88 89 -
TabularUnified trunk/Source/WebCore/dom/LiveNodeList.cpp ¶
r158663 r158698 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 4 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2004, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.5 * Copyright (C) 2004, 2006, 2007, 2008, 2010, 2013 Apple Inc. All rights reserved. 6 6 * 7 7 * This library is free software; you can redistribute it and/or … … 68 68 } 69 69 70 ALWAYS_INLINE Element* LiveNodeList::itemBefore(Element* previous) const 70 template <class NodeListType> 71 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode& root) 71 72 { 72 Element* current; 73 if (LIKELY(!!previous)) // Without this LIKELY, length() and item() can be 10% slower. 74 current = ElementTraversal::previous(previous, &rootNode()); 75 else 76 current = ElementTraversal::lastWithin(&rootNode()); 77 78 return iterateForPreviousElement(current); 79 } 80 81 template <class NodeListType> 82 inline Element* firstMatchingElement(const NodeListType* nodeList, ContainerNode* root) 83 { 84 Element* element = ElementTraversal::firstWithin(root); 73 Element* element = ElementTraversal::firstWithin(&root); 85 74 while (element && !isMatchingElement(nodeList, element)) 86 element = ElementTraversal::next(element, root);75 element = ElementTraversal::next(element, &root); 87 76 return element; 88 77 } 89 78 90 79 template <class NodeListType> 91 inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode *root)80 inline Element* nextMatchingElement(const NodeListType* nodeList, Element* current, ContainerNode& root) 92 81 { 93 82 do { 94 current = ElementTraversal::next(current, root);83 current = ElementTraversal::next(current, &root); 95 84 } while (current && !isMatchingElement(nodeList, current)); 96 85 return current; … … 98 87 99 88 template <class NodeListType> 100 inline Element* traverseMatchingElementsForward ToOffset(const NodeListType* nodeList, unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode*root)89 inline Element* traverseMatchingElementsForward(const NodeListType* nodeList, Element& current, unsigned count, unsigned& traversedCount, ContainerNode& root) 101 90 { 102 ASSERT_WITH_SECURITY_IMPLICATION(currentOffset < offset); 103 while ((currentElement = nextMatchingElement(nodeList, currentElement, root))) { 104 if (++currentOffset == offset) 105 return currentElement; 91 Element* element = ¤t; 92 for (traversedCount = 0; traversedCount < count; ++traversedCount) { 93 element = nextMatchingElement(nodeList, element, root); 94 if (!element) 95 return nullptr; 106 96 } 107 return 0;97 return element; 108 98 } 109 99 110 inline Element* LiveNodeList::traverseLiveNodeListFirstElement(ContainerNode* root) const100 Element* LiveNodeList::collectionFirst() const 111 101 { 102 auto& root = rootNode(); 112 103 if (type() == HTMLTagNodeListType) 113 104 return firstMatchingElement(static_cast<const HTMLTagNodeList*>(this), root); … … 117 108 } 118 109 119 inline Element* LiveNodeList::traverseLiveNodeListForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) const110 Element* LiveNodeList::collectionLast() const 120 111 { 121 if (type() == HTMLTagNodeListType) 122 return traverseMatchingElementsForwardToOffset(static_cast<const HTMLTagNodeList*>(this), offset, currentElement, currentOffset, root); 123 if (type() == ClassNodeListType) 124 return traverseMatchingElementsForwardToOffset(static_cast<const ClassNodeList*>(this), offset, currentElement, currentOffset, root); 125 return traverseMatchingElementsForwardToOffset(static_cast<const LiveNodeList*>(this), offset, currentElement, currentOffset, root); 112 // FIXME: This should be optimized similarly to the forward case. 113 return iterateForPreviousElement(ElementTraversal::lastWithin(&rootNode())); 126 114 } 127 115 128 bool ALWAYS_INLINE LiveNodeList::isLastItemCloserThanLastOrCachedItem(unsigned offset) const116 Element* LiveNodeList::collectionTraverseForward(Element& current, unsigned count, unsigned& traversedCount) const 129 117 { 130 ASSERT(isLengthCacheValid()); 131 unsigned distanceFromLastItem = cachedLength() - offset; 132 if (!isElementCacheValid()) 133 return distanceFromLastItem < offset; 118 auto& root = rootNode(); 119 if (type() == HTMLTagNodeListType) 120 return traverseMatchingElementsForward(static_cast<const HTMLTagNodeList*>(this), current, count, traversedCount, root); 121 if (type() == ClassNodeListType) 122 return traverseMatchingElementsForward(static_cast<const ClassNodeList*>(this), current, count, traversedCount, root); 123 return traverseMatchingElementsForward(static_cast<const LiveNodeList*>(this), current, count, traversedCount, root); 124 } 134 125 135 return cachedElementOffset() < offset && distanceFromLastItem < offset - cachedElementOffset(); 136 } 137 138 bool ALWAYS_INLINE LiveNodeList::isFirstItemCloserThanCachedItem(unsigned offset) const 126 Element* LiveNodeList::collectionTraverseBackward(Element& current, unsigned count) const 139 127 { 140 ASSERT(isElementCacheValid());141 if (cachedElementOffset() < offset)142 return false;143 144 unsigned distanceFromCachedItem = cachedElementOffset() - offset;145 return offset < distanceFromCachedItem;128 // FIXME: This should be optimized similarly to the forward case. 129 auto& root = rootNode(); 130 Element* element = ¤t; 131 for (; count && element ; --count) 132 element = iterateForPreviousElement(ElementTraversal::previous(element, &root)); 133 return element; 146 134 } 147 135 148 136 unsigned LiveNodeList::length() const 149 137 { 150 if (isLengthCacheValid()) 151 return cachedLength(); 152 153 item(UINT_MAX); 154 ASSERT(isLengthCacheValid()); 155 156 return cachedLength(); 138 return m_indexCache.nodeCount(*this); 157 139 } 158 140 159 141 Node* LiveNodeList::item(unsigned offset) const 160 142 { 161 if (isElementCacheValid() && cachedElementOffset() == offset) 162 return cachedElement(); 163 164 if (isLengthCacheValid() && cachedLength() <= offset) 165 return 0; 166 167 ContainerNode& root = rootNode(); 168 169 if (isLengthCacheValid() && isLastItemCloserThanLastOrCachedItem(offset)) { 170 Element* lastItem = itemBefore(0); 171 ASSERT(lastItem); 172 setCachedElement(*lastItem, cachedLength() - 1); 173 } else if (!isElementCacheValid() || isFirstItemCloserThanCachedItem(offset)) { 174 Element* firstItem = traverseLiveNodeListFirstElement(&root); 175 if (!firstItem) { 176 setLengthCache(0); 177 return 0; 178 } 179 setCachedElement(*firstItem, 0); 180 ASSERT(!cachedElementOffset()); 181 } 182 183 if (cachedElementOffset() == offset) 184 return cachedElement(); 185 186 return elementBeforeOrAfterCachedElement(offset, &root); 187 } 188 189 inline Element* LiveNodeList::elementBeforeOrAfterCachedElement(unsigned offset, ContainerNode* root) const 190 { 191 unsigned currentOffset = cachedElementOffset(); 192 Element* currentItem = cachedElement(); 193 ASSERT(currentItem); 194 ASSERT(currentOffset != offset); 195 196 if (offset < cachedElementOffset()) { 197 while ((currentItem = itemBefore(currentItem))) { 198 ASSERT(currentOffset); 199 currentOffset--; 200 if (currentOffset == offset) { 201 setCachedElement(*currentItem, currentOffset); 202 return currentItem; 203 } 204 } 205 ASSERT_NOT_REACHED(); 206 return 0; 207 } 208 209 currentItem = traverseLiveNodeListForwardToOffset(offset, currentItem, currentOffset, root); 210 211 if (!currentItem) { 212 // Did not find the item. On plus side, we now know the length. 213 setLengthCache(currentOffset + 1); 214 return 0; 215 } 216 setCachedElement(*currentItem, currentOffset); 217 return currentItem; 143 return m_indexCache.nodeAt(*this, offset); 218 144 } 219 145 220 146 void LiveNodeList::invalidateCache() const 221 147 { 222 m_cachedElement = nullptr; 223 m_isLengthCacheValid = false; 224 m_isElementCacheValid = false; 148 m_indexCache.invalidate(); 225 149 } 226 150 -
TabularUnified trunk/Source/WebCore/dom/LiveNodeList.h ¶
r158665 r158698 3 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 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, 2013 Apple Inc. All rights reserved. 6 6 * 7 7 * This library is free software; you can redistribute it and/or … … 25 25 #define LiveNodeList_h 26 26 27 #include "CollectionIndexCache.h" 27 28 #include "CollectionType.h" 28 29 #include "Document.h" … … 56 57 LiveNodeList(ContainerNode& ownerNode, Type type, NodeListInvalidationType invalidationType, NodeListRootType rootType = NodeListIsRootedAtNode) 57 58 : m_ownerNode(ownerNode) 58 , m_cachedElement(nullptr)59 , m_isLengthCacheValid(false)60 , m_isElementCacheValid(false)61 59 , m_rootType(rootType) 62 60 , m_invalidationType(invalidationType) … … 92 90 void invalidateCache() const; 93 91 92 // For CollectionIndexCache 93 Element* collectionFirst() const; 94 Element* collectionLast() const; 95 Element* collectionTraverseForward(Element&, unsigned count, unsigned& traversedCount) const; 96 Element* collectionTraverseBackward(Element&, unsigned count) const; 97 94 98 protected: 95 99 Document& document() const { return m_ownerNode->document(); } 96 100 ContainerNode& rootNode() const; 97 98 ALWAYS_INLINE bool isElementCacheValid() const { return m_isElementCacheValid; }99 ALWAYS_INLINE Element* cachedElement() const { return m_cachedElement; }100 ALWAYS_INLINE unsigned cachedElementOffset() const { return m_cachedElementOffset; }101 102 ALWAYS_INLINE bool isLengthCacheValid() const { return m_isLengthCacheValid; }103 ALWAYS_INLINE unsigned cachedLength() const { return m_cachedLength; }104 ALWAYS_INLINE void setLengthCache(unsigned length) const105 {106 m_cachedLength = length;107 m_isLengthCacheValid = true;108 }109 ALWAYS_INLINE void setCachedElement(Element& element, unsigned offset) const110 {111 m_cachedElement = &element;112 m_cachedElementOffset = offset;113 m_isElementCacheValid = true;114 }115 101 116 102 ALWAYS_INLINE NodeListRootType rootType() const { return static_cast<NodeListRootType>(m_rootType); } … … 119 105 virtual bool isLiveNodeList() const OVERRIDE { return true; } 120 106 121 Element* elementBeforeOrAfterCachedElement(unsigned offset, ContainerNode* root) const;122 Element* traverseLiveNodeListFirstElement(ContainerNode* root) const;123 Element* traverseLiveNodeListForwardToOffset(unsigned offset, Element* currentElement, unsigned& currentOffset, ContainerNode* root) const;124 bool isLastItemCloserThanLastOrCachedItem(unsigned offset) const;125 bool isFirstItemCloserThanCachedItem(unsigned offset) const;126 107 Element* iterateForPreviousElement(Element* current) const; 127 Element* itemBefore(Element* previousItem) const;128 108 129 109 Ref<ContainerNode> m_ownerNode; 130 mutable Element* m_cachedElement; 131 mutable unsigned m_cachedLength; 132 mutable unsigned m_cachedElementOffset; 133 mutable unsigned m_isLengthCacheValid : 1; 134 mutable unsigned m_isElementCacheValid : 1; 110 111 mutable CollectionIndexCache<LiveNodeList, Element> m_indexCache; 112 135 113 const unsigned m_rootType : 2; 136 114 const unsigned m_invalidationType : 4;
Note:
See TracChangeset
for help on using the changeset viewer.