OLD | NEW |
1 /* | 1 /* |
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) | 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) | 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) |
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) | 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) |
5 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 5 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
6 | 6 |
7 This library is free software; you can redistribute it and/or | 7 This library is free software; you can redistribute it and/or |
8 modify it under the terms of the GNU Library General Public | 8 modify it under the terms of the GNU Library General Public |
9 License as published by the Free Software Foundation; either | 9 License as published by the Free Software Foundation; either |
10 version 2 of the License, or (at your option) any later version. | 10 version 2 of the License, or (at your option) any later version. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 if (!originalURL.protocolIsInHTTPFamily()) | 102 if (!originalURL.protocolIsInHTTPFamily()) |
103 return originalURL; | 103 return originalURL; |
104 KURL url = originalURL; | 104 KURL url = originalURL; |
105 url.removeFragmentIdentifier(); | 105 url.removeFragmentIdentifier(); |
106 return url; | 106 return url; |
107 } | 107 } |
108 | 108 |
109 void MemoryCache::add(Resource* resource) | 109 void MemoryCache::add(Resource* resource) |
110 { | 110 { |
111 ASSERT(WTF::isMainThread()); | 111 ASSERT(WTF::isMainThread()); |
112 m_resources.set(resource->url(), resource); | 112 ASSERT(!m_resources.contains(resource->url())); |
| 113 m_resources.set(resource->url(), MemoryCacheEntry::create(resource)); |
113 resource->setInCache(true); | 114 resource->setInCache(true); |
114 resource->updateForAccess(); | 115 resource->updateForAccess(); |
115 | 116 |
116 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou
rce->url().string().latin1().data(), resource); | 117 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou
rce->url().string().latin1().data(), resource); |
117 } | 118 } |
118 | 119 |
119 void MemoryCache::replace(Resource* newResource, Resource* oldResource) | 120 void MemoryCache::replace(Resource* newResource, Resource* oldResource) |
120 { | 121 { |
121 evict(oldResource); | 122 evict(oldResource); |
122 ASSERT(!m_resources.get(newResource->url())); | 123 ASSERT(!m_resources.contains(newResource->url())); |
123 m_resources.set(newResource->url(), newResource); | 124 m_resources.set(newResource->url(), MemoryCacheEntry::create(newResource)); |
124 newResource->setInCache(true); | 125 newResource->setInCache(true); |
125 insertInLRUList(newResource); | 126 insertInLRUList(newResource); |
126 int delta = newResource->size(); | 127 int delta = newResource->size(); |
127 if (newResource->decodedSize() && newResource->hasClients()) | 128 if (newResource->decodedSize() && newResource->hasClients()) |
128 insertInLiveDecodedResourcesList(newResource); | 129 insertInLiveDecodedResourcesList(newResource); |
129 if (delta) | 130 if (delta) |
130 adjustSize(newResource->hasClients(), delta); | 131 adjustSize(newResource->hasClients(), delta); |
131 } | 132 } |
132 | 133 |
133 Resource* MemoryCache::resourceForURL(const KURL& resourceURL) | 134 Resource* MemoryCache::resourceForURL(const KURL& resourceURL) |
134 { | 135 { |
135 ASSERT(WTF::isMainThread()); | 136 ASSERT(WTF::isMainThread()); |
136 KURL url = removeFragmentIdentifierIfNeeded(resourceURL); | 137 KURL url = removeFragmentIdentifierIfNeeded(resourceURL); |
137 Resource* resource = m_resources.get(url); | 138 MemoryCacheEntry* entry = m_resources.get(url); |
| 139 if (!entry) |
| 140 return 0; |
| 141 Resource* resource = entry->m_resource.get(); |
138 if (resource && !resource->lock()) { | 142 if (resource && !resource->lock()) { |
139 ASSERT(!resource->hasClients()); | 143 ASSERT(!resource->hasClients()); |
140 bool didEvict = evict(resource); | 144 bool didEvict = evict(resource); |
141 ASSERT_UNUSED(didEvict, didEvict); | 145 ASSERT_UNUSED(didEvict, didEvict); |
142 return 0; | 146 return 0; |
143 } | 147 } |
144 return resource; | 148 return resource; |
145 } | 149 } |
146 | 150 |
147 size_t MemoryCache::deadCapacity() const | 151 size_t MemoryCache::deadCapacity() const |
(...skipping 25 matching lines...) Expand all Loading... |
173 // and least recently accessed of the objects. | 177 // and least recently accessed of the objects. |
174 | 178 |
175 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impa
ct | 179 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impa
ct |
176 // of this weaker invariant is minor as the below if statement to check the | 180 // of this weaker invariant is minor as the below if statement to check the |
177 // elapsedTime will evaluate to false as the current time will be a lot | 181 // elapsedTime will evaluate to false as the current time will be a lot |
178 // greater than the current->m_lastDecodedFrameTimeStamp. | 182 // greater than the current->m_lastDecodedFrameTimeStamp. |
179 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 | 183 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 |
180 | 184 |
181 // Start pruning from the lowest priority list. | 185 // Start pruning from the lowest priority list. |
182 for (int priority = Resource::CacheLiveResourcePriorityLow; priority <= Reso
urce::CacheLiveResourcePriorityHigh; ++priority) { | 186 for (int priority = Resource::CacheLiveResourcePriorityLow; priority <= Reso
urce::CacheLiveResourcePriorityHigh; ++priority) { |
183 Resource* current = m_liveDecodedResources[priority].m_tail; | 187 MemoryCacheEntry* current = m_liveDecodedResources[priority].m_tail; |
184 while (current) { | 188 while (current) { |
185 Resource* prev = current->m_prevInLiveResourcesList; | 189 MemoryCacheEntry* previous = current->m_previousInLiveResourcesList; |
186 ASSERT(current->hasClients()); | 190 ASSERT(current->m_resource->hasClients()); |
187 if (current->isLoaded() && current->decodedSize()) { | 191 if (current->m_resource->isLoaded() && current->m_resource->decodedS
ize()) { |
188 // Check to see if the remaining resources are too new to prune. | 192 // Check to see if the remaining resources are too new to prune. |
189 double elapsedTime = m_pruneFrameTimeStamp - current->m_lastDeco
dedAccessTime; | 193 double elapsedTime = m_pruneFrameTimeStamp - current->m_resource
->m_lastDecodedAccessTime; |
190 if (elapsedTime < m_delayBeforeLiveDecodedPrune) | 194 if (elapsedTime < m_delayBeforeLiveDecodedPrune) |
191 return; | 195 return; |
192 | 196 |
193 // Destroy our decoded data if possible. This will remove us | 197 // Destroy our decoded data if possible. This will remove us |
194 // from m_liveDecodedResources, and possibly move us to a | 198 // from m_liveDecodedResources, and possibly move us to a |
195 // different LRU list in m_allResources. | 199 // different LRU list in m_allResources. |
196 current->prune(); | 200 current->m_resource->prune(); |
197 | 201 |
198 if (targetSize && m_liveSize <= targetSize) | 202 if (targetSize && m_liveSize <= targetSize) |
199 return; | 203 return; |
200 } | 204 } |
201 current = prev; | 205 current = previous; |
202 } | 206 } |
203 } | 207 } |
204 } | 208 } |
205 | 209 |
206 void MemoryCache::pruneDeadResources() | 210 void MemoryCache::pruneDeadResources() |
207 { | 211 { |
208 size_t capacity = deadCapacity(); | 212 size_t capacity = deadCapacity(); |
209 if (!m_deadSize || (capacity && m_deadSize <= capacity)) | 213 if (!m_deadSize || (capacity && m_deadSize <= capacity)) |
210 return; | 214 return; |
211 | 215 |
212 size_t targetSize = static_cast<size_t>(capacity * cTargetPrunePercentage);
// Cut by a percentage to avoid immediately pruning again. | 216 size_t targetSize = static_cast<size_t>(capacity * cTargetPrunePercentage);
// Cut by a percentage to avoid immediately pruning again. |
213 | 217 |
214 int size = m_allResources.size(); | 218 int size = m_allResources.size(); |
215 | 219 |
216 // See if we have any purged resources we can evict. | 220 // See if we have any purged resources we can evict. |
217 for (int i = 0; i < size; i++) { | 221 for (int i = 0; i < size; i++) { |
218 Resource* current = m_allResources[i].m_tail; | 222 MemoryCacheEntry* current = m_allResources[i].m_tail; |
219 while (current) { | 223 while (current) { |
220 Resource* prev = current->m_prevInAllResourcesList; | 224 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
221 if (current->wasPurged()) { | 225 if (current->m_resource->wasPurged()) { |
222 ASSERT(!current->hasClients()); | 226 ASSERT(!current->m_resource->hasClients()); |
223 ASSERT(!current->isPreloaded()); | 227 ASSERT(!current->m_resource->isPreloaded()); |
224 evict(current); | 228 evict(current->m_resource.get()); |
225 } | 229 } |
226 current = prev; | 230 current = previous; |
227 } | 231 } |
228 } | 232 } |
229 if (targetSize && m_deadSize <= targetSize) | 233 if (targetSize && m_deadSize <= targetSize) |
230 return; | 234 return; |
231 | 235 |
232 bool canShrinkLRULists = true; | 236 bool canShrinkLRULists = true; |
233 for (int i = size - 1; i >= 0; i--) { | 237 for (int i = size - 1; i >= 0; i--) { |
234 // Remove from the tail, since this is the least frequently accessed of
the objects. | 238 // Remove from the tail, since this is the least frequently accessed of
the objects. |
235 Resource* current = m_allResources[i].m_tail; | 239 MemoryCacheEntry* current = m_allResources[i].m_tail; |
236 | 240 |
237 // First flush all the decoded data in this queue. | 241 // First flush all the decoded data in this queue. |
238 while (current) { | 242 while (current) { |
239 // Protect 'previous' so it can't get deleted during destroyDecodedD
ata(). | 243 // Protect 'previous' so it can't get deleted during destroyDecodedD
ata(). |
240 ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; | 244 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
241 ASSERT(!previous || previous->inCache()); | 245 ASSERT(!previous || previous->m_resource->inCache()); |
242 if (!current->hasClients() && !current->isPreloaded() && current->is
Loaded()) { | 246 if (!current->m_resource->hasClients() && !current->m_resource->isPr
eloaded() && current->m_resource->isLoaded()) { |
243 // Destroy our decoded data if possible. This will remove us | 247 // Destroy our decoded data. This will remove us from |
244 // from m_liveDecodedResources, and possibly move us to a | 248 // m_liveDecodedResources, and possibly move us to a different |
245 // different LRU list in m_allResources. | 249 // LRU list in m_allResources. |
246 current->prune(); | 250 current->m_resource->prune(); |
247 | 251 |
248 if (targetSize && m_deadSize <= targetSize) | 252 if (targetSize && m_deadSize <= targetSize) |
249 return; | 253 return; |
250 } | 254 } |
251 // Decoded data may reference other resources. Stop iterating if 'pr
evious' somehow got | 255 // Decoded data may reference other resources. Stop iterating if 'pr
evious' somehow got |
252 // kicked out of cache during destroyDecodedData(). | 256 // kicked out of cache during destroyDecodedData(). |
253 if (previous && !previous->inCache()) | 257 if (previous && !previous->m_resource->inCache()) |
254 break; | 258 break; |
255 current = previous.get(); | 259 current = previous; |
256 } | 260 } |
257 | 261 |
258 // Now evict objects from this queue. | 262 // Now evict objects from this queue. |
259 current = m_allResources[i].m_tail; | 263 current = m_allResources[i].m_tail; |
260 while (current) { | 264 while (current) { |
261 ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; | 265 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
262 ASSERT(!previous || previous->inCache()); | 266 ASSERT(!previous || previous->m_resource->inCache()); |
263 if (!current->hasClients() && !current->isPreloaded() && !current->i
sCacheValidator()) { | 267 if (!current->m_resource->hasClients() && !current->m_resource->isPr
eloaded() && !current->m_resource->isCacheValidator()) { |
264 evict(current); | 268 evict(current->m_resource.get()); |
265 if (targetSize && m_deadSize <= targetSize) | 269 if (targetSize && m_deadSize <= targetSize) |
266 return; | 270 return; |
267 } | 271 } |
268 if (previous && !previous->inCache()) | 272 if (previous && !previous->m_resource->inCache()) |
269 break; | 273 break; |
270 current = previous.get(); | 274 current = previous; |
271 } | 275 } |
272 | 276 |
273 // Shrink the vector back down so we don't waste time inspecting | 277 // Shrink the vector back down so we don't waste time inspecting |
274 // empty LRU lists on future prunes. | 278 // empty LRU lists on future prunes. |
275 if (m_allResources[i].m_head) | 279 if (m_allResources[i].m_head) |
276 canShrinkLRULists = false; | 280 canShrinkLRULists = false; |
277 else if (canShrinkLRULists) | 281 else if (canShrinkLRULists) |
278 m_allResources.resize(i); | 282 m_allResources.resize(i); |
279 } | 283 } |
280 } | 284 } |
281 | 285 |
282 void MemoryCache::setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t
totalBytes) | 286 void MemoryCache::setCapacities(size_t minDeadBytes, size_t maxDeadBytes, size_t
totalBytes) |
283 { | 287 { |
284 ASSERT(minDeadBytes <= maxDeadBytes); | 288 ASSERT(minDeadBytes <= maxDeadBytes); |
285 ASSERT(maxDeadBytes <= totalBytes); | 289 ASSERT(maxDeadBytes <= totalBytes); |
286 m_minDeadCapacity = minDeadBytes; | 290 m_minDeadCapacity = minDeadBytes; |
287 m_maxDeadCapacity = maxDeadBytes; | 291 m_maxDeadCapacity = maxDeadBytes; |
288 m_maxDeferredPruneDeadCapacity = cDeferredPruneDeadCapacityFactor * maxDeadB
ytes; | 292 m_maxDeferredPruneDeadCapacity = cDeferredPruneDeadCapacityFactor * maxDeadB
ytes; |
289 m_capacity = totalBytes; | 293 m_capacity = totalBytes; |
290 prune(); | 294 prune(); |
291 } | 295 } |
292 | 296 |
293 bool MemoryCache::evict(Resource* resource) | 297 bool MemoryCache::evict(Resource* resource) |
294 { | 298 { |
295 ASSERT(WTF::isMainThread()); | 299 ASSERT(WTF::isMainThread()); |
296 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc
e, resource->url().string().latin1().data()); | 300 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc
e, resource->url().string().latin1().data()); |
297 // The resource may have already been removed by someone other than our call
er, | 301 // The resource may have already been removed by someone other than our call
er, |
298 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu
g.cgi?id=12479#c6>. | 302 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu
g.cgi?id=12479#c6>. |
299 if (resource->inCache()) { | 303 if (resource->inCache()) { |
300 // Remove from the resource map. | |
301 m_resources.remove(resource->url()); | |
302 resource->setInCache(false); | |
303 | |
304 // Remove from the appropriate LRU list. | 304 // Remove from the appropriate LRU list. |
305 removeFromLRUList(resource); | 305 removeFromLRUList(resource); |
306 removeFromLiveDecodedResourcesList(resource); | 306 removeFromLiveDecodedResourcesList(resource); |
307 adjustSize(resource->hasClients(), -static_cast<ptrdiff_t>(resource->siz
e())); | 307 adjustSize(resource->hasClients(), -static_cast<ptrdiff_t>(resource->siz
e())); |
| 308 |
| 309 // Remove from the resource map. |
| 310 m_resources.remove(resource->url()); |
| 311 resource->setInCache(false); |
308 } else { | 312 } else { |
309 ASSERT(m_resources.get(resource->url()) != resource); | 313 ASSERT(!m_resources.get(resource->url()) || m_resources.get(resource->ur
l())->m_resource != resource); |
310 } | 314 } |
311 | 315 |
312 return resource->deleteIfPossible(); | 316 return resource->deleteIfPossible(); |
313 } | 317 } |
314 | 318 |
315 MemoryCache::LRUList* MemoryCache::lruListFor(Resource* resource) | 319 MemoryCache::LRUList* MemoryCache::lruListFor(MemoryCacheEntry* entry) |
316 { | 320 { |
317 unsigned accessCount = std::max(resource->accessCount(), 1U); | 321 unsigned accessCount = std::max(entry->m_resource->accessCount(), 1U); |
318 unsigned queueIndex = WTF::fastLog2(resource->size() / accessCount); | 322 unsigned queueIndex = WTF::fastLog2(entry->m_resource->size() / accessCount)
; |
319 #ifndef NDEBUG | |
320 resource->m_lruIndex = queueIndex; | |
321 #endif | |
322 if (m_allResources.size() <= queueIndex) | 323 if (m_allResources.size() <= queueIndex) |
323 m_allResources.grow(queueIndex + 1); | 324 m_allResources.grow(queueIndex + 1); |
324 return &m_allResources[queueIndex]; | 325 return &m_allResources[queueIndex]; |
325 } | 326 } |
326 | 327 |
327 void MemoryCache::removeFromLRUList(Resource* resource) | 328 void MemoryCache::removeFromLRUList(Resource* resource) |
328 { | 329 { |
329 // If we've never been accessed, then we're brand new and not in any list. | 330 // If we've never been accessed, then we're brand new and not in any list. |
330 if (!resource->accessCount()) | 331 if (!resource->accessCount()) |
331 return; | 332 return; |
332 | 333 |
333 #if !ASSERT_DISABLED | 334 MemoryCacheEntry* entry = m_resources.get(resource->url()); |
334 unsigned oldListIndex = resource->m_lruIndex; | 335 ASSERT(entry->m_resource == resource); |
335 #endif | 336 LRUList* list = lruListFor(entry); |
336 | |
337 LRUList* list = lruListFor(resource); | |
338 | 337 |
339 #if !ASSERT_DISABLED | 338 #if !ASSERT_DISABLED |
340 // Verify that the list we got is the list we want. | |
341 ASSERT(resource->m_lruIndex == oldListIndex); | |
342 | |
343 // Verify that we are in fact in this list. | 339 // Verify that we are in fact in this list. |
344 bool found = false; | 340 bool found = false; |
345 for (Resource* current = list->m_head; current; current = current->m_nextInA
llResourcesList) { | 341 for (MemoryCacheEntry* current = list->m_head; current; current = current->m
_nextInAllResourcesList) { |
346 if (current == resource) { | 342 if (current == entry) { |
347 found = true; | 343 found = true; |
348 break; | 344 break; |
349 } | 345 } |
350 } | 346 } |
351 ASSERT(found); | 347 ASSERT(found); |
352 #endif | 348 #endif |
353 | 349 |
354 Resource* next = resource->m_nextInAllResourcesList; | 350 MemoryCacheEntry* next = entry->m_nextInAllResourcesList; |
355 Resource* prev = resource->m_prevInAllResourcesList; | 351 MemoryCacheEntry* previous = entry->m_previousInAllResourcesList; |
356 | 352 |
357 if (!next && !prev && list->m_head != resource) | 353 entry->m_nextInAllResourcesList = 0; |
358 return; | 354 entry->m_previousInAllResourcesList = 0; |
359 | |
360 resource->m_nextInAllResourcesList = 0; | |
361 resource->m_prevInAllResourcesList = 0; | |
362 | 355 |
363 if (next) | 356 if (next) |
364 next->m_prevInAllResourcesList = prev; | 357 next->m_previousInAllResourcesList = previous; |
365 else if (list->m_tail == resource) | 358 else |
366 list->m_tail = prev; | 359 list->m_tail = previous; |
367 | 360 |
368 if (prev) | 361 if (previous) |
369 prev->m_nextInAllResourcesList = next; | 362 previous->m_nextInAllResourcesList = next; |
370 else if (list->m_head == resource) | 363 else |
371 list->m_head = next; | 364 list->m_head = next; |
372 } | 365 } |
373 | 366 |
374 void MemoryCache::insertInLRUList(Resource* resource) | 367 void MemoryCache::insertInLRUList(Resource* resource) |
375 { | 368 { |
| 369 MemoryCacheEntry* entry = m_resources.get(resource->url()); |
| 370 ASSERT(entry->m_resource == resource); |
| 371 |
376 // Make sure we aren't in some list already. | 372 // Make sure we aren't in some list already. |
377 ASSERT(!resource->m_nextInAllResourcesList && !resource->m_prevInAllResource
sList); | 373 ASSERT(!entry->m_nextInAllResourcesList && !entry->m_previousInAllResourcesL
ist); |
378 ASSERT(resource->inCache()); | 374 ASSERT(resource->inCache()); |
379 ASSERT(resource->accessCount() > 0); | 375 ASSERT(resource->accessCount() > 0); |
380 | 376 |
381 LRUList* list = lruListFor(resource); | 377 LRUList* list = lruListFor(entry); |
382 | 378 |
383 resource->m_nextInAllResourcesList = list->m_head; | 379 entry->m_nextInAllResourcesList = list->m_head; |
384 if (list->m_head) | 380 if (list->m_head) |
385 list->m_head->m_prevInAllResourcesList = resource; | 381 list->m_head->m_previousInAllResourcesList = entry; |
386 list->m_head = resource; | 382 list->m_head = entry; |
387 | 383 |
388 if (!resource->m_nextInAllResourcesList) | 384 if (!entry->m_nextInAllResourcesList) |
389 list->m_tail = resource; | 385 list->m_tail = entry; |
390 | 386 |
391 #if !ASSERT_DISABLED | 387 #if !ASSERT_DISABLED |
392 // Verify that we are in now in the list like we should be. | 388 // Verify that we are in now in the list like we should be. |
393 list = lruListFor(resource); | 389 list = lruListFor(entry); |
394 bool found = false; | 390 bool found = false; |
395 for (Resource* current = list->m_head; current; current = current->m_nextInA
llResourcesList) { | 391 for (MemoryCacheEntry* current = list->m_head; current; current = current->m
_nextInAllResourcesList) { |
396 if (current == resource) { | 392 if (current == entry) { |
397 found = true; | 393 found = true; |
398 break; | 394 break; |
399 } | 395 } |
400 } | 396 } |
401 ASSERT(found); | 397 ASSERT(found); |
402 #endif | 398 #endif |
403 | |
404 } | 399 } |
405 | 400 |
406 void MemoryCache::removeFromLiveDecodedResourcesList(Resource* resource) | 401 void MemoryCache::removeFromLiveDecodedResourcesList(Resource* resource) |
407 { | 402 { |
| 403 MemoryCacheEntry* entry = m_resources.get(resource->url()); |
| 404 ASSERT(entry->m_resource == resource); |
| 405 |
408 // If we've never been accessed, then we're brand new and not in any list. | 406 // If we've never been accessed, then we're brand new and not in any list. |
409 if (!resource->m_inLiveDecodedResourcesList) | 407 if (!entry->m_inLiveDecodedResourcesList) |
410 return; | 408 return; |
411 resource->m_inLiveDecodedResourcesList = false; | 409 entry->m_inLiveDecodedResourcesList = false; |
412 | 410 |
413 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority(
)]; | 411 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority(
)]; |
414 | 412 |
415 #if !ASSERT_DISABLED | 413 #if !ASSERT_DISABLED |
416 // Verify that we are in fact in this list. | 414 // Verify that we are in fact in this list. |
417 bool found = false; | 415 bool found = false; |
418 for (Resource* current = list->m_head; current; current = current->m_nextInL
iveResourcesList) { | 416 for (MemoryCacheEntry* current = list->m_head; current; current = current->m
_nextInLiveResourcesList) { |
419 if (current == resource) { | 417 if (current == entry) { |
420 found = true; | 418 found = true; |
421 break; | 419 break; |
422 } | 420 } |
423 } | 421 } |
424 ASSERT(found); | 422 ASSERT(found); |
425 #endif | 423 #endif |
426 | 424 |
427 Resource* next = resource->m_nextInLiveResourcesList; | 425 MemoryCacheEntry* next = entry->m_nextInLiveResourcesList; |
428 Resource* prev = resource->m_prevInLiveResourcesList; | 426 MemoryCacheEntry* previous = entry->m_previousInLiveResourcesList; |
429 | 427 |
430 if (!next && !prev && list->m_head != resource) | 428 entry->m_nextInLiveResourcesList = 0; |
431 return; | 429 entry->m_previousInLiveResourcesList = 0; |
432 | |
433 resource->m_nextInLiveResourcesList = 0; | |
434 resource->m_prevInLiveResourcesList = 0; | |
435 | 430 |
436 if (next) | 431 if (next) |
437 next->m_prevInLiveResourcesList = prev; | 432 next->m_previousInLiveResourcesList = previous; |
438 else if (list->m_tail == resource) | 433 else |
439 list->m_tail = prev; | 434 list->m_tail = previous; |
440 | 435 |
441 if (prev) | 436 if (previous) |
442 prev->m_nextInLiveResourcesList = next; | 437 previous->m_nextInLiveResourcesList = next; |
443 else if (list->m_head == resource) | 438 else |
444 list->m_head = next; | 439 list->m_head = next; |
445 } | 440 } |
446 | 441 |
447 void MemoryCache::insertInLiveDecodedResourcesList(Resource* resource) | 442 void MemoryCache::insertInLiveDecodedResourcesList(Resource* resource) |
448 { | 443 { |
| 444 MemoryCacheEntry* entry = m_resources.get(resource->url()); |
| 445 ASSERT(entry->m_resource == resource); |
| 446 |
449 // Make sure we aren't in the list already. | 447 // Make sure we aren't in the list already. |
450 ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResour
cesList && !resource->m_inLiveDecodedResourcesList); | 448 ASSERT(!entry->m_nextInLiveResourcesList && !entry->m_previousInLiveResource
sList && !entry->m_inLiveDecodedResourcesList); |
451 resource->m_inLiveDecodedResourcesList = true; | 449 entry->m_inLiveDecodedResourcesList = true; |
452 | 450 |
453 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority(
)]; | 451 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority(
)]; |
454 resource->m_nextInLiveResourcesList = list->m_head; | 452 entry->m_nextInLiveResourcesList = list->m_head; |
455 if (list->m_head) | 453 if (list->m_head) |
456 list->m_head->m_prevInLiveResourcesList = resource; | 454 list->m_head->m_previousInLiveResourcesList = entry; |
457 list->m_head = resource; | 455 list->m_head = entry; |
458 | 456 |
459 if (!resource->m_nextInLiveResourcesList) | 457 if (!entry->m_nextInLiveResourcesList) |
460 list->m_tail = resource; | 458 list->m_tail = entry; |
461 | 459 |
462 #if !ASSERT_DISABLED | 460 #if !ASSERT_DISABLED |
463 // Verify that we are in now in the list like we should be. | 461 // Verify that we are in now in the list like we should be. |
464 bool found = false; | 462 bool found = false; |
465 for (Resource* current = list->m_head; current; current = current->m_nextInL
iveResourcesList) { | 463 for (MemoryCacheEntry* current = list->m_head; current; current = current->m
_nextInLiveResourcesList) { |
466 if (current == resource) { | 464 if (current == entry) { |
467 found = true; | 465 found = true; |
468 break; | 466 break; |
469 } | 467 } |
470 } | 468 } |
471 ASSERT(found); | 469 ASSERT(found); |
472 #endif | 470 #endif |
| 471 } |
473 | 472 |
| 473 bool MemoryCache::isInLiveDecodedResourcesList(Resource* resource) |
| 474 { |
| 475 MemoryCacheEntry* entry = m_resources.get(resource->url()); |
| 476 ASSERT(entry->m_resource == resource); |
| 477 return entry ? entry->m_inLiveDecodedResourcesList : false; |
474 } | 478 } |
475 | 479 |
476 void MemoryCache::addToLiveResourcesSize(Resource* resource) | 480 void MemoryCache::addToLiveResourcesSize(Resource* resource) |
477 { | 481 { |
478 ASSERT(m_deadSize >= resource->size()); | 482 ASSERT(m_deadSize >= resource->size()); |
479 m_liveSize += resource->size(); | 483 m_liveSize += resource->size(); |
480 m_deadSize -= resource->size(); | 484 m_deadSize -= resource->size(); |
481 } | 485 } |
482 | 486 |
483 void MemoryCache::removeFromLiveResourcesSize(Resource* resource) | 487 void MemoryCache::removeFromLiveResourcesSize(Resource* resource) |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 encodedSizeDuplicatedInDataURLs += o->url().protocolIsData() ? o->encodedSiz
e() : 0; | 531 encodedSizeDuplicatedInDataURLs += o->url().protocolIsData() ? o->encodedSiz
e() : 0; |
528 purgeableSize += purgeable ? pageSize : 0; | 532 purgeableSize += purgeable ? pageSize : 0; |
529 purgedSize += purged ? pageSize : 0; | 533 purgedSize += purged ? pageSize : 0; |
530 } | 534 } |
531 | 535 |
532 MemoryCache::Statistics MemoryCache::getStatistics() | 536 MemoryCache::Statistics MemoryCache::getStatistics() |
533 { | 537 { |
534 Statistics stats; | 538 Statistics stats; |
535 ResourceMap::iterator e = m_resources.end(); | 539 ResourceMap::iterator e = m_resources.end(); |
536 for (ResourceMap::iterator i = m_resources.begin(); i != e; ++i) { | 540 for (ResourceMap::iterator i = m_resources.begin(); i != e; ++i) { |
537 Resource* resource = i->value; | 541 Resource* resource = i->value->m_resource.get(); |
538 switch (resource->type()) { | 542 switch (resource->type()) { |
539 case Resource::Image: | 543 case Resource::Image: |
540 stats.images.addResource(resource); | 544 stats.images.addResource(resource); |
541 break; | 545 break; |
542 case Resource::CSSStyleSheet: | 546 case Resource::CSSStyleSheet: |
543 stats.cssStyleSheets.addResource(resource); | 547 stats.cssStyleSheets.addResource(resource); |
544 break; | 548 break; |
545 case Resource::Script: | 549 case Resource::Script: |
546 stats.scripts.addResource(resource); | 550 stats.scripts.addResource(resource); |
547 break; | 551 break; |
(...skipping 10 matching lines...) Expand all Loading... |
558 } | 562 } |
559 return stats; | 563 return stats; |
560 } | 564 } |
561 | 565 |
562 void MemoryCache::evictResources() | 566 void MemoryCache::evictResources() |
563 { | 567 { |
564 for (;;) { | 568 for (;;) { |
565 ResourceMap::iterator i = m_resources.begin(); | 569 ResourceMap::iterator i = m_resources.begin(); |
566 if (i == m_resources.end()) | 570 if (i == m_resources.end()) |
567 break; | 571 break; |
568 evict(i->value); | 572 evict(i->value->m_resource.get()); |
569 } | 573 } |
570 } | 574 } |
571 | 575 |
572 void MemoryCache::prune(Resource* justReleasedResource) | 576 void MemoryCache::prune(Resource* justReleasedResource) |
573 { | 577 { |
574 TRACE_EVENT0("renderer", "MemoryCache::prune()"); | 578 TRACE_EVENT0("renderer", "MemoryCache::prune()"); |
575 | 579 |
576 if (m_inPruneResources) | 580 if (m_inPruneResources) |
577 return; | 581 return; |
578 if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize
<= m_maxDeadCapacity) // Fast path. | 582 if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize
<= m_maxDeadCapacity) // Fast path. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 printf("(%.1fK, %.1fK, %uA, %dR, %d, %d); ", current->decodedSiz
e() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, cur
rent->accessCount(), current->hasClients(), current->isPurgeable(), current->was
Purged()); | 682 printf("(%.1fK, %.1fK, %uA, %dR, %d, %d); ", current->decodedSiz
e() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, cur
rent->accessCount(), current->hasClients(), current->isPurgeable(), current->was
Purged()); |
679 | 683 |
680 current = prev; | 684 current = prev; |
681 } | 685 } |
682 } | 686 } |
683 } | 687 } |
684 | 688 |
685 #endif // MEMORY_CACHE_STATS | 689 #endif // MEMORY_CACHE_STATS |
686 | 690 |
687 } // namespace WebCore | 691 } // namespace WebCore |
OLD | NEW |