| 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 |