Index: Source/core/fetch/MemoryCache.cpp |
diff --git a/Source/core/fetch/MemoryCache.cpp b/Source/core/fetch/MemoryCache.cpp |
index 4aa2a5aca2024e0ee814717db0681b78b05a0111..9d10f0f8f5772d3b391a3805f3b92a7b6b816448 100644 |
--- a/Source/core/fetch/MemoryCache.cpp |
+++ b/Source/core/fetch/MemoryCache.cpp |
@@ -153,12 +153,25 @@ KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL) |
return url; |
} |
+String MemoryCache::defaultCacheIdentifier() |
+{ |
+ return emptyString(); |
+} |
+ |
+MemoryCache::ResourceMap* MemoryCache::getResourceMap(const String& cacheIdentifier) |
+{ |
+ if (!m_resources.contains(cacheIdentifier)) |
+ m_resources.add(cacheIdentifier, adoptPtrWillBeNoop(new ResourceMap())); |
Mike West
2014/10/24 12:42:59
`add()` can fail, can't it? That could cause a nul
nhiroki
2014/10/27 14:30:12
Hmmm... I think a null-deref never happens because
|
+ return m_resources.get(cacheIdentifier); |
+} |
+ |
void MemoryCache::add(Resource* resource) |
{ |
ASSERT(WTF::isMainThread()); |
ASSERT(resource->url().isValid()); |
- RELEASE_ASSERT(!m_resources.contains(resource->url())); |
- m_resources.set(resource->url().string(), MemoryCacheEntry::create(resource)); |
+ ResourceMap* resources = getResourceMap(resource->cacheIdentifier()); |
+ RELEASE_ASSERT(!resources->contains(resource->url())); |
+ resources->set(resource->url(), MemoryCacheEntry::create(resource)); |
update(resource, 0, resource->size(), true); |
WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resource->url().string().latin1().data(), resource); |
@@ -166,11 +179,13 @@ void MemoryCache::add(Resource* resource) |
void MemoryCache::replace(Resource* newResource, Resource* oldResource) |
{ |
- if (MemoryCacheEntry* oldEntry = m_resources.get(oldResource->url())) |
+ ASSERT(newResource->cacheIdentifier() == oldResource->cacheIdentifier()); |
+ ResourceMap* resources = getResourceMap(oldResource->cacheIdentifier()); |
+ if (MemoryCacheEntry* oldEntry = resources->get(oldResource->url())) |
evict(oldEntry); |
add(newResource); |
if (newResource->decodedSize() && newResource->hasClients()) |
- insertInLiveDecodedResourcesList(m_resources.get(newResource->url())); |
+ insertInLiveDecodedResourcesList(resources->get(newResource->url())); |
} |
void MemoryCache::remove(Resource* resource) |
@@ -179,22 +194,26 @@ void MemoryCache::remove(Resource* resource) |
// who needed a fresh copy for a reload. |
if (!contains(resource)) |
Mike West
2014/10/24 12:42:59
Rather than doing the lookup twice, it might make
nhiroki
2014/10/27 14:30:13
Good point! Removed redundant contains() calls.
|
return; |
- evict(m_resources.get(resource->url())); |
+ evict(getEntryForResource(resource)); |
} |
bool MemoryCache::contains(const Resource* resource) const |
{ |
if (resource->url().isNull()) |
return false; |
- const MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ ResourceMap* resources = m_resources.get(resource->cacheIdentifier()); |
Mike West
2014/10/24 12:43:00
It's odd to have `getResourceMap` and not use it h
nhiroki
2014/10/27 14:30:12
Yes, that's right.
|
+ if (!resources) |
+ return false; |
+ MemoryCacheEntry* entry = resources->get(resource->url()); |
return entry && entry->m_resource == resource; |
} |
-Resource* MemoryCache::resourceForURL(const KURL& resourceURL) |
+Resource* MemoryCache::resourceForURL(const String& cacheIdentifier, const KURL& resourceURL) |
{ |
ASSERT(WTF::isMainThread()); |
+ ResourceMap* resources = getResourceMap(cacheIdentifier); |
KURL url = removeFragmentIdentifierIfNeeded(resourceURL); |
- MemoryCacheEntry* entry = m_resources.get(url); |
+ MemoryCacheEntry* entry = resources->get(url); |
if (!entry) |
return 0; |
Resource* resource = entry->m_resource.get(); |
@@ -207,6 +226,19 @@ Resource* MemoryCache::resourceForURL(const KURL& resourceURL) |
return resource; |
} |
+WillBeHeapVector<Member<Resource>> MemoryCache::resourcesForURL(const KURL& resourceURL) |
+{ |
+ ASSERT(WTF::isMainThread()); |
+ KURL url = removeFragmentIdentifierIfNeeded(resourceURL); |
+ WillBeHeapVector<Member<Resource>> results; |
+ for (const auto& resources : m_resources) { |
Mike West
2014/10/24 12:42:59
"ResourceMap" seems clearer than "auto".
nhiroki
2014/10/27 14:30:12
"m_resources" is a HashMap object, so this "auto"
|
+ MemoryCacheEntry* entry = resources.value->get(url); |
+ if (entry) |
+ results.append(entry->m_resource.get()); |
+ } |
+ return results; |
+} |
+ |
size_t MemoryCache::deadCapacity() const |
{ |
// Dead resource capacity is whatever space is not occupied by live resources, bounded by an independent minimum and maximum. |
@@ -374,15 +406,16 @@ bool MemoryCache::evict(MemoryCacheEntry* entry) |
update(resource, resource->size(), 0, false); |
removeFromLiveDecodedResourcesList(entry); |
- ResourceMap::iterator it = m_resources.find(resource->url()); |
- ASSERT(it != m_resources.end()); |
+ ResourceMap* resources = getResourceMap(resource->cacheIdentifier()); |
+ ResourceMap::iterator it = resources->find(resource->url()); |
+ ASSERT(it != resources->end()); |
#if ENABLE(OILPAN) |
MemoryCacheEntry* entryPtr = it->value; |
#else |
OwnPtr<MemoryCacheEntry> entryPtr; |
entryPtr.swap(it->value); |
#endif |
- m_resources.remove(it); |
+ resources->remove(it); |
#if ENABLE(OILPAN) |
if (entryPtr) |
entryPtr->dispose(); |
@@ -390,6 +423,19 @@ bool MemoryCache::evict(MemoryCacheEntry* entry) |
return canDelete; |
} |
+MemoryCacheEntry* MemoryCache::getEntryForResource(const Resource* resource) const |
+{ |
+ if (resource->url().isNull()) |
Mike West
2014/10/24 12:43:00
isNull or isEmpty?
nhiroki
2014/10/27 14:30:13
Done.
|
+ return nullptr; |
+ ResourceMap* resources = m_resources.get(resource->cacheIdentifier()); |
+ if (!resources) |
+ return nullptr; |
+ MemoryCacheEntry* entry = resources->get(resource->url()); |
+ if (!entry || entry->m_resource != resource) |
+ return nullptr; |
+ return entry; |
+} |
+ |
MemoryCacheLRUList* MemoryCache::lruListFor(unsigned accessCount, size_t size) |
{ |
ASSERT(accessCount > 0); |
@@ -522,14 +568,14 @@ void MemoryCache::makeDead(Resource* resource) |
return; |
m_liveSize -= resource->size(); |
m_deadSize += resource->size(); |
- removeFromLiveDecodedResourcesList(m_resources.get(resource->url())); |
+ removeFromLiveDecodedResourcesList(getEntryForResource(resource)); |
} |
void MemoryCache::update(Resource* resource, size_t oldSize, size_t newSize, bool wasAccessed) |
{ |
if (!contains(resource)) |
return; |
- MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ MemoryCacheEntry* entry = getEntryForResource(resource); |
// 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. |
@@ -554,7 +600,7 @@ void MemoryCache::updateDecodedResource(Resource* resource, UpdateReason reason, |
{ |
if (!contains(resource)) |
return; |
- MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ MemoryCacheEntry* entry = getEntryForResource(resource); |
removeFromLiveDecodedResourcesList(entry); |
if (priority != MemoryCacheLiveResourcePriorityUnknown && priority != entry->m_liveResourcePriority) |
@@ -575,7 +621,7 @@ MemoryCacheLiveResourcePriority MemoryCache::priority(Resource* resource) const |
{ |
if (!contains(resource)) |
return MemoryCacheLiveResourcePriorityUnknown; |
- MemoryCacheEntry* entry = m_resources.get(resource->url()); |
+ MemoryCacheEntry* entry = getEntryForResource(resource); |
return entry->m_liveResourcePriority; |
} |
@@ -591,7 +637,8 @@ void MemoryCache::removeURLFromCache(ExecutionContext* context, const KURL& url) |
void MemoryCache::removeURLFromCacheInternal(ExecutionContext*, const KURL& url) |
{ |
- if (Resource* resource = memoryCache()->resourceForURL(url)) |
+ auto resources = memoryCache()->resourcesForURL(url); |
+ for (const auto& resource : resources) |
Mike West
2014/10/24 12:42:59
"Resource" seems clearer than "auto".
nhiroki
2014/10/27 14:30:12
Done.
|
memoryCache()->remove(resource); |
} |
@@ -613,27 +660,29 @@ void MemoryCache::TypeStatistic::addResource(Resource* o) |
MemoryCache::Statistics MemoryCache::getStatistics() |
{ |
Statistics stats; |
- for (const auto& resourceIter : m_resources) { |
- Resource* resource = resourceIter.value->m_resource.get(); |
- switch (resource->type()) { |
- case Resource::Image: |
- stats.images.addResource(resource); |
- break; |
- case Resource::CSSStyleSheet: |
- stats.cssStyleSheets.addResource(resource); |
- break; |
- case Resource::Script: |
- stats.scripts.addResource(resource); |
- break; |
- case Resource::XSLStyleSheet: |
- stats.xslStyleSheets.addResource(resource); |
- break; |
- case Resource::Font: |
- stats.fonts.addResource(resource); |
- break; |
- default: |
- stats.other.addResource(resource); |
- break; |
+ for (const auto& resources : m_resources) { |
Mike West
2014/10/24 12:42:59
"ResourceMap* resourceMap" seems clearer.
nhiroki
2014/10/27 14:30:13
Ditto ("const OwnPtr<ResourceMap>& resources"?).
|
+ for (const auto& resourceIter : *resources.value) { |
Mike West
2014/10/24 12:42:59
Resource rather than auto.
nhiroki
2014/10/27 14:30:12
Ditto.
|
+ Resource* resource = resourceIter.value->m_resource.get(); |
+ switch (resource->type()) { |
+ case Resource::Image: |
+ stats.images.addResource(resource); |
+ break; |
+ case Resource::CSSStyleSheet: |
+ stats.cssStyleSheets.addResource(resource); |
+ break; |
+ case Resource::Script: |
+ stats.scripts.addResource(resource); |
+ break; |
+ case Resource::XSLStyleSheet: |
+ stats.xslStyleSheets.addResource(resource); |
+ break; |
+ case Resource::Font: |
+ stats.fonts.addResource(resource); |
+ break; |
+ default: |
+ stats.other.addResource(resource); |
+ break; |
+ } |
} |
} |
return stats; |
@@ -642,10 +691,17 @@ MemoryCache::Statistics MemoryCache::getStatistics() |
void MemoryCache::evictResources() |
{ |
for (;;) { |
- ResourceMap::iterator i = m_resources.begin(); |
- if (i == m_resources.end()) |
+ ResourceMapIndex::iterator indexIter = m_resources.begin(); |
+ if (indexIter == m_resources.end()) |
break; |
- evict(i->value.get()); |
+ ResourceMap* resources = indexIter->value.get(); |
+ for (;;) { |
Mike West
2014/10/24 12:42:59
Would you mind changing this, and line 693, to `wh
nhiroki
2014/10/27 14:30:13
Done.
|
+ ResourceMap::iterator resourceIter = resources->begin(); |
+ if (resourceIter == resources->end()) |
+ break; |
+ evict(resourceIter->value.get()); |
+ } |
+ m_resources.remove(indexIter); |
} |
} |
@@ -690,7 +746,7 @@ void MemoryCache::prune(Resource* justReleasedResource) |
// Main Resources in the cache are only substitue data that was |
// precached and should not be evicted. |
if (contains(justReleasedResource) && justReleasedResource->type() != Resource::MainResource) |
- evict(m_resources.get(justReleasedResource->url())); |
+ evict(getEntryForResource(justReleasedResource)); |
// As a last resort, prune immediately |
if (m_deadSize > m_maxDeferredPruneDeadCapacity) |