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: 54 ptrdiff_t allocationSize() const { return m_cachedList.capacity() * sizeof(NodeType*); } 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> 65 CollectionItemsCache<Collection, NodeType>::CollectionItemsCache() 66 : m_listValid(false) 67 { 68 } 69 70 template <typename Collection, typename NodeType> 71 CollectionItemsCache<Collection, NodeType>::~CollectionItemsCache() 72 { 73 if (ptrdiff_t diff = allocationSize()) 74 reportExtraMemoryCostForCollectionItemsCache(-diff); 75 } 76 77 template <typename Collection, typename NodeType> 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> 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> 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