/*
    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
    Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.
*/

#include "config.h"
#include "MemoryCache.h"

#include "BitmapImage.h"
#include "CachedImage.h"
#include "CachedImageClient.h"
#include "CachedResource.h"
#include "CachedResourceHandle.h"
#include "Document.h"
#include "FrameLoader.h"
#include "FrameLoaderTypes.h"
#include "FrameView.h"
#include "Image.h"
#include "Logging.h"
#include "PublicSuffix.h"
#include "SharedBuffer.h"
#include "WorkerGlobalScope.h"
#include "WorkerLoaderProxy.h"
#include "WorkerThread.h"
#include <pal/Logging.h>
#include <stdio.h>
#include <wtf/MathExtras.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/SetForScope.h>
#include <wtf/text/CString.h>

namespace WebCore {

static const int cDefaultCacheCapacity = 8192 * 1024;
static const Seconds cMinDelayBeforeLiveDecodedPrune { 1_s };
static const float cTargetPrunePercentage = .95f; // Percentage of capacity toward which we prune, to avoid immediately pruning again.

MemoryCache& MemoryCache::singleton()
{
    ASSERT(isMainThread());
    static NeverDestroyed<MemoryCache> memoryCache;
    return memoryCache;
}

MemoryCache::MemoryCache()
    : m_capacity(cDefaultCacheCapacity)
    , m_maxDeadCapacity(cDefaultCacheCapacity)
    , m_pruneTimer(*this, &MemoryCache::prune)
{
    static_assert(sizeof(long long) > sizeof(unsigned), "Numerical overflow can happen when adjusting the size of the cached memory.");

    static std::once_flag onceFlag;
    std::call_once(onceFlag, [] {
        PAL::registerNotifyCallback("com.apple.WebKit.showMemoryCache", [] {
            MemoryCache::singleton().dumpStats();
            MemoryCache::singleton().dumpLRULists(true);
        });
    });
}

auto MemoryCache::sessionResourceMap(PAL::SessionID sessionID) const -> CachedResourceMap*
{
    ASSERT(sessionID.isValid());
    return m_sessionResources.get(sessionID);
}

auto MemoryCache::ensureSessionResourceMap(PAL::SessionID sessionID) -> CachedResourceMap&
{
    ASSERT(sessionID.isValid());
    auto& map = m_sessionResources.add(sessionID, nullptr).iterator->value;
    if (!map)
        map = makeUnique<CachedResourceMap>();
    return *map;
}

bool MemoryCache::shouldRemoveFragmentIdentifier(const URL& originalURL)
{
    if (!originalURL.hasFragmentIdentifier())
        return false;
    // Strip away fragment identifier from HTTP URLs.
    // Data URLs must be unmodified. For file and custom URLs clients may expect resources
    // to be unique even when they differ by the fragment identifier only.
    return originalURL.protocolIsInHTTPFamily();
}

URL MemoryCache::removeFragmentIdentifierIfNeeded(const URL& originalURL)
{
    if (!shouldRemoveFragmentIdentifier(originalURL))
        return originalURL;
    URL url = originalURL;
    url.removeFragmentIdentifier();
    return url;
}

bool MemoryCache::add(CachedResource& resource)
{
    if (disabled())
        return false;

    if (resource.resourceRequest().httpMethod() != "GET")
        return false;

    ASSERT(isMainThread());

    auto key = std::make_pair(resource.url(), resource.cachePartition());

    ensureSessionResourceMap(resource.sessionID()).set(key, &resource);
    resource.setInCache(true);
    
    resourceAccessed(resource);

    LOG(ResourceLoading, "MemoryCache::add Added '%.255s', resource %p\n", resource.url().string().latin1().data(), &resource);
    return true;
}

void MemoryCache::revalidationSucceeded(CachedResource& revalidatingResource, const ResourceResponse& response)
{
    ASSERT(response.source() == ResourceResponse::Source::MemoryCacheAfterValidation);
    ASSERT(revalidatingResource.resourceToRevalidate());
    CachedResource& resource = *revalidatingResource.resourceToRevalidate();
    ASSERT(!resource.inCache());
    ASSERT(resource.isLoaded());

    // Calling remove() can potentially delete revalidatingResource, which we use
    // below. This mustn't be the case since revalidation means it is loaded
    // and so canDelete() is false.
    ASSERT(!revalidatingResource.canDelete());

    remove(revalidatingResource);

    auto& resources = ensureSessionResourceMap(resource.sessionID());
    auto key = std::make_pair(resource.url(), resource.cachePartition());

    ASSERT(!resources.get(key));
    resources.set(key, &resource);
    resource.setInCache(true);
    resource.updateResponseAfterRevalidation(response);
    insertInLRUList(resource);
    long long delta = resource.size();
    if (resource.decodedSize() && resource.hasClients())
        insertInLiveDecodedResourcesList(resource);
    if (delta)
        adjustSize(resource.hasClients(), delta);

    revalidatingResource.switchClientsToRevalidatedResource();
    ASSERT(!revalidatingResource.m_deleted);
    // this deletes the revalidating resource
    revalidatingResource.clearResourceToRevalidate();
}

void MemoryCache::revalidationFailed(CachedResource& revalidatingResource)
{
    ASSERT(isMainThread());
    LOG(ResourceLoading, "Revalidation failed for %p", &revalidatingResource);
    ASSERT(revalidatingResource.resourceToRevalidate());
    revalidatingResource.clearResourceToRevalidate();
}

CachedResource* MemoryCache::resourceForRequest(const ResourceRequest& request, PAL::SessionID sessionID)
{
    // FIXME: Change all clients to make sure HTTP(s) URLs have no fragment identifiers before calling here.
    // CachedResourceLoader is now doing this. Add an assertion once all other clients are doing it too.
    auto* resources = sessionResourceMap(sessionID);
    if (!resources)
        return nullptr;
    return resourceForRequestImpl(request, *resources);
}

CachedResource* MemoryCache::resourceForRequestImpl(const ResourceRequest& request, CachedResourceMap& resources)
{
    ASSERT(isMainThread());
    URL url = removeFragmentIdentifierIfNeeded(request.url());

    auto key = std::make_pair(url, request.cachePartition());
    return resources.get(key);
}

unsigned MemoryCache::deadCapacity() const 
{
    // Dead resource capacity is whatever space is not occupied by live resources, bounded by an independent minimum and maximum.
    unsigned capacity = m_capacity - std::min(m_liveSize, m_capacity); // Start with available capacity.
    capacity = std::max(capacity, m_minDeadCapacity); // Make sure it's above the minimum.
    capacity = std::min(capacity, m_maxDeadCapacity); // Make sure it's below the maximum.
    return capacity;
}

unsigned MemoryCache::liveCapacity() const 
{ 
    // Live resource capacity is whatever is left over after calculating dead resource capacity.
    return m_capacity - deadCapacity();
}

void MemoryCache::pruneLiveResources(bool shouldDestroyDecodedDataForAllLiveResources)
{
    unsigned capacity = shouldDestroyDecodedDataForAllLiveResources ? 0 : liveCapacity();
    if (capacity && m_liveSize <= capacity)
        return;

    unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again.

    pruneLiveResourcesToSize(targetSize, shouldDestroyDecodedDataForAllLiveResources);
}

void MemoryCache::forEachResource(const Function<void(CachedResource&)>& function)
{
    for (auto& unprotectedLRUList : m_allResources) {
        for (auto& resource : copyToVector(*unprotectedLRUList))
            function(*resource);
    }
}

void MemoryCache::forEachSessionResource(PAL::SessionID sessionID, const Function<void(CachedResource&)>& function)
{
    auto it = m_sessionResources.find(sessionID);
    if (it == m_sessionResources.end())
        return;

    for (auto& resource : copyToVector(it->value->values()))
        function(*resource);
}

void MemoryCache::destroyDecodedDataForAllImages()
{
    MemoryCache::singleton().forEachResource([](CachedResource& resource) {
        if (!resource.isImage())
            return;

        if (auto image = downcast<CachedImage>(resource).image())
            image->destroyDecodedData();
    });
}

void MemoryCache::pruneLiveResourcesToSize(unsigned targetSize, bool shouldDestroyDecodedDataForAllLiveResources)
{
    if (m_inPruneResources)
        return;

    LOG(ResourceLoading, "MemoryCache::pruneLiveResourcesToSize(%d, shouldDestroyDecodedDataForAllLiveResources = %d)", targetSize, shouldDestroyDecodedDataForAllLiveResources);

    SetForScope<bool> reentrancyProtector(m_inPruneResources, true);

    MonotonicTime currentTime = FrameView::currentPaintTimeStamp();
    if (!currentTime) // In case prune is called directly, outside of a Frame paint.
        currentTime = MonotonicTime::now();
    
    // Destroy any decoded data in live objects that we can.
    // Start from the head, since this is the least recently accessed of the objects.

    // The list might not be sorted by the m_lastDecodedAccessTime. The impact
    // of this weaker invariant is minor as the below if statement to check the
    // elapsedTime will evaluate to false as the currentTime will be a lot
    // greater than the current->m_lastDecodedAccessTime.
    // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209
    auto it = m_liveDecodedResources.begin();
    while (it != m_liveDecodedResources.end()) {
        auto* current = *it;

        LOG(ResourceLoading, " live resource %p %.255s - loaded %d, decodedSize %u", current, current->url().string().utf8().data(), current->isLoaded(), current->decodedSize());

        // Increment the iterator now because the call to destroyDecodedData() below
        // may cause a call to ListHashSet::remove() and invalidate the current
        // iterator. Note that this is safe because unlike iteration of most
        // WTF Hash data structures, iteration is guaranteed safe against mutation
        // of the ListHashSet, except for removal of the item currently pointed to
        // by a given iterator.
        ++it;

        ASSERT(current->hasClients());
        if (current->isLoaded() && current->decodedSize()) {
            // Check to see if the remaining resources are too new to prune.
            Seconds elapsedTime = currentTime - current->m_lastDecodedAccessTime;
            if (!shouldDestroyDecodedDataForAllLiveResources && elapsedTime < cMinDelayBeforeLiveDecodedPrune) {
                LOG(ResourceLoading, " current time is less than min delay before pruning (%.3fms)", elapsedTime.milliseconds());
                return;
            }

            // Destroy our decoded data. This will remove us from m_liveDecodedResources, and possibly move us
            // to a different LRU list in m_allResources.
            current->destroyDecodedData();

            if (targetSize && m_liveSize <= targetSize)
                return;
        }
    }
}

void MemoryCache::pruneDeadResources()
{
    LOG(ResourceLoading, "MemoryCache::pruneDeadResources");

    unsigned capacity = deadCapacity();
    if (capacity && m_deadSize <= capacity)
        return;

    unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again.
    pruneDeadResourcesToSize(targetSize);
}

void MemoryCache::pruneDeadResourcesToSize(unsigned targetSize)
{
    if (m_inPruneResources)
        return;

    LOG(ResourceLoading, "MemoryCache::pruneDeadResourcesToSize(%d)", targetSize);

    SetForScope<bool> reentrancyProtector(m_inPruneResources, true);
 
    if (targetSize && m_deadSize <= targetSize)
        return;

    bool canShrinkLRULists = true;
    for (int i = m_allResources.size() - 1; i >= 0; i--) {
        // Make a copy of the LRUList first (and ref the resources) as calling
        // destroyDecodedData() can alter the LRUList.
        auto lruList = copyToVector(*m_allResources[i]);

        LOG(ResourceLoading, " lru list (size %lu) - flushing stage", lruList.size());

        // First flush all the decoded data in this queue.
        // Remove from the head, since this is the least frequently accessed of the objects.
        for (auto& resource : lruList) {
            LOG(ResourceLoading, " lru resource %p - in cache %d, has clients %d, preloaded %d, loaded %d", resource, resource->inCache(), resource->hasClients(), resource->isPreloaded(), resource->isLoaded());
            if (!resource->inCache())
                continue;

            if (!resource->hasClients() && !resource->isPreloaded() && 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.

                LOG(ResourceLoading, " lru resource %p destroyDecodedData", resource);

                resource->destroyDecodedData();

                if (targetSize && m_deadSize <= targetSize)
                    return;
            }
        }

        LOG(ResourceLoading, " lru list (size %lu) - eviction stage", lruList.size());

        // Now evict objects from this list.
        // Remove from the head, since this is the least frequently accessed of the objects.
        for (auto& resource : lruList) {
            LOG(ResourceLoading, " lru resource %p - in cache %d, has clients %d, preloaded %d, loaded %d", resource, resource->inCache(), resource->hasClients(), resource->isPreloaded(), resource->isLoaded());
            if (!resource->inCache())
                continue;

            if (!resource->hasClients() && !resource->isPreloaded() && !resource->isCacheValidator()) {
                remove(*resource);
                if (targetSize && m_deadSize <= targetSize)
                    return;
            }
        }
            
        // Shrink the vector back down so we don't waste time inspecting
        // empty LRU lists on future prunes.
        if (!m_allResources[i]->isEmpty())
            canShrinkLRULists = false;
        else if (canShrinkLRULists)
            m_allResources.shrink(i);
    }
}

void MemoryCache::setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes)
{
    ASSERT(minDeadBytes <= maxDeadBytes);
    ASSERT(maxDeadBytes <= totalBytes);
    m_minDeadCapacity = minDeadBytes;
    m_maxDeadCapacity = maxDeadBytes;
    m_capacity = totalBytes;
    prune();
}

