Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / graphics / ImageDecodingStore.cpp
blobf65428b4e552cf625aa4b3ce2bacb7b2acb0130d
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "config.h"
27 #include "platform/graphics/ImageDecodingStore.h"
29 #include "platform/TraceEvent.h"
30 #include "wtf/Threading.h"
32 namespace blink {
34 namespace {
36 static const size_t defaultMaxTotalSizeOfHeapEntries = 32 * 1024 * 1024;
38 } // namespace
40 ImageDecodingStore::ImageDecodingStore()
41 : m_heapLimitInBytes(defaultMaxTotalSizeOfHeapEntries)
42 , m_heapMemoryUsageInBytes(0)
46 ImageDecodingStore::~ImageDecodingStore()
48 #if ENABLE(ASSERT)
49 setCacheLimitInBytes(0);
50 ASSERT(!m_decoderCacheMap.size());
51 ASSERT(!m_orderedCacheList.size());
52 ASSERT(!m_decoderCacheKeyMap.size());
53 #endif
56 ImageDecodingStore& ImageDecodingStore::instance()
58 AtomicallyInitializedStaticReference(ImageDecodingStore, store, ImageDecodingStore::create().leakPtr());
59 return store;
62 bool ImageDecodingStore::lockDecoder(const ImageFrameGenerator* generator, const SkISize& scaledSize, ImageDecoder** decoder)
64 ASSERT(decoder);
66 MutexLocker lock(m_mutex);
67 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, scaledSize));
68 if (iter == m_decoderCacheMap.end())
69 return false;
71 DecoderCacheEntry* cacheEntry = iter->value.get();
73 // There can only be one user of a decoder at a time.
74 ASSERT(!cacheEntry->useCount());
75 cacheEntry->incrementUseCount();
76 *decoder = cacheEntry->cachedDecoder();
77 return true;
80 void ImageDecodingStore::unlockDecoder(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
82 MutexLocker lock(m_mutex);
83 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, decoder));
84 ASSERT_WITH_SECURITY_IMPLICATION(iter != m_decoderCacheMap.end());
86 CacheEntry* cacheEntry = iter->value.get();
87 cacheEntry->decrementUseCount();
89 // Put the entry to the end of list.
90 m_orderedCacheList.remove(cacheEntry);
91 m_orderedCacheList.append(cacheEntry);
94 void ImageDecodingStore::insertDecoder(const ImageFrameGenerator* generator, PassOwnPtr<ImageDecoder> decoder)
96 // Prune old cache entries to give space for the new one.
97 prune();
99 OwnPtr<DecoderCacheEntry> newCacheEntry = DecoderCacheEntry::create(generator, decoder);
101 MutexLocker lock(m_mutex);
102 ASSERT(!m_decoderCacheMap.contains(newCacheEntry->cacheKey()));
103 insertCacheInternal(newCacheEntry.release(), &m_decoderCacheMap, &m_decoderCacheKeyMap);
106 void ImageDecodingStore::removeDecoder(const ImageFrameGenerator* generator, const ImageDecoder* decoder)
108 Vector<OwnPtr<CacheEntry>> cacheEntriesToDelete;
110 MutexLocker lock(m_mutex);
111 DecoderCacheMap::iterator iter = m_decoderCacheMap.find(DecoderCacheEntry::makeCacheKey(generator, decoder));
112 ASSERT_WITH_SECURITY_IMPLICATION(iter != m_decoderCacheMap.end());
114 CacheEntry* cacheEntry = iter->value.get();
115 ASSERT(cacheEntry->useCount());
116 cacheEntry->decrementUseCount();
118 // Delete only one decoder cache entry. Ownership of the cache entry
119 // is transfered to cacheEntriesToDelete such that object can be deleted
120 // outside of the lock.
121 removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
123 // Remove from LRU list.
124 removeFromCacheListInternal(cacheEntriesToDelete);
128 void ImageDecodingStore::removeCacheIndexedByGenerator(const ImageFrameGenerator* generator)
130 Vector<OwnPtr<CacheEntry>> cacheEntriesToDelete;
132 MutexLocker lock(m_mutex);
134 // Remove image cache objects and decoder cache objects associated
135 // with a ImageFrameGenerator.
136 removeCacheIndexedByGeneratorInternal(&m_decoderCacheMap, &m_decoderCacheKeyMap, generator, &cacheEntriesToDelete);
138 // Remove from LRU list as well.
139 removeFromCacheListInternal(cacheEntriesToDelete);
143 void ImageDecodingStore::clear()
145 size_t cacheLimitInBytes;
147 MutexLocker lock(m_mutex);
148 cacheLimitInBytes = m_heapLimitInBytes;
149 m_heapLimitInBytes = 0;
152 prune();
155 MutexLocker lock(m_mutex);
156 m_heapLimitInBytes = cacheLimitInBytes;
160 void ImageDecodingStore::setCacheLimitInBytes(size_t cacheLimit)
163 MutexLocker lock(m_mutex);
164 m_heapLimitInBytes = cacheLimit;
166 prune();
169 size_t ImageDecodingStore::memoryUsageInBytes()
171 MutexLocker lock(m_mutex);
172 return m_heapMemoryUsageInBytes;
175 int ImageDecodingStore::cacheEntries()
177 MutexLocker lock(m_mutex);
178 return m_decoderCacheMap.size();
181 void ImageDecodingStore::prune()
183 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStore::prune");
185 Vector<OwnPtr<CacheEntry>> cacheEntriesToDelete;
187 MutexLocker lock(m_mutex);
189 // Head of the list is the least recently used entry.
190 const CacheEntry* cacheEntry = m_orderedCacheList.head();
192 // Walk the list of cache entries starting from the least recently used
193 // and then keep them for deletion later.
194 while (cacheEntry) {
195 const bool isPruneNeeded = m_heapMemoryUsageInBytes > m_heapLimitInBytes || !m_heapLimitInBytes;
196 if (!isPruneNeeded)
197 break;
199 // Cache is not used; Remove it.
200 if (!cacheEntry->useCount())
201 removeFromCacheInternal(cacheEntry, &cacheEntriesToDelete);
202 cacheEntry = cacheEntry->next();
205 // Remove from cache list as well.
206 removeFromCacheListInternal(cacheEntriesToDelete);
210 template<class T, class U, class V>
211 void ImageDecodingStore::insertCacheInternal(PassOwnPtr<T> cacheEntry, U* cacheMap, V* identifierMap)
213 const size_t cacheEntryBytes = cacheEntry->memoryUsageInBytes();
214 m_heapMemoryUsageInBytes += cacheEntryBytes;
216 // m_orderedCacheList is used to support LRU operations to reorder cache
217 // entries quickly.
218 m_orderedCacheList.append(cacheEntry.get());
220 typename U::KeyType key = cacheEntry->cacheKey();
221 typename V::AddResult result = identifierMap->add(cacheEntry->generator(), typename V::MappedType());
222 result.storedValue->value.add(key);
223 cacheMap->add(key, cacheEntry);
225 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreHeapMemoryUsageBytes", m_heapMemoryUsageInBytes);
226 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreNumOfDecoders", m_decoderCacheMap.size());
229 template<class T, class U, class V>
230 void ImageDecodingStore::removeFromCacheInternal(const T* cacheEntry, U* cacheMap, V* identifierMap, Vector<OwnPtr<CacheEntry>>* deletionList)
232 const size_t cacheEntryBytes = cacheEntry->memoryUsageInBytes();
233 ASSERT(m_heapMemoryUsageInBytes >= cacheEntryBytes);
234 m_heapMemoryUsageInBytes -= cacheEntryBytes;
236 // Remove entry from identifier map.
237 typename V::iterator iter = identifierMap->find(cacheEntry->generator());
238 ASSERT(iter != identifierMap->end());
239 iter->value.remove(cacheEntry->cacheKey());
240 if (!iter->value.size())
241 identifierMap->remove(iter);
243 // Remove entry from cache map.
244 deletionList->append(cacheMap->take(cacheEntry->cacheKey()));
246 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreHeapMemoryUsageBytes", m_heapMemoryUsageInBytes);
247 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.image_decoding"), "ImageDecodingStoreNumOfDecoders", m_decoderCacheMap.size());
250 void ImageDecodingStore::removeFromCacheInternal(const CacheEntry* cacheEntry, Vector<OwnPtr<CacheEntry>>* deletionList)
252 if (cacheEntry->type() == CacheEntry::TypeDecoder) {
253 removeFromCacheInternal(static_cast<const DecoderCacheEntry*>(cacheEntry), &m_decoderCacheMap, &m_decoderCacheKeyMap, deletionList);
254 } else {
255 ASSERT(false);
259 template<class U, class V>
260 void ImageDecodingStore::removeCacheIndexedByGeneratorInternal(U* cacheMap, V* identifierMap, const ImageFrameGenerator* generator, Vector<OwnPtr<CacheEntry>>* deletionList)
262 typename V::iterator iter = identifierMap->find(generator);
263 if (iter == identifierMap->end())
264 return;
266 // Get all cache identifiers associated with generator.
267 Vector<typename U::KeyType> cacheIdentifierList;
268 copyToVector(iter->value, cacheIdentifierList);
270 // For each cache identifier find the corresponding CacheEntry and remove it.
271 for (size_t i = 0; i < cacheIdentifierList.size(); ++i) {
272 ASSERT(cacheMap->contains(cacheIdentifierList[i]));
273 const typename U::MappedType::PtrType cacheEntry = cacheMap->get(cacheIdentifierList[i]);
274 ASSERT(!cacheEntry->useCount());
275 removeFromCacheInternal(cacheEntry, cacheMap, identifierMap, deletionList);
279 void ImageDecodingStore::removeFromCacheListInternal(const Vector<OwnPtr<CacheEntry>>& deletionList)
281 for (size_t i = 0; i < deletionList.size(); ++i)
282 m_orderedCacheList.remove(deletionList[i].get());
285 } // namespace blink