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 39namespace blink { 40 41template <typename Collection, typename NodeType> 42class CollectionItemsCache : public CollectionIndexCache<Collection, NodeType> { 43 typedef CollectionIndexCache<Collection, NodeType> Base; 44 45public: 46 CollectionItemsCache(); 47 ~CollectionItemsCache(); 48 49 unsigned nodeCount(const Collection&); 50 NodeType* nodeAt(const Collection&, unsigned index); 51 void invalidate(); 52 53private: 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 64template <typename Collection, typename NodeType> 65CollectionItemsCache<Collection, NodeType>::CollectionItemsCache() 66 : m_listValid(false) 67{ 68} 69 70template <typename Collection, typename NodeType> 71CollectionItemsCache<Collection, NodeType>::~CollectionItemsCache() 72{ 73 if (ptrdiff_t diff = allocationSize()) 74 reportExtraMemoryCostForCollectionItemsCache(-diff); 75} 76 77template <typename Collection, typename NodeType> 78void CollectionItemsCache<Collection, NodeType>::invalidate() 79{ 80 Base::invalidate(); 81 if (m_listValid) { 82 m_cachedList.shrink(0); 83 m_listValid = false; 84 } 85} 86 87template <class Collection, class NodeType> 88unsigned 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 108template <typename Collection, typename NodeType> 109inline 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