Home | History | Annotate | Download | only in html
      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