void MemoryCache::remove(CachedResource& resource)
{
    ASSERT(isMainThread());
    LOG(ResourceLoading, "Evicting resource %p for '%.255s' 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 (auto* resources = sessionResourceMap(resource.sessionID())) {
        auto key = std::make_pair(resource.url(), resource.cachePartition());

        if (resource.inCache()) {
            ASSERT_WITH_MESSAGE(resource.response().source() != ResourceResponse::Source::InspectorOverride, "InspectorOverride responses should not get into the MemoryCache");

            // Remove resource from the resource map.
            resources->remove(key);
            resource.setInCache(false);

            // If the resource map is now empty, remove it from m_sessionResources.
            if (resources->isEmpty())
                m_sessionResources.remove(resource.sessionID());

            // Remove from the appropriate LRU list.
            removeFromLRUList(resource);
            removeFromLiveDecodedResourcesList(resource);
            adjustSize(resource.hasClients(), -static_cast<long long>(resource.size()));
        } else {
            ASSERT(resources->get(key) != &resource);
            LOG(ResourceLoading, "  resource %p is not in cache", &resource);
        }
    }

    if (resource.canDelete())
        resource.deleteThis();
}

auto MemoryCache::lruListFor(CachedResource& resource) -> LRUList&
{
    unsigned accessCount = std::max(resource.accessCount(), 1U);
    unsigned queueIndex = WTF::fastLog2(resource.size() / accessCount);
#if ASSERT_ENABLED
    resource.m_lruIndex = queueIndex;
#endif

    m_allResources.reserveCapacity(queueIndex + 1);
    while (m_allResources.size() <= queueIndex)
        m_allResources.uncheckedAppend(makeUnique<LRUList>());
    return *m_allResources[queueIndex];
}

