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