| 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 23 matching lines...) Expand all Loading... |
| 34 #include "wtf/text/CString.h" | 34 #include "wtf/text/CString.h" |
| 35 | 35 |
| 36 namespace blink { | 36 namespace blink { |
| 37 | 37 |
| 38 static Persistent<MemoryCache>* gMemoryCache; | 38 static Persistent<MemoryCache>* gMemoryCache; |
| 39 | 39 |
| 40 static const unsigned cDefaultCacheCapacity = 8192 * 1024; | 40 static const unsigned cDefaultCacheCapacity = 8192 * 1024; |
| 41 static const unsigned cDeferredPruneDeadCapacityFactor = 2; | 41 static const unsigned cDeferredPruneDeadCapacityFactor = 2; |
| 42 static const int cMinDelayBeforeLiveDecodedPrune = 1; // Seconds. | 42 static const int cMinDelayBeforeLiveDecodedPrune = 1; // Seconds. |
| 43 static const double cMaxPruneDeferralDelay = 0.5; // Seconds. | 43 static const double cMaxPruneDeferralDelay = 0.5; // Seconds. |
| 44 static const float cTargetPrunePercentage = | 44 |
| 45 .95f; // Percentage of capacity toward which we prune, to avoid immediately
pruning again. | 45 // Percentage of capacity toward which we prune, to avoid immediately pruning |
| 46 // again. |
| 47 static const float cTargetPrunePercentage = .95f; |
| 46 | 48 |
| 47 MemoryCache* memoryCache() { | 49 MemoryCache* memoryCache() { |
| 48 DCHECK(WTF::isMainThread()); | 50 DCHECK(WTF::isMainThread()); |
| 49 if (!gMemoryCache) | 51 if (!gMemoryCache) |
| 50 gMemoryCache = new Persistent<MemoryCache>(MemoryCache::create()); | 52 gMemoryCache = new Persistent<MemoryCache>(MemoryCache::create()); |
| 51 return gMemoryCache->get(); | 53 return gMemoryCache->get(); |
| 52 } | 54 } |
| 53 | 55 |
| 54 MemoryCache* replaceMemoryCacheForTesting(MemoryCache* cache) { | 56 MemoryCache* replaceMemoryCacheForTesting(MemoryCache* cache) { |
| 55 memoryCache(); | 57 memoryCache(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 visitor->trace(m_allResources); | 124 visitor->trace(m_allResources); |
| 123 visitor->trace(m_liveDecodedResources); | 125 visitor->trace(m_liveDecodedResources); |
| 124 visitor->trace(m_resourceMaps); | 126 visitor->trace(m_resourceMaps); |
| 125 MemoryCacheDumpClient::trace(visitor); | 127 MemoryCacheDumpClient::trace(visitor); |
| 126 MemoryCoordinatorClient::trace(visitor); | 128 MemoryCoordinatorClient::trace(visitor); |
| 127 } | 129 } |
| 128 | 130 |
| 129 KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) { | 131 KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) { |
| 130 if (!originalURL.hasFragmentIdentifier()) | 132 if (!originalURL.hasFragmentIdentifier()) |
| 131 return originalURL; | 133 return originalURL; |
| 132 // Strip away fragment identifier from HTTP URLs. | 134 // Strip away fragment identifier from HTTP URLs. Data URLs must be |
| 133 // Data URLs must be unmodified. For file and custom URLs clients may expect r
esources | 135 // unmodified. For file and custom URLs clients may expect resources to be |
| 134 // to be unique even when they differ by the fragment identifier only. | 136 // unique even when they differ by the fragment identifier only. |
| 135 if (!originalURL.protocolIsInHTTPFamily()) | 137 if (!originalURL.protocolIsInHTTPFamily()) |
| 136 return originalURL; | 138 return originalURL; |
| 137 KURL url = originalURL; | 139 KURL url = originalURL; |
| 138 url.removeFragmentIdentifier(); | 140 url.removeFragmentIdentifier(); |
| 139 return url; | 141 return url; |
| 140 } | 142 } |
| 141 | 143 |
| 142 String MemoryCache::defaultCacheIdentifier() { | 144 String MemoryCache::defaultCacheIdentifier() { |
| 143 return emptyString(); | 145 return emptyString(); |
| 144 } | 146 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 161 CHECK(!contains(resource)); | 163 CHECK(!contains(resource)); |
| 162 resources->set(url, MemoryCacheEntry::create(resource)); | 164 resources->set(url, MemoryCacheEntry::create(resource)); |
| 163 update(resource, 0, resource->size(), true); | 165 update(resource, 0, resource->size(), true); |
| 164 | 166 |
| 165 RESOURCE_LOADING_DVLOG(1) << "MemoryCache::add Added " | 167 RESOURCE_LOADING_DVLOG(1) << "MemoryCache::add Added " |
| 166 << resource->url().getString() << ", resource " | 168 << resource->url().getString() << ", resource " |
| 167 << resource; | 169 << resource; |
| 168 } | 170 } |
| 169 | 171 |
| 170 void MemoryCache::remove(Resource* resource) { | 172 void MemoryCache::remove(Resource* resource) { |
| 171 // The resource may have already been removed by someone other than our caller
, | 173 // The resource may have already been removed by someone other than our |
| 172 // who needed a fresh copy for a reload. | 174 // caller, who needed a fresh copy for a reload. |
| 173 if (MemoryCacheEntry* entry = getEntryForResource(resource)) | 175 if (MemoryCacheEntry* entry = getEntryForResource(resource)) |
| 174 evict(entry); | 176 evict(entry); |
| 175 } | 177 } |
| 176 | 178 |
| 177 bool MemoryCache::contains(const Resource* resource) const { | 179 bool MemoryCache::contains(const Resource* resource) const { |
| 178 return getEntryForResource(resource); | 180 return getEntryForResource(resource); |
| 179 } | 181 } |
| 180 | 182 |
| 181 Resource* MemoryCache::resourceForURL(const KURL& resourceURL) { | 183 Resource* MemoryCache::resourceForURL(const KURL& resourceURL) { |
| 182 return resourceForURL(resourceURL, defaultCacheIdentifier()); | 184 return resourceForURL(resourceURL, defaultCacheIdentifier()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 207 if (MemoryCacheEntry* entry = resourceMapIter.value->get(url)) { | 209 if (MemoryCacheEntry* entry = resourceMapIter.value->get(url)) { |
| 208 Resource* resource = entry->resource(); | 210 Resource* resource = entry->resource(); |
| 209 DCHECK(resource); | 211 DCHECK(resource); |
| 210 results.append(resource); | 212 results.append(resource); |
| 211 } | 213 } |
| 212 } | 214 } |
| 213 return results; | 215 return results; |
| 214 } | 216 } |
| 215 | 217 |
| 216 size_t MemoryCache::deadCapacity() const { | 218 size_t MemoryCache::deadCapacity() const { |
| 217 // Dead resource capacity is whatever space is not occupied by live resources,
bounded by an independent minimum and maximum. | 219 // Dead resource capacity is whatever space is not occupied by live resources, |
| 220 // bounded by an independent minimum and maximum. |
| 218 size_t capacity = | 221 size_t capacity = |
| 219 m_capacity - | 222 m_capacity - |
| 220 std::min(m_liveSize, m_capacity); // Start with available capacity. | 223 std::min(m_liveSize, m_capacity); // Start with available capacity. |
| 221 capacity = std::max(capacity, | 224 capacity = std::max(capacity, |
| 222 m_minDeadCapacity); // Make sure it's above the minimum. | 225 m_minDeadCapacity); // Make sure it's above the minimum. |
| 223 capacity = std::min(capacity, | 226 capacity = std::min(capacity, |
| 224 m_maxDeadCapacity); // Make sure it's below the maximum. | 227 m_maxDeadCapacity); // Make sure it's below the maximum. |
| 225 return capacity; | 228 return capacity; |
| 226 } | 229 } |
| 227 | 230 |
| 228 size_t MemoryCache::liveCapacity() const { | 231 size_t MemoryCache::liveCapacity() const { |
| 229 // Live resource capacity is whatever is left over after calculating dead reso
urce capacity. | 232 // Live resource capacity is whatever is left over after calculating dead |
| 233 // resource capacity. |
| 230 return m_capacity - deadCapacity(); | 234 return m_capacity - deadCapacity(); |
| 231 } | 235 } |
| 232 | 236 |
| 233 void MemoryCache::pruneLiveResources(PruneStrategy strategy) { | 237 void MemoryCache::pruneLiveResources(PruneStrategy strategy) { |
| 234 DCHECK(!m_prunePending); | 238 DCHECK(!m_prunePending); |
| 235 size_t capacity = liveCapacity(); | 239 size_t capacity = liveCapacity(); |
| 236 if (strategy == MaximalPrune) | 240 if (strategy == MaximalPrune) |
| 237 capacity = 0; | 241 capacity = 0; |
| 238 if (!m_liveSize || (capacity && m_liveSize <= capacity)) | 242 if (!m_liveSize || (capacity && m_liveSize <= capacity)) |
| 239 return; | 243 return; |
| 240 | 244 |
| 241 size_t targetSize = static_cast<size_t>( | 245 // Cut by a percentage to avoid immediately pruning again. |
| 242 capacity * | 246 size_t targetSize = static_cast<size_t>(capacity * cTargetPrunePercentage); |
| 243 cTargetPrunePercentage); // Cut by a percentage to avoid immediately prun
ing again. | |
| 244 | 247 |
| 245 // Destroy any decoded data in live objects that we can. | 248 // Destroy any decoded data in live objects that we can. Start from the tail, |
| 246 // Start from the tail, since this is the lowest priority | 249 // since this is the lowest priority and least recently accessed of the |
| 247 // and least recently accessed of the objects. | 250 // objects. |
| 248 | 251 |
| 249 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impact | 252 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impact |
| 250 // of this weaker invariant is minor as the below if statement to check the | 253 // of this weaker invariant is minor as the below if statement to check the |
| 251 // elapsedTime will evaluate to false as the current time will be a lot | 254 // elapsedTime will evaluate to false as the current time will be a lot |
| 252 // greater than the current->m_lastDecodedFrameTimeStamp. | 255 // greater than the current->m_lastDecodedFrameTimeStamp. For more details |
| 253 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 | 256 // see: https://bugs.webkit.org/show_bug.cgi?id=30209 |
| 254 | 257 |
| 255 MemoryCacheEntry* current = m_liveDecodedResources.m_tail; | 258 MemoryCacheEntry* current = m_liveDecodedResources.m_tail; |
| 256 while (current) { | 259 while (current) { |
| 257 Resource* resource = current->resource(); | 260 Resource* resource = current->resource(); |
| 258 MemoryCacheEntry* previous = current->m_previousInLiveResourcesList; | 261 MemoryCacheEntry* previous = current->m_previousInLiveResourcesList; |
| 259 DCHECK(resource->isAlive()); | 262 DCHECK(resource->isAlive()); |
| 260 | 263 |
| 261 if (resource->isLoaded() && resource->decodedSize()) { | 264 if (resource->isLoaded() && resource->decodedSize()) { |
| 262 // Check to see if the remaining resources are too new to prune. | 265 // Check to see if the remaining resources are too new to prune. |
| 263 double elapsedTime = | 266 double elapsedTime = |
| 264 m_pruneFrameTimeStamp - current->m_lastDecodedAccessTime; | 267 m_pruneFrameTimeStamp - current->m_lastDecodedAccessTime; |
| 265 if (strategy == AutomaticPrune && | 268 if (strategy == AutomaticPrune && |
| 266 elapsedTime < m_delayBeforeLiveDecodedPrune) | 269 elapsedTime < m_delayBeforeLiveDecodedPrune) |
| 267 return; | 270 return; |
| 268 | 271 |
| 269 // Destroy our decoded data if possible. This will remove us | 272 // Destroy our decoded data if possible. This will remove us from |
| 270 // from m_liveDecodedResources, and possibly move us to a | 273 // m_liveDecodedResources, and possibly move us to a different LRU list in |
| 271 // different LRU list in m_allResources. | 274 // m_allResources. |
| 272 resource->prune(); | 275 resource->prune(); |
| 273 | 276 |
| 274 if (targetSize && m_liveSize <= targetSize) | 277 if (targetSize && m_liveSize <= targetSize) |
| 275 return; | 278 return; |
| 276 } | 279 } |
| 277 current = previous; | 280 current = previous; |
| 278 } | 281 } |
| 279 } | 282 } |
| 280 | 283 |
| 281 void MemoryCache::pruneDeadResources(PruneStrategy strategy) { | 284 void MemoryCache::pruneDeadResources(PruneStrategy strategy) { |
| 282 size_t capacity = deadCapacity(); | 285 size_t capacity = deadCapacity(); |
| 283 if (strategy == MaximalPrune) | 286 if (strategy == MaximalPrune) |
| 284 capacity = 0; | 287 capacity = 0; |
| 285 if (!m_deadSize || (capacity && m_deadSize <= capacity)) | 288 if (!m_deadSize || (capacity && m_deadSize <= capacity)) |
| 286 return; | 289 return; |
| 287 | 290 |
| 288 size_t targetSize = static_cast<size_t>( | 291 // Cut by a percentage to avoid immediately pruning again. |
| 289 capacity * | 292 size_t targetSize = static_cast<size_t>(capacity * cTargetPrunePercentage); |
| 290 cTargetPrunePercentage); // Cut by a percentage to avoid immediately prun
ing again. | |
| 291 | 293 |
| 292 int size = m_allResources.size(); | 294 int size = m_allResources.size(); |
| 293 if (targetSize && m_deadSize <= targetSize) | 295 if (targetSize && m_deadSize <= targetSize) |
| 294 return; | 296 return; |
| 295 | 297 |
| 296 bool canShrinkLRULists = true; | 298 bool canShrinkLRULists = true; |
| 297 for (int i = size - 1; i >= 0; i--) { | 299 for (int i = size - 1; i >= 0; i--) { |
| 298 // Remove from the tail, since this is the least frequently accessed of the
objects. | 300 // Remove from the tail, since this is the least frequently accessed of the |
| 301 // objects. |
| 299 MemoryCacheEntry* current = m_allResources[i].m_tail; | 302 MemoryCacheEntry* current = m_allResources[i].m_tail; |
| 300 | 303 |
| 301 // First flush all the decoded data in this queue. | 304 // First flush all the decoded data in this queue. |
| 302 while (current) { | 305 while (current) { |
| 303 Resource* resource = current->resource(); | 306 Resource* resource = current->resource(); |
| 304 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; | 307 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
| 305 | 308 |
| 306 // Decoded data may reference other resources. Skip |current| if | 309 // Decoded data may reference other resources. Skip |current| if |current| |
| 307 // |current| somehow got kicked out of cache during | 310 // somehow got kicked out of cache during destroyDecodedData(). |
| 308 // destroyDecodedData(). | |
| 309 if (!resource || !contains(resource)) { | 311 if (!resource || !contains(resource)) { |
| 310 current = previous; | 312 current = previous; |
| 311 continue; | 313 continue; |
| 312 } | 314 } |
| 313 | 315 |
| 314 if (!resource->isAlive() && !resource->isPreloaded() && | 316 if (!resource->isAlive() && !resource->isPreloaded() && |
| 315 resource->isLoaded()) { | 317 resource->isLoaded()) { |
| 316 // Destroy our decoded data. This will remove us from | 318 // Destroy our decoded data. This will remove us from |
| 317 // m_liveDecodedResources, and possibly move us to a different | 319 // m_liveDecodedResources, and possibly move us to a different LRU list |
| 318 // LRU list in m_allResources. | 320 // in m_allResources. |
| 319 resource->prune(); | 321 resource->prune(); |
| 320 | 322 |
| 321 if (targetSize && m_deadSize <= targetSize) | 323 if (targetSize && m_deadSize <= targetSize) |
| 322 return; | 324 return; |
| 323 } | 325 } |
| 324 current = previous; | 326 current = previous; |
| 325 } | 327 } |
| 326 | 328 |
| 327 // Now evict objects from this queue. | 329 // Now evict objects from this queue. |
| 328 current = m_allResources[i].m_tail; | 330 current = m_allResources[i].m_tail; |
| 329 while (current) { | 331 while (current) { |
| 330 Resource* resource = current->resource(); | 332 Resource* resource = current->resource(); |
| 331 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; | 333 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
| 332 if (!resource || !contains(resource)) { | 334 if (!resource || !contains(resource)) { |
| 333 current = previous; | 335 current = previous; |
| 334 continue; | 336 continue; |
| 335 } | 337 } |
| 336 if (!resource->isAlive() && !resource->isPreloaded()) { | 338 if (!resource->isAlive() && !resource->isPreloaded()) { |
| 337 evict(current); | 339 evict(current); |
| 338 if (targetSize && m_deadSize <= targetSize) | 340 if (targetSize && m_deadSize <= targetSize) |
| 339 return; | 341 return; |
| 340 } | 342 } |
| 341 current = previous; | 343 current = previous; |
| 342 } | 344 } |
| 343 | 345 |
| 344 // Shrink the vector back down so we don't waste time inspecting | 346 // Shrink the vector back down so we don't waste time inspecting empty LRU |
| 345 // empty LRU lists on future prunes. | 347 // lists on future prunes. |
| 346 if (m_allResources[i].m_head) | 348 if (m_allResources[i].m_head) |
| 347 canShrinkLRULists = false; | 349 canShrinkLRULists = false; |
| 348 else if (canShrinkLRULists) | 350 else if (canShrinkLRULists) |
| 349 m_allResources.resize(i); | 351 m_allResources.resize(i); |
| 350 } | 352 } |
| 351 } | 353 } |
| 352 | 354 |
| 353 void MemoryCache::setCapacities(size_t minDeadBytes, | 355 void MemoryCache::setCapacities(size_t minDeadBytes, |
| 354 size_t maxDeadBytes, | 356 size_t maxDeadBytes, |
| 355 size_t totalBytes) { | 357 size_t totalBytes) { |
| 356 DCHECK_LE(minDeadBytes, maxDeadBytes); | 358 DCHECK_LE(minDeadBytes, maxDeadBytes); |
| 357 DCHECK_LE(maxDeadBytes, totalBytes); | 359 DCHECK_LE(maxDeadBytes, totalBytes); |
| 358 m_minDeadCapacity = minDeadBytes; | 360 m_minDeadCapacity = minDeadBytes; |
| 359 m_maxDeadCapacity = maxDeadBytes; | 361 m_maxDeadCapacity = maxDeadBytes; |
| 360 m_maxDeferredPruneDeadCapacity = | 362 m_maxDeferredPruneDeadCapacity = |
| 361 cDeferredPruneDeadCapacityFactor * maxDeadBytes; | 363 cDeferredPruneDeadCapacityFactor * maxDeadBytes; |
| 362 m_capacity = totalBytes; | 364 m_capacity = totalBytes; |
| 363 prune(); | 365 prune(); |
| 364 } | 366 } |
| 365 | 367 |
| 366 void MemoryCache::evict(MemoryCacheEntry* entry) { | 368 void MemoryCache::evict(MemoryCacheEntry* entry) { |
| 367 DCHECK(WTF::isMainThread()); | 369 DCHECK(WTF::isMainThread()); |
| 368 | 370 |
| 369 Resource* resource = entry->resource(); | 371 Resource* resource = entry->resource(); |
| 370 DCHECK(resource); | 372 DCHECK(resource); |
| 371 RESOURCE_LOADING_DVLOG(1) << "Evicting resource " << resource << " for " | 373 RESOURCE_LOADING_DVLOG(1) << "Evicting resource " << resource << " for " |
| 372 << resource->url().getString() << " from cache"; | 374 << resource->url().getString() << " from cache"; |
| 373 TRACE_EVENT1("blink", "MemoryCache::evict", "resource", | 375 TRACE_EVENT1("blink", "MemoryCache::evict", "resource", |
| 374 resource->url().getString().utf8()); | 376 resource->url().getString().utf8()); |
| 375 // The resource may have already been removed by someone other than our caller
, | 377 // The resource may have already been removed by someone other than our |
| 376 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bug.
cgi?id=12479#c6>. | 378 // caller, who needed a fresh copy for a reload. See |
| 379 // <http://bugs.webkit.org/show_bug.cgi?id=12479#c6>. |
| 377 update(resource, resource->size(), 0, false); | 380 update(resource, resource->size(), 0, false); |
| 378 removeFromLiveDecodedResourcesList(entry); | 381 removeFromLiveDecodedResourcesList(entry); |
| 379 | 382 |
| 380 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier()); | 383 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier()); |
| 381 DCHECK(resources); | 384 DCHECK(resources); |
| 382 KURL url = removeFragmentIdentifierIfNeeded(resource->url()); | 385 KURL url = removeFragmentIdentifierIfNeeded(resource->url()); |
| 383 ResourceMap::iterator it = resources->find(url); | 386 ResourceMap::iterator it = resources->find(url); |
| 384 DCHECK_NE(it, resources->end()); | 387 DCHECK_NE(it, resources->end()); |
| 385 | 388 |
| 386 MemoryCacheEntry* entryPtr = it->value; | 389 MemoryCacheEntry* entryPtr = it->value; |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 537 } |
| 535 | 538 |
| 536 void MemoryCache::update(Resource* resource, | 539 void MemoryCache::update(Resource* resource, |
| 537 size_t oldSize, | 540 size_t oldSize, |
| 538 size_t newSize, | 541 size_t newSize, |
| 539 bool wasAccessed) { | 542 bool wasAccessed) { |
| 540 MemoryCacheEntry* entry = getEntryForResource(resource); | 543 MemoryCacheEntry* entry = getEntryForResource(resource); |
| 541 if (!entry) | 544 if (!entry) |
| 542 return; | 545 return; |
| 543 | 546 |
| 544 // The object must now be moved to a different queue, since either its size or
its accessCount has been changed, | 547 // The object must now be moved to a different queue, since either its size or |
| 545 // and both of those are used to determine which LRU queue the resource should
be in. | 548 // its accessCount has been changed, and both of those are used to determine |
| 549 // which LRU queue the resource should be in. |
| 546 if (oldSize) | 550 if (oldSize) |
| 547 removeFromLRUList(entry, lruListFor(entry->m_accessCount, oldSize)); | 551 removeFromLRUList(entry, lruListFor(entry->m_accessCount, oldSize)); |
| 548 if (wasAccessed) | 552 if (wasAccessed) |
| 549 entry->m_accessCount++; | 553 entry->m_accessCount++; |
| 550 if (newSize) | 554 if (newSize) |
| 551 insertInLRUList(entry, lruListFor(entry->m_accessCount, newSize)); | 555 insertInLRUList(entry, lruListFor(entry->m_accessCount, newSize)); |
| 552 | 556 |
| 553 ptrdiff_t delta = newSize - oldSize; | 557 ptrdiff_t delta = newSize - oldSize; |
| 554 if (resource->isAlive()) { | 558 if (resource->isAlive()) { |
| 555 DCHECK(delta >= 0 || m_liveSize >= static_cast<size_t>(-delta)); | 559 DCHECK(delta >= 0 || m_liveSize >= static_cast<size_t>(-delta)); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 | 649 |
| 646 void MemoryCache::prune() { | 650 void MemoryCache::prune() { |
| 647 TRACE_EVENT0("renderer", "MemoryCache::prune()"); | 651 TRACE_EVENT0("renderer", "MemoryCache::prune()"); |
| 648 | 652 |
| 649 if (m_inPruneResources) | 653 if (m_inPruneResources) |
| 650 return; | 654 return; |
| 651 if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && | 655 if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && |
| 652 m_deadSize <= m_maxDeadCapacity) // Fast path. | 656 m_deadSize <= m_maxDeadCapacity) // Fast path. |
| 653 return; | 657 return; |
| 654 | 658 |
| 655 // To avoid burdening the current thread with repetitive pruning jobs, | 659 // To avoid burdening the current thread with repetitive pruning jobs, pruning |
| 656 // pruning is postponed until the end of the current task. If it has | 660 // is postponed until the end of the current task. If it has been more than |
| 657 // been more than m_maxPruneDeferralDelay since the last prune, | 661 // m_maxPruneDeferralDelay since the last prune, then we prune immediately. If |
| 658 // then we prune immediately. | 662 // the current thread's run loop is not active, then pruning will happen |
| 659 // If the current thread's run loop is not active, then pruning will happen | 663 // immediately only if it has been over m_maxPruneDeferralDelay since the last |
| 660 // immediately only if it has been over m_maxPruneDeferralDelay | 664 // prune. |
| 661 // since the last prune. | |
| 662 double currentTime = WTF::currentTime(); | 665 double currentTime = WTF::currentTime(); |
| 663 if (m_prunePending) { | 666 if (m_prunePending) { |
| 664 if (currentTime - m_pruneTimeStamp >= m_maxPruneDeferralDelay) { | 667 if (currentTime - m_pruneTimeStamp >= m_maxPruneDeferralDelay) { |
| 665 pruneNow(currentTime, AutomaticPrune); | 668 pruneNow(currentTime, AutomaticPrune); |
| 666 } | 669 } |
| 667 } else { | 670 } else { |
| 668 if (currentTime - m_pruneTimeStamp >= m_maxPruneDeferralDelay) { | 671 if (currentTime - m_pruneTimeStamp >= m_maxPruneDeferralDelay) { |
| 669 pruneNow(currentTime, AutomaticPrune); // Delay exceeded, prune now. | 672 pruneNow(currentTime, AutomaticPrune); // Delay exceeded, prune now. |
| 670 } else { | 673 } else { |
| 671 // Defer. | 674 // Defer. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 688 pruneNow(currentTime, MaximalPrune); | 691 pruneNow(currentTime, MaximalPrune); |
| 689 } | 692 } |
| 690 | 693 |
| 691 void MemoryCache::pruneNow(double currentTime, PruneStrategy strategy) { | 694 void MemoryCache::pruneNow(double currentTime, PruneStrategy strategy) { |
| 692 if (m_prunePending) { | 695 if (m_prunePending) { |
| 693 m_prunePending = false; | 696 m_prunePending = false; |
| 694 Platform::current()->currentThread()->removeTaskObserver(this); | 697 Platform::current()->currentThread()->removeTaskObserver(this); |
| 695 } | 698 } |
| 696 | 699 |
| 697 AutoReset<bool> reentrancyProtector(&m_inPruneResources, true); | 700 AutoReset<bool> reentrancyProtector(&m_inPruneResources, true); |
| 698 pruneDeadResources( | 701 |
| 699 strategy); // Prune dead first, in case it was "borrowing" capacity from
live. | 702 // Prune dead first, in case it was "borrowing" capacity from live. |
| 703 pruneDeadResources(strategy); |
| 700 pruneLiveResources(strategy); | 704 pruneLiveResources(strategy); |
| 701 m_pruneFrameTimeStamp = m_lastFramePaintTimeStamp; | 705 m_pruneFrameTimeStamp = m_lastFramePaintTimeStamp; |
| 702 m_pruneTimeStamp = currentTime; | 706 m_pruneTimeStamp = currentTime; |
| 703 } | 707 } |
| 704 | 708 |
| 705 void MemoryCache::updateFramePaintTimestamp() { | 709 void MemoryCache::updateFramePaintTimestamp() { |
| 706 m_lastFramePaintTimeStamp = currentTime(); | 710 m_lastFramePaintTimeStamp = currentTime(); |
| 707 } | 711 } |
| 708 | 712 |
| 709 bool MemoryCache::onMemoryDump(WebMemoryDumpLevelOfDetail levelOfDetail, | 713 bool MemoryCache::onMemoryDump(WebMemoryDumpLevelOfDetail levelOfDetail, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 bool MemoryCache::isInSameLRUListForTest(const Resource* x, const Resource* y) { | 757 bool MemoryCache::isInSameLRUListForTest(const Resource* x, const Resource* y) { |
| 754 MemoryCacheEntry* ex = getEntryForResource(x); | 758 MemoryCacheEntry* ex = getEntryForResource(x); |
| 755 MemoryCacheEntry* ey = getEntryForResource(y); | 759 MemoryCacheEntry* ey = getEntryForResource(y); |
| 756 DCHECK(ex); | 760 DCHECK(ex); |
| 757 DCHECK(ey); | 761 DCHECK(ey); |
| 758 return lruListFor(ex->m_accessCount, x->size()) == | 762 return lruListFor(ex->m_accessCount, x->size()) == |
| 759 lruListFor(ey->m_accessCount, y->size()); | 763 lruListFor(ey->m_accessCount, y->size()); |
| 760 } | 764 } |
| 761 | 765 |
| 762 } // namespace blink | 766 } // namespace blink |
| OLD | NEW |