void MemoryCache::removeFromLRUList(CachedResource& resource)
{
    // If we've never been accessed, then we're brand new and not in any list.
    if (!resource.accessCount())
        return;

#if ASSERT_ENABLED
    unsigned oldListIndex = resource.m_lruIndex;
#endif

    LRUList& list = lruListFor(resource);

    // Verify that the list we got is the list we want.
    ASSERT(resource.m_lruIndex == oldListIndex);

    bool removed = list.remove(&resource);
    ASSERT_UNUSED(removed, removed);
}

void MemoryCache::insertInLRUList(CachedResource& resource)
{
    ASSERT(resource.inCache());
    ASSERT(resource.accessCount() > 0);
    
    auto addResult = lruListFor(resource).add(&resource);
    ASSERT_UNUSED(addResult, addResult.isNewEntry);
}

void MemoryCache::resourceAccessed(CachedResource& resource)
{
    ASSERT(resource.inCache());
    
    // Need to make sure to remove before we increase the access count, since
    // the queue will possibly change.
    removeFromLRUList(resource);
    
    // If this is the first time the resource has been accessed, adjust the size of the cache to account for its initial size.
    if (!resource.accessCount())
        adjustSize(resource.hasClients(), resource.size());
    
    // Add to our access count.
    resource.increaseAccessCount();
    
    // Now insert into the new queue.
    insertInLRUList(resource);
}

