Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(505)

Side by Side Diff: Source/core/fetch/MemoryCache.cpp

Issue 164333008: Make MemoryCache's LRUList manipulation private (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/fetch/MemoryCache.h ('k') | Source/core/fetch/MemoryCacheTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 ASSERT(!m_resources.contains(resource->url())); 112 ASSERT(!m_resources.contains(resource->url()));
113 m_resources.set(resource->url(), MemoryCacheEntry::create(resource)); 113 m_resources.set(resource->url(), MemoryCacheEntry::create(resource));
114 resource->setInCache(true); 114 update(resource, 0, resource->size(), true);
115 resource->updateForAccess();
116 115
117 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou rce->url().string().latin1().data(), resource); 116 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou rce->url().string().latin1().data(), resource);
118 } 117 }
119 118
120 void MemoryCache::replace(Resource* newResource, Resource* oldResource) 119 void MemoryCache::replace(Resource* newResource, Resource* oldResource)
121 { 120 {
122 evict(oldResource); 121 evict(oldResource);
123 ASSERT(!m_resources.contains(newResource->url())); 122 add(newResource);
124 m_resources.set(newResource->url(), MemoryCacheEntry::create(newResource));
125 newResource->setInCache(true);
126 insertInLRUList(newResource);
127 int delta = newResource->size();
128 if (newResource->decodedSize() && newResource->hasClients()) 123 if (newResource->decodedSize() && newResource->hasClients())
129 insertInLiveDecodedResourcesList(newResource); 124 insertInLiveDecodedResourcesList(newResource);
130 if (delta) 125 }
131 adjustSize(newResource->hasClients(), delta); 126
127 bool MemoryCache::contains(Resource* resource)
128 {
129 if (resource->url().isNull())
130 return false;
131 MemoryCacheEntry* entry = m_resources.get(resource->url());
132 return entry && entry->m_resource == resource;
132 } 133 }
133 134
134 Resource* MemoryCache::resourceForURL(const KURL& resourceURL) 135 Resource* MemoryCache::resourceForURL(const KURL& resourceURL)
135 { 136 {
136 ASSERT(WTF::isMainThread()); 137 ASSERT(WTF::isMainThread());
137 KURL url = removeFragmentIdentifierIfNeeded(resourceURL); 138 KURL url = removeFragmentIdentifierIfNeeded(resourceURL);
138 MemoryCacheEntry* entry = m_resources.get(url); 139 MemoryCacheEntry* entry = m_resources.get(url);
139 if (!entry) 140 if (!entry)
140 return 0; 141 return 0;
141 Resource* resource = entry->m_resource.get(); 142 Resource* resource = entry->m_resource.get();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 236
236 bool canShrinkLRULists = true; 237 bool canShrinkLRULists = true;
237 for (int i = size - 1; i >= 0; i--) { 238 for (int i = size - 1; i >= 0; i--) {
238 // Remove from the tail, since this is the least frequently accessed of the objects. 239 // Remove from the tail, since this is the least frequently accessed of the objects.
239 MemoryCacheEntry* current = m_allResources[i].m_tail; 240 MemoryCacheEntry* current = m_allResources[i].m_tail;
240 241
241 // First flush all the decoded data in this queue. 242 // First flush all the decoded data in this queue.
242 while (current) { 243 while (current) {
243 // Protect 'previous' so it can't get deleted during destroyDecodedD ata(). 244 // Protect 'previous' so it can't get deleted during destroyDecodedD ata().
244 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; 245 MemoryCacheEntry* previous = current->m_previousInAllResourcesList;
245 ASSERT(!previous || previous->m_resource->inCache()); 246 ASSERT(!previous || contains(previous->m_resource.get()));
246 if (!current->m_resource->hasClients() && !current->m_resource->isPr eloaded() && current->m_resource->isLoaded()) { 247 if (!current->m_resource->hasClients() && !current->m_resource->isPr eloaded() && current->m_resource->isLoaded()) {
247 // Destroy our decoded data. This will remove us from 248 // Destroy our decoded data. This will remove us from
248 // m_liveDecodedResources, and possibly move us to a different 249 // m_liveDecodedResources, and possibly move us to a different
249 // LRU list in m_allResources. 250 // LRU list in m_allResources.
250 current->m_resource->prune(); 251 current->m_resource->prune();
251 252
252 if (targetSize && m_deadSize <= targetSize) 253 if (targetSize && m_deadSize <= targetSize)
253 return; 254 return;
254 } 255 }
255 // Decoded data may reference other resources. Stop iterating if 'pr evious' somehow got 256 // Decoded data may reference other resources. Stop iterating if 'pr evious' somehow got
256 // kicked out of cache during destroyDecodedData(). 257 // kicked out of cache during destroyDecodedData().
257 if (previous && !previous->m_resource->inCache()) 258 if (previous && !contains(previous->m_resource.get()))
258 break; 259 break;
259 current = previous; 260 current = previous;
260 } 261 }
261 262
262 // Now evict objects from this queue. 263 // Now evict objects from this queue.
263 current = m_allResources[i].m_tail; 264 current = m_allResources[i].m_tail;
264 while (current) { 265 while (current) {
265 MemoryCacheEntry* previous = current->m_previousInAllResourcesList; 266 MemoryCacheEntry* previous = current->m_previousInAllResourcesList;
266 ASSERT(!previous || previous->m_resource->inCache()); 267 ASSERT(!previous || contains(previous->m_resource.get()));
267 if (!current->m_resource->hasClients() && !current->m_resource->isPr eloaded() && !current->m_resource->isCacheValidator()) { 268 if (!current->m_resource->hasClients() && !current->m_resource->isPr eloaded() && !current->m_resource->isCacheValidator()) {
268 evict(current->m_resource.get()); 269 evict(current->m_resource.get());
269 if (targetSize && m_deadSize <= targetSize) 270 if (targetSize && m_deadSize <= targetSize)
270 return; 271 return;
271 } 272 }
272 if (previous && !previous->m_resource->inCache()) 273 if (previous && !contains(previous->m_resource.get()))
273 break; 274 break;
274 current = previous; 275 current = previous;
275 } 276 }
276 277
277 // Shrink the vector back down so we don't waste time inspecting 278 // Shrink the vector back down so we don't waste time inspecting
278 // empty LRU lists on future prunes. 279 // empty LRU lists on future prunes.
279 if (m_allResources[i].m_head) 280 if (m_allResources[i].m_head)
280 canShrinkLRULists = false; 281 canShrinkLRULists = false;
281 else if (canShrinkLRULists) 282 else if (canShrinkLRULists)
282 m_allResources.resize(i); 283 m_allResources.resize(i);
(...skipping 10 matching lines...) Expand all
293 m_capacity = totalBytes; 294 m_capacity = totalBytes;
294 prune(); 295 prune();
295 } 296 }
296 297
297 bool MemoryCache::evict(Resource* resource) 298 bool MemoryCache::evict(Resource* resource)
298 { 299 {
299 ASSERT(WTF::isMainThread()); 300 ASSERT(WTF::isMainThread());
300 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc e, resource->url().string().latin1().data()); 301 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc e, resource->url().string().latin1().data());
301 // The resource may have already been removed by someone other than our call er, 302 // The resource may have already been removed by someone other than our call er,
302 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu g.cgi?id=12479#c6>. 303 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu g.cgi?id=12479#c6>.
303 if (resource->inCache()) { 304 if (contains(resource)) {
304 // Remove from the appropriate LRU list. 305 update(resource, resource->size(), 0, false);
305 removeFromLRUList(resource);
306 removeFromLiveDecodedResourcesList(resource); 306 removeFromLiveDecodedResourcesList(resource);
307 adjustSize(resource->hasClients(), -static_cast<ptrdiff_t>(resource->siz e()));
308 307
309 // Remove from the resource map. 308 // Remove from the resource map.
310 m_resources.remove(resource->url()); 309 m_resources.remove(resource->url());
311 resource->setInCache(false);
312 } else {
313 ASSERT(!m_resources.get(resource->url()) || m_resources.get(resource->ur l())->m_resource != resource);
314 } 310 }
315 311
316 return resource->deleteIfPossible(); 312 return resource->deleteIfPossible();
317 } 313 }
318 314
319 MemoryCache::LRUList* MemoryCache::lruListFor(MemoryCacheEntry* entry) 315 MemoryCache::LRUList* MemoryCache::lruListFor(unsigned accessCount, size_t size)
320 { 316 {
321 unsigned accessCount = std::max(entry->m_resource->accessCount(), 1U); 317 ASSERT(accessCount > 0);
322 unsigned queueIndex = WTF::fastLog2(entry->m_resource->size() / accessCount) ; 318 unsigned queueIndex = WTF::fastLog2(size / accessCount);
323 if (m_allResources.size() <= queueIndex) 319 if (m_allResources.size() <= queueIndex)
324 m_allResources.grow(queueIndex + 1); 320 m_allResources.grow(queueIndex + 1);
325 return &m_allResources[queueIndex]; 321 return &m_allResources[queueIndex];
326 } 322 }
327 323
328 void MemoryCache::removeFromLRUList(Resource* resource) 324 void MemoryCache::removeFromLRUList(MemoryCacheEntry* entry, LRUList* list)
329 { 325 {
330 MemoryCacheEntry* entry = m_resources.get(resource->url());
331 ASSERT(entry->m_resource == resource);
332
333 LRUList* list = lruListFor(entry);
334 MemoryCacheEntry* next = entry->m_nextInAllResourcesList;
335 MemoryCacheEntry* previous = entry->m_previousInAllResourcesList;
336 if (!next && !previous && list->m_head != entry)
337 return;
338
339 #if !ASSERT_DISABLED 326 #if !ASSERT_DISABLED
340 // Verify that we are in fact in this list. 327 // Verify that we are in fact in this list.
341 bool found = false; 328 bool found = false;
342 for (MemoryCacheEntry* current = list->m_head; current; current = current->m _nextInAllResourcesList) { 329 for (MemoryCacheEntry* current = list->m_head; current; current = current->m _nextInAllResourcesList) {
343 if (current == entry) { 330 if (current == entry) {
344 found = true; 331 found = true;
345 break; 332 break;
346 } 333 }
347 } 334 }
348 ASSERT(found); 335 ASSERT(found);
349 #endif 336 #endif
350 337
338 MemoryCacheEntry* next = entry->m_nextInAllResourcesList;
339 MemoryCacheEntry* previous = entry->m_previousInAllResourcesList;
351 entry->m_nextInAllResourcesList = 0; 340 entry->m_nextInAllResourcesList = 0;
352 entry->m_previousInAllResourcesList = 0; 341 entry->m_previousInAllResourcesList = 0;
353 342
354 if (next) 343 if (next)
355 next->m_previousInAllResourcesList = previous; 344 next->m_previousInAllResourcesList = previous;
356 else 345 else
357 list->m_tail = previous; 346 list->m_tail = previous;
358 347
359 if (previous) 348 if (previous)
360 previous->m_nextInAllResourcesList = next; 349 previous->m_nextInAllResourcesList = next;
361 else 350 else
362 list->m_head = next; 351 list->m_head = next;
363 } 352 }
364 353
365 void MemoryCache::insertInLRUList(Resource* resource) 354 void MemoryCache::insertInLRUList(MemoryCacheEntry* entry, LRUList* list)
366 { 355 {
367 MemoryCacheEntry* entry = m_resources.get(resource->url());
368 ASSERT(entry->m_resource == resource);
369
370 // Make sure we aren't in some list already.
371 ASSERT(!entry->m_nextInAllResourcesList && !entry->m_previousInAllResourcesL ist); 356 ASSERT(!entry->m_nextInAllResourcesList && !entry->m_previousInAllResourcesL ist);
372 ASSERT(resource->inCache());
373
374 LRUList* list = lruListFor(entry);
375 357
376 entry->m_nextInAllResourcesList = list->m_head; 358 entry->m_nextInAllResourcesList = list->m_head;
377 if (list->m_head)
378 list->m_head->m_previousInAllResourcesList = entry;
379 list->m_head = entry; 359 list->m_head = entry;
380 360
381 if (!entry->m_nextInAllResourcesList) 361 if (entry->m_nextInAllResourcesList)
362 entry->m_nextInAllResourcesList->m_previousInAllResourcesList = entry;
363 else
382 list->m_tail = entry; 364 list->m_tail = entry;
383 365
384 #if !ASSERT_DISABLED 366 #if !ASSERT_DISABLED
385 // Verify that we are in now in the list like we should be. 367 // Verify that we are in now in the list like we should be.
386 list = lruListFor(entry);
387 bool found = false; 368 bool found = false;
388 for (MemoryCacheEntry* current = list->m_head; current; current = current->m _nextInAllResourcesList) { 369 for (MemoryCacheEntry* current = list->m_head; current; current = current->m _nextInAllResourcesList) {
389 if (current == entry) { 370 if (current == entry) {
390 found = true; 371 found = true;
391 break; 372 break;
392 } 373 }
393 } 374 }
394 ASSERT(found); 375 ASSERT(found);
395 #endif 376 #endif
396 } 377 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 break; 444 break;
464 } 445 }
465 } 446 }
466 ASSERT(found); 447 ASSERT(found);
467 #endif 448 #endif
468 } 449 }
469 450
470 bool MemoryCache::isInLiveDecodedResourcesList(Resource* resource) 451 bool MemoryCache::isInLiveDecodedResourcesList(Resource* resource)
471 { 452 {
472 MemoryCacheEntry* entry = m_resources.get(resource->url()); 453 MemoryCacheEntry* entry = m_resources.get(resource->url());
473 ASSERT(entry->m_resource == resource); 454 ASSERT(entry && entry->m_resource == resource);
474 return entry ? entry->m_inLiveDecodedResourcesList : false; 455 return entry->m_inLiveDecodedResourcesList;
475 } 456 }
476 457
477 void MemoryCache::addToLiveResourcesSize(Resource* resource) 458 void MemoryCache::addToLiveResourcesSize(Resource* resource)
478 { 459 {
479 ASSERT(m_deadSize >= resource->size()); 460 ASSERT(m_deadSize >= resource->size());
480 m_liveSize += resource->size(); 461 m_liveSize += resource->size();
481 m_deadSize -= resource->size(); 462 m_deadSize -= resource->size();
482 } 463 }
483 464
484 void MemoryCache::removeFromLiveResourcesSize(Resource* resource) 465 void MemoryCache::removeFromLiveResourcesSize(Resource* resource)
485 { 466 {
486 ASSERT(m_liveSize >= resource->size()); 467 ASSERT(m_liveSize >= resource->size());
487 m_liveSize -= resource->size(); 468 m_liveSize -= resource->size();
488 m_deadSize += resource->size(); 469 m_deadSize += resource->size();
489 } 470 }
490 471
491 void MemoryCache::adjustSize(bool live, ptrdiff_t delta) 472 void MemoryCache::update(Resource* resource, size_t oldSize, size_t newSize, boo l wasAccessed)
492 { 473 {
493 if (live) { 474 ASSERT(contains(resource));
475 MemoryCacheEntry* entry = m_resources.get(resource->url());
476
477 // The object must now be moved to a different queue, since either its size or its accessCount has been changed,
478 // and both of those are used to determine which LRU queue the resource shou ld be in.
479 if (oldSize)
480 removeFromLRUList(entry, lruListFor(entry->m_accessCount, oldSize));
481 if (wasAccessed)
482 entry->m_accessCount++;
483 if (newSize)
484 insertInLRUList(entry, lruListFor(entry->m_accessCount, newSize));
485
486 ptrdiff_t delta = newSize - oldSize;
487 if (resource->hasClients()) {
494 ASSERT(delta >= 0 || m_liveSize >= static_cast<size_t>(-delta) ); 488 ASSERT(delta >= 0 || m_liveSize >= static_cast<size_t>(-delta) );
495 m_liveSize += delta; 489 m_liveSize += delta;
496 } else { 490 } else {
497 ASSERT(delta >= 0 || m_deadSize >= static_cast<size_t>(-delta) ); 491 ASSERT(delta >= 0 || m_deadSize >= static_cast<size_t>(-delta) );
498 m_deadSize += delta; 492 m_deadSize += delta;
499 } 493 }
500 } 494 }
501 495
502 void MemoryCache::removeURLFromCache(ExecutionContext* context, const KURL& url) 496 void MemoryCache::removeURLFromCache(ExecutionContext* context, const KURL& url)
503 { 497 {
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 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()); 673 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());
680 674
681 current = prev; 675 current = prev;
682 } 676 }
683 } 677 }
684 } 678 }
685 679
686 #endif // MEMORY_CACHE_STATS 680 #endif // MEMORY_CACHE_STATS
687 681
688 } // namespace WebCore 682 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/fetch/MemoryCache.h ('k') | Source/core/fetch/MemoryCacheTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698