15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    This library is free software; you can redistribute it and/or
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    modify it under the terms of the GNU Library General Public
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    License as published by the Free Software Foundation; either
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    version 2 of the License, or (at your option) any later version.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    This library is distributed in the hope that it will be useful,
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    but WITHOUT ANY WARRANTY; without even the implied warranty of
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Library General Public License for more details.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    You should have received a copy of the GNU Library General Public License
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    along with this library; see the file COPYING.LIB.  If not, write to
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Boston, MA 02110-1301, USA.
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/loader/cache/MemoryCache.h"
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include <stdio.h>
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/CrossThreadTask.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Document.h"
29fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch#include "core/loader/cache/Resource.h"
30fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch#include "core/loader/cache/ResourcePtr.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/page/FrameView.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/platform/Logging.h"
33591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/workers/WorkerGlobalScope.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerLoaderProxy.h"
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/workers/WorkerThread.h"
36e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "weborigin/SecurityOrigin.h"
37e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "weborigin/SecurityOriginHash.h"
38521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/Assertions.h"
39521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/CurrentTime.h"
40521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/MathExtras.h"
41521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/TemporaryChange.h"
42521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "wtf/text/CString.h"
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace std;
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)static MemoryCache* gMemoryCache;
49521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int cDefaultCacheCapacity = 8192 * 1024;
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const double cMinDelayBeforeLiveDecodedPrune = 1; // Seconds.
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const float cTargetPrunePercentage = .95f; // Percentage of capacity toward which we prune, to avoid immediately pruning again.
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)MemoryCache* memoryCache()
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(WTF::isMainThread());
57521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (!gMemoryCache)
58521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        gMemoryCache = new MemoryCache();
59521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    return gMemoryCache;
60521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
62521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void setMemoryCacheForTesting(MemoryCache* memoryCache)
63521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){
64521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    gMemoryCache = memoryCache;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)MemoryCache::MemoryCache()
6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    : m_inPruneResources(false)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_capacity(cDefaultCacheCapacity)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_minDeadCapacity(0)
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_maxDeadCapacity(cDefaultCacheCapacity)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_liveSize(0)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_deadSize(0)
741fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    , m_delayBeforeLiveDecodedPrune(cMinDelayBeforeLiveDecodedPrune)
755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef MEMORY_CACHE_STATS
765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    , m_statsTimer(this, &MemoryCache::dumpStats)
775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#endif
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef MEMORY_CACHE_STATS
805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    const double statsIntervalInSeconds = 15;
815267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    m_statsTimer.startRepeating(statsIntervalInSeconds);
825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#endif
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)KURL MemoryCache::removeFragmentIdentifierIfNeeded(const KURL& originalURL)
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!originalURL.hasFragmentIdentifier())
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return originalURL;
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Strip away fragment identifier from HTTP URLs.
9002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // Data URLs must be unmodified. For file and custom URLs clients may expect resources
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // to be unique even when they differ by the fragment identifier only.
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!originalURL.protocolIsInHTTPFamily())
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return originalURL;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    KURL url = originalURL;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    url.removeFragmentIdentifier();
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return url;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
99fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::add(Resource* resource)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(WTF::isMainThread());
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_resources.set(resource->url(), resource);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->setInCache(true);
10493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    resource->updateForAccess();
10502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resource->url().string().latin1().data(), resource);
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
109fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::replace(Resource* newResource, Resource* oldResource)
110e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch{
111e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    evict(oldResource);
112e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    ASSERT(!m_resources.get(newResource->url()));
113e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    m_resources.set(newResource->url(), newResource);
114e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    newResource->setInCache(true);
115e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    insertInLRUList(newResource);
116e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    int delta = newResource->size();
117e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (newResource->decodedSize() && newResource->hasClients())
118e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        insertInLiveDecodedResourcesList(newResource);
119e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (delta)
120e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        adjustSize(newResource->hasClients(), delta);
121e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch}
122e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
123fff8884795cb540f87cf6e6d67b629519b00eb8bBen MurdochResource* MemoryCache::resourceForURL(const KURL& resourceURL)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(WTF::isMainThread());
12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    KURL url = removeFragmentIdentifierIfNeeded(resourceURL);
127fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    Resource* resource = m_resources.get(url);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (resource && !resource->makePurgeable(false)) {
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!resource->hasClients());
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        evict(resource);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return resource;
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
13602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdochunsigned MemoryCache::deadCapacity() const
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Dead resource capacity is whatever space is not occupied by live resources, bounded by an independent minimum and maximum.
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned capacity = m_capacity - min(m_liveSize, m_capacity); // Start with available capacity.
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    capacity = max(capacity, m_minDeadCapacity); // Make sure it's above the minimum.
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    capacity = min(capacity, m_maxDeadCapacity); // Make sure it's below the maximum.
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return capacity;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
14502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdochunsigned MemoryCache::liveCapacity() const
14602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch{
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Live resource capacity is whatever is left over after calculating dead resource capacity.
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return m_capacity - deadCapacity();
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::pruneLiveResources()
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned capacity = liveCapacity();
154e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    if (!m_liveSize || (capacity && m_liveSize <= capacity))
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again.
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double currentTime = FrameView::currentPaintTimeStamp();
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!currentTime) // In case prune is called directly, outside of a Frame paint.
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        currentTime = WTF::currentTime();
16202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Destroy any decoded data in live objects that we can.
1641fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    // Start from the tail, since this is the lowest priority
1651fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    // and least recently accessed of the objects.
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The list might not be sorted by the m_lastDecodedAccessTime. The impact
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // of this weaker invariant is minor as the below if statement to check the
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // elapsedTime will evaluate to false as the currentTime will be a lot
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // greater than the current->m_lastDecodedAccessTime.
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209
1721fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
1731fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    // Start pruning from the lowest priority list.
1741fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    for (int priority = Resource::CacheLiveResourcePriorityLow; priority <= Resource::CacheLiveResourcePriorityHigh; ++priority) {
1751fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        Resource* current = m_liveDecodedResources[priority].m_tail;
1761fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        while (current) {
1771fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            Resource* prev = current->m_prevInLiveResourcesList;
1781fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            ASSERT(current->hasClients());
1791fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            if (current->isLoaded() && current->decodedSize()) {
1801fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                // Check to see if the remaining resources are too new to prune.
1811fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                double elapsedTime = currentTime - current->m_lastDecodedAccessTime;
1821fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                if (elapsedTime < m_delayBeforeLiveDecodedPrune)
1831fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                    return;
1841fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
1851fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                // Destroy our decoded data. This will remove us from
1861fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                // m_liveDecodedResources, and possibly move us to a different LRU
1871fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                // list in m_allResources.
1881fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                current->destroyDecodedData();
1891fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
1901fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                if (targetSize && m_liveSize <= targetSize)
1911fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch                    return;
1921fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            }
1931fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch            current = prev;
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::pruneDeadResources()
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned capacity = deadCapacity();
201e6d4491e48613634a83c1957c72759da80987961Ben Murdoch    if (!m_deadSize || (capacity && m_deadSize <= capacity))
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again.
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int size = m_allResources.size();
20702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // See if we have any purged resources we can evict.
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < size; i++) {
210fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        Resource* current = m_allResources[i].m_tail;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (current) {
212fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            Resource* prev = current->m_prevInAllResourcesList;
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (current->wasPurged()) {
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ASSERT(!current->hasClients());
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ASSERT(!current->isPreloaded());
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                evict(current);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current = prev;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (targetSize && m_deadSize <= targetSize)
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool canShrinkLRULists = true;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = size - 1; i >= 0; i--) {
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove from the tail, since this is the least frequently accessed of the objects.
227fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        Resource* current = m_allResources[i].m_tail;
22802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // First flush all the decoded data in this queue.
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (current) {
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Protect 'previous' so it can't get deleted during destroyDecodedData().
232fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            ResourcePtr<Resource> previous = current->m_prevInAllResourcesList;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(!previous || previous->inCache());
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!current->hasClients() && !current->isPreloaded() && current->isLoaded()) {
23502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                // Destroy our decoded data. This will remove us from
23602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch                // m_liveDecodedResources, and possibly move us to a different
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // LRU list in m_allResources.
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                current->destroyDecodedData();
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (targetSize && m_deadSize <= targetSize)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return;
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Decoded data may reference other resources. Stop iterating if 'previous' somehow got
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // kicked out of cache during destroyDecodedData().
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (previous && !previous->inCache())
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current = previous.get();
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Now evict objects from this queue.
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        current = m_allResources[i].m_tail;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (current) {
253fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            ResourcePtr<Resource> previous = current->m_prevInAllResourcesList;
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ASSERT(!previous || previous->inCache());
255521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) {
256521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                evict(current);
257521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                if (targetSize && m_deadSize <= targetSize)
258521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)                    return;
259521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            }
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (previous && !previous->inCache())
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                break;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current = previous.get();
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
26402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Shrink the vector back down so we don't waste time inspecting
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // empty LRU lists on future prunes.
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_allResources[i].m_head)
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            canShrinkLRULists = false;
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (canShrinkLRULists)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            m_allResources.resize(i);
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(minDeadBytes <= maxDeadBytes);
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(maxDeadBytes <= totalBytes);
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_minDeadCapacity = minDeadBytes;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_maxDeadCapacity = maxDeadBytes;
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_capacity = totalBytes;
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    prune();
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
284fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::evict(Resource* resource)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(WTF::isMainThread());
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resource, resource->url().string().latin1().data());
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The resource may have already been removed by someone other than our caller,
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bug.cgi?id=12479#c6>.
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (resource->inCache()) {
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove from the resource map.
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_resources.remove(resource->url());
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        resource->setInCache(false);
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Remove from the appropriate LRU list.
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeFromLRUList(resource);
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        removeFromLiveDecodedResourcesList(resource);
298521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        adjustSize(resource->hasClients(), -static_cast<int>(resource->size()));
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(m_resources.get(resource->url()) != resource);
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->deleteIfPossible();
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
305fff8884795cb540f87cf6e6d67b629519b00eb8bBen MurdochMemoryCache::LRUList* MemoryCache::lruListFor(Resource* resource)
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned accessCount = max(resource->accessCount(), 1U);
308926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    unsigned queueIndex = WTF::fastLog2(resource->size() / accessCount);
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_lruIndex = queueIndex;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_allResources.size() <= queueIndex)
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_allResources.grow(queueIndex + 1);
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return &m_allResources[queueIndex];
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
317fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::removeFromLRUList(Resource* resource)
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we've never been accessed, then we're brand new and not in any list.
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (resource->accessCount() == 0)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !ASSERT_DISABLED
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned oldListIndex = resource->m_lruIndex;
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LRUList* list = lruListFor(resource);
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !ASSERT_DISABLED
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that the list we got is the list we want.
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(resource->m_lruIndex == oldListIndex);
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that we are in fact in this list.
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool found = false;
335fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    for (Resource* current = list->m_head; current; current = current->m_nextInAllResourcesList) {
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (current == resource) {
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            found = true;
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(found);
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
344fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    Resource* next = resource->m_nextInAllResourcesList;
345fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    Resource* prev = resource->m_prevInAllResourcesList;
34602772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (next == 0 && prev == 0 && list->m_head != resource)
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
34902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_nextInAllResourcesList = 0;
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_prevInAllResourcesList = 0;
35202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (next)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        next->m_prevInAllResourcesList = prev;
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (list->m_tail == resource)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        list->m_tail = prev;
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (prev)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        prev->m_nextInAllResourcesList = next;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (list->m_head == resource)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        list->m_head = next;
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
364fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::insertInLRUList(Resource* resource)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make sure we aren't in some list already.
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!resource->m_nextInAllResourcesList && !resource->m_prevInAllResourcesList);
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(resource->inCache());
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(resource->accessCount() > 0);
37002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LRUList* list = lruListFor(resource);
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_nextInAllResourcesList = list->m_head;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (list->m_head)
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        list->m_head->m_prevInAllResourcesList = resource;
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    list->m_head = resource;
37702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resource->m_nextInAllResourcesList)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        list->m_tail = resource;
38002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !ASSERT_DISABLED
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that we are in now in the list like we should be.
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    list = lruListFor(resource);
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool found = false;
385fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    for (Resource* current = list->m_head; current; current = current->m_nextInAllResourcesList) {
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (current == resource) {
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            found = true;
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(found);
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
396fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::removeFromLiveDecodedResourcesList(Resource* resource)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we've never been accessed, then we're brand new and not in any list.
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resource->m_inLiveDecodedResourcesList)
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_inLiveDecodedResourcesList = false;
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4031fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority()];
4041fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !ASSERT_DISABLED
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that we are in fact in this list.
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool found = false;
4081fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    for (Resource* current = list->m_head; current; current = current->m_nextInLiveResourcesList) {
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (current == resource) {
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            found = true;
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(found);
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
417fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    Resource* next = resource->m_nextInLiveResourcesList;
418fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    Resource* prev = resource->m_prevInLiveResourcesList;
41902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4201fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    if (!next && !prev && list->m_head != resource)
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
42202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_nextInLiveResourcesList = 0;
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_prevInLiveResourcesList = 0;
42502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (next)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        next->m_prevInLiveResourcesList = prev;
4281fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    else if (list->m_tail == resource)
4291fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        list->m_tail = prev;
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (prev)
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        prev->m_nextInLiveResourcesList = next;
4331fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    else if (list->m_head == resource)
4341fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        list->m_head = next;
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
437fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::insertInLiveDecodedResourcesList(Resource* resource)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Make sure we aren't in the list already.
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!resource->m_nextInLiveResourcesList && !resource->m_prevInLiveResourcesList && !resource->m_inLiveDecodedResourcesList);
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource->m_inLiveDecodedResourcesList = true;
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4431fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    LRUList* list = &m_liveDecodedResources[resource->cacheLiveResourcePriority()];
4441fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    resource->m_nextInLiveResourcesList = list->m_head;
4451fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    if (list->m_head)
4461fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        list->m_head->m_prevInLiveResourcesList = resource;
4471fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    list->m_head = resource;
44802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resource->m_nextInLiveResourcesList)
4501fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        list->m_tail = resource;
45102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if !ASSERT_DISABLED
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that we are in now in the list like we should be.
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool found = false;
4551fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    for (Resource* current = list->m_head; current; current = current->m_nextInLiveResourcesList) {
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (current == resource) {
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            found = true;
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(found);
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
466fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::addToLiveResourcesSize(Resource* resource)
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_liveSize += resource->size();
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_deadSize -= resource->size();
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
472fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::removeFromLiveResourcesSize(Resource* resource)
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_liveSize -= resource->size();
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_deadSize += resource->size();
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::adjustSize(bool live, int delta)
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (live) {
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(delta >= 0 || ((int)m_liveSize + delta >= 0));
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_liveSize += delta;
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(delta >= 0 || ((int)m_deadSize + delta >= 0));
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_deadSize += delta;
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MemoryCache::removeURLFromCache(ScriptExecutionContext* context, const KURL& url)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
491591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (context->isWorkerGlobalScope()) {
492591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
493591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        workerGlobalScope->thread()->workerLoaderProxy().postTaskToLoader(createCallbackTask(&removeURLFromCacheInternal, url));
4945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    removeURLFromCacheInternal(context, url);
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MemoryCache::removeURLFromCacheInternal(ScriptExecutionContext*, const KURL& url)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
501fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    if (Resource* resource = memoryCache()->resourceForURL(url))
50253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        memoryCache()->remove(resource);
503926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
504926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
505fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdochvoid MemoryCache::TypeStatistic::addResource(Resource* o)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool purged = o->wasPurged();
50802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    bool purgeable = o->isPurgeable() && !purged;
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int pageSize = (o->encodedSize() + o->overheadSize() + 4095) & ~4095;
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    count++;
5115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    size += purged ? 0 : o->size();
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    liveSize += o->hasClients() ? o->size() : 0;
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    decodedSize += o->decodedSize();
5145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    encodedSize += o->encodedSize();
5155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    encodedSizeDuplicatedInDataURLs += o->url().protocolIsData() ? o->encodedSize() : 0;
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    purgeableSize += purgeable ? pageSize : 0;
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    purgedSize += purged ? pageSize : 0;
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)MemoryCache::Statistics MemoryCache::getStatistics()
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Statistics stats;
523fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    ResourceMap::iterator e = m_resources.end();
524fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch    for (ResourceMap::iterator i = m_resources.begin(); i != e; ++i) {
525fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        Resource* resource = i->value;
52653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        switch (resource->type()) {
527e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        case Resource::Image:
52853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            stats.images.addResource(resource);
52953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
530fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        case Resource::CSSStyleSheet:
53153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            stats.cssStyleSheets.addResource(resource);
53253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
533fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        case Resource::Script:
53453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            stats.scripts.addResource(resource);
53553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
536fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        case Resource::XSLStyleSheet:
53753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            stats.xslStyleSheets.addResource(resource);
53853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
539e6d4491e48613634a83c1957c72759da80987961Ben Murdoch        case Resource::Font:
54053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            stats.fonts.addResource(resource);
54153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
54253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        default:
543521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            stats.other.addResource(resource);
54453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)            break;
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return stats;
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void MemoryCache::evictResources()
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (;;) {
553fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        ResourceMap::iterator i = m_resources.begin();
55453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        if (i == m_resources.end())
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
55653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        evict(i->value);
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::prune()
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize <= m_maxDeadCapacity) // Fast path.
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
564e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (m_inPruneResources)
565e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        return;
566e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    TemporaryChange<bool> reentrancyProtector(m_inPruneResources, true);
567e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live.
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    pruneLiveResources();
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef MEMORY_CACHE_STATS
5745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
5755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void MemoryCache::dumpStats(Timer<MemoryCache>*)
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Statistics s = getStatistics();
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "", "Count", "Size", "LiveSize", "DecodedSize", "PurgeableSize", "PurgedSize");
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Images", s.images.count, s.images.size, s.images.liveSize, s.images.decodedSize, s.images.purgeableSize, s.images.purgedSize);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "CSS", s.cssStyleSheets.count, s.cssStyleSheets.size, s.cssStyleSheets.liveSize, s.cssStyleSheets.decodedSize, s.cssStyleSheets.purgeableSize, s.cssStyleSheets.purgedSize);
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "XSL", s.xslStyleSheets.count, s.xslStyleSheets.size, s.xslStyleSheets.liveSize, s.xslStyleSheets.decodedSize, s.xslStyleSheets.purgeableSize, s.xslStyleSheets.purgedSize);
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "JavaScript", s.scripts.count, s.scripts.size, s.scripts.liveSize, s.scripts.decodedSize, s.scripts.purgeableSize, s.scripts.purgedSize);
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Fonts", s.fonts.count, s.fonts.size, s.fonts.liveSize, s.fonts.decodedSize, s.fonts.purgeableSize, s.fonts.purgedSize);
585521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    printf("%-13s %13d %13d %13d %13d %13d %13d\n", "Other", s.other.count, s.other.size, s.other.liveSize, s.other.decodedSize, s.other.purgeableSize, s.other.purgedSize);
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("%-13s %-13s %-13s %-13s %-13s %-13s %-13s\n\n", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
5875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
5885267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("Duplication of encoded data from data URLs\n");
5895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("%-13s %13d of %13d\n", "Images",     s.images.encodedSizeDuplicatedInDataURLs,         s.images.encodedSize);
5905267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("%-13s %13d of %13d\n", "CSS",        s.cssStyleSheets.encodedSizeDuplicatedInDataURLs, s.cssStyleSheets.encodedSize);
5915267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("%-13s %13d of %13d\n", "XSL",        s.xslStyleSheets.encodedSizeDuplicatedInDataURLs, s.xslStyleSheets.encodedSize);
5925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("%-13s %13d of %13d\n", "JavaScript", s.scripts.encodedSizeDuplicatedInDataURLs,        s.scripts.encodedSize);
5935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    printf("%-13s %13d of %13d\n", "Fonts",      s.fonts.encodedSizeDuplicatedInDataURLs,          s.fonts.encodedSize);
594521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    printf("%-13s %13d of %13d\n", "Other",      s.other.encodedSizeDuplicatedInDataURLs,          s.other.encodedSize);
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void MemoryCache::dumpLRULists(bool includeLive) const
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded, Access count, Referenced, isPurgeable, wasPurged):\n");
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int size = m_allResources.size();
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = size - 1; i >= 0; i--) {
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        printf("\n\nList %d: ", i);
604fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch        Resource* current = m_allResources[i].m_tail;
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (current) {
606fff8884795cb540f87cf6e6d67b629519b00eb8bBen Murdoch            Resource* prev = current->m_prevInAllResourcesList;
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (includeLive || !current->hasClients())
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                printf("(%.1fK, %.1fK, %uA, %dR, %d, %d); ", current->decodedSize() / 1024.0f, (current->encodedSize() + current->overheadSize()) / 1024.0f, current->accessCount(), current->hasClients(), current->isPurgeable(), current->wasPurged());
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            current = prev;
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
6155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#endif // MEMORY_CACHE_STATS
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
618