void MemoryCache::removeResourcesWithOrigin(SecurityOrigin& origin)
{
    String originPartition = ResourceRequest::partitionName(origin.host());

    Vector<CachedResource*> resourcesWithOrigin;
    for (auto& resources : m_sessionResources.values()) {
        for (auto& keyValue : *resources) {
            auto& resource = *keyValue.value;
            auto& partitionName = keyValue.key.second;
            if (partitionName == originPartition) {
                resourcesWithOrigin.append(&resource);
                continue;
            }
            auto resourceOrigin = SecurityOrigin::create(resource.url());
            if (resourceOrigin->equal(&origin))
                resourcesWithOrigin.append(&resource);
        }
    }

    for (auto* resource : resourcesWithOrigin)
        remove(*resource);
}

void MemoryCache::removeResourcesWithOrigins(PAL::SessionID sessionID, const HashSet<RefPtr<SecurityOrigin>>& origins)
{
    auto* resourceMap = sessionResourceMap(sessionID);
    if (!resourceMap)
        return;

    HashSet<String> originPartitions;

    for (auto& origin : origins)
        originPartitions.add(ResourceRequest::partitionName(origin->host()));

    Vector<CachedResource*> resourcesToRemove;
    for (auto& keyValuePair : *resourceMap) {
        auto& resource = *keyValuePair.value;
        auto& partitionName = keyValuePair.key.second;
        if (originPartitions.contains(partitionName)) {
            resourcesToRemove.append(&resource);
            continue;
        }
        if (origins.contains(SecurityOrigin::create(resource.url()).ptr()))
            resourcesToRemove.append(&resource);
    }

    for (auto& resource : resourcesToRemove)
        remove(*resource);
}

