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

Side by Side Diff: Source/core/html/CollectionIndexCache.h

Issue 164983007: Refactor CollectionIndexCache for clarity and performance (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
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
« no previous file with comments | « no previous file | no next file » | 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) 2013 Apple Inc. All rights reserved. 2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 * Copyright (C) 2014 Samsung Electronics. All rights reserved. 3 * Copyright (C) 2014 Samsung Electronics. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 return !cachedNodeIndex() && !nodeAt(collection, 1); 57 return !cachedNodeIndex() && !nodeAt(collection, 1);
58 return nodeAt(collection, 0) && !nodeAt(collection, 1); 58 return nodeAt(collection, 0) && !nodeAt(collection, 1);
59 } 59 }
60 60
61 unsigned nodeCount(const Collection&); 61 unsigned nodeCount(const Collection&);
62 NodeType* nodeAt(const Collection&, unsigned index); 62 NodeType* nodeAt(const Collection&, unsigned index);
63 63
64 void invalidate(); 64 void invalidate();
65 65
66 private: 66 private:
67 NodeType* nodeBeforeOrAfterCachedNode(const Collection&, unsigned index, con st ContainerNode& root); 67 NodeType* nodeBeforeCachedNode(const Collection&, unsigned index, const Cont ainerNode& root);
68 bool isLastNodeCloserThanLastOrCachedNode(unsigned index) const; 68 NodeType* nodeAfterCachedNode(const Collection&, unsigned index, const Conta inerNode& root);
69 bool isFirstNodeCloserThanCachedNode(unsigned index) const;
70 69
71 ALWAYS_INLINE NodeType* cachedNode() const { return m_currentNode; } 70 ALWAYS_INLINE NodeType* cachedNode() const { return m_currentNode; }
72 ALWAYS_INLINE unsigned cachedNodeIndex() const { ASSERT(cachedNode()); retur n m_cachedNodeIndex; } 71 ALWAYS_INLINE unsigned cachedNodeIndex() const { ASSERT(cachedNode()); retur n m_cachedNodeIndex; }
73 ALWAYS_INLINE void setCachedNode(NodeType* node, unsigned index) 72 ALWAYS_INLINE void setCachedNode(NodeType* node, unsigned index)
74 { 73 {
75 ASSERT(node); 74 ASSERT(node);
76 m_currentNode = node; 75 m_currentNode = node;
77 m_cachedNodeIndex = index; 76 m_cachedNodeIndex = index;
78 } 77 }
79 78
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 114
116 nodeAt(collection, UINT_MAX); 115 nodeAt(collection, UINT_MAX);
117 ASSERT(isCachedNodeCountValid()); 116 ASSERT(isCachedNodeCountValid());
118 117
119 return cachedNodeCount(); 118 return cachedNodeCount();
120 } 119 }
121 120
122 template <typename Collection, typename NodeType> 121 template <typename Collection, typename NodeType>
123 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAt(const Collec tion& collection, unsigned index) 122 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAt(const Collec tion& collection, unsigned index)
124 { 123 {
125 if (cachedNode() && cachedNodeIndex() == index) 124 if (isCachedNodeCountValid() && index >= cachedNodeCount())
126 return cachedNode();
127
128 if (isCachedNodeCountValid() && cachedNodeCount() <= index)
129 return 0; 125 return 0;
130 126
131 ContainerNode& root = collection.rootNode(); 127 ContainerNode& root = collection.rootNode();
132 if (isCachedNodeCountValid() && collection.canTraverseBackward() && isLastNo deCloserThanLastOrCachedNode(index)) { 128 if (cachedNode()) {
133 NodeType* lastNode = collection.itemBefore(0); 129 if (index > cachedNodeIndex())
134 ASSERT(lastNode); 130 return nodeAfterCachedNode(collection, index, root);
135 setCachedNode(lastNode, cachedNodeCount() - 1); 131 if (index < cachedNodeIndex())
136 } else if (!cachedNode() || isFirstNodeCloserThanCachedNode(index) || (!coll ection.canTraverseBackward() && index < cachedNodeIndex())) { 132 return nodeBeforeCachedNode(collection, index, root);
137 NodeType* firstNode = collection.traverseToFirstElement(root); 133 return cachedNode();
138 if (!firstNode) {
139 setCachedNodeCount(0);
140 return 0;
141 }
142 setCachedNode(firstNode, 0);
143 ASSERT(!cachedNodeIndex());
144 } 134 }
145 135
146 if (cachedNodeIndex() == index) 136 // No valid cache yet, let's find the first matching element.
147 return cachedNode(); 137 ASSERT(!isCachedNodeCountValid());
148 138 NodeType* firstNode = collection.traverseToFirstElement(root);
149 return nodeBeforeOrAfterCachedNode(collection, index, root); 139 if (!firstNode) {
140 // The collection is empty.
141 setCachedNodeCount(0);
142 return 0;
143 }
144 setCachedNode(firstNode, 0);
145 return index ? nodeAfterCachedNode(collection, index, root) : firstNode;
150 } 146 }
151 147
152 template <typename Collection, typename NodeType> 148 template <typename Collection, typename NodeType>
153 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeBeforeOrAfterCa chedNode(const Collection& collection, unsigned index, const ContainerNode &root ) 149 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeBeforeCachedNod e(const Collection& collection, unsigned index, const ContainerNode& root)
154 { 150 {
151 ASSERT(cachedNode()); // Cache should be valid.
155 unsigned currentIndex = cachedNodeIndex(); 152 unsigned currentIndex = cachedNodeIndex();
156 NodeType* currentNode = cachedNode(); 153 ASSERT(currentIndex > index);
157 ASSERT(currentNode);
158 ASSERT(currentIndex != index);
159 154
160 if (index < cachedNodeIndex()) { 155 // Determine if we should traverse from the beginning of the collection inst ead of the cached node.
161 ASSERT(collection.canTraverseBackward()); 156 bool firstIsCloser = index < currentIndex - index;
162 while ((currentNode = collection.itemBefore(currentNode))) { 157 if (firstIsCloser || !collection.canTraverseBackward()) {
163 ASSERT(currentIndex); 158 NodeType* firstNode = collection.traverseToFirstElement(root);
164 currentIndex--; 159 ASSERT(firstNode);
165 if (currentIndex == index) { 160 setCachedNode(firstNode, 0);
166 setCachedNode(currentNode, currentIndex); 161 return index ? nodeAfterCachedNode(collection, index, root) : firstNode;
167 return currentNode;
168 }
169 }
170 ASSERT_NOT_REACHED();
171 return 0;
172 } 162 }
173 163
174 currentNode = collection.traverseForwardToOffset(index, *currentNode, curren tIndex, root); 164 // Backward traversal from the cached node to the requested index.
165 NodeType* currentNode = cachedNode();
166 ASSERT(collection.canTraverseBackward());
167 while ((currentNode = collection.itemBefore(currentNode))) {
168 ASSERT(currentIndex);
169 --currentIndex;
170 if (currentIndex == index) {
171 setCachedNode(currentNode, currentIndex);
172 return currentNode;
173 }
174 }
175 ASSERT_NOT_REACHED();
176 return 0;
177 }
178
179 template <typename Collection, typename NodeType>
180 inline NodeType* CollectionIndexCache<Collection, NodeType>::nodeAfterCachedNode (const Collection& collection, unsigned index, const ContainerNode& root)
181 {
182 ASSERT(cachedNode()); // Cache should be valid.
183 unsigned currentIndex = cachedNodeIndex();
184 ASSERT(currentIndex < index);
185
186 // Determine if we should traverse from the end of the collection instead of the cached node.
187 bool lastIsCloser = isCachedNodeCountValid() && cachedNodeCount() - index < index - currentIndex;
188 if (lastIsCloser && collection.canTraverseBackward()) {
189 NodeType* lastItem = collection.itemBefore(0);
190 ASSERT(lastItem);
191 setCachedNode(lastItem, cachedNodeCount() - 1);
192 if (index < cachedNodeCount() - 1)
193 return nodeBeforeCachedNode(collection, index, root);
194 return lastItem;
195 }
196
197 // Forward traversal from the cached node to the requested index.
198 NodeType* currentNode = collection.traverseForwardToOffset(index, *cachedNod e(), currentIndex, root);
175 if (!currentNode) { 199 if (!currentNode) {
176 // Did not find the node. On plus side, we now know the length. 200 // Did not find the node. On plus side, we now know the length.
177 setCachedNodeCount(currentIndex + 1); 201 setCachedNodeCount(currentIndex + 1);
178 return 0; 202 return 0;
179 } 203 }
180 setCachedNode(currentNode, currentIndex); 204 setCachedNode(currentNode, currentIndex);
181 return currentNode; 205 return currentNode;
182 } 206 }
183 207
184 template <typename Collection, typename NodeType>
185 ALWAYS_INLINE bool CollectionIndexCache<Collection, NodeType>::isLastNodeCloserT hanLastOrCachedNode(unsigned index) const
186 {
187 ASSERT(isCachedNodeCountValid());
188 unsigned distanceFromLastNode = cachedNodeCount() - index;
189 if (!cachedNode())
190 return distanceFromLastNode < index;
191
192 return cachedNodeIndex() < index && distanceFromLastNode < index - cachedNod eIndex();
193 }
194
195 template <typename Collection, typename NodeType>
196 ALWAYS_INLINE bool CollectionIndexCache<Collection, NodeType>::isFirstNodeCloser ThanCachedNode(unsigned index) const
197 {
198 if (cachedNodeIndex() < index)
199 return false;
200
201 unsigned distanceFromCachedNode = cachedNodeIndex() - index;
202 return index < distanceFromCachedNode;
203 }
204
205 } // namespace WebCore 208 } // namespace WebCore
206 209
207 #endif // CollectionIndexCache_h 210 #endif // CollectionIndexCache_h
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698