Index: Source/core/fetch/MemoryCache.cpp |
diff --git a/Source/core/fetch/MemoryCache.cpp b/Source/core/fetch/MemoryCache.cpp |
index 489d62b398bf6a1ebd8b57a01089b38f74ad6c42..ba3dcd8d3c1714eef7fcd1e22b7912d81df3e050 100644 |
--- a/Source/core/fetch/MemoryCache.cpp |
+++ b/Source/core/fetch/MemoryCache.cpp |
@@ -109,7 +109,8 @@ KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) |
void MemoryCache::add(Resource* resource) |
{ |
ASSERT(WTF::isMainThread()); |
- m_resources.set(resource->url(), resource); |
+ ASSERT(!m_resources.contains(resource->url())); |
+ m_resources.set(resource->url(), MemoryCacheEntry::create(resource)); |
resource->setInCache(true); |
resource->updateForAccess(); |
@@ -119,8 +120,8 @@ void MemoryCache::add(Resource* resource) |
void MemoryCache::replace(Resource* newResource, Resource* oldResource) |
{ |
evict(oldResource); |
- ASSERT(!m_resources.get(newResource->url())); |
- m_resources.set(newResource->url(), newResource); |
+ ASSERT(!m_resources.contains(newResource->url())); |
+ m_resources.set(newResource->url(), MemoryCacheEntry::create(newResource)); |
newResource->setInCache(true); |
insertInLRUList(newResource); |
int delta = newResource->size(); |
@@ -134,7 +135,10 @@ Resource* MemoryCache::resourceForURL(const KURL& resourceURL) |
{ |
ASSERT(WTF::isMainThread()); |
KURL url = removeFragmentIdentifierIfNeeded(resourceURL); |
- Resource* resource = m_resources.get(url); |
+ MemoryCacheEntry* entry = m_resources.get(url); |
+ if (!entry) |
+ return 0; |
+ Resource* resource = entry->m_resource.get(); |
if (resource && !resource->lock()) { |
ASSERT(!resource->hasClients()); |
bool didEvict = evict(resource); |
@@ -180,25 +184,25 @@ void MemoryCache::pruneLiveResources() |
// Start pruning from the lowest priority list. |
for (int priority = Resource::CacheLiveResourcePriorityLow; priority <= Resource::CacheLiveResourcePriorityHigh; ++priority) { |
- Resource* current = m_liveDecodedResources[priority].m_tail; |
+ MemoryCacheEntry* current = m_liveDecodedResources[priority].m_tail; |
while (current) { |
- Resource* prev = current->m_prevInLiveResourcesList; |
- ASSERT(current->hasClients()); |
- if (current->isLoaded() && current->decodedSize()) { |
+ MemoryCacheEntry* previous = current->m_previousInLiveResourcesList; |
+ ASSERT(current->m_resource->hasClients()); |
+ if (current->m_resource->isLoaded() && current->m_resource->decodedSize()) { |
// Check to see if the remaining resources are too new to prune. |
- double elapsedTime = m_pruneFrameTimeStamp - current->m_lastDecodedAccessTime; |
+ double elapsedTime = m_pruneFrameTimeStamp - current->m_resource->m_lastDecodedAccessTime; |
if (elapsedTime < m_delayBeforeLiveDecodedPrune) |
return; |
// Destroy our decoded data if possible. This will remove us |
// from m_liveDecodedResources, and possibly move us to a |
// different LRU list in m_allResources. |
- current->prune(); |
+ current->m_resource->prune(); |
if (targetSize && m_liveSize <= targetSize) |
return; |
} |
- current = prev; |
+ current = previous; |
} |
} |
} |
@@ -215,15 +219,15 @@ void MemoryCache::pruneDeadResources() |
// See if we have any purged resources we can evict. |
for (int i = 0; i < size; i++) { |
- Resource* current = m_allResources[i].m_tail; |
+ MemoryCacheEntry* current = m_allResources[i].m_tail; |
while (current) { |
- Resource* prev = current->m_prevInAllResourcesList; |
- if (current->wasPurged()) { |
- ASSERT(!current->hasClients()); |
- ASSERT(!current->isPreloaded()); |
- evict(current); |
+ MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
+ if (current->m_resource->wasPurged()) { |
+ ASSERT(!current->m_resource->hasClients()); |
+ ASSERT(!current->m_resource->isPreloaded()); |
+ evict(current->m_resource.get()); |
} |
- current = prev; |
+ current = previous; |
} |
} |
if (targetSize && m_deadSize <= targetSize) |
@@ -232,42 +236,42 @@ void MemoryCache::pruneDeadResources() |
bool canShrinkLRULists = true; |
for (int i = size - 1; i >= 0; i--) { |
// Remove from the tail, since this is the least frequently accessed of the objects. |
- Resource* current = m_allResources[i].m_tail; |
+ MemoryCacheEntry* current = m_allResources[i].m_tail; |
// First flush all the decoded data in this queue. |
while (current) { |
// Protect 'previous' so it can't get deleted during destroyDecodedData(). |
- ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; |
- ASSERT(!previous || previous->inCache()); |
- if (!current->hasClients() && !current->isPreloaded() && current->isLoaded()) { |
- // Destroy our decoded data if possible. This will remove us |
- // from m_liveDecodedResources, and possibly move us to a |
- // different LRU list in m_allResources. |
- current->prune(); |
+ MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
+ ASSERT(!previous || previous->m_resource->inCache()); |
+ 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 |
+ // LRU list in m_allResources. |
+ current->m_resource->prune(); |
if (targetSize && m_deadSize <= targetSize) |
return; |
} |
// Decoded data may reference other resources. Stop iterating if 'previous' somehow got |
// kicked out of cache during destroyDecodedData(). |
- if (previous && !previous->inCache()) |
+ if (previous && !previous->m_resource->inCache()) |
break; |
- current = previous.get(); |
+ current = previous; |
} |
// Now evict objects from this queue. |
current = m_allResources[i].m_tail; |
while (current) { |
- ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; |
- ASSERT(!previous || previous->inCache()); |
- if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) { |
- evict(current); |
+ MemoryCacheEntry* previous = current->m_previousInAllResourcesList; |
+ ASSERT(!previous || previous->m_resource->inCache()); |
+ 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->inCache()) |
+ if (previous && !previous->m_resource->inCache()) |
break; |
- current = previous.get(); |
+ current = previous; |
} |
// Shrink the vector back down so we don't waste time inspecting |
@@ -297,28 +301,25 @@ bool MemoryCache::evict(Resource* resource) |
// 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 resource map. |
- m_resources.remove(resource->url()); |
- resource->setInCache(false); |
- |
// Remove from the appropriate LRU list. |
removeFromLRUList(resource); |
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()) != resource); |
+ ASSERT(!m_resources.get(resource->url()) || m_resources.get(resource->url())->m_resource != resource); |
} |
return resource->deleteIfPossible(); |
} |
-MemoryCache::LRUList* MemoryCache::lruListFor(Resource* resource) |
+MemoryCache::LRUList* MemoryCache::lruListFor(MemoryCacheEntry* entry) |
{ |
- unsigned accessCount = std::max(resource->accessCount(), 1U); |
- unsigned queueIndex = WTF::fastLog2(resource->size() / accessCount); |
-#ifndef NDEBUG |
- resource->m_lruIndex = queueIndex; |
-#endif |
+ unsigned accessCount = std::max(entry->m_resource->accessCount(), 1U); |
+ unsigned queueIndex = WTF::fastLog2(entry->m_resource->size() / accessCount); |
if (m_allResources.size() <= queueIndex) |
m_allResources.grow(queueIndex + 1); |
return &m_allResources[queueIndex]; |
@@ -330,20 +331,15 @@ void MemoryCache::removeFromLRUList(Resource* resource) |
if (!resource->accessCount()) |
return; |
-#if !ASSERT_DISABLED |
- unsigned oldListIndex = resource->m_lruIndex; |
-#endif |
- |
- LRUList* list = lruListFor(resource); |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ASSERT(entry->m_resource == resource); |
+ LRUList* list = lruListFor(entry); |
#if !ASSERT_DISABLED |
- // Verify that the list we got is the list we want. |
- ASSERT(resource->m_lruIndex == oldListIndex); |
- |
// Verify that we are in fact in this list. |
bool found = false; |
- for (Resource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { |
- if (current == resource) { |
+ for (MemoryCacheEntry* current = list->m_head; current; current = current->m_nextInAllResourcesList) { |
+ if (current == entry) { |
found = true; |
break; |
} |
@@ -351,72 +347,74 @@ void MemoryCache::removeFromLRUList(Resource* resource) |
ASSERT(found); |
#endif |
- Resource* next = resource->m_nextInAllResourcesList; |
- Resource* prev = resource->m_prevInAllResourcesList; |
- |
- if (!next && !prev && list->m_head != resource) |
- return; |
+ MemoryCacheEntry* next = entry->m_nextInAllResourcesList; |
+ MemoryCacheEntry* previous = entry->m_previousInAllResourcesList; |
- resource->m_nextInAllResourcesList = 0; |
- resource->m_prevInAllResourcesList = 0; |
+ entry->m_nextInAllResourcesList = 0; |
+ entry->m_previousInAllResourcesList = 0; |
if (next) |
- next->m_prevInAllResourcesList = prev; |
- else if (list->m_tail == resource) |
- list->m_tail = prev; |
+ next->m_previousInAllResourcesList = previous; |
+ else |
+ list->m_tail = previous; |
- if (prev) |
- prev->m_nextInAllResourcesList = next; |
- else if (list->m_head == resource) |
+ if (previous) |
+ previous->m_nextInAllResourcesList = next; |
+ else |
list->m_head = next; |
} |
void MemoryCache::insertInLRUList(Resource* resource) |
{ |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ASSERT(entry->m_resource == resource); |
+ |
// Make sure we aren't in some list already. |
- ASSERT(!resource->m_nextInAllResourcesList && !resource->m_prevInAllResourcesList); |
+ ASSERT(!entry->m_nextInAllResourcesList && !entry->m_previousInAllResourcesList); |
ASSERT(resource->inCache()); |
ASSERT(resource->accessCount() > 0); |
- LRUList* list = lruListFor(resource); |
+ LRUList* list = lruListFor(entry); |
- resource->m_nextInAllResourcesList = list->m_head; |
+ entry->m_nextInAllResourcesList = list->m_head; |
if (list->m_head) |
- list->m_head->m_prevInAllResourcesList = resource; |
- list->m_head = resource; |
+ list->m_head->m_previousInAllResourcesList = entry; |
+ list->m_head = entry; |
- if (!resource->m_nextInAllResourcesList) |
- list->m_tail = resource; |
+ if (!entry->m_nextInAllResourcesList) |
+ list->m_tail = entry; |
#if !ASSERT_DISABLED |
// Verify that we are in now in the list like we should be. |
- list = lruListFor(resource); |
+ list = lruListFor(entry); |
bool found = false; |
- for (Resource* current = list->m_head; current; current = current->m_nextInAllResourcesList) { |
- if (current == resource) { |
+ for (MemoryCacheEntry* current = list->m_head; current; current = current->m_nextInAllResourcesList) { |
+ if (current == entry) { |
found = true; |
break; |
} |
} |
ASSERT(found); |
#endif |
- |
} |
void MemoryCache::removeFromLiveDecodedResourcesList(Resource* resource) |
{ |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ASSERT(entry->m_resource == resource); |
+ |
// If we've never been accessed, then we're brand new and not in any list. |
- if (!resource->m_inLiveDecodedResourcesList) |
+ if (!entry->m_inLiveDecodedResourcesList) |
return; |
- resource->m_inLiveDecodedResourcesList = false; |
+ entry->m_inLiveDecodedResourcesList = false; |
LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority()]; |
#if !ASSERT_DISABLED |
// Verify that we are in fact in this list. |
bool found = false; |
- for (Resource* current = list->m_head; current; current = current->m_nextInLiveResourcesList) { |
- if (current == resource) { |
+ for (MemoryCacheEntry* current = list->m_head; current; current = current->m_nextInLiveResourcesList) { |
+ if (current == entry) { |
found = true; |
break; |
} |
@@ -424,53 +422,59 @@ void MemoryCache::removeFromLiveDecodedResourcesList(Resource* resource) |
ASSERT(found); |
#endif |
- Resource* next = resource->m_nextInLiveResourcesList; |
- Resource* prev = resource->m_prevInLiveResourcesList; |
- |
- if (!next && !prev && list->m_head != resource) |
- return; |
+ MemoryCacheEntry* next = entry->m_nextInLiveResourcesList; |
+ MemoryCacheEntry* previous = entry->m_previousInLiveResourcesList; |
- resource->m_nextInLiveResourcesList = 0; |
- resource->m_prevInLiveResourcesList = 0; |
+ entry->m_nextInLiveResourcesList = 0; |
+ entry->m_previousInLiveResourcesList = 0; |
if (next) |
- next->m_prevInLiveResourcesList = prev; |
- else if (list->m_tail == resource) |
- list->m_tail = prev; |
+ next->m_previousInLiveResourcesList = previous; |
+ else |
+ list->m_tail = previous; |
- if (prev) |
- prev->m_nextInLiveResourcesList = next; |
- else if (list->m_head == resource) |
+ if (previous) |
+ previous->m_nextInLiveResourcesList = next; |
+ else |
list->m_head = next; |
} |
void MemoryCache::insertInLiveDecodedResourcesList(Resource* resource) |
{ |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ASSERT(entry->m_resource == resource); |
+ |
// Make sure we aren't in the list already. |
- ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResourcesList && !resource->m_inLiveDecodedResourcesList); |
- resource->m_inLiveDecodedResourcesList = true; |
+ ASSERT(!entry->m_nextInLiveResourcesList && !entry->m_previousInLiveResourcesList && !entry->m_inLiveDecodedResourcesList); |
+ entry->m_inLiveDecodedResourcesList = true; |
LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority()]; |
- resource->m_nextInLiveResourcesList = list->m_head; |
+ entry->m_nextInLiveResourcesList = list->m_head; |
if (list->m_head) |
- list->m_head->m_prevInLiveResourcesList = resource; |
- list->m_head = resource; |
+ list->m_head->m_previousInLiveResourcesList = entry; |
+ list->m_head = entry; |
- if (!resource->m_nextInLiveResourcesList) |
- list->m_tail = resource; |
+ if (!entry->m_nextInLiveResourcesList) |
+ list->m_tail = entry; |
#if !ASSERT_DISABLED |
// Verify that we are in now in the list like we should be. |
bool found = false; |
- for (Resource* current = list->m_head; current; current = current->m_nextInLiveResourcesList) { |
- if (current == resource) { |
+ for (MemoryCacheEntry* current = list->m_head; current; current = current->m_nextInLiveResourcesList) { |
+ if (current == entry) { |
found = true; |
break; |
} |
} |
ASSERT(found); |
#endif |
+} |
+bool MemoryCache::isInLiveDecodedResourcesList(Resource* resource) |
+{ |
+ MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ASSERT(entry->m_resource == resource); |
+ return entry ? entry->m_inLiveDecodedResourcesList : false; |
} |
void MemoryCache::addToLiveResourcesSize(Resource* resource) |
@@ -534,7 +538,7 @@ MemoryCache::Statistics MemoryCache::getStatistics() |
Statistics stats; |
ResourceMap::iterator e = m_resources.end(); |
for (ResourceMap::iterator i = m_resources.begin(); i != e; ++i) { |
- Resource* resource = i->value; |
+ Resource* resource = i->value->m_resource.get(); |
switch (resource->type()) { |
case Resource::Image: |
stats.images.addResource(resource); |
@@ -565,7 +569,7 @@ void MemoryCache::evictResources() |
ResourceMap::iterator i = m_resources.begin(); |
if (i == m_resources.end()) |
break; |
- evict(i->value); |
+ evict(i->value->m_resource.get()); |
} |
} |