void MemoryCache::getOriginsWithCache(SecurityOriginSet& origins)
{
    for (auto& resources : m_sessionResources.values()) {
        for (auto& keyValue : *resources) {
            auto& resource = *keyValue.value;
            auto& partitionName = keyValue.key.second;
            if (!partitionName.isEmpty())
                origins.add(SecurityOrigin::create("http"_s, partitionName, 0));
            else
                origins.add(SecurityOrigin::create(resource.url()));
        }
    }
}

HashSet<RefPtr<SecurityOrigin>> MemoryCache::originsWithCache(PAL::SessionID sessionID) const
{
    HashSet<RefPtr<SecurityOrigin>> origins;

    auto it = m_sessionResources.find(sessionID);
    if (it != m_sessionResources.end()) {
        for (auto& keyValue : *it->value) {
            auto& resource = *keyValue.value;
            auto& partitionName = keyValue.key.second;
            if (!partitionName.isEmpty())
                origins.add(SecurityOrigin::create("http", partitionName, 0));
            else
                origins.add(SecurityOrigin::create(resource.url()));
        }
    }

    return origins;
}

void MemoryCache::removeFromLiveDecodedResourcesList(CachedResource& resource)
{
    m_liveDecodedResources.remove(&resource);
}

void MemoryCache::insertInLiveDecodedResourcesList(CachedResource& resource)
{
    // Make sure we aren't in the list already.
    ASSERT(!m_liveDecodedResources.contains(&resource));
    m_liveDecodedResources.add(&resource);
}

void MemoryCache::addToLiveResourcesSize(CachedResource& resource)
{
    m_liveSize += resource.size();
    m_deadSize -= resource.size();
}

void MemoryCache::removeFromLiveResourcesSize(CachedResource& resource)
{
    m_liveSize -= resource.size();
    m_deadSize += resource.size();
}

void MemoryCache::adjustSize(bool live, long long delta)
{
    if (live) {
        ASSERT(delta >= 0 || (static_cast<long long>(m_liveSize) + delta >= 0));
        m_liveSize += delta;
    } else {
        ASSERT(delta >= 0 || (static_cast<long long>(m_deadSize) + delta >= 0));
        m_deadSize += delta;
    }
}

void MemoryCache::removeRequestFromSessionCaches(ScriptExecutionContext& context, const ResourceRequest& request)
{
    if (is<WorkerGlobalScope>(context)) {
        downcast<WorkerGlobalScope>(context).thread().workerLoaderProxy().postTaskToLoader([request = request.isolatedCopy()] (ScriptExecutionContext& context) {
            MemoryCache::removeRequestFromSessionCaches(context, request);
        });
        return;
    }

    auto& memoryCache = MemoryCache::singleton();
    for (auto& resources : memoryCache.m_sessionResources) {
        if (CachedResource* resource = memoryCache.resourceForRequestImpl(request, *resources.value))
            memoryCache.remove(*resource);
    }
}

void MemoryCache::TypeStatistic::addResource(CachedResource& resource)
{
    count++;
    size += resource.size();
    liveSize += resource.hasClients() ? resource.size() : 0;
    decodedSize += resource.decodedSize();
}

