• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3     Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
4     Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15 
16     You should have received a copy of the GNU Library General Public License
17     along with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 
21     This class provides all functionality needed for loading images, style sheets and html
22     pages from the web. It has a memory cache for these objects.
23 */
24 
25 #ifndef MemoryCache_h
26 #define MemoryCache_h
27 
28 #include "core/fetch/Resource.h"
29 #include "core/fetch/ResourcePtr.h"
30 #include "public/platform/WebThread.h"
31 #include "wtf/HashMap.h"
32 #include "wtf/Noncopyable.h"
33 #include "wtf/Vector.h"
34 #include "wtf/text/StringHash.h"
35 #include "wtf/text/WTFString.h"
36 
37 namespace blink  {
38 
39 class CSSStyleSheetResource;
40 class Resource;
41 class ResourceFetcher;
42 class KURL;
43 class ExecutionContext;
44 class SecurityOrigin;
45 struct SecurityOriginHash;
46 
47 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc.
48 
49 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks
50 // depending on the live resource load. Here's an example of cache growth over time,
51 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%:
52 
53 //        |-----|                              Dead: -
54 //        |----------|                         Live: +
55 //      --|----------|                         Cache boundary: | (objects outside this mark have been evicted)
56 //      --|----------++++++++++|
57 // -------|-----+++++++++++++++|
58 // -------|-----+++++++++++++++|+++++
59 
60 // Enable this macro to periodically log information about the memory cache.
61 #undef MEMORY_CACHE_STATS
62 
63 // Determines the order in which CachedResources are evicted
64 // from the decoded resources cache.
65 enum MemoryCacheLiveResourcePriority {
66     MemoryCacheLiveResourcePriorityLow = 0,
67     MemoryCacheLiveResourcePriorityHigh,
68     MemoryCacheLiveResourcePriorityUnknown
69 };
70 
71 enum UpdateReason {
72     UpdateForAccess,
73     UpdateForPropertyChange
74 };
75 
76 // MemoryCacheEntry class is used only in MemoryCache class, but we don't make
77 // MemoryCacheEntry class an inner class of MemoryCache because of dependency
78 // from MemoryCacheLRUList.
79 class MemoryCacheEntry FINAL : public NoBaseWillBeGarbageCollectedFinalized<MemoryCacheEntry> {
80 public:
create(Resource * resource)81     static PassOwnPtrWillBeRawPtr<MemoryCacheEntry> create(Resource* resource) { return adoptPtrWillBeNoop(new MemoryCacheEntry(resource)); }
82     void trace(Visitor*);
83 
84     ResourcePtr<Resource> m_resource;
85     bool m_inLiveDecodedResourcesList;
86     unsigned m_accessCount;
87     MemoryCacheLiveResourcePriority m_liveResourcePriority;
88     double m_lastDecodedAccessTime; // Used as a thrash guard
89 
90     RawPtrWillBeMember<MemoryCacheEntry> m_previousInLiveResourcesList;
91     RawPtrWillBeMember<MemoryCacheEntry> m_nextInLiveResourcesList;
92     RawPtrWillBeMember<MemoryCacheEntry> m_previousInAllResourcesList;
93     RawPtrWillBeMember<MemoryCacheEntry> m_nextInAllResourcesList;
94 
95 private:
MemoryCacheEntry(Resource * resource)96     explicit MemoryCacheEntry(Resource* resource)
97         : m_resource(resource)
98         , m_inLiveDecodedResourcesList(false)
99         , m_accessCount(0)
100         , m_liveResourcePriority(MemoryCacheLiveResourcePriorityLow)
101         , m_lastDecodedAccessTime(0.0)
102         , m_previousInLiveResourcesList(nullptr)
103         , m_nextInLiveResourcesList(nullptr)
104         , m_previousInAllResourcesList(nullptr)
105         , m_nextInAllResourcesList(nullptr)
106     {
107     }
108 };
109 
110 // MemoryCacheLRUList is used only in MemoryCache class, but we don't make
111 // MemoryCacheLRUList an inner struct of MemoryCache because we can't define
112 // VectorTraits for inner structs.
113 struct MemoryCacheLRUList FINAL {
114     ALLOW_ONLY_INLINE_ALLOCATION();
115 public:
116     RawPtrWillBeMember<MemoryCacheEntry> m_head;
117     RawPtrWillBeMember<MemoryCacheEntry> m_tail;
118 
MemoryCacheLRUListFINAL119     MemoryCacheLRUList() : m_head(nullptr), m_tail(nullptr) { }
120     void trace(Visitor*);
121 };
122 
123 }
124 
125 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::MemoryCacheLRUList);
126 
127 namespace blink {
128 
129 class MemoryCache FINAL : public NoBaseWillBeGarbageCollectedFinalized<MemoryCache>, public WebThread::TaskObserver {
130     WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
131 public:
132     static PassOwnPtrWillBeRawPtr<MemoryCache> create();
133     ~MemoryCache();
134     void trace(Visitor*);
135 
136     struct TypeStatistic {
137         int count;
138         int size;
139         int liveSize;
140         int decodedSize;
141         int encodedSize;
142         int encodedSizeDuplicatedInDataURLs;
143         int purgeableSize;
144         int purgedSize;
145 
TypeStatisticTypeStatistic146         TypeStatistic()
147             : count(0)
148             , size(0)
149             , liveSize(0)
150             , decodedSize(0)
151             , encodedSize(0)
152             , encodedSizeDuplicatedInDataURLs(0)
153             , purgeableSize(0)
154             , purgedSize(0)
155         {
156         }
157 
158         void addResource(Resource*);
159     };
160 
161     struct Statistics {
162         TypeStatistic images;
163         TypeStatistic cssStyleSheets;
164         TypeStatistic scripts;
165         TypeStatistic xslStyleSheets;
166         TypeStatistic fonts;
167         TypeStatistic other;
168     };
169 
170     Resource* resourceForURL(const KURL&);
171 
172     void add(Resource*);
173     void replace(Resource* newResource, Resource* oldResource);
174     void remove(Resource*);
175     bool contains(const Resource*) const;
176 
177     static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL);
178 
179     // Sets the cache's memory capacities, in bytes. These will hold only approximately,
180     // since the decoded cost of resources like scripts and stylesheets is not known.
181     //  - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure.
182     //  - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure.
183     //  - totalBytes: The maximum number of bytes that the cache should consume overall.
184     void setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t totalBytes);
setDelayBeforeLiveDecodedPrune(double seconds)185     void setDelayBeforeLiveDecodedPrune(double seconds) { m_delayBeforeLiveDecodedPrune = seconds; }
setMaxPruneDeferralDelay(double seconds)186     void setMaxPruneDeferralDelay(double seconds) { m_maxPruneDeferralDelay = seconds; }
187 
188     void evictResources();
189 
190     void prune(Resource* justReleasedResource = 0);
191 
192     // Called to adjust a resource's size, lru list position, and access count.
193     void update(Resource*, size_t oldSize, size_t newSize, bool wasAccessed = false);
updateForAccess(Resource * resource)194     void updateForAccess(Resource* resource) { update(resource, resource->size(), resource->size(), true); }
195     void updateDecodedResource(Resource*, UpdateReason, MemoryCacheLiveResourcePriority = MemoryCacheLiveResourcePriorityUnknown);
196 
197     void makeLive(Resource*);
198     void makeDead(Resource*);
199 
200     // This should be called when a Resource object is created.
201     void registerLiveResource(Resource&);
202     // This should be called when a Resource object becomes unnecesarry.
203     void unregisterLiveResource(Resource&);
204 
205     static void removeURLFromCache(ExecutionContext*, const KURL&);
206 
207     Statistics getStatistics();
208 
minDeadCapacity()209     size_t minDeadCapacity() const { return m_minDeadCapacity; }
maxDeadCapacity()210     size_t maxDeadCapacity() const { return m_maxDeadCapacity; }
capacity()211     size_t capacity() const { return m_capacity; }
liveSize()212     size_t liveSize() const { return m_liveSize; }
deadSize()213     size_t deadSize() const { return m_deadSize; }
214 
215     // Exposed for testing
216     MemoryCacheLiveResourcePriority priority(Resource*) const;
217 
218     // TaskObserver implementation
219     virtual void willProcessTask() OVERRIDE;
220     virtual void didProcessTask() OVERRIDE;
221 
222 private:
223     MemoryCache();
224 
225     MemoryCacheLRUList* lruListFor(unsigned accessCount, size_t);
226 
227 #ifdef MEMORY_CACHE_STATS
228     void dumpStats(Timer<MemoryCache>*);
229     void dumpLRULists(bool includeLive) const;
230 #endif
231 
232     // Calls to put the cached resource into and out of LRU lists.
233     void insertInLRUList(MemoryCacheEntry*, MemoryCacheLRUList*);
234     void removeFromLRUList(MemoryCacheEntry*, MemoryCacheLRUList*);
235 
236     // Track decoded resources that are in the cache and referenced by a Web page.
237     void insertInLiveDecodedResourcesList(MemoryCacheEntry*);
238     void removeFromLiveDecodedResourcesList(MemoryCacheEntry*);
239 
240     size_t liveCapacity() const;
241     size_t deadCapacity() const;
242 
243     // pruneDeadResources() - Flush decoded and encoded data from resources not referenced by Web pages.
244     // pruneLiveResources() - Flush decoded data from resources still referenced by Web pages.
245     void pruneDeadResources(); // Automatically decide how much to prune.
246     void pruneLiveResources();
247     void pruneNow(double currentTime);
248 
249     bool evict(MemoryCacheEntry*);
250 
251     static void removeURLFromCacheInternal(ExecutionContext*, const KURL&);
252 
253     bool m_inPruneResources;
254     bool m_prunePending;
255     double m_maxPruneDeferralDelay;
256     double m_pruneTimeStamp;
257     double m_pruneFrameTimeStamp;
258 
259     size_t m_capacity;
260     size_t m_minDeadCapacity;
261     size_t m_maxDeadCapacity;
262     size_t m_maxDeferredPruneDeadCapacity;
263     double m_delayBeforeLiveDecodedPrune;
264 
265     size_t m_liveSize; // The number of bytes currently consumed by "live" resources in the cache.
266     size_t m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache.
267 
268     // Size-adjusted and popularity-aware LRU list collection for cache objects. This collection can hold
269     // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
270     // waiting to die when the clients referencing them go away.
271     WillBeHeapVector<MemoryCacheLRUList, 32> m_allResources;
272 
273     // Lists just for live resources with decoded data. Access to this list is based off of painting the resource.
274     // The lists are ordered by decode priority, with higher indices having higher priorities.
275     MemoryCacheLRUList m_liveDecodedResources[MemoryCacheLiveResourcePriorityHigh + 1];
276 
277     // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
278     // referenced by a Web page).
279     typedef WillBeHeapHashMap<String, OwnPtrWillBeMember<MemoryCacheEntry> > ResourceMap;
280     ResourceMap m_resources;
281 
282 #if ENABLE(OILPAN)
283     // Unlike m_allResources, m_liveResources is a set of Resource objects which
284     // should not be deleted. m_allResources only contains on-cache Resource
285     // objects.
286     // FIXME: Can we remove manual lifetime management of Resource and this?
287     HeapHashSet<Member<Resource> > m_liveResources;
288     friend RawPtr<MemoryCache> replaceMemoryCacheForTesting(RawPtr<MemoryCache>);
289 #endif
290 
291     friend class MemoryCacheTest;
292 #ifdef MEMORY_CACHE_STATS
293     Timer<MemoryCache> m_statsTimer;
294 #endif
295 };
296 
297 // Returns the global cache.
298 MemoryCache* memoryCache();
299 
300 // Sets the global cache, used to swap in a test instance. Returns the old
301 // MemoryCache object.
302 PassOwnPtrWillBeRawPtr<MemoryCache> replaceMemoryCacheForTesting(PassOwnPtrWillBeRawPtr<MemoryCache>);
303 
304 }
305 
306 #endif
307