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

Side by Side Diff: Source/core/loader/cache/MemoryCache.cpp

Issue 19393004: Allow eviction of ImageBitmaps that are created from ImageElements. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Name change. Created 7 years, 4 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
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.
11 11
12 This library is distributed in the hope that it will be useful, 12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details. 15 Library General Public License for more details.
16 16
17 You should have received a copy of the GNU Library General Public License 17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to 18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. 20 Boston, MA 02110-1301, USA.
21 */ 21 */
22 22
23 #include "config.h" 23 #include "config.h"
24 #include "core/loader/cache/MemoryCache.h" 24 #include "core/loader/cache/MemoryCache.h"
25 25
26 #include <stdio.h> 26 #include <stdio.h>
27 #include "core/dom/CrossThreadTask.h" 27 #include "core/dom/CrossThreadTask.h"
28 #include "core/dom/Document.h" 28 #include "core/dom/Document.h"
29 #include "core/loader/cache/CachedResource.h"
30 #include "core/loader/cache/CachedResourceHandle.h" 29 #include "core/loader/cache/CachedResourceHandle.h"
31 #include "core/page/FrameView.h" 30 #include "core/page/FrameView.h"
32 #include "core/platform/Logging.h" 31 #include "core/platform/Logging.h"
33 #include "core/workers/WorkerGlobalScope.h" 32 #include "core/workers/WorkerGlobalScope.h"
34 #include "core/workers/WorkerLoaderProxy.h" 33 #include "core/workers/WorkerLoaderProxy.h"
35 #include "core/workers/WorkerThread.h" 34 #include "core/workers/WorkerThread.h"
36 #include "weborigin/SecurityOrigin.h" 35 #include "weborigin/SecurityOrigin.h"
37 #include "weborigin/SecurityOriginHash.h" 36 #include "weborigin/SecurityOriginHash.h"
38 #include "wtf/Assertions.h" 37 #include "wtf/Assertions.h"
39 #include "wtf/CurrentTime.h" 38 #include "wtf/CurrentTime.h"
(...skipping 24 matching lines...) Expand all
64 gMemoryCache = memoryCache; 63 gMemoryCache = memoryCache;
65 } 64 }
66 65
67 MemoryCache::MemoryCache() 66 MemoryCache::MemoryCache()
68 : m_inPruneResources(false) 67 : m_inPruneResources(false)
69 , m_capacity(cDefaultCacheCapacity) 68 , m_capacity(cDefaultCacheCapacity)
70 , m_minDeadCapacity(0) 69 , m_minDeadCapacity(0)
71 , m_maxDeadCapacity(cDefaultCacheCapacity) 70 , m_maxDeadCapacity(cDefaultCacheCapacity)
72 , m_liveSize(0) 71 , m_liveSize(0)
73 , m_deadSize(0) 72 , m_deadSize(0)
73 , m_delayBeforeLiveDecodedPrune(cMinDelayBeforeLiveDecodedPrune)
74 #ifdef MEMORY_CACHE_STATS 74 #ifdef MEMORY_CACHE_STATS
75 , m_statsTimer(this, &MemoryCache::dumpStats) 75 , m_statsTimer(this, &MemoryCache::dumpStats)
76 #endif 76 #endif
77 { 77 {
78 #ifdef MEMORY_CACHE_STATS 78 #ifdef MEMORY_CACHE_STATS
79 const double statsIntervalInSeconds = 15; 79 const double statsIntervalInSeconds = 15;
80 m_statsTimer.startRepeating(statsIntervalInSeconds); 80 m_statsTimer.startRepeating(statsIntervalInSeconds);
81 #endif 81 #endif
82 } 82 }
83 83
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 if (capacity && m_liveSize <= capacity) 153 if (capacity && m_liveSize <= capacity)
154 return; 154 return;
155 155
156 unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentag e); // Cut by a percentage to avoid immediately pruning again. 156 unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentag e); // Cut by a percentage to avoid immediately pruning again.
157 157
158 double currentTime = FrameView::currentPaintTimeStamp(); 158 double currentTime = FrameView::currentPaintTimeStamp();
159 if (!currentTime) // In case prune is called directly, outside of a Frame pa int. 159 if (!currentTime) // In case prune is called directly, outside of a Frame pa int.
160 currentTime = WTF::currentTime(); 160 currentTime = WTF::currentTime();
161 161
162 // Destroy any decoded data in live objects that we can. 162 // Destroy any decoded data in live objects that we can.
163 // Start from the tail, since this is the least recently accessed of the obj ects. 163 // Start from the tail, since this is the lowest priority
164 // and least recently accessed of the objects.
164 165
165 // The list might not be sorted by the m_lastDecodedAccessTime. The impact 166 // The list might not be sorted by the m_lastDecodedAccessTime. The impact
166 // of this weaker invariant is minor as the below if statement to check the 167 // of this weaker invariant is minor as the below if statement to check the
167 // elapsedTime will evaluate to false as the currentTime will be a lot 168 // elapsedTime will evaluate to false as the currentTime will be a lot
168 // greater than the current->m_lastDecodedAccessTime. 169 // greater than the current->m_lastDecodedAccessTime.
169 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 170 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209
170 CachedResource* current = m_liveDecodedResources.m_tail;
171 while (current) {
172 CachedResource* prev = current->m_prevInLiveResourcesList;
173 ASSERT(current->hasClients());
174 if (current->isLoaded() && current->decodedSize()) {
175 // Check to see if the remaining resources are too new to prune.
176 double elapsedTime = currentTime - current->m_lastDecodedAccessTime;
177 if (elapsedTime < cMinDelayBeforeLiveDecodedPrune)
178 return;
179 171
180 // Destroy our decoded data. This will remove us from 172 // Start pruning from the lowest priority list.
181 // m_liveDecodedResources, and possibly move us to a different LRU 173 for (int priority = CachedResource::CacheLiveResourcePriorityLow; priority < = CachedResource::CacheLiveResourcePriorityHigh; ++priority) {
182 // list in m_allResources. 174 CachedResource* current = m_liveDecodedResources[priority].m_tail;
183 current->destroyDecodedData(); 175 while (current) {
176 CachedResource* prev = current->m_prevInLiveResourcesList;
177 ASSERT(current->hasClients());
178 if (current->isLoaded() && current->decodedSize()) {
179 // Check to see if the remaining resources are too new to prune.
180 double elapsedTime = currentTime - current->m_lastDecodedAccessT ime;
181 if (elapsedTime < m_delayBeforeLiveDecodedPrune)
182 return;
184 183
185 if (targetSize && m_liveSize <= targetSize) 184 // Destroy our decoded data. This will remove us from
186 return; 185 // m_liveDecodedResources, and possibly move us to a different L RU
186 // list in m_allResources.
187 current->destroyDecodedData();
188
189 if (targetSize && m_liveSize <= targetSize)
190 return;
191 }
192 current = prev;
187 } 193 }
188 current = prev;
189 } 194 }
190 } 195 }
191 196
192 void MemoryCache::pruneDeadResources() 197 void MemoryCache::pruneDeadResources()
193 { 198 {
194 unsigned capacity = deadCapacity(); 199 unsigned capacity = deadCapacity();
195 if (capacity && m_deadSize <= capacity) 200 if (capacity && m_deadSize <= capacity)
196 return; 201 return;
197 202
198 unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentag e); // Cut by a percentage to avoid immediately pruning again. 203 unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentag e); // Cut by a percentage to avoid immediately pruning again.
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 392
388 } 393 }
389 394
390 void MemoryCache::removeFromLiveDecodedResourcesList(CachedResource* resource) 395 void MemoryCache::removeFromLiveDecodedResourcesList(CachedResource* resource)
391 { 396 {
392 // If we've never been accessed, then we're brand new and not in any list. 397 // If we've never been accessed, then we're brand new and not in any list.
393 if (!resource->m_inLiveDecodedResourcesList) 398 if (!resource->m_inLiveDecodedResourcesList)
394 return; 399 return;
395 resource->m_inLiveDecodedResourcesList = false; 400 resource->m_inLiveDecodedResourcesList = false;
396 401
402 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority( )];
403
397 #if !ASSERT_DISABLED 404 #if !ASSERT_DISABLED
398 // Verify that we are in fact in this list. 405 // Verify that we are in fact in this list.
399 bool found = false; 406 bool found = false;
400 for (CachedResource* current = m_liveDecodedResources.m_head; current; curre nt = current->m_nextInLiveResourcesList) { 407 for (CachedResource* current = list->m_head; current; current = current->m_n extInLiveResourcesList) {
401 if (current == resource) { 408 if (current == resource) {
402 found = true; 409 found = true;
403 break; 410 break;
404 } 411 }
405 } 412 }
406 ASSERT(found); 413 ASSERT(found);
407 #endif 414 #endif
408 415
409 CachedResource* next = resource->m_nextInLiveResourcesList; 416 CachedResource* next = resource->m_nextInLiveResourcesList;
410 CachedResource* prev = resource->m_prevInLiveResourcesList; 417 CachedResource* prev = resource->m_prevInLiveResourcesList;
411 418
412 if (next == 0 && prev == 0 && m_liveDecodedResources.m_head != resource) 419 if (!next && !prev && list->m_head != resource)
413 return; 420 return;
414 421
415 resource->m_nextInLiveResourcesList = 0; 422 resource->m_nextInLiveResourcesList = 0;
416 resource->m_prevInLiveResourcesList = 0; 423 resource->m_prevInLiveResourcesList = 0;
417 424
418 if (next) 425 if (next)
419 next->m_prevInLiveResourcesList = prev; 426 next->m_prevInLiveResourcesList = prev;
420 else if (m_liveDecodedResources.m_tail == resource) 427 else if (list->m_tail == resource)
421 m_liveDecodedResources.m_tail = prev; 428 list->m_tail = prev;
422 429
423 if (prev) 430 if (prev)
424 prev->m_nextInLiveResourcesList = next; 431 prev->m_nextInLiveResourcesList = next;
425 else if (m_liveDecodedResources.m_head == resource) 432 else if (list->m_head == resource)
426 m_liveDecodedResources.m_head = next; 433 list->m_head = next;
427 } 434 }
428 435
429 void MemoryCache::insertInLiveDecodedResourcesList(CachedResource* resource) 436 void MemoryCache::insertInLiveDecodedResourcesList(CachedResource* resource)
430 { 437 {
431 // Make sure we aren't in the list already. 438 // Make sure we aren't in the list already.
432 ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResour cesList && !resource->m_inLiveDecodedResourcesList); 439 ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResour cesList && !resource->m_inLiveDecodedResourcesList);
433 resource->m_inLiveDecodedResourcesList = true; 440 resource->m_inLiveDecodedResourcesList = true;
434 441
435 resource->m_nextInLiveResourcesList = m_liveDecodedResources.m_head; 442 LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority( )];
436 if (m_liveDecodedResources.m_head) 443 resource->m_nextInLiveResourcesList = list->m_head;
437 m_liveDecodedResources.m_head->m_prevInLiveResourcesList = resource; 444 if (list->m_head)
438 m_liveDecodedResources.m_head = resource; 445 list->m_head->m_prevInLiveResourcesList = resource;
439 446 list->m_head = resource;
447
440 if (!resource->m_nextInLiveResourcesList) 448 if (!resource->m_nextInLiveResourcesList)
441 m_liveDecodedResources.m_tail = resource; 449 list->m_tail = resource;
442 450
443 #if !ASSERT_DISABLED 451 #if !ASSERT_DISABLED
444 // Verify that we are in now in the list like we should be. 452 // Verify that we are in now in the list like we should be.
445 bool found = false; 453 bool found = false;
446 for (CachedResource* current = m_liveDecodedResources.m_head; current; curre nt = current->m_nextInLiveResourcesList) { 454 for (CachedResource* current = list->m_head; current; current = current->m_n extInLiveResourcesList) {
447 if (current == resource) { 455 if (current == resource) {
448 found = true; 456 found = true;
449 break; 457 break;
450 } 458 }
451 } 459 }
452 ASSERT(found); 460 ASSERT(found);
453 #endif 461 #endif
454 462
455 } 463 }
456 464
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
599 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()); 607 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());
600 608
601 current = prev; 609 current = prev;
602 } 610 }
603 } 611 }
604 } 612 }
605 613
606 #endif // MEMORY_CACHE_STATS 614 #endif // MEMORY_CACHE_STATS
607 615
608 } // namespace WebCore 616 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698