• 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 Cache_h
26 #define Cache_h
27 
28 #include "CachePolicy.h"
29 #include "CachedResource.h"
30 #include "PlatformString.h"
31 #include <wtf/HashMap.h>
32 #include <wtf/HashSet.h>
33 #include <wtf/Noncopyable.h>
34 #include <wtf/Vector.h>
35 #include <wtf/text/StringHash.h>
36 
37 namespace WebCore  {
38 
39 class CachedCSSStyleSheet;
40 class CachedResource;
41 class CachedResourceLoader;
42 class KURL;
43 class SecurityOrigin;
44 struct SecurityOriginHash;
45 
46 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc.
47 
48 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks
49 // depending on the live resource load. Here's an example of cache growth over time,
50 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%:
51 
52 //        |-----|                              Dead: -
53 //        |----------|                         Live: +
54 //      --|----------|                         Cache boundary: | (objects outside this mark have been evicted)
55 //      --|----------++++++++++|
56 // -------|-----+++++++++++++++|
57 // -------|-----+++++++++++++++|+++++
58 
59 // The behavior of the cache changes in the following way if shouldMakeResourcePurgeableOnEviction
60 // returns true.
61 //
62 // 1. Dead resources in the cache are kept in non-purgeable memory.
63 // 2. When we prune dead resources, instead of freeing them, we mark their memory as purgeable and
64 //    keep the resources until the kernel reclaims the purgeable memory.
65 //
66 // By leaving the in-cache dead resources in dirty resident memory, we decrease the likelihood of
67 // the kernel claiming that memory and forcing us to refetch the resource (for example when a user
68 // presses back).
69 //
70 // And by having an unbounded number of resource objects using purgeable memory, we can use as much
71 // memory as is available on the machine. The trade-off here is that the CachedResource object (and
72 // its member variables) are allocated in non-purgeable TC-malloc'd memory so we would see slightly
73 // more memory use due to this.
74 
75 class MemoryCache {
76     WTF_MAKE_NONCOPYABLE(MemoryCache); WTF_MAKE_FAST_ALLOCATED;
77 public:
78     friend MemoryCache* memoryCache();
79 
80     typedef HashMap<String, CachedResource*> CachedResourceMap;
81 
82     struct LRUList {
83         CachedResource* m_head;
84         CachedResource* m_tail;
LRUListLRUList85         LRUList() : m_head(0), m_tail(0) { }
86     };
87 
88     struct TypeStatistic {
89         int count;
90         int size;
91         int liveSize;
92         int decodedSize;
93         int purgeableSize;
94         int purgedSize;
TypeStatisticTypeStatistic95         TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0) { }
96         void addResource(CachedResource*);
97     };
98 
99     struct Statistics {
100         TypeStatistic images;
101         TypeStatistic cssStyleSheets;
102         TypeStatistic scripts;
103 #if ENABLE(XSLT)
104         TypeStatistic xslStyleSheets;
105 #endif
106         TypeStatistic fonts;
107     };
108 
109     CachedResource* resourceForURL(const KURL&);
110 
111     bool add(CachedResource* resource);
remove(CachedResource * resource)112     void remove(CachedResource* resource) { evict(resource); }
113 
114     static KURL removeFragmentIdentifierIfNeeded(const KURL& originalURL);
115 
116     void revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse&);
117     void revalidationFailed(CachedResource* revalidatingResource);
118 
119     // Sets the cache's memory capacities, in bytes. These will hold only approximately,
120     // since the decoded cost of resources like scripts and stylesheets is not known.
121     //  - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure.
122     //  - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure.
123     //  - totalBytes: The maximum number of bytes that the cache should consume overall.
124     void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes);
125 
126     // Turn the cache on and off.  Disabling the cache will remove all resources from the cache.  They may
127     // still live on if they are referenced by some Web page though.
128     void setDisabled(bool);
disabled()129     bool disabled() const { return m_disabled; }
130 
131     void evictResources();
132 
setPruneEnabled(bool enabled)133     void setPruneEnabled(bool enabled) { m_pruneEnabled = enabled; }
prune()134     void prune()
135     {
136         if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize <= m_maxDeadCapacity) // Fast path.
137             return;
138 
139         pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live.
140         pruneLiveResources();
141     }
142 
setDeadDecodedDataDeletionInterval(double interval)143     void setDeadDecodedDataDeletionInterval(double interval) { m_deadDecodedDataDeletionInterval = interval; }
deadDecodedDataDeletionInterval()144     double deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; }
145 
146     void addCachedResourceLoader(CachedResourceLoader*);
147     void removeCachedResourceLoader(CachedResourceLoader*);
148 
149     // Calls to put the cached resource into and out of LRU lists.
150     void insertInLRUList(CachedResource*);
151     void removeFromLRUList(CachedResource*);
152 
153     // Called to adjust the cache totals when a resource changes size.
154     void adjustSize(bool live, int delta);
155 
156     // Track decoded resources that are in the cache and referenced by a Web page.
157     void insertInLiveDecodedResourcesList(CachedResource*);
158     void removeFromLiveDecodedResourcesList(CachedResource*);
159 
160     void addToLiveResourcesSize(CachedResource*);
161     void removeFromLiveResourcesSize(CachedResource*);
162 
163     static bool shouldMakeResourcePurgeableOnEviction();
164 
165     // Function to collect cache statistics for the caches window in the Safari Debug menu.
166     Statistics getStatistics();
167 
168     void resourceAccessed(CachedResource*);
169 
170     typedef HashSet<RefPtr<SecurityOrigin>, SecurityOriginHash> SecurityOriginSet;
171     void removeResourcesWithOrigin(SecurityOrigin*);
172     void getOriginsWithCache(SecurityOriginSet& origins);
173 
174 #ifdef ANDROID_INSTRUMENT
getLiveSize()175     unsigned getLiveSize() { return m_liveSize; }
getDeadSize()176     unsigned getDeadSize() { return m_deadSize; }
177 #endif
178 
179 
180 private:
181     MemoryCache();
182     ~MemoryCache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
183 
184     LRUList* lruListFor(CachedResource*);
185 #ifndef NDEBUG
186     void dumpStats();
187     void dumpLRULists(bool includeLive) const;
188 #endif
189 
190     unsigned liveCapacity() const;
191     unsigned deadCapacity() const;
192 
193     void pruneDeadResources(); // Flush decoded and encoded data from resources not referenced by Web pages.
194     void pruneLiveResources(); // Flush decoded data from resources still referenced by Web pages.
195 
196     bool makeResourcePurgeable(CachedResource*);
197     void evict(CachedResource*);
198 
199     bool m_disabled;  // Whether or not the cache is enabled.
200     bool m_pruneEnabled;
201     bool m_inPruneDeadResources;
202 
203     unsigned m_capacity;
204     unsigned m_minDeadCapacity;
205     unsigned m_maxDeadCapacity;
206     double m_deadDecodedDataDeletionInterval;
207 
208     unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache.
209     unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache.
210 
211     // Size-adjusted and popularity-aware LRU list collection for cache objects.  This collection can hold
212     // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
213     // waiting to die when the clients referencing them go away.
214     Vector<LRUList, 32> m_allResources;
215 
216     // List just for live resources with decoded data.  Access to this list is based off of painting the resource.
217     LRUList m_liveDecodedResources;
218 
219     // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
220     // referenced by a Web page).
221     HashMap<String, CachedResource*> m_resources;
222 };
223 
shouldMakeResourcePurgeableOnEviction()224 inline bool MemoryCache::shouldMakeResourcePurgeableOnEviction()
225 {
226 #if PLATFORM(IOS)
227     return true;
228 #else
229     return false;
230 #endif
231 }
232 
233 // Function to obtain the global cache.
234 MemoryCache* memoryCache();
235 
236 }
237 
238 #endif
239