| Index: Source/core/fetch/MemoryCache.cpp
|
| diff --git a/Source/core/fetch/MemoryCache.cpp b/Source/core/fetch/MemoryCache.cpp
|
| index 4aa2a5aca2024e0ee814717db0681b78b05a0111..52603e3d0eb16583fbb3502fa2953b7c7017b3be 100644
|
| --- a/Source/core/fetch/MemoryCache.cpp
|
| +++ b/Source/core/fetch/MemoryCache.cpp
|
| @@ -134,7 +134,7 @@ void MemoryCache::trace(Visitor* visitor)
|
| visitor->trace(m_allResources);
|
| for (size_t i = 0; i < WTF_ARRAY_LENGTH(m_liveDecodedResources); ++i)
|
| visitor->trace(m_liveDecodedResources[i]);
|
| - visitor->trace(m_resources);
|
| + visitor->trace(m_resourceMaps);
|
| visitor->trace(m_liveResources);
|
| #endif
|
| }
|
| @@ -153,12 +153,27 @@ KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL)
|
| return url;
|
| }
|
|
|
| +String MemoryCache::defaultCacheIdentifier()
|
| +{
|
| + return emptyString();
|
| +}
|
| +
|
| +MemoryCache::ResourceMap* MemoryCache::ensureResourceMap(const String& cacheIdentifier)
|
| +{
|
| + if (!m_resourceMaps.contains(cacheIdentifier)) {
|
| + ResourceMapIndex::AddResult result = m_resourceMaps.add(cacheIdentifier, adoptPtrWillBeNoop(new ResourceMap()));
|
| + RELEASE_ASSERT(result.isNewEntry);
|
| + }
|
| + return m_resourceMaps.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 = ensureResourceMap(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,47 +181,65 @@ 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 = ensureResourceMap(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)
|
| {
|
| // The resource may have already been removed by someone other than our caller,
|
| // who needed a fresh copy for a reload.
|
| - if (!contains(resource))
|
| - return;
|
| - evict(m_resources.get(resource->url()));
|
| + if (MemoryCacheEntry* entry = getEntryForResource(resource))
|
| + evict(entry);
|
| }
|
|
|
| bool MemoryCache::contains(const Resource* resource) const
|
| {
|
| - if (resource->url().isNull())
|
| - return false;
|
| - const MemoryCacheEntry* entry = m_resources.get(resource->url());
|
| - return entry && entry->m_resource == resource;
|
| + return getEntryForResource(resource);
|
| }
|
|
|
| Resource* MemoryCache::resourceForURL(const KURL& resourceURL)
|
| {
|
| + return resourceForURL(resourceURL, defaultCacheIdentifier());
|
| +}
|
| +
|
| +Resource* MemoryCache::resourceForURL(const KURL& resourceURL, const String& cacheIdentifier)
|
| +{
|
| ASSERT(WTF::isMainThread());
|
| + ResourceMap* resources = m_resourceMaps.get(cacheIdentifier);
|
| + if (!resources)
|
| + return nullptr;
|
| KURL url = removeFragmentIdentifierIfNeeded(resourceURL);
|
| - MemoryCacheEntry* entry = m_resources.get(url);
|
| + MemoryCacheEntry* entry = resources->get(url);
|
| if (!entry)
|
| - return 0;
|
| + return nullptr;
|
| Resource* resource = entry->m_resource.get();
|
| if (resource && !resource->lock()) {
|
| ASSERT(!resource->hasClients());
|
| bool didEvict = evict(entry);
|
| ASSERT_UNUSED(didEvict, didEvict);
|
| - return 0;
|
| + return nullptr;
|
| }
|
| return resource;
|
| }
|
|
|
| +WillBeHeapVector<Member<Resource>> MemoryCache::resourcesForURL(const KURL& resourceURL)
|
| +{
|
| + ASSERT(WTF::isMainThread());
|
| + KURL url = removeFragmentIdentifierIfNeeded(resourceURL);
|
| + WillBeHeapVector<Member<Resource>> results;
|
| + for (const auto& resourceMapIter : m_resourceMaps) {
|
| + if (MemoryCacheEntry* entry = resourceMapIter.value->get(url))
|
| + 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 +407,17 @@ 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 = m_resourceMaps.get(resource->cacheIdentifier());
|
| + ASSERT(resources);
|
| + 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 +425,19 @@ bool MemoryCache::evict(MemoryCacheEntry* entry)
|
| return canDelete;
|
| }
|
|
|
| +MemoryCacheEntry* MemoryCache::getEntryForResource(const Resource* resource) const
|
| +{
|
| + if (resource->url().isNull() || resource->url().isEmpty())
|
| + return nullptr;
|
| + ResourceMap* resources = m_resourceMaps.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 +570,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))
|
| + MemoryCacheEntry* entry = getEntryForResource(resource);
|
| + if (!entry)
|
| return;
|
| - 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.
|
| @@ -552,9 +600,9 @@ void MemoryCache::update(Resource* resource, size_t oldSize, size_t newSize, boo
|
|
|
| void MemoryCache::updateDecodedResource(Resource* resource, UpdateReason reason, MemoryCacheLiveResourcePriority priority)
|
| {
|
| - if (!contains(resource))
|
| + MemoryCacheEntry* entry = getEntryForResource(resource);
|
| + if (!entry)
|
| return;
|
| - MemoryCacheEntry* entry = m_resources.get(resource->url());
|
|
|
| removeFromLiveDecodedResourcesList(entry);
|
| if (priority != MemoryCacheLiveResourcePriorityUnknown && priority != entry->m_liveResourcePriority)
|
| @@ -573,9 +621,9 @@ void MemoryCache::updateDecodedResource(Resource* resource, UpdateReason reason,
|
|
|
| MemoryCacheLiveResourcePriority MemoryCache::priority(Resource* resource) const
|
| {
|
| - if (!contains(resource))
|
| + MemoryCacheEntry* entry = getEntryForResource(resource);
|
| + if (!entry)
|
| return MemoryCacheLiveResourcePriorityUnknown;
|
| - MemoryCacheEntry* entry = m_resources.get(resource->url());
|
| return entry->m_liveResourcePriority;
|
| }
|
|
|
| @@ -591,7 +639,8 @@ void MemoryCache::removeURLFromCache(ExecutionContext* context, const KURL& url)
|
|
|
| void MemoryCache::removeURLFromCacheInternal(ExecutionContext*, const KURL& url)
|
| {
|
| - if (Resource* resource = memoryCache()->resourceForURL(url))
|
| + WillBeHeapVector<Member<Resource>> resources = memoryCache()->resourcesForURL(url);
|
| + for (Resource* resource : resources)
|
| memoryCache()->remove(resource);
|
| }
|
|
|
| @@ -613,27 +662,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& resourceMapIter : m_resourceMaps) {
|
| + for (const auto& resourceIter : *resourceMapIter.value) {
|
| + 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;
|
| @@ -641,11 +692,18 @@ MemoryCache::Statistics MemoryCache::getStatistics()
|
|
|
| void MemoryCache::evictResources()
|
| {
|
| - for (;;) {
|
| - ResourceMap::iterator i = m_resources.begin();
|
| - if (i == m_resources.end())
|
| + while (true) {
|
| + ResourceMapIndex::iterator resourceMapIter = m_resourceMaps.begin();
|
| + if (resourceMapIter == m_resourceMaps.end())
|
| break;
|
| - evict(i->value.get());
|
| + ResourceMap* resources = resourceMapIter->value.get();
|
| + while (true) {
|
| + ResourceMap::iterator resourceIter = resources->begin();
|
| + if (resourceIter == resources->end())
|
| + break;
|
| + evict(resourceIter->value.get());
|
| + }
|
| + m_resourceMaps.remove(resourceMapIter);
|
| }
|
| }
|
|
|
| @@ -689,8 +747,10 @@ void MemoryCache::prune(Resource* justReleasedResource)
|
| // while a prune is pending.
|
| // 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()));
|
| + if (justReleasedResource->type() != Resource::MainResource) {
|
| + if (MemoryCacheEntry* entry = getEntryForResource(justReleasedResource))
|
| + evict(entry);
|
| + }
|
|
|
| // As a last resort, prune immediately
|
| if (m_deadSize > m_maxDeferredPruneDeadCapacity)
|
|
|