Index: Source/core/fetch/MemoryCache.cpp |
diff --git a/Source/core/fetch/MemoryCache.cpp b/Source/core/fetch/MemoryCache.cpp |
index 208ade0cfca0f96f8504c0522baee41ae5ecab34..4e0d6023a6601d46e792b103183c77e4eb2362d9 100644 |
--- a/Source/core/fetch/MemoryCache.cpp |
+++ b/Source/core/fetch/MemoryCache.cpp |
@@ -111,8 +111,7 @@ void MemoryCache::add(Resource* resource) |
ASSERT(WTF::isMainThread()); |
ASSERT(!m_resources.contains(resource->url())); |
m_resources.set(resource->url(), MemoryCacheEntry::create(resource)); |
- resource->setInCache(true); |
- resource->updateForAccess(); |
+ update(resource, 0, resource->size(), true); |
WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resource->url().string().latin1().data(), resource); |
} |
@@ -120,15 +119,17 @@ void MemoryCache::add(Resource* resource) |
void MemoryCache::replace(Resource* newResource, Resource* oldResource) |
{ |
evict(oldResource); |
- ASSERT(!m_resources.contains(newResource->url())); |
- m_resources.set(newResource->url(), MemoryCacheEntry::create(newResource)); |
- newResource->setInCache(true); |
- insertInLRUList(newResource); |
- int delta = newResource->size(); |
+ add(newResource); |
if (newResource->decodedSize() && newResource->hasClients()) |
insertInLiveDecodedResourcesList(newResource); |
- if (delta) |
- adjustSize(newResource->hasClients(), delta); |
+} |
+ |
+bool MemoryCache::contains(Resource* resource) |
+{ |
+ if (resource->url().isNull()) |
+ return false; |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ return entry && entry->m_resource == resource; |
} |
Resource* MemoryCache::resourceForURL(const KURL& resourceURL) |
@@ -242,7 +243,7 @@ void MemoryCache::pruneDeadResources() |
while (current) { |
// Protect 'previous' so it can't get deleted during destroyDecodedData(). |
MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
- ASSERT(!previous || previous->m_resource->inCache()); |
+ ASSERT(!previous || contains(previous->m_resource.get())); |
if (!current->m_resource->hasClients() && !current->m_resource->isPreloaded() && current->m_resource->isLoaded()) { |
// Destroy our decoded data. This will remove us from |
// m_liveDecodedResources, and possibly move us to a different |
@@ -254,7 +255,7 @@ void MemoryCache::pruneDeadResources() |
} |
// Decoded data may reference other resources. Stop iterating if 'previous' somehow got |
// kicked out of cache during destroyDecodedData(). |
- if (previous && !previous->m_resource->inCache()) |
+ if (previous && !contains(previous->m_resource.get())) |
break; |
current = previous; |
} |
@@ -263,13 +264,13 @@ void MemoryCache::pruneDeadResources() |
current = m_allResources[i].m_tail; |
while (current) { |
MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
- ASSERT(!previous || previous->m_resource->inCache()); |
+ ASSERT(!previous || contains(previous->m_resource.get())); |
if (!current->m_resource->hasClients() && !current->m_resource->isPreloaded() && !current->m_resource->isCacheValidator()) { |
evict(current->m_resource.get()); |
if (targetSize && m_deadSize <= targetSize) |
return; |
} |
- if (previous && !previous->m_resource->inCache()) |
+ if (previous && !contains(previous->m_resource.get())) |
break; |
current = previous; |
} |
@@ -300,42 +301,28 @@ bool MemoryCache::evict(Resource* resource) |
WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resource, resource->url().string().latin1().data()); |
// The resource may have already been removed by someone other than our caller, |
// who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bug.cgi?id=12479#c6>. |
- if (resource->inCache()) { |
- // Remove from the appropriate LRU list. |
- removeFromLRUList(resource); |
+ if (contains(resource)) { |
+ update(resource, resource->size(), 0, false); |
removeFromLiveDecodedResourcesList(resource); |
- adjustSize(resource->hasClients(), -static_cast<ptrdiff_t>(resource->size())); |
// Remove from the resource map. |
m_resources.remove(resource->url()); |
- resource->setInCache(false); |
- } else { |
- ASSERT(!m_resources.get(resource->url()) || m_resources.get(resource->url())->m_resource != resource); |
} |
return resource->deleteIfPossible(); |
} |
-MemoryCache::LRUList* MemoryCache::lruListFor(MemoryCacheEntry* entry) |
+MemoryCache::LRUList* MemoryCache::lruListFor(unsigned accessCount, size_t size) |
{ |
- unsigned accessCount = std::max(entry->m_resource->accessCount(), 1U); |
- unsigned queueIndex = WTF::fastLog2(entry->m_resource->size() / accessCount); |
+ ASSERT(accessCount > 0); |
+ unsigned queueIndex = WTF::fastLog2(size / accessCount); |
if (m_allResources.size() <= queueIndex) |
m_allResources.grow(queueIndex + 1); |
return &m_allResources[queueIndex]; |
} |
-void MemoryCache::removeFromLRUList(Resource* resource) |
+void MemoryCache::removeFromLRUList(MemoryCacheEntry* entry, LRUList* list) |
{ |
- MemoryCacheEntry* entry = m_resources.get(resource->url()); |
- ASSERT(entry->m_resource == resource); |
- |
- LRUList* list = lruListFor(entry); |
- MemoryCacheEntry* next = entry->m_nextInAllResourcesList; |
- MemoryCacheEntry* previous = entry->m_previousInAllResourcesList; |
- if (!next && !previous && list->m_head != entry) |
- return; |
- |
#if !ASSERT_DISABLED |
// Verify that we are in fact in this list. |
bool found = false; |
@@ -348,6 +335,8 @@ void MemoryCache::removeFromLRUList(Resource* resource) |
ASSERT(found); |
#endif |
+ MemoryCacheEntry* next = entry->m_nextInAllResourcesList; |
+ MemoryCacheEntry* previous = entry->m_previousInAllResourcesList; |
entry->m_nextInAllResourcesList = 0; |
entry->m_previousInAllResourcesList = 0; |
@@ -362,28 +351,20 @@ void MemoryCache::removeFromLRUList(Resource* resource) |
list->m_head = next; |
} |
-void MemoryCache::insertInLRUList(Resource* resource) |
+void MemoryCache::insertInLRUList(MemoryCacheEntry* entry, LRUList* list) |
{ |
- MemoryCacheEntry* entry = m_resources.get(resource->url()); |
- ASSERT(entry->m_resource == resource); |
- |
- // Make sure we aren't in some list already. |
ASSERT(!entry->m_nextInAllResourcesList && !entry->m_previousInAllResourcesList); |
- ASSERT(resource->inCache()); |
- |
- LRUList* list = lruListFor(entry); |
entry->m_nextInAllResourcesList = list->m_head; |
- if (list->m_head) |
- list->m_head->m_previousInAllResourcesList = entry; |
list->m_head = entry; |
- if (!entry->m_nextInAllResourcesList) |
+ if (entry->m_nextInAllResourcesList) |
+ entry->m_nextInAllResourcesList->m_previousInAllResourcesList = entry; |
+ else |
list->m_tail = entry; |
#if !ASSERT_DISABLED |
// Verify that we are in now in the list like we should be. |
- list = lruListFor(entry); |
bool found = false; |
for (MemoryCacheEntry* current = list->m_head; current; current = current->m_nextInAllResourcesList) { |
if (current == entry) { |
@@ -470,8 +451,8 @@ void MemoryCache::insertInLiveDecodedResourcesList(Resource* resource) |
bool MemoryCache::isInLiveDecodedResourcesList(Resource* resource) |
{ |
MemoryCacheEntry* entry = m_resources.get(resource->url()); |
- ASSERT(entry->m_resource == resource); |
- return entry ? entry->m_inLiveDecodedResourcesList : false; |
+ ASSERT(entry && entry->m_resource == resource); |
+ return entry->m_inLiveDecodedResourcesList; |
} |
void MemoryCache::addToLiveResourcesSize(Resource* resource) |
@@ -488,9 +469,22 @@ void MemoryCache::removeFromLiveResourcesSize(Resource* resource) |
m_deadSize += resource->size(); |
} |
-void MemoryCache::adjustSize(bool live, ptrdiff_t delta) |
+void MemoryCache::update(Resource* resource, size_t oldSize, size_t newSize, bool wasAccessed) |
{ |
- if (live) { |
+ ASSERT(contains(resource)); |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ |
+ // The object must now be moved to a different queue, since either its size or its accessCount has been changed, |
+ // and both of those are used to determine which LRU queue the resource should be in. |
+ if (oldSize) |
+ removeFromLRUList(entry, lruListFor(entry->m_accessCount, oldSize)); |
+ if (wasAccessed) |
+ entry->m_accessCount++; |
+ if (newSize) |
+ insertInLRUList(entry, lruListFor(entry->m_accessCount, newSize)); |
+ |
+ ptrdiff_t delta = newSize - oldSize; |
+ if (resource->hasClients()) { |
ASSERT(delta >= 0 || m_liveSize >= static_cast<size_t>(-delta) ); |
m_liveSize += delta; |
} else { |