• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012,2013 Google Inc. All rights reserved.
3  * Copyright (C) 2014 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef CollectionItemsCache_h
33 #define CollectionItemsCache_h
34 
35 #include "core/html/CollectionIndexCache.h"
36 #include "wtf/Vector.h"
37 #include <v8.h>
38 
39 namespace blink {
40 
41 template <typename Collection, typename NodeType>
42 class CollectionItemsCache : public CollectionIndexCache<Collection, NodeType> {
43     typedef CollectionIndexCache<Collection, NodeType> Base;
44 
45 public:
46     CollectionItemsCache();
47     ~CollectionItemsCache();
48 
49     unsigned nodeCount(const Collection&);
50     NodeType* nodeAt(const Collection&, unsigned index);
51     void invalidate();
52 
53 private:
allocationSize()54     ptrdiff_t allocationSize() const { return m_cachedList.capacity() * sizeof(NodeType*); }
reportExtraMemoryCostForCollectionItemsCache(ptrdiff_t diff)55     static void reportExtraMemoryCostForCollectionItemsCache(ptrdiff_t diff)
56     {
57         v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(diff);
58     }
59 
60     bool m_listValid;
61     Vector<NodeType*> m_cachedList;
62 };
63 
64 template <typename Collection, typename NodeType>
CollectionItemsCache()65 CollectionItemsCache<Collection, NodeType>::CollectionItemsCache()
66     : m_listValid(false)
67 {
68 }
69 
70 template <typename Collection, typename NodeType>
~CollectionItemsCache()71 CollectionItemsCache<Collection, NodeType>::~CollectionItemsCache()
72 {
73     if (ptrdiff_t diff = allocationSize())
74         reportExtraMemoryCostForCollectionItemsCache(-diff);
75 }
76 
77 template <typename Collection, typename NodeType>
invalidate()78 void CollectionItemsCache<Collection, NodeType>::invalidate()
79 {
80     Base::invalidate();
81     if (m_listValid) {
82         m_cachedList.shrink(0);
83         m_listValid = false;
84     }
85 }
86 
87 template <class Collection, class NodeType>
nodeCount(const Collection & collection)88 unsigned CollectionItemsCache<Collection, NodeType>::nodeCount(const Collection& collection)
89 {
90     if (this->isCachedNodeCountValid())
91         return this->cachedNodeCount();
92 
93     NodeType* currentNode = collection.traverseToFirst();
94     unsigned currentIndex = 0;
95     ptrdiff_t oldCapacity = allocationSize();
96     while (currentNode) {
97         m_cachedList.append(currentNode);
98         currentNode = collection.traverseForwardToOffset(currentIndex + 1, *currentNode, currentIndex);
99     }
100     if (ptrdiff_t diff = allocationSize() - oldCapacity)
101         reportExtraMemoryCostForCollectionItemsCache(diff);
102 
103     this->setCachedNodeCount(m_cachedList.size());
104     m_listValid = true;
105     return this->cachedNodeCount();
106 }
107 
108 template <typename Collection, typename NodeType>
nodeAt(const Collection & collection,unsigned index)109 inline NodeType* CollectionItemsCache<Collection, NodeType>::nodeAt(const Collection& collection, unsigned index)
110 {
111     if (m_listValid) {
112         ASSERT(this->isCachedNodeCountValid());
113         return index < this->cachedNodeCount() ? m_cachedList[index] : 0;
114     }
115     return Base::nodeAt(collection, index);
116 }
117 
118 } // namespace blink
119 
120 #endif // CollectionItemsCache_h
121