MemoryCache::Statistics MemoryCache::getStatistics()
{
    Statistics stats;

    for (auto& resources : m_sessionResources.values()) {
        for (auto* resource : resources->values()) {
            switch (resource->type()) {
            case CachedResource::Type::ImageResource:
                stats.images.addResource(*resource);
                break;
            case CachedResource::Type::CSSStyleSheet:
                stats.cssStyleSheets.addResource(*resource);
                break;
            case CachedResource::Type::Script:
                stats.scripts.addResource(*resource);
                break;
#if ENABLE(XSLT)
            case CachedResource::Type::XSLStyleSheet:
                stats.xslStyleSheets.addResource(*resource);
                break;
#endif
            case CachedResource::Type::SVGFontResource:
            case CachedResource::Type::FontResource:
                stats.fonts.addResource(*resource);
                break;
            default:
                break;
            }
        }
    }
    return stats;
}

void MemoryCache::setDisabled(bool disabled)
{
    m_disabled = disabled;
    if (!m_disabled)
        return;

    while (!m_sessionResources.isEmpty()) {
        auto& resources = *m_sessionResources.begin()->value;
        ASSERT(!resources.isEmpty());
        remove(*resources.begin()->value);
    }
}

void MemoryCache::evictResources()
{
    if (disabled())
        return;

    setDisabled(true);
    setDisabled(false);
}

void MemoryCache::evictResources(PAL::SessionID sessionID)
{
    if (disabled())
        return;

    forEachSessionResource(sessionID, [this] (CachedResource& resource) { remove(resource); });

    ASSERT(!m_sessionResources.contains(sessionID));
}

bool MemoryCache::needsPruning() const
{
    return m_liveSize + m_deadSize > m_capacity || m_deadSize > m_maxDeadCapacity;
}

void MemoryCache::prune()
{
    if (!needsPruning())
        return;
        
    pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live.
    pruneLiveResources();
}

void MemoryCache::pruneSoon()
{
    if (m_pruneTimer.isActive())
        return;
    if (!needsPruning())
        return;
    m_pruneTimer.startOneShot(0_s);
}

void MemoryCache::dumpStats()
{
    Statistics s = getStatistics();
    WTFLogAlways("\nMemory Cache");
    WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize");
    WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------");
    WTFLogAlways("%-13s %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize);
    WTFLogAlways("%-13s %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize);
#if ENABLE(XSLT)
    WTFLogAlways("%-13s %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize);
#endif
    WTFLogAlways("%-13s %13d %13d %13d %13d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize);
    WTFLogAlways("%-13s %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize);
    WTFLogAlways("%-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------");

    unsigned countTotal = s.images.count + s.cssStyleSheets.count + s.scripts.count + s.fonts.count;
    unsigned sizeTotal = s.images.size + s.cssStyleSheets.size + s.scripts.size + s.fonts.size;
    unsigned liveSizeTotal = s.images.liveSize + s.cssStyleSheets.liveSize + s.scripts.liveSize + s.fonts.liveSize;
    unsigned decodedSizeTotal = s.images.decodedSize + s.cssStyleSheets.decodedSize + s.scripts.decodedSize + s.fonts.decodedSize;
#if ENABLE(XSLT)
    countTotal += s.xslStyleSheets.count;
    sizeTotal += s.xslStyleSheets.size;
    liveSizeTotal += s.xslStyleSheets.liveSize;
    decodedSizeTotal += s.xslStyleSheets.decodedSize;
#endif

    WTFLogAlways("%-13s %13d %11.2fKB %11.2fKB %11.2fKB\n", "Total", countTotal, sizeTotal / 1024., liveSizeTotal / 1024., decodedSizeTotal / 1024.);
}

void MemoryCache::dumpLRULists(bool includeLive) const
{
    WTFLogAlways("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced):\n");

    int size = m_allResources.size();
    for (int i = size - 1; i >= 0; i--) {
        WTFLogAlways("\nList %d:\n", i);
        for (auto* resource : *m_allResources[i]) {
            if (includeLive || !resource->hasClients())
                WTFLogAlways("  %p %.255s %.1fK, %.1fK, accesses: %u, clients: %d\n", resource, resource->url().string().utf8().data(), resource->decodedSize() / 1024.0f, (resource->encodedSize() + resource->overheadSize()) / 1024.0f, resource->accessCount(), resource->numberOfClients());
        }
    }
}

} // namespace WebCore
