Changeset 17131 in webkit


Ignore:
Timestamp:
Oct 19, 2006 2:21:54 AM (17 years ago)
Author:
hyatt
Message:

Rewrite of the WebCore memory cache. The following changes have been made (along with many more):

(1) Referenced objects are now also cached.

(2) Pruning of the cache will occur once the cache is both full and in addition
more than half full with unreferenced objects.

(3) The prune is much more aggressive now, since referenced objects are counted when
pruning. The cache will therefore often prune out every unreferenced object if lots of
windows/tabs are open.

(4) Consolidated the request methods for various types of resources to go through a single
requestResource bottleneck function.

(5) deref on CachedResource is no longer virtual, since the implementation in every subclass was
identical.

(6) Changed "object" to "resource" everywhere.

(7) The Cache is now an actual object, obtained via cache().

(8) Fixed bugs with the autoload images preference so that it would really work properly when disabled
and enabled.

(9) Tweaked ImageDocuments to set up the status properly for the CachedResource that they use.

(10) Fixed the LRU-SP algorithm so that the LRU aspect really kicks in (by leaving the live objects
in the LRU lists). Also fixed a bug with the "-SP" part of the algorithm where the access count was
being incorrectly weighted too much due to a math error.

(11) Fixed a bug where the old cache could grow without bound because it didn't know anything about
the size of referenced resources.

Reviewed by Maciej, bradee-oh

  • bridge/mac/WebCoreCache.mm: (+[WebCoreCache statistics]): (+[WebCoreCache empty]): (+[WebCoreCache setDisabled:]):
  • bridge/mac/WebCoreFrameBridge.mm: (-[WebCoreFrameBridge initMainFrameWithPage:]): (-[WebCoreFrameBridge getData:andResponse:forURL:]): (-[WebCoreFrameBridge getAllResourceDatas:andResponses:]):
  • css/CSSImageValue.cpp: (WebCore::CSSImageValue::image):
  • dom/XMLTokenizer.cpp: (WebCore::openFunc):
  • html/HTMLImageLoader.cpp: (WebCore::HTMLImageLoader::updateFromElement):
  • loader/Cache.cpp: (WebCore::cache): (WebCore::Cache::Cache): (WebCore::createResource): (WebCore::Cache::requestResource): (WebCore::Cache::resourceForURL): (WebCore::Cache::prune): (WebCore::Cache::setMaximumSize): (WebCore::Cache::remove): (WebCore::Cache::addDocLoader): (WebCore::Cache::removeDocLoader): (WebCore::fastLog2): (WebCore::Cache::lruListFor): (WebCore::Cache::removeFromLRUList): (WebCore::Cache::insertInLRUList): (WebCore::Cache::resourceAccessed): (WebCore::Cache::adjustSize): (WebCore::Cache::getStatistics): (WebCore::Cache::setDisabled):
  • loader/Cache.h: (WebCore::LRUList::LRUList): (WebCore::Cache::loader): (WebCore::Cache::maximumSize): (WebCore::Cache::disabled): (WebCore::Cache::addToLiveObjectSize): (WebCore::Cache::removeFromLiveObjectSize): (WebCore::Cache::TypeStatistic::TypeStatistic):
  • loader/CachedCSSStyleSheet.cpp: (WebCore::CachedCSSStyleSheet::CachedCSSStyleSheet):
  • loader/CachedCSSStyleSheet.h:
  • loader/CachedImage.cpp: (WebCore::CachedImage::CachedImage): (WebCore::CachedImage::~CachedImage): (WebCore::brokenImage): (WebCore::nullImage): (WebCore::CachedImage::image): (WebCore::CachedImage::data):
  • loader/CachedImage.h: (WebCore::CachedImage::stillNeedsLoad):
  • loader/CachedResource.cpp: (WebCore::CachedResource::CachedResource): (WebCore::CachedResource::~CachedResource): (WebCore::CachedResource::finish): (WebCore::CachedResource::setExpireDate): (WebCore::CachedResource::isExpired): (WebCore::CachedResource::setRequest): (WebCore::CachedResource::ref): (WebCore::CachedResource::deref): (WebCore::CachedResource::setSize):
  • loader/CachedResource.h: (WebCore::CachedResource::): (WebCore::CachedResource::setCharset): (WebCore::CachedResource::url): (WebCore::CachedResource::type): (WebCore::CachedResource::referenced): (WebCore::CachedResource::count): (WebCore::CachedResource::status): (WebCore::CachedResource::size): (WebCore::CachedResource::isLoaded): (WebCore::CachedResource::setLoading): (WebCore::CachedResource::isImage): (WebCore::CachedResource::accessCount): (WebCore::CachedResource::increaseAccessCount): (WebCore::CachedResource::setInCache): (WebCore::CachedResource::inCache): (WebCore::CachedResource::cachePolicy): (WebCore::CachedResource::response): (WebCore::CachedResource::allData): (WebCore::CachedResource::canDelete): (WebCore::CachedResource::schedule): (WebCore::CachedResource::accept): (WebCore::CachedResource::setAccept):
  • loader/CachedScript.cpp: (WebCore::CachedScript::CachedScript):
  • loader/CachedScript.h:
  • loader/CachedXBLDocument.cpp:
  • loader/CachedXBLDocument.h:
  • loader/CachedXSLStyleSheet.cpp: (WebCore::CachedXSLStyleSheet::CachedXSLStyleSheet):
  • loader/CachedXSLStyleSheet.h:
  • loader/DocLoader.cpp: (WebCore::DocLoader::DocLoader): (WebCore::DocLoader::~DocLoader): (WebCore::DocLoader::checkForReload): (WebCore::DocLoader::requestImage): (WebCore::DocLoader::requestCSSStyleSheet): (WebCore::DocLoader::requestScript): (WebCore::DocLoader::requestXSLStyleSheet): (WebCore::DocLoader::requestXBLDocument): (WebCore::DocLoader::requestResource): (WebCore::DocLoader::setAutoLoadImages): (WebCore::DocLoader::removeCachedResource):
  • loader/DocLoader.h: (WebCore::DocLoader::cachedResource): (WebCore::DocLoader::allCachedResources): (WebCore::DocLoader::autoLoadImages): (WebCore::DocLoader::cachePolicy): (WebCore::DocLoader::expireDate): (WebCore::DocLoader::frame): (WebCore::DocLoader::doc): (WebCore::DocLoader::loadInProgress):
  • loader/ImageDocument.cpp: (WebCore::ImageTokenizer::finish):
  • loader/loader.cpp: (WebCore::Loader::receivedAllData): (WebCore::Loader::cancelRequests):
  • loader/mac/LoaderFunctionsMac.mm: (WebCore::NumberOfPendingOrLoadingRequests): (WebCore::CheckCacheObjectStatus):
  • page/Frame.cpp: (WebCore::UserStyleSheetLoader::UserStyleSheetLoader): (WebCore::Frame::Frame): (WebCore::Frame::stopLoading): (WebCore::Frame::setAutoLoadImages): (WebCore::Frame::autoLoadImages): (WebCore::Frame::begin): (WebCore::Frame::checkCompleted): (WebCore::Frame::reparseConfiguration):
  • page/Frame.h:
  • xml/XSLTProcessor.cpp: (WebCore::docLoaderFunc):
  • xml/xmlhttprequest.cpp: (WebCore::XMLHttpRequest::send):
Location:
trunk/WebCore
Files:
29 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r17127 r17131  
     12006-10-19  David Hyatt  <hyatt@apple.com>
     2
     3        Rewrite of the WebCore memory cache.  The following changes have been made (along with many more):
     4
     5        (1) Referenced objects are now also cached.
     6
     7        (2) Pruning of the cache will occur once the cache is both full and in addition
     8        more than half full with unreferenced objects.
     9
     10        (3) The prune is much more aggressive now, since referenced objects are counted when
     11        pruning.  The cache will therefore often prune out every unreferenced object if lots of
     12        windows/tabs are open.
     13
     14        (4) Consolidated the request methods for various types of resources to go through a single
     15        requestResource bottleneck function.
     16
     17        (5) deref on CachedResource is no longer virtual, since the implementation in every subclass was
     18        identical.
     19
     20        (6) Changed "object" to "resource" everywhere.
     21
     22        (7) The Cache is now an actual object, obtained via cache().
     23
     24        (8) Fixed bugs with the autoload images preference so that it would really work properly when disabled
     25        and enabled.
     26
     27        (9) Tweaked ImageDocuments to set up the status properly for the CachedResource that they use.
     28
     29        (10) Fixed the LRU-SP algorithm so that the LRU aspect really kicks in (by leaving the live objects
     30        in the LRU lists).  Also fixed a bug with the "-SP" part of the algorithm where the access count was
     31        being incorrectly weighted too much due to a math error.
     32
     33        (11) Fixed a bug where the old cache could grow without bound because it didn't know anything about
     34        the size of referenced resources.
     35
     36        Reviewed by Maciej, bradee-oh
     37
     38        * bridge/mac/WebCoreCache.mm:
     39        (+[WebCoreCache statistics]):
     40        (+[WebCoreCache empty]):
     41        (+[WebCoreCache setDisabled:]):
     42        * bridge/mac/WebCoreFrameBridge.mm:
     43        (-[WebCoreFrameBridge initMainFrameWithPage:]):
     44        (-[WebCoreFrameBridge getData:andResponse:forURL:]):
     45        (-[WebCoreFrameBridge getAllResourceDatas:andResponses:]):
     46        * css/CSSImageValue.cpp:
     47        (WebCore::CSSImageValue::image):
     48        * dom/XMLTokenizer.cpp:
     49        (WebCore::openFunc):
     50        * html/HTMLImageLoader.cpp:
     51        (WebCore::HTMLImageLoader::updateFromElement):
     52        * loader/Cache.cpp:
     53        (WebCore::cache):
     54        (WebCore::Cache::Cache):
     55        (WebCore::createResource):
     56        (WebCore::Cache::requestResource):
     57        (WebCore::Cache::resourceForURL):
     58        (WebCore::Cache::prune):
     59        (WebCore::Cache::setMaximumSize):
     60        (WebCore::Cache::remove):
     61        (WebCore::Cache::addDocLoader):
     62        (WebCore::Cache::removeDocLoader):
     63        (WebCore::fastLog2):
     64        (WebCore::Cache::lruListFor):
     65        (WebCore::Cache::removeFromLRUList):
     66        (WebCore::Cache::insertInLRUList):
     67        (WebCore::Cache::resourceAccessed):
     68        (WebCore::Cache::adjustSize):
     69        (WebCore::Cache::getStatistics):
     70        (WebCore::Cache::setDisabled):
     71        * loader/Cache.h:
     72        (WebCore::LRUList::LRUList):
     73        (WebCore::Cache::loader):
     74        (WebCore::Cache::maximumSize):
     75        (WebCore::Cache::disabled):
     76        (WebCore::Cache::addToLiveObjectSize):
     77        (WebCore::Cache::removeFromLiveObjectSize):
     78        (WebCore::Cache::TypeStatistic::TypeStatistic):
     79        * loader/CachedCSSStyleSheet.cpp:
     80        (WebCore::CachedCSSStyleSheet::CachedCSSStyleSheet):
     81        * loader/CachedCSSStyleSheet.h:
     82        * loader/CachedImage.cpp:
     83        (WebCore::CachedImage::CachedImage):
     84        (WebCore::CachedImage::~CachedImage):
     85        (WebCore::brokenImage):
     86        (WebCore::nullImage):
     87        (WebCore::CachedImage::image):
     88        (WebCore::CachedImage::data):
     89        * loader/CachedImage.h:
     90        (WebCore::CachedImage::stillNeedsLoad):
     91        * loader/CachedResource.cpp:
     92        (WebCore::CachedResource::CachedResource):
     93        (WebCore::CachedResource::~CachedResource):
     94        (WebCore::CachedResource::finish):
     95        (WebCore::CachedResource::setExpireDate):
     96        (WebCore::CachedResource::isExpired):
     97        (WebCore::CachedResource::setRequest):
     98        (WebCore::CachedResource::ref):
     99        (WebCore::CachedResource::deref):
     100        (WebCore::CachedResource::setSize):
     101        * loader/CachedResource.h:
     102        (WebCore::CachedResource::):
     103        (WebCore::CachedResource::setCharset):
     104        (WebCore::CachedResource::url):
     105        (WebCore::CachedResource::type):
     106        (WebCore::CachedResource::referenced):
     107        (WebCore::CachedResource::count):
     108        (WebCore::CachedResource::status):
     109        (WebCore::CachedResource::size):
     110        (WebCore::CachedResource::isLoaded):
     111        (WebCore::CachedResource::setLoading):
     112        (WebCore::CachedResource::isImage):
     113        (WebCore::CachedResource::accessCount):
     114        (WebCore::CachedResource::increaseAccessCount):
     115        (WebCore::CachedResource::setInCache):
     116        (WebCore::CachedResource::inCache):
     117        (WebCore::CachedResource::cachePolicy):
     118        (WebCore::CachedResource::response):
     119        (WebCore::CachedResource::allData):
     120        (WebCore::CachedResource::canDelete):
     121        (WebCore::CachedResource::schedule):
     122        (WebCore::CachedResource::accept):
     123        (WebCore::CachedResource::setAccept):
     124        * loader/CachedScript.cpp:
     125        (WebCore::CachedScript::CachedScript):
     126        * loader/CachedScript.h:
     127        * loader/CachedXBLDocument.cpp:
     128        * loader/CachedXBLDocument.h:
     129        * loader/CachedXSLStyleSheet.cpp:
     130        (WebCore::CachedXSLStyleSheet::CachedXSLStyleSheet):
     131        * loader/CachedXSLStyleSheet.h:
     132        * loader/DocLoader.cpp:
     133        (WebCore::DocLoader::DocLoader):
     134        (WebCore::DocLoader::~DocLoader):
     135        (WebCore::DocLoader::checkForReload):
     136        (WebCore::DocLoader::requestImage):
     137        (WebCore::DocLoader::requestCSSStyleSheet):
     138        (WebCore::DocLoader::requestScript):
     139        (WebCore::DocLoader::requestXSLStyleSheet):
     140        (WebCore::DocLoader::requestXBLDocument):
     141        (WebCore::DocLoader::requestResource):
     142        (WebCore::DocLoader::setAutoLoadImages):
     143        (WebCore::DocLoader::removeCachedResource):
     144        * loader/DocLoader.h:
     145        (WebCore::DocLoader::cachedResource):
     146        (WebCore::DocLoader::allCachedResources):
     147        (WebCore::DocLoader::autoLoadImages):
     148        (WebCore::DocLoader::cachePolicy):
     149        (WebCore::DocLoader::expireDate):
     150        (WebCore::DocLoader::frame):
     151        (WebCore::DocLoader::doc):
     152        (WebCore::DocLoader::loadInProgress):
     153        * loader/ImageDocument.cpp:
     154        (WebCore::ImageTokenizer::finish):
     155        * loader/loader.cpp:
     156        (WebCore::Loader::receivedAllData):
     157        (WebCore::Loader::cancelRequests):
     158        * loader/mac/LoaderFunctionsMac.mm:
     159        (WebCore::NumberOfPendingOrLoadingRequests):
     160        (WebCore::CheckCacheObjectStatus):
     161        * page/Frame.cpp:
     162        (WebCore::UserStyleSheetLoader::UserStyleSheetLoader):
     163        (WebCore::Frame::Frame):
     164        (WebCore::Frame::stopLoading):
     165        (WebCore::Frame::setAutoLoadImages):
     166        (WebCore::Frame::autoLoadImages):
     167        (WebCore::Frame::begin):
     168        (WebCore::Frame::checkCompleted):
     169        (WebCore::Frame::reparseConfiguration):
     170        * page/Frame.h:
     171        * xml/XSLTProcessor.cpp:
     172        (WebCore::docLoaderFunc):
     173        * xml/xmlhttprequest.cpp:
     174        (WebCore::XMLHttpRequest::send):
     175
    11762006-10-18  Maciej Stachowiak  <mjs@apple.com>
    2177
  • trunk/WebCore/bridge/mac/WebCoreCache.mm

    r15034 r17131  
    3333+ (NSArray *)statistics
    3434{
    35     WebCore::Cache::Statistics s = WebCore::Cache::getStatistics();
     35    WebCore::Cache::Statistics s = WebCore::cache()->getStatistics();
    3636
    3737    return [NSArray arrayWithObjects:
    3838        [NSDictionary dictionaryWithObjectsAndKeys:
    3939            [NSNumber numberWithInt:s.images.count], @"images",
    40             [NSNumber numberWithInt:s.movies.count], @"movies",
    41             [NSNumber numberWithInt:s.styleSheets.count], @"style sheets",
     40            [NSNumber numberWithInt:s.cssStyleSheets.count], @"style sheets",
    4241            [NSNumber numberWithInt:s.scripts.count], @"scripts",
    43             [NSNumber numberWithInt:s.other.count], @"other",
    4442            nil],
    4543        [NSDictionary dictionaryWithObjectsAndKeys:
    4644            [NSNumber numberWithInt:s.images.size], @"images",
    47             [NSNumber numberWithInt:s.movies.size], @"movies",
    48             [NSNumber numberWithInt:s.styleSheets.size] ,@"style sheets",
     45            [NSNumber numberWithInt:s.cssStyleSheets.size] ,@"style sheets",
    4946            [NSNumber numberWithInt:s.scripts.size], @"scripts",
    50             [NSNumber numberWithInt:s.other.size], @"other",
    5147            nil],
    5248        nil];
     
    5551+ (void)empty
    5652{
    57     WebCore::Cache::flushAll();
     53    if (WebCore::cache()->disabled())
     54        return;
     55    WebCore::cache()->setDisabled(YES);
     56    WebCore::cache()->setDisabled(NO);
    5857}
    5958
    6059+ (void)setDisabled:(BOOL)disabled
    6160{
    62     WebCore::Cache::setCacheDisabled(disabled);
     61    WebCore::cache()->setDisabled(disabled);
    6362}
    6463
  • trunk/WebCore/bridge/mac/WebCoreFrameBridge.mm

    r17121 r17131  
    490490    // current WebView. That's a mismatch and not good!
    491491    if (!initializedObjectCacheSize) {
    492         WebCore::Cache::setSize([self getObjectCacheSize]);
     492        WebCore::cache()->setMaximumSize([self getObjectCacheSize]);
    493493        initializedObjectCacheSize = true;
    494494    }
     
    25432543        return NO;
    25442544
    2545     CachedResource* o = doc->docLoader()->cachedObject([URL absoluteString]);
    2546     if (!o)
     2545    CachedResource* resource = doc->docLoader()->cachedResource([URL absoluteString]);
     2546    if (!resource)
    25472547        return NO;
    25482548
    2549     *data = o->allData();
    2550     *response = o->response();
     2549    *data = resource->allData();
     2550    *response = resource->response();
    25512551    return YES;
    25522552}
     
    25622562    }
    25632563
    2564     const HashMap<String, CachedResource*>& allResources = doc->docLoader()->allCachedObjects();
     2564    const HashMap<String, CachedResource*>& allResources = doc->docLoader()->allCachedResources();
    25652565
    25662566    NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
  • trunk/WebCore/css/CSSImageValue.cpp

    r14407 r17131  
    5858            m_image = loader->requestImage(getStringValue());
    5959        else
    60             m_image = Cache::requestImage(0, getStringValue());
    61        
     60            // FIXME: Should find a way to make these images sit in their own memory partition, since they are user agent images.
     61            m_image = static_cast<CachedImage*>(cache()->requestResource(0, CachedResource::ImageResource, KURL(getStringValue().deprecatedString()), 0, 0));
     62
    6263        if (m_image)
    6364            m_image->ref(this);
  • trunk/WebCore/dom/XMLTokenizer.cpp

    r16803 r17131  
    461461    RefPtr<ResourceLoader> loader = ResourceLoader::create(0, "GET", uri);
    462462    DeprecatedString headers;
    463     Vector<char> data = ServeSynchronousRequest(Cache::loader(), globalDocLoader, loader.get(), finalURL, headers);
     463    Vector<char> data = ServeSynchronousRequest(cache()->loader(), globalDocLoader, loader.get(), finalURL, headers);
    464464   
    465465    return new OffsetBuffer(data);
  • trunk/WebCore/html/HTMLImageLoader.cpp

    r15870 r17131  
    7878    if (!attr.isEmpty()) {
    7979        if (m_loadManually) {
     80            doc->docLoader()->setAutoLoadImages(false);
    8081            newImage = new CachedImage(doc->docLoader(), parseURL(attr), CachePolicyVerify, 0);
    81             doc->docLoader()->m_docObjects.set(newImage->url(), newImage);
     82            newImage->setLoading(true);
     83            doc->docLoader()->m_docResources.set(newImage->url(), newImage);
    8284        } else
    8385            newImage = doc->docLoader()->requestImage(parseURL(attr));
  • trunk/WebCore/loader/Cache.cpp

    r17097 r17131  
    4343namespace WebCore {
    4444
    45 const int defaultCacheSize = 8192 * 1024;
    46 
    47 // maxCacheableObjectSize is cache size divided by 128, but with this as a minimum
    48 const int minMaxCacheableObjectSize = 80 * 1024;
    49 
    50 const int maxLRULists = 20;
    51    
    52 struct LRUList {
    53     CachedResource* m_head;
    54     CachedResource* m_tail;
    55     LRUList() : m_head(0), m_tail(0) { }
    56 };
    57 
    58 static bool cacheDisabled;
    59 
    60 typedef HashMap<String, CachedResource*> CacheMap;
    61 
    62 static CacheMap* cache = 0;
    63 
    64 HashSet<DocLoader*>* Cache::docloaders = 0;
    65 Loader *Cache::m_loader = 0;
    66 
    67 int Cache::maxSize = defaultCacheSize;
    68 int Cache::maxCacheable = minMaxCacheableObjectSize;
    69 int Cache::flushCount = 0;
    70 
    71 Image *Cache::nullImage = 0;
    72 Image *Cache::brokenImage = 0;
    73 
    74 CachedResource *Cache::m_headOfUncacheableList = 0;
    75 int Cache::m_totalSizeOfLRULists = 0;
    76 int Cache::m_countOfLRUAndUncacheableLists;
    77 LRUList *Cache::m_LRULists = 0;
    78 
    79 void Cache::init()
    80 {
    81     if (!cache)
    82         cache = new CacheMap;
    83 
    84     if (!docloaders)
    85         docloaders = new HashSet<DocLoader*>;
    86 
    87     if (!nullImage)
    88         nullImage = new Image;
    89 
    90     if (!brokenImage)
    91         brokenImage = Image::loadPlatformResource("missingImage");
    92 
    93     if (!m_loader)
    94         m_loader = new Loader();
    95 }
    96 
    97 void Cache::clear()
    98 {
    99     if (!cache)
    100         return;
    101 
    102     deleteAllValues(*cache);
    103 
    104     delete cache; cache = 0;
    105     delete nullImage; nullImage = 0;
    106     delete brokenImage; brokenImage = 0;
    107     delete m_loader; m_loader = 0;
    108     ASSERT(docloaders->isEmpty());
    109     delete docloaders; docloaders = 0;
    110 }
    111 
    112 void Cache::updateCacheStatus(DocLoader* dl, CachedResource* o)
    113 {
    114     moveToHeadOfLRUList(o);
    115     if (dl) {
    116         ASSERT(!o->url().isNull());
    117         if (cacheDisabled)
    118             dl->m_docObjects.remove(o->url());
    119         else
    120             dl->m_docObjects.set(o->url(), o);
    121     }
    122 }
    123 
    124 CachedImage* Cache::requestImage(DocLoader* dl, const String& url, bool reload, time_t expireDate)
    125 {
    126     // this brings the _url to a standard form...
    127     KURL kurl;
    128     if (dl)
    129         kurl = dl->m_doc->completeURL(url.deprecatedString());
    130     else
    131         kurl = url.deprecatedString();
    132     return requestImage(dl, kurl, reload, expireDate);
    133 }
    134 
    135 CachedImage* Cache::requestImage(DocLoader* dl, const KURL& url, bool reload, time_t expireDate)
    136 {
    137     CachePolicy cachePolicy;
    138     if (dl)
    139         cachePolicy = dl->cachePolicy();
    140     else
    141         cachePolicy = CachePolicyVerify;
    142 
    143     // Checking if the URL is malformed is lots of extra work for little benefit.
    144 
    145     if (!dl->doc()->shouldCreateRenderers())
     45const int cDefaultCacheSize = 8192 * 1024;
     46const int cDefaultLargeResourceSize = 80 * 1024;
     47
     48Cache* cache()
     49{
     50    static Cache cache;
     51    return &cache;
     52}
     53
     54Cache::Cache()
     55: m_disabled(false)
     56, m_maximumSize(cDefaultCacheSize)
     57, m_currentSize(0)
     58, m_liveResourcesSize(0)
     59{
     60}
     61
     62static CachedResource* createResource(CachedResource::Type type, DocLoader* docLoader, const KURL& url, time_t expireDate, const String* charset)
     63{
     64    switch (type) {
     65    case CachedResource::ImageResource:
     66        // User agent images need to null check the docloader.  No other resources need to.
     67        return new CachedImage(docLoader, url.url(), docLoader ? docLoader->cachePolicy() : CachePolicyCache, expireDate);
     68    case CachedResource::CSSStyleSheet:
     69        return new CachedCSSStyleSheet(docLoader, url.url(), docLoader->cachePolicy(), expireDate, *charset);
     70    case CachedResource::Script:
     71        return new CachedScript(docLoader, url.url(), docLoader->cachePolicy(), expireDate, *charset);
     72#ifdef XSLT_SUPPORT
     73    case CachedResource::XSLStyleSheet:
     74        return new CachedXSLStyleSheet(docLoader, url.url(), docLoader->cachePolicy(), expireDate);
     75#endif
     76#ifdef XBL_SUPPORT
     77    case CachedResource::XBLStyleSheet:
     78        return new CachedXBLDocument(docLoader, url.url(), docLoader->cachePolicy(), expireDate);
     79#endif
     80    default:
     81        break;
     82    }
     83
     84    return 0;
     85}
     86
     87CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Type type, const KURL& url, time_t expireDate, const String* charset)
     88{
     89    // Look up the resource in our map.
     90    CachedResource* resource = m_resources.get(url.url());
     91
     92    if (!resource) {
     93        // The resource does not exist.  Create it.
     94        resource = createResource(type, docLoader, url.url(), expireDate, charset);
     95        ASSERT(resource);
     96        resource->setInCache(!disabled());
     97        if (!disabled())
     98            m_resources.set(url.url(), resource);  // The size will be added in later once the resource is loaded and calls back to us with the new size.
     99    }
     100
     101    // This will move the resource to the front of its LRU list and increase its access count.
     102    resourceAccessed(resource);
     103
     104    if (resource->type() != type)
    146105        return 0;
    147106
    148     CachedResource *o = 0;
    149     if (!reload)
    150         o = cache->get(url.url());
    151     if (!o) {
    152 #ifdef CACHE_DEBUG
    153         kdDebug(6060) << "Cache: new: " << url.url() << endl;
    154 #endif
    155         CachedImage *im = new CachedImage(dl, url.url(), cachePolicy, expireDate);
    156         if (dl && dl->autoloadImages()) Cache::loader()->load(dl, im, true);
    157         if (cacheDisabled)
    158             im->setFree(true);
    159         else {
    160             cache->set(url.url(), im);
    161             moveToHeadOfLRUList(im);
     107    return resource;
     108}
     109
     110CachedResource* Cache::resourceForURL(const String& url)
     111{
     112    return m_resources.get(url);
     113}
     114
     115void Cache::prune()
     116{
     117    // No need to prune if all of our objects fit.
     118    if (m_currentSize <= m_maximumSize)
     119        return;
     120
     121    // We allow the cache to get as big as the # of live objects + half the maximum cache size
     122    // before we do a prune.  Once we do decide to prune though, we are aggressive about it.
     123    // We will include the live objects as part of the overall cache size when pruneing, so will often
     124    // kill every last object that isn't referenced by a Web page.
     125    unsigned unreferencedResourcesSize = m_currentSize - m_liveResourcesSize;
     126    if (unreferencedResourcesSize < m_maximumSize / 2U)
     127        return;
     128
     129    bool canShrinkLRULists = true;
     130    unsigned size = m_lruLists.size();
     131    for (int i = size - 1; i >= 0; i--) {
     132        // Remove from the tail, since this is the least frequently accessed of the objects.
     133        CachedResource* current = m_lruLists[i].m_tail;
     134        while (current) {
     135            CachedResource* prev = current->m_prevInLRUList;
     136            if (!current->referenced()) {
     137                remove(current);
     138               
     139                // Stop pruneing if our total cache size is back under the maximum or if every
     140                // remaining object in the cache is live (meaning there is nothing left we are able
     141                // to prune).
     142                if (m_currentSize <= m_maximumSize || m_currentSize == m_liveResourcesSize)
     143                    return;
     144            }
     145            current = prev;
    162146        }
    163         o = im;
    164     }
    165 
    166    
    167     if (o->type() != CachedResource::ImageResource)
    168         return 0;
    169 
    170 #ifdef CACHE_DEBUG
    171     if (o->status() == CachedResource::Pending)
    172         kdDebug(6060) << "Cache: loading in progress: " << kurl.url() << endl;
    173     else
    174         kdDebug(6060) << "Cache: using cached: " << kurl.url() << ", status " << o->status() << endl;
    175 #endif
    176 
    177     updateCacheStatus(dl, o);
    178     return static_cast<CachedImage *>(o);
    179 }
    180 
    181 CachedCSSStyleSheet* Cache::requestCSSStyleSheet(DocLoader* dl, const String& url, bool reload, time_t expireDate, const String& charset)
    182 {
    183     // this brings the _url to a standard form...
    184     KURL kurl;
    185     CachePolicy cachePolicy;
    186     if (dl) {
    187         kurl = dl->m_doc->completeURL(url.deprecatedString());
    188         cachePolicy = dl->cachePolicy();
    189     } else {
    190         kurl = url.deprecatedString();
    191         cachePolicy = CachePolicyVerify;
    192     }
    193 
    194     // Checking if the URL is malformed is lots of extra work for little benefit.
    195 
    196     CachedResource *o = cache->get(kurl.url());
    197     if (!o) {
    198 #ifdef CACHE_DEBUG
    199         kdDebug(6060) << "Cache: new: " << kurl.url() << endl;
    200 #endif
    201         CachedCSSStyleSheet *sheet = new CachedCSSStyleSheet(dl, kurl.url(), cachePolicy, expireDate, charset);
    202         if (cacheDisabled)
    203             sheet->setFree(true);
    204         else {
    205             cache->set(kurl.url(), sheet);
    206             moveToHeadOfLRUList(sheet);
    207         }
    208         o = sheet;
    209     }
    210 
    211    
    212     if (o->type() != CachedResource::CSSStyleSheet)
    213     {
    214 #ifdef CACHE_DEBUG
    215         kdDebug(6060) << "Cache::Internal Error in requestCSSStyleSheet url=" << kurl.url() << "!" << endl;
    216 #endif
    217         return 0;
    218     }
    219 
    220 #ifdef CACHE_DEBUG
    221     if (o->status() == CachedResource::Pending)
    222         kdDebug(6060) << "Cache: loading in progress: " << kurl.url() << endl;
    223     else
    224         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
    225 #endif
    226 
    227     updateCacheStatus(dl, o);
    228     return static_cast<CachedCSSStyleSheet *>(o);
    229 }
    230 
    231 CachedScript* Cache::requestScript(DocLoader* dl, const String& url, bool reload, time_t expireDate, const String& charset)
    232 {
    233     // this brings the _url to a standard form...
    234     KURL kurl;
    235     CachePolicy cachePolicy;
    236     if (dl) {
    237         kurl = dl->m_doc->completeURL(url.deprecatedString());
    238         cachePolicy = dl->cachePolicy();
    239     } else {
    240         kurl = url.deprecatedString();
    241         cachePolicy = CachePolicyVerify;
    242     }
    243 
    244     // Checking if the URL is malformed is lots of extra work for little benefit.
    245 
    246     CachedResource *o = cache->get(kurl.url());
    247     if (!o)
    248     {
    249 #ifdef CACHE_DEBUG
    250         kdDebug(6060) << "Cache: new: " << kurl.url() << endl;
    251 #endif
    252         CachedScript *script = new CachedScript(dl, kurl.url(), cachePolicy, expireDate, charset);
    253         if (cacheDisabled)
    254             script->setFree(true);
    255         else {
    256             cache->set(kurl.url(), script);
    257             moveToHeadOfLRUList(script);
    258         }
    259         o = script;
    260     }
    261 
    262    
    263     if (!(o->type() == CachedResource::Script)) {
    264 #ifdef CACHE_DEBUG
    265         kdDebug(6060) << "Cache::Internal Error in requestScript url=" << kurl.url() << "!" << endl;
    266 #endif
    267         return 0;
    268     }
    269    
    270    
    271 #ifdef CACHE_DEBUG
    272     if (o->status() == CachedResource::Pending)
    273         kdDebug(6060) << "Cache: loading in progress: " << kurl.url() << endl;
    274     else
    275         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
    276 #endif
    277 
    278     updateCacheStatus(dl, o);
    279     return static_cast<CachedScript *>(o);
    280 }
    281 
    282 #ifdef XSLT_SUPPORT
    283 CachedXSLStyleSheet* Cache::requestXSLStyleSheet(DocLoader* dl, const String& url, bool reload, time_t expireDate)
    284 {
    285     // this brings the _url to a standard form...
    286     KURL kurl;
    287     CachePolicy cachePolicy;
    288     if (dl) {
    289         kurl = dl->m_doc->completeURL(url.deprecatedString());
    290         cachePolicy = dl->cachePolicy();
    291     }
    292     else {
    293         kurl = url.deprecatedString();
    294         cachePolicy = CachePolicyVerify;
    295     }
    296    
    297     // Checking if the URL is malformed is lots of extra work for little benefit.
    298    
    299     CachedResource *o = cache->get(kurl.url());
    300     if (!o) {
    301 #ifdef CACHE_DEBUG
    302         kdDebug(6060) << "Cache: new: " << kurl.url() << endl;
    303 #endif
    304         CachedXSLStyleSheet* doc = new CachedXSLStyleSheet(dl, kurl.url(), cachePolicy, expireDate);
    305         if (cacheDisabled)
    306             doc->setFree(true);
    307         else {
    308             cache->set(kurl.url(), doc);
    309             moveToHeadOfLRUList(doc);
    310         }
    311         o = doc;
    312     }
    313    
    314    
    315     if (o->type() != CachedResource::XSLStyleSheet) {
    316 #ifdef CACHE_DEBUG
    317         kdDebug(6060) << "Cache::Internal Error in requestXSLStyleSheet url=" << kurl.url() << "!" << endl;
    318 #endif
    319         return 0;
    320     }
    321    
    322 #ifdef CACHE_DEBUG
    323     if (o->status() == CachedResource::Pending)
    324         kdDebug(6060) << "Cache: loading in progress: " << kurl.url() << endl;
    325     else
    326         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
    327 #endif
    328    
    329     updateCacheStatus(dl, o);
    330     return static_cast<CachedXSLStyleSheet*>(o);
    331 }
    332 #endif
    333 
    334 #ifdef XBL_SUPPORT
    335 CachedXBLDocument* Cache::requestXBLDocument(DocLoader* dl, const String& url, bool reload,
    336                                              time_t expireDate)
    337 {
    338     // this brings the _url to a standard form...
    339     KURL kurl;
    340     CachePolicy cachePolicy;
    341     if (dl) {
    342         kurl = dl->m_doc->completeURL(url.deprecatedString());
    343         cachePolicy = dl->cachePolicy();
    344     } else {
    345         kurl = url.deprecatedString();
    346         cachePolicy = CachePolicyVerify;
    347     }
    348    
    349     // Checking if the URL is malformed is lots of extra work for little benefit.
    350    
    351     CachedResource *o = cache->get(kurl.url());
    352     if (!o) {
    353 #ifdef CACHE_DEBUG
    354         kdDebug(6060) << "Cache: new: " << kurl.url() << endl;
    355 #endif
    356         CachedXBLDocument* doc = new CachedXBLDocument(dl, kurl.url(), cachePolicy, expireDate);
    357         if (cacheDisabled)
    358             doc->setFree(true);
    359         else {
    360             cache->set(kurl.url(), doc);
    361             moveToHeadOfLRUList(doc);
    362         }
    363         o = doc;
    364     }
    365    
    366    
    367     if (o->type() != CachedResource::XBL) {
    368 #ifdef CACHE_DEBUG
    369         kdDebug(6060) << "Cache::Internal Error in requestXBLDocument url=" << kurl.url() << "!" << endl;
    370 #endif
    371         return 0;
    372     }
    373    
    374 #ifdef CACHE_DEBUG
    375     if (o->status() == CachedResource::Pending)
    376         kdDebug(6060) << "Cache: loading in progress: " << kurl.url() << endl;
    377     else
    378         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
    379 #endif
    380    
    381     updateCacheStatus(dl, o);
    382     return static_cast<CachedXBLDocument*>(o);
    383 }
    384 #endif
    385 
    386 void Cache::flush(bool force)
    387 {
    388     if (force)
    389        flushCount = 0;
    390     // Don't flush for every image.
    391     if (m_countOfLRUAndUncacheableLists < flushCount)
    392        return;
    393 
    394     init();
    395 
    396     while (m_headOfUncacheableList)
    397         remove(m_headOfUncacheableList);
    398 
    399     for (int i = maxLRULists-1; i>=0; i--) {
    400         if (m_totalSizeOfLRULists <= maxSize)
    401             break;
    402147           
    403         while (m_totalSizeOfLRULists > maxSize && m_LRULists[i].m_tail)
    404             remove(m_LRULists[i].m_tail);
    405     }
    406 
    407     flushCount = m_countOfLRUAndUncacheableLists+10; // Flush again when the cache has grown.
    408 }
    409 
    410 
    411 void Cache::setSize(int bytes)
    412 {
    413     maxSize = bytes;
    414     maxCacheable = max(maxSize / 128, minMaxCacheableObjectSize);
    415 
    416     // may be we need to clear parts of the cache
    417     flushCount = 0;
    418     flush(true);
    419 }
    420 
    421 void Cache::remove(CachedResource *object)
    422 {
    423   // this indicates the deref() method of CachedResource to delete itself when the reference counter
    424   // drops down to zero
    425   object->setFree(true);
    426 
    427   cache->remove(object->url());
    428   removeFromLRUList(object);
    429 
    430   HashSet<DocLoader*>::iterator end = docloaders->end();
    431   for (HashSet<DocLoader*>::iterator itr = docloaders->begin(); itr != end; ++itr)
    432       (*itr)->removeCachedObject(object);
    433 
    434   if (object->canDelete())
    435      delete object;
    436 }
    437 
    438 static inline int FastLog2(uint32_t i)
    439 {
    440     int log2 = 0;
     148        // Shrink the vector back down so we don't waste time inspecting
     149        // empty LRU lists on future prunees.
     150        if (m_lruLists[i].m_head)
     151            canShrinkLRULists = false;
     152        else if (canShrinkLRULists)
     153            m_lruLists.resize(i);
     154    }
     155}
     156
     157void Cache::setMaximumSize(int bytes)
     158{
     159    m_maximumSize = bytes;
     160    prune();
     161}
     162
     163void Cache::remove(CachedResource* resource)
     164{
     165    ASSERT(resource->inCache());
     166
     167    // Remove from the resource map.
     168    m_resources.remove(resource->url());
     169    resource->setInCache(false);
     170
     171    // Remove from the appropriate LRU list.
     172    removeFromLRUList(resource);
     173
     174    // Notify all doc loaders that might be observing this object still that it has been
     175    // extracted from the set of resources.
     176    HashSet<DocLoader*>::iterator end = m_docLoaders.end();
     177    for (HashSet<DocLoader*>::iterator itr = m_docLoaders.begin(); itr != end; ++itr)
     178        (*itr)->removeCachedResource(resource);
     179
     180    // Subtract from our size totals.
     181    m_currentSize -= resource->size();
     182    if (resource->referenced())
     183        m_liveResourcesSize -= resource->size();
     184
     185    if (resource->canDelete())
     186        delete resource;
     187}
     188
     189void Cache::addDocLoader(DocLoader* docLoader)
     190{
     191    m_docLoaders.add(docLoader);
     192}
     193
     194void Cache::removeDocLoader(DocLoader* docLoader)
     195{
     196    m_docLoaders.remove(docLoader);
     197}
     198
     199static inline unsigned fastLog2(unsigned i)
     200{
     201    unsigned log2 = 0;
    441202    if (i & (i - 1))
    442203        log2 += 1;
     
    454215}
    455216
    456 LRUList* Cache::getLRUListFor(CachedResource* o)
    457 {
    458     int accessCount = o->accessCount();
    459     int queueIndex;
    460     if (accessCount == 0) {
    461         queueIndex = 0;
    462     } else {
    463         int sizeLog = FastLog2(o->size());
    464         queueIndex = sizeLog / o->accessCount() - 1;
    465         if (queueIndex < 0)
    466             queueIndex = 0;
    467         if (queueIndex >= maxLRULists)
    468             queueIndex = maxLRULists-1;
    469     }
    470     if (!m_LRULists)
    471         m_LRULists = new LRUList [maxLRULists];
    472     return &m_LRULists[queueIndex];
    473 }
    474 
    475 void Cache::removeFromLRUList(CachedResource *object)
    476 {
    477     CachedResource *next = object->m_nextInLRUList;
    478     CachedResource *prev = object->m_prevInLRUList;
    479     bool uncacheable = object->status() == CachedResource::Uncacheable;
    480    
    481     LRUList* list = uncacheable ? 0 : getLRUListFor(object);
    482     CachedResource *&head = uncacheable ? m_headOfUncacheableList : list->m_head;
    483    
    484     if (next == 0 && prev == 0 && head != object) {
    485         return;
    486     }
    487    
    488     object->m_nextInLRUList = 0;
    489     object->m_prevInLRUList = 0;
     217LRUList* Cache::lruListFor(CachedResource* resource)
     218{
     219    unsigned accessCount = max(resource->accessCount(), 1U);
     220    unsigned queueIndex = fastLog2(resource->size() / accessCount);
     221#ifndef NDEBUG
     222    resource->m_lruIndex = queueIndex;
     223#endif
     224    if (m_lruLists.size() <= queueIndex)
     225        m_lruLists.resize(queueIndex + 1);
     226    return &m_lruLists[queueIndex];
     227}
     228
     229void Cache::removeFromLRUList(CachedResource* resource)
     230{
     231    // If we've never been accessed, then we're brand new and not in any list.
     232    if (resource->accessCount() == 0)
     233        return;
     234
     235#ifndef NDEBUG
     236    unsigned oldListIndex = resource->m_lruIndex;
     237#endif
     238
     239    LRUList* list = lruListFor(resource);
     240
     241#ifndef NDEBUG
     242    // Verify that the list we got is the list we want.
     243    ASSERT(resource->m_lruIndex == oldListIndex);
     244
     245    // Verify that we are in fact in this list.
     246    bool found = false;
     247    for (CachedResource* current = list->m_head; current; current = current->m_nextInLRUList) {
     248        if (current == resource) {
     249            found = true;
     250            break;
     251        }
     252    }
     253    ASSERT(found);
     254#endif
     255
     256    CachedResource* next = resource->m_nextInLRUList;
     257    CachedResource* prev = resource->m_prevInLRUList;
     258   
     259    if (next == 0 && prev == 0 && list->m_head != resource)
     260        return;
     261   
     262    resource->m_nextInLRUList = 0;
     263    resource->m_prevInLRUList = 0;
    490264   
    491265    if (next)
    492266        next->m_prevInLRUList = prev;
    493     else if (!uncacheable && list->m_tail == object)
     267    else if (list->m_tail == resource)
    494268        list->m_tail = prev;
    495269
    496270    if (prev)
    497271        prev->m_nextInLRUList = next;
    498     else if (head == object)
    499         head = next;
    500    
    501     --m_countOfLRUAndUncacheableLists;
    502    
    503     if (!uncacheable)
    504         m_totalSizeOfLRULists -= object->size();
    505 }
    506 
    507 void Cache::moveToHeadOfLRUList(CachedResource *object)
    508 {
    509     insertInLRUList(object);
    510 }
    511 
    512 void Cache::insertInLRUList(CachedResource *object)
    513 {
    514     removeFromLRUList(object);
    515    
    516     if (!object->allowInLRUList())
    517         return;
    518    
    519     LRUList* list = getLRUListFor(object);
    520    
    521     bool uncacheable = object->status() == CachedResource::Uncacheable;
    522     CachedResource *&head = uncacheable ? m_headOfUncacheableList : list->m_head;
    523 
    524     object->m_nextInLRUList = head;
    525     if (head)
    526         head->m_prevInLRUList = object;
    527     head = object;
    528    
    529     if (object->m_nextInLRUList == 0 && !uncacheable)
    530         list->m_tail = object;
    531    
    532     ++m_countOfLRUAndUncacheableLists;
    533    
    534     if (!uncacheable)
    535         m_totalSizeOfLRULists += object->size();
    536 }
    537 
    538 bool Cache::adjustSize(CachedResource *object, int delta)
    539 {
    540     if (object->status() == CachedResource::Uncacheable)
    541         return false;
    542 
    543     if (object->m_nextInLRUList == 0 && object->m_prevInLRUList == 0 &&
    544         getLRUListFor(object)->m_head != object)
    545         return false;
    546    
    547     m_totalSizeOfLRULists += delta;
    548     return delta != 0;
     272    else if (list->m_head == resource)
     273        list->m_head = next;
     274}
     275
     276void Cache::insertInLRUList(CachedResource* resource)
     277{
     278    // Make sure we aren't in some list already.
     279    ASSERT(!resource->m_nextInLRUList && !resource->m_prevInLRUList);
     280
     281    LRUList* list = lruListFor(resource);
     282
     283    resource->m_nextInLRUList = list->m_head;
     284    if (list->m_head)
     285        list->m_head->m_prevInLRUList = resource;
     286    list->m_head = resource;
     287   
     288    if (!resource->m_nextInLRUList)
     289        list->m_tail = resource;
     290       
     291#ifndef NDEBUG
     292    // Verify that we are in now in the list like we should be.
     293    list = lruListFor(resource);
     294    bool found = false;
     295    for (CachedResource* current = list->m_head; current; current = current->m_nextInLRUList) {
     296        if (current == resource) {
     297            found = true;
     298            break;
     299        }
     300    }
     301    ASSERT(found);
     302#endif
     303
     304}
     305
     306void Cache::resourceAccessed(CachedResource* resource)
     307{
     308    // Need to make sure to remove before we increase the access count, since
     309    // the queue will possibly change.
     310    removeFromLRUList(resource);
     311   
     312    // Add to our access count.
     313    resource->increaseAccessCount();
     314   
     315    // Now insert into the new queue.
     316    insertInLRUList(resource);
     317}
     318
     319void Cache::adjustSize(bool live, unsigned oldResourceSize, unsigned newResourceSize)
     320{
     321    m_currentSize -= oldResourceSize;
     322    if (live)
     323        m_liveResourcesSize -= oldResourceSize;
     324       
     325    m_currentSize += newResourceSize;
     326    if (live)
     327        m_liveResourcesSize += newResourceSize;
    549328}
    550329
     
    552331{
    553332    Statistics stats;
    554 
    555     if (!cache)
    556         return stats;
    557 
    558     CacheMap::iterator e = cache->end();
    559     for (CacheMap::iterator i = cache->begin(); i != e; ++i) {
     333    CachedResourceMap::iterator e = m_resources.end();
     334    for (CachedResourceMap::iterator i = m_resources.begin(); i != e; ++i) {
    560335        CachedResource *o = i->second;
    561336        switch (o->type()) {
     
    566341
    567342            case CachedResource::CSSStyleSheet:
    568                 stats.styleSheets.count++;
    569                 stats.styleSheets.size += o->size();
     343                stats.cssStyleSheets.count++;
     344                stats.cssStyleSheets.size += o->size();
    570345                break;
    571346
     
    587362#endif
    588363            default:
    589                 stats.other.count++;
    590                 stats.other.size += o->size();
     364                break;
    591365        }
    592366    }
     
    595369}
    596370
    597 void Cache::flushAll()
    598 {
    599     if (!cache)
     371void Cache::setDisabled(bool disabled)
     372{
     373    m_disabled = disabled;
     374    if (!m_disabled)
    600375        return;
    601376
    602377    for (;;) {
    603         CacheMap::iterator i = cache->begin();
    604         if (i == cache->end())
     378        CachedResourceMap::iterator i = m_resources.begin();
     379        if (i == m_resources.end())
    605380            break;
    606381        remove(i->second);
     
    608383}
    609384
    610 void Cache::setCacheDisabled(bool disabled)
    611 {
    612     cacheDisabled = disabled;
    613     if (disabled)
    614         flushAll();
    615 }
    616 
    617 CachedResource* Cache::get(const String& s)
    618 {
    619     return (cache && s.impl()) ? cache->get(s) : 0;
    620 }
    621 
    622 }
     385}
  • trunk/WebCore/loader/Cache.h

    r17097 r17131  
    2929
    3030#include "CachePolicy.h"
     31#include "CachedResource.h"
     32#include "Loader.h"
    3133#include "PlatformString.h"
     34#include "StringHash.h"
     35#include <wtf/Vector.h>
    3236#include <wtf/HashSet.h>
     37#include <wtf/HashMap.h>
    3338
    3439namespace WebCore  {
    3540
    36     class CachedCSSStyleSheet;
    37     class CachedImage;
    38     class CachedResource;
    39     class CachedScript;
    40     class CachedXSLStyleSheet;
    41     class DocLoader;
    42     class Image;
    43     class KURL;
    44     class Loader;
    45     struct LRUList;
     41class CachedCSSStyleSheet;
     42class CachedImage;
     43class CachedResource;
     44class CachedScript;
     45class CachedXSLStyleSheet;
     46class DocLoader;
     47class Image;
     48class KURL;
     49
     50struct LRUList {
     51    CachedResource* m_head;
     52    CachedResource* m_tail;
     53    LRUList() : m_head(0), m_tail(0) { }
     54};
     55
     56typedef HashMap<String, CachedResource*> CachedResourceMap;
     57
     58// This cache hold subresources used by Web pages.  These resources consist of images, scripts and stylesheets.
     59class Cache {
     60public:
     61    Cache();
     62       
     63    // The loader that fetches resources.
     64    Loader* loader() { return &m_loader; }
     65
     66    // Request resources from the cache.  A load will be initiated and a cache object created if the object is not
     67    // found in the cache.
     68    CachedResource* requestResource(DocLoader*, CachedResource::Type, const KURL& url, time_t expireDate = 0, const String* charset = 0);
     69
     70    // Set/retreive the size of the cache. This will only hold approximately, since the size some
     71    // cached objects (like stylesheets) take up in memory is not exactly known.
     72    void setMaximumSize(int bytes);
     73    int maximumSize() const { return m_maximumSize; };
     74
     75    // Turn the cache on and off.  Disabling the cache will remove all resources from the cache.  They may
     76    // still live on if they are referenced by some Web page though.
     77    void setDisabled(bool);
     78    bool disabled() const { return m_disabled; }
    4679   
    47     /**
    48      * Provides a cache/loader for objects needed for displaying the html page.
    49      */
    50     class Cache {
    51         friend class DocLoader;
    52     public:
    53         /**
    54          * Initialize the cache in case it's not already.
    55          * This needs to get called once before using it.
    56          */
    57         static void init();
    58        
    59         /**
    60          * Ask the cache for some URL.
    61          * If the DocLoader is zero, the URL must be fully-qualified. Otherwise, it is automatically base-URL expanded
    62          */
    63         static CachedImage* requestImage(DocLoader*, const String& URL, bool reload = false, time_t expireDate = 0);
    64         static CachedImage* requestImage(DocLoader*, const KURL& URL, bool reload, time_t expireDate);
    65         static CachedCSSStyleSheet* requestCSSStyleSheet(DocLoader*, const String& URL, bool reload, time_t expireDate, const String& charset);
    66         static CachedScript* requestScript(DocLoader*, const String& URL, bool reload, time_t expireDate, const String& charset);
     80    // Remove an existing cache entry from both the resource map and from the LRU list.
     81    void remove(CachedResource*);
    6782
     83    // Flush the cache.  Any resources still referenced by Web pages will not be removed by this call.
     84    void prune();
     85
     86    void addDocLoader(DocLoader*);
     87    void removeDocLoader(DocLoader*);
     88
     89    CachedResource* resourceForURL(const String&);
     90
     91    // Calls to put the cached resource into and out of LRU lists.
     92    void insertInLRUList(CachedResource*);
     93    void removeFromLRUList(CachedResource*);
     94
     95    // Called to adjust the cache totals when a resource changes size.
     96    void adjustSize(bool live, unsigned oldResourceSize, unsigned newResourceSize);
     97
     98    // Track the size of all resources that are in the cache and still referenced by a Web page.
     99    void addToLiveObjectSize(unsigned s) { m_liveResourcesSize += s; }
     100    void removeFromLiveObjectSize(unsigned s) { m_liveResourcesSize -= s; }
     101
     102    // Functions to collect cache statistics for the caches window in the Safari Debug menu.
     103    struct TypeStatistic {
     104        int count;
     105        int size;
     106        TypeStatistic() : count(0), size(0) { }
     107    };
     108   
     109    struct Statistics {
     110        TypeStatistic images;
     111        TypeStatistic cssStyleSheets;
     112        TypeStatistic scripts;
    68113#ifdef XSLT_SUPPORT
    69         static CachedXSLStyleSheet* requestXSLStyleSheet(DocLoader*, const String& URL, bool reload, time_t expireDate);
    70 #endif
    71 
    72 #ifdef XBL_SUPPORT
    73         static CachedXBLDocument* requestXBLDocument(DocLoader*, const String& URL, bool reload, time_t expireDate);
    74 #endif
    75 
    76         /**
    77          * Sets the size of the cache. This will only hold approximately, since the size some
    78          * cached objects (like stylesheets) take up in memory is not exactly known.
    79          */
    80         static void setSize(int bytes);
    81 
    82         /**
    83          * returns the size of the cache
    84          */
    85         static int size() { return maxSize; };
    86 
    87         static int maxCacheableObjectSize() { return maxCacheable; }
    88 
    89         // Get an existing cache entry by URL.
    90         static CachedResource* get(const String& URL);
    91 
    92         // Remove an existing cache entry.
    93         static void remove(CachedResource*);
    94 
    95         /**
    96          * clean up cache
    97          */
    98         static void flush(bool force = false);
    99 
    100         /**
    101          * clears the cache
    102          * Warning: call this only at the end of your program, to clean up memory
    103          * (useful for finding memory leaks).
    104          */
    105         static void clear();
    106 
    107         static Loader* loader() { return m_loader; }
    108 
    109         static Image* nullImage;
    110         static Image* brokenImage;
    111 
    112         struct TypeStatistic {
    113             int count;
    114             int size;
    115             TypeStatistic() : count(0), size(0) { }
    116         };
    117        
    118         struct Statistics {
    119             TypeStatistic images;
    120             TypeStatistic movies;
    121             TypeStatistic styleSheets;
    122             TypeStatistic scripts;
    123 #ifdef XSLT_SUPPORT
    124             TypeStatistic xslStyleSheets;
     114        TypeStatistic xslStyleSheets;
    125115#endif
    126116#ifdef XBL_SUPPORT
    127             TypeStatistic xblDocs;
     117        TypeStatistic xblDocs;
    128118#endif
    129             TypeStatistic other;
    130         };
     119    };
    131120
    132         static Statistics getStatistics();
    133         static void flushAll();
    134         static void setCacheDisabled(bool);
     121    Statistics getStatistics();
    135122
    136         static void insertInLRUList(CachedResource*);
    137         static void removeFromLRUList(CachedResource*);
    138         static bool adjustSize(CachedResource*, int sizeDelta);
    139        
    140         static LRUList* getLRUListFor(CachedResource*);
    141        
    142         static void checkLRUAndUncacheableListIntegrity();
     123private:
     124    LRUList* lruListFor(CachedResource*);
     125   
     126    void resourceAccessed(CachedResource*);
    143127
    144     private:
    145         static HashSet<DocLoader*>* docloaders;
     128private:
     129    // Member variables.
     130    HashSet<DocLoader*> m_docLoaders;
     131    Loader m_loader;
     132
     133    bool m_disabled;  // Whether or not the cache is enabled.
     134
     135    int m_maximumSize;  // The maximum size in bytes that the global cache can consume.
     136    int m_currentSize;  // The current size of the global cache in bytes.
     137    int m_liveResourcesSize; // The current size of "live" resources that cannot be flushed.
     138
     139    // Size-adjusted and popularity-aware LRU list collection for cache objects.  This collection can hold
     140    // more resources than the cached resource map, since it can also hold "stale" muiltiple versions of objects that are
     141    // waiting to die when the clients referencing them go away.
     142    Vector<LRUList, 32> m_lruLists;
    146143   
    147         static int maxSize;
    148         static int maxCacheable;
    149         static int flushCount;
    150    
    151         static Loader* m_loader;
    152    
    153         static void moveToHeadOfLRUList(CachedResource*);
    154         static void updateCacheStatus(DocLoader*, CachedResource*);
    155    
    156         static LRUList* m_LRULists;
    157         static int m_totalSizeOfLRULists;
    158            
    159         static CachedResource* m_headOfUncacheableList;
    160            
    161         static int m_countOfLRUAndUncacheableLists;
    162     };
     144    // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
     145    // referenced by a Web page).
     146    HashMap<String, CachedResource*> m_resources;
     147};
     148
     149// Function to obtain the global cache.
     150Cache* cache();
    163151
    164152}
  • trunk/WebCore/loader/CachedCSSStyleSheet.cpp

    r17097 r17131  
    4848    setAccept("text/css");
    4949    // load the file
    50     Cache::loader()->load(dl, this, false);
     50    cache()->loader()->load(dl, this, false);
    5151    m_loading = true;
    5252}
     
    6262    if (!m_loading)
    6363        c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), m_sheet);
    64 }
    65 
    66 void CachedCSSStyleSheet::deref(CachedResourceClient *c)
    67 {
    68     Cache::flush();
    69     CachedResource::deref(c);
    70     if (canDelete() && m_free)
    71         delete this;
    7264}
    7365
  • trunk/WebCore/loader/CachedCSSStyleSheet.h

    r17097 r17131  
    4646
    4747        virtual void ref(CachedResourceClient*);
    48         virtual void deref(CachedResourceClient*);
    49 
     48 
    5049        virtual void setCharset(const String&);
    5150        virtual void data(Vector<char>&, bool allDataReceived);
  • trunk/WebCore/loader/CachedImage.cpp

    r17097 r17131  
    4343namespace WebCore {
    4444
    45 CachedImage::CachedImage(DocLoader* dl, const String &url, CachePolicy cachePolicy, time_t _expireDate)
     45CachedImage::CachedImage(DocLoader* docLoader, const String& url, CachePolicy cachePolicy, time_t _expireDate)
    4646    : CachedResource(url, ImageResource, cachePolicy, _expireDate)
    4747    , m_dataSize(0)
     
    5050    m_errorOccurred = false;
    5151    m_status = Unknown;
    52     m_loading = true;
     52    if (!docLoader || docLoader->autoLoadImages())  {
     53        m_loading = true;
     54        cache()->loader()->load(docLoader, this, true);
     55    } else
     56        m_loading = false;
    5357}
    5458
    5559CachedImage::~CachedImage()
    5660{
    57     clear();
     61    delete m_image;
    5862}
    5963
     
    6973}
    7074
    71 void CachedImage::deref(CachedResourceClient *c)
    72 {
    73     Cache::flush();
    74     CachedResource::deref(c);
    75     if (canDelete() && m_free)
    76         delete this;
     75static Image* brokenImage()
     76{
     77    static Image* brokenImage;
     78    if (!brokenImage)
     79        brokenImage = Image::loadPlatformResource("missingImage");
     80    return brokenImage;
     81}
     82
     83static Image* nullImage()
     84{
     85    static Image nullImage;
     86    return &nullImage;
    7787}
    7888
     
    8090{
    8191    if (m_errorOccurred)
    82         return Cache::brokenImage;
     92        return brokenImage();
    8393
    8494    if (m_image)
    8595        return m_image;
    8696
    87     return Cache::nullImage;
     97    return nullImage();
    8898}
    8999
     
    154164            m_errorOccurred = true;
    155165            notifyObservers();
    156             Cache::remove(this);
     166            if (inCache())
     167                cache()->remove(this);
    157168        } else
    158169            notifyObservers();
     
    161172        // want to decode the image to determine the frame count, so what we do instead is max the projected size of a single
    162173        // RGBA32 buffer (width*height*4) with the data size.  This will help ensure that large animated GIFs with thousands of
    163         // frames are properly designated as uncacheable.
     174        // frames are at least given a reasonably large size.
    164175        IntSize s = imageSize();
    165176        setSize(max(s.width() * s.height() * 4, m_dataSize));
  • trunk/WebCore/loader/CachedImage.h

    r17097 r17131  
    5353
    5454    virtual void ref(CachedResourceClient*);
    55     virtual void deref(CachedResourceClient*);
    5655
    5756    virtual Vector<char>& bufferData(const char* bytes, int addedSize, Request*);
     
    7271    virtual void animationAdvanced(const Image* image);
    7372
     73    bool stillNeedsLoad() const { return !m_errorOccurred && m_status == Unknown && m_loading == false; }
     74    void load();
     75
    7476private:
    7577    void createImage();
  • trunk/WebCore/loader/CachedResource.cpp

    r17097 r17131  
    3737namespace WebCore {
    3838
     39CachedResource::CachedResource(const String& URL, Type type, CachePolicy cachePolicy, time_t expireDate, unsigned size)
     40{
     41    m_url = URL;
     42    m_type = type;
     43    m_status = Pending;
     44    m_size = size;
     45    m_inCache = false;
     46    m_cachePolicy = cachePolicy;
     47    m_request = 0;
     48    m_response = 0;
     49    m_allData = 0;
     50    m_expireDate = expireDate;
     51    m_expireDateChanged = false;
     52    m_accessCount = 0;
     53    m_nextInLRUList = 0;
     54    m_prevInLRUList = 0;
     55#ifndef NDEBUG
     56    m_deleted = false;
     57    m_lruIndex = 0;
     58#endif
     59}
     60
    3961CachedResource::~CachedResource()
    4062{
    41     if (m_deleted)
    42         abort();
    43     Cache::removeFromLRUList(this);
     63    ASSERT(!inCache());
     64    ASSERT(!m_deleted);
     65#ifndef NDEBUG
    4466    m_deleted = true;
     67#endif
    4568    setResponse(0);
    4669    setAllData(0);
     
    6184void CachedResource::finish()
    6285{
    63     if (m_size > Cache::maxCacheableObjectSize())
    64         m_status = Uncacheable;
    65     else
    66         m_status = Cached;
     86    m_status = Cached;
    6787    KURL url(m_url.deprecatedString());
    6888    if (m_expireDateChanged && url.protocol().startsWith("http"))
     
    7595        return;
    7696
    77     if (m_status == Uncacheable || m_status == Cached)
     97    if (m_status == Cached)
    7898        finish();
    7999
     
    85105bool CachedResource::isExpired() const
    86106{
    87     if (!m_expireDate) return false;
     107    if (!m_expireDate)
     108        return false;
    88109    time_t now = time(0);
    89110    return (difftime(now, m_expireDate) >= 0);
    90111}
    91112
    92 void CachedResource::setRequest(Request *_request)
     113void CachedResource::setRequest(Request* request)
    93114{
    94     if ( _request && !m_request )
     115    if (request && !m_request)
    95116        m_status = Pending;
    96     m_request = _request;
    97     if (canDelete() && m_free)
     117    m_request = request;
     118    if (canDelete() && !inCache())
    98119        delete this;
    99     else if (allowInLRUList())
    100         Cache::insertInLRUList(this);
    101120}
    102121
    103122void CachedResource::ref(CachedResourceClient *c)
    104123{
     124    if (!referenced() && inCache())
     125        cache()->addToLiveObjectSize(size());
    105126    m_clients.add(c);
    106     Cache::removeFromLRUList(this);
    107     increaseAccessCount();
    108127}
    109128
     
    111130{
    112131    m_clients.remove(c);
    113     if (allowInLRUList())
    114         Cache::insertInLRUList(this);
     132    if (canDelete() && !inCache())
     133        delete this;
     134    else if (!referenced() && inCache()) {
     135        cache()->removeFromLiveObjectSize(size());
     136        cache()->prune();
     137    }
    115138}
    116139
    117 void CachedResource::setSize(int size)
     140void CachedResource::setSize(unsigned size)
    118141{
    119     bool sizeChanged = Cache::adjustSize(this, size - m_size);
     142    if (size == m_size)
     143        return;
     144
     145    unsigned oldSize = m_size;
    120146
    121147    // The object must now be moved to a different queue, since its size has been changed.
    122     if (sizeChanged && allowInLRUList())
    123         Cache::removeFromLRUList(this);
    124 
     148    // We have to remove explicitly before updating m_size, so that we find the correct previous
     149    // queue.
     150    if (inCache())
     151        cache()->removeFromLRUList(this);
     152   
    125153    m_size = size;
    126    
    127     if (sizeChanged && allowInLRUList())
    128         Cache::insertInLRUList(this);
     154   
     155    if (inCache()) {
     156        // Now insert into the new LRU list.
     157        cache()->insertInLRUList(this);
     158       
     159        // Update the cache's size totals.
     160        cache()->adjustSize(referenced(), oldSize, size);
     161    }
    129162}
    130163
  • trunk/WebCore/loader/CachedResource.h

    r17097 r17131  
    3737
    3838namespace WebCore {
    39     class CachedResourceClient;
    40     class Request;
    41    
    42     /**
    43      *
    44      * A cached object. Classes who want to use this object should derive
    45      * from CachedResourceClient, to get the function calls in case the requested data has arrived.
    46      *
    47      * This class also does the actual communication with kio and loads the file.
    48      */
    49     class CachedResource {
    50     public:
    51         enum Type {
    52             ImageResource,
    53             CSSStyleSheet,
    54             Script
     39
     40class Cache;
     41class CachedResourceClient;
     42class Request;
     43
     44// A resource that is held in the cache. Classes who want to use this object should derive
     45// from CachedResourceClient, to get the function calls in case the requested data has arrived.
     46// This class also does the actual communication with the loader to obtain the resource from the network.
     47class CachedResource {
     48public:
     49    enum Type {
     50        ImageResource,
     51        CSSStyleSheet,
     52        Script
    5553#ifdef XSLT_SUPPORT
    56             , XSLStyleSheet
     54        , XSLStyleSheet
    5755#endif
    5856#ifdef XBL_SUPPORT
    59             , XBL
     57        , XBL
    6058#endif
    61         };
     59    };
    6260
    63         enum Status {
    64             NotCached,    // this URL is not cached
    65             Unknown,      // let cache decide what to do with it
    66             New,          // inserting new item
    67             Pending,      // only partially loaded
    68             Persistent,   // never delete this
    69             Cached,       // regular case
    70             Uncacheable   // too big to be cached, will be destroyed as soon as possible
    71         };
     61    enum Status {
     62        NotCached,    // this URL is not cached
     63        Unknown,      // let cache decide what to do with it
     64        New,          // inserting new item
     65        Pending,      // only partially loaded
     66        Cached       // regular case
     67    };
    7268
    73         CachedResource(const String& URL, Type type, CachePolicy cachePolicy, time_t expireDate, int size = 0)
    74         {
    75             m_url = URL;
    76             m_type = type;
    77             m_status = Pending;
    78             m_size = size;
    79             m_free = false;
    80             m_cachePolicy = cachePolicy;
    81             m_request = 0;
    82             m_response = 0;
    83             m_allData = 0;
    84             m_expireDate = expireDate;
    85             m_deleted = false;
    86             m_expireDateChanged = false;
    87            
    88             m_accessCount = 0;
    89            
    90             m_nextInLRUList = 0;
    91             m_prevInLRUList = 0;
    92         }
    93         virtual ~CachedResource();
     69    CachedResource(const String& URL, Type type, CachePolicy cachePolicy, time_t expireDate, unsigned size = 0);
     70    virtual ~CachedResource();
    9471
    95         virtual void setCharset(const String&) { }
    96         virtual Vector<char>& bufferData(const char* bytes, int addedSize, Request*);
    97         virtual void data(Vector<char>&, bool allDataReceived) = 0;
    98         virtual void error() = 0;
     72    virtual void setCharset(const String&) { }
     73    virtual Vector<char>& bufferData(const char* bytes, int addedSize, Request*);
     74    virtual void data(Vector<char>&, bool allDataReceived) = 0;
     75    virtual void error() = 0;
    9976
    100         const String &url() const { return m_url; }
    101         Type type() const { return m_type; }
     77    const String &url() const { return m_url; }
     78    Type type() const { return m_type; }
    10279
    103         virtual void ref(CachedResourceClient*);
    104         virtual void deref(CachedResourceClient*);
     80    virtual void ref(CachedResourceClient*);
     81    void deref(CachedResourceClient*);
     82    bool referenced() const { return !m_clients.isEmpty(); }
    10583
    106         int count() const { return m_clients.size(); }
     84    unsigned count() const { return m_clients.size(); }
    10785
    108         Status status() const { return m_status; }
     86    Status status() const { return m_status; }
    10987
    110         int size() const { return m_size; }
     88    unsigned size() const { return m_size; }
    11189
    112         bool isLoaded() const { return !m_loading; }
     90    bool isLoaded() const { return !m_loading; }
     91    void setLoading(bool b) { m_loading = b; }
    11392
    114         virtual bool isImage() const { return false; }
     93    virtual bool isImage() const { return false; }
    11594
    116         int accessCount() const { return m_accessCount; }
    117         void increaseAccessCount() { m_accessCount++; }
     95    unsigned accessCount() const { return m_accessCount; }
     96    void increaseAccessCount() { m_accessCount++; }
     97
     98    // Computes the status of an object after loading. 
     99    // Updates the expire date on the cache entry file
     100    void finish();
     101
     102    // Called by the cache if the object has been removed from the cache
     103    // while still being referenced. This means the object should delete itself
     104    // if the number of clients observing it ever drops to 0.
     105    void setInCache(bool b) { m_inCache = b; }
     106    bool inCache() const { return m_inCache; }
    118107   
    119         /**
    120          * computes the status of an object after loading.
    121          * the result depends on the objects size and the size of the cache
    122          * also updates the expire date on the cache entry file
    123          */
    124         void finish();
     108    CachePolicy cachePolicy() const { return m_cachePolicy; }
    125109
    126         /**
    127          * Called by the cache if the object has been removed from the cache dict
    128          * while still being referenced. This means the object should kill itself
    129          * if its reference counter drops down to zero.
    130          */
    131         void setFree(bool b) { m_free = b; }
     110    void setRequest(Request*);
    132111
    133         CachePolicy cachePolicy() const { return m_cachePolicy; }
     112    PlatformResponse response() const { return m_response; }
     113    void setResponse(PlatformResponse);
     114    PlatformData allData() const { return m_allData; }
     115    void setAllData(PlatformData);
    134116
    135         void setRequest(Request*);
     117    bool canDelete() const { return !referenced() && !m_request; }
    136118
    137         PlatformResponse response() const { return m_response; }
    138         void setResponse(PlatformResponse);
    139         PlatformData allData() const { return m_allData; }
    140         void setAllData(PlatformData);
     119    void setExpireDate(time_t expireDate, bool changeHttpCache);
    141120
    142         bool canDelete() const { return m_clients.isEmpty() && !m_request; }
     121    bool isExpired() const;
    143122
    144         void setExpireDate(time_t expireDate, bool changeHttpCache);
     123    virtual bool schedule() const { return false; }
    145124
    146         bool isExpired() const;
     125    // List of acceptable MIME types seperated by ",".
     126    // A MIME type may contain a wildcard, e.g. "text/*".
     127    String accept() const { return m_accept; }
     128    void setAccept(const String& accept) { m_accept = accept; }
    147129
    148         virtual bool schedule() const { return false; }
     130protected:
     131    void setSize(unsigned size);
    149132
    150         // List of acceptable MIME types seperated by ",".
    151         // A MIME type may contain a wildcard, e.g. "text/*".
    152         String accept() const { return m_accept; }
    153         void setAccept(const String& accept) { m_accept = accept; }
     133    HashSet<CachedResourceClient*> m_clients;
    154134
    155     protected:
    156         void setSize(int size);
     135    String m_url;
     136    String m_accept;
     137    Request* m_request;
    157138
    158         HashSet<CachedResourceClient*> m_clients;
     139    PlatformResponse m_response;
     140    PlatformData m_allData;
    159141
    160         String m_url;
    161         String m_accept;
    162         Request* m_request;
     142    Type m_type;
     143    Status m_status;
    163144
    164         PlatformResponse m_response;
    165         PlatformData m_allData;
     145private:
     146    unsigned m_size;
     147    unsigned m_accessCount;
    166148
    167         Type m_type;
    168         Status m_status;
     149protected:
     150    time_t m_expireDate;
     151    CachePolicy m_cachePolicy;
     152    bool m_inCache;
     153    bool m_loading;
     154    bool m_expireDateChanged;
     155#ifndef NDEBUG
     156    bool m_deleted;
     157    unsigned m_lruIndex;
     158#endif
    169159
    170     private:
    171         int m_size;
    172         int m_accessCount;
    173    
    174     protected:
    175         time_t m_expireDate;
    176         CachePolicy m_cachePolicy;
    177         bool m_free : 1;
    178         bool m_deleted : 1;
    179         bool m_loading : 1;
    180         bool m_expireDateChanged : 1;
    181 
    182     private:
    183         bool allowInLRUList() const { return canDelete() && status() != Persistent; }
    184 
    185         CachedResource* m_nextInLRUList;
    186         CachedResource* m_prevInLRUList;
    187         friend class Cache;
    188     };
     160private:
     161    CachedResource* m_nextInLRUList;
     162    CachedResource* m_prevInLRUList;
     163    friend class Cache;
     164};
    189165
    190166}
  • trunk/WebCore/loader/CachedScript.cpp

    r17097 r17131  
    4848    m_errorOccurred = false;
    4949    // load the file
    50     Cache::loader()->load(dl, this, false);
     50    cache()->loader()->load(dl, this, false);
    5151    m_loading = true;
    5252    if (!m_encoding.isValid())
    5353        m_encoding = Latin1Encoding();
    54 }
    55 
    56 CachedScript::CachedScript(const String& url, const String& scriptData)
    57     : CachedResource(url, Script, CachePolicyVerify, 0, scriptData.length())
    58 {
    59     m_errorOccurred = false;
    60     m_loading = false;
    61     m_status = Persistent;
    62     m_script = scriptData;
    6354}
    6455
     
    7263    if (!m_loading)
    7364        c->notifyFinished(this);
    74 }
    75 
    76 void CachedScript::deref(CachedResourceClient* c)
    77 {
    78     Cache::flush();
    79     CachedResource::deref(c);
    80     if (canDelete() && m_free)
    81         delete this;
    8265}
    8366
  • trunk/WebCore/loader/CachedScript.h

    r17097 r17131  
    3939    public:
    4040        CachedScript(DocLoader*, const String& URL, CachePolicy, time_t expireDate, const String& charset);
    41         CachedScript(const String& URL, const String& scriptData);
    4241        virtual ~CachedScript();
    4342
     
    4544
    4645        virtual void ref(CachedResourceClient*);
    47         virtual void deref(CachedResourceClient*);
    4846
    4947        virtual void setCharset(const String&);
  • trunk/WebCore/loader/CachedXBLDocument.cpp

    r17097 r17131  
    6666}
    6767
    68 void CachedXBLDocument::deref(CachedResourceClient *c)
    69 {
    70     Cache::flush();
    71     CachedResource::deref(c);
    72     if (canDelete() && m_free)
    73         delete this;
    74 }
    75 
    7668void CachedXBLDocument::setCharset(const String& chs)
    7769{
  • trunk/WebCore/loader/CachedXBLDocument.h

    r17097 r17131  
    4848       
    4949        virtual void ref(CachedResourceClient*);
    50         virtual void deref(CachedResourceClient*);
    5150       
    5251        virtual void setCharset(const String&);
  • trunk/WebCore/loader/CachedXSLStyleSheet.cpp

    r17097 r17131  
    5050   
    5151    // load the file
    52     Cache::loader()->load(dl, this, false);
     52    cache()->loader()->load(dl, this, false);
    5353    m_loading = true;
    5454}
     
    6060    if (!m_loading)
    6161        c->setXSLStyleSheet(m_url, m_sheet);
    62 }
    63 
    64 void CachedXSLStyleSheet::deref(CachedResourceClient *c)
    65 {
    66     Cache::flush();
    67     CachedResource::deref(c);
    68     if (canDelete() && m_free)
    69         delete this;
    7062}
    7163
  • trunk/WebCore/loader/CachedXSLStyleSheet.h

    r17097 r17131  
    4545       
    4646        virtual void ref(CachedResourceClient*);
    47         virtual void deref(CachedResourceClient*);
    4847       
    4948        virtual void setCharset(const String&);
  • trunk/WebCore/loader/DocLoader.cpp

    r16689 r17131  
    4242
    4343DocLoader::DocLoader(Frame *frame, Document* doc)
     44: m_cache(cache())
    4445{
    4546    m_cachePolicy = CachePolicyVerify;
    4647    m_expireDate = 0;
    47     m_bautoloadImages = true;
     48    m_autoLoadImages = true;
    4849    m_frame = frame;
    4950    m_doc = doc;
    5051    m_loadInProgress = false;
    5152
    52     Cache::init();
    53     Cache::docloaders->add(this);
     53    m_cache->addDocLoader(this);
    5454}
    5555
    5656DocLoader::~DocLoader()
    5757{
    58     Cache::docloaders->remove(this);
     58    m_cache->removeDocLoader(this);
    5959}
    6060
     
    6464}
    6565
    66 bool DocLoader::needReload(const KURL& fullURL)
     66void DocLoader::checkForReload(const KURL& fullURL)
    6767{
    68     bool reload = false;
    6968    if (m_cachePolicy == CachePolicyVerify) {
    7069       if (!m_reloadedURLs.contains(fullURL.url())) {
    71           CachedResource* existing = Cache::get(fullURL.url());
     70          CachedResource* existing = cache()->resourceForURL(fullURL.url());
    7271          if (existing && existing->isExpired()) {
    73              Cache::remove(existing);
     72             cache()->remove(existing);
    7473             m_reloadedURLs.add(fullURL.url());
    75              reload = true;
    7674          }
    7775       }
    7876    } else if ((m_cachePolicy == CachePolicyReload) || (m_cachePolicy == CachePolicyRefresh)) {
    7977       if (!m_reloadedURLs.contains(fullURL.url())) {
    80           CachedResource* existing = Cache::get(fullURL.url());
     78          CachedResource* existing = cache()->resourceForURL(fullURL.url());
    8179          if (existing)
    82              Cache::remove(existing);
     80             cache()->remove(existing);
    8381          m_reloadedURLs.add(fullURL.url());
    84           reload = true;
    8582       }
    8683    }
    87     return reload;
    8884}
    8985
    90 CachedImage *DocLoader::requestImage(const String& url)
     86CachedImage* DocLoader::requestImage(const String& url)
     87{
     88    CachedImage* resource = static_cast<CachedImage*>(requestResource(CachedResource::ImageResource, url));
     89    if (autoLoadImages() && resource && resource->stillNeedsLoad()) {
     90        resource->setLoading(true);
     91        cache()->loader()->load(this, resource, true);
     92    }
     93    return resource;
     94}
     95
     96CachedCSSStyleSheet* DocLoader::requestCSSStyleSheet(const String& url, const String& charset)
     97{
     98    return static_cast<CachedCSSStyleSheet*>(requestResource(CachedResource::CSSStyleSheet, url, &charset));
     99}
     100
     101CachedScript* DocLoader::requestScript(const String& url, const String& charset)
     102{
     103    return static_cast<CachedScript*>(requestResource(CachedResource::Script, url, &charset));
     104}
     105
     106#ifdef XSLT_SUPPORT
     107CachedXSLStyleSheet* DocLoader::requestXSLStyleSheet(const String& url)
     108{
     109    return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XSLStyleSheet, url));
     110}
     111#endif
     112
     113#ifdef XBL_SUPPORT
     114CachedXBLDocument* DocLoader::requestXBLDocument(const String& url)
     115{
     116    return static_cast<CachedXSLStyleSheet*>(requestResource(CachedResource::XBL, url));
     117}
     118#endif
     119
     120CachedResource* DocLoader::requestResource(CachedResource::Type type, const String& url, const String* charset)
    91121{
    92122    KURL fullURL = m_doc->completeURL(url.deprecatedString());
     
    95125        setCachePolicy(CachePolicyReload);
    96126
    97     bool reload = needReload(fullURL);
     127    checkForReload(fullURL);
    98128
    99     CachedImage *cachedObject = Cache::requestImage(this, fullURL, reload, m_expireDate);
    100     CheckCacheObjectStatus(this, cachedObject);
    101     return cachedObject;
     129    CachedResource* resource = cache()->requestResource(this, type, fullURL, m_expireDate, charset);
     130    m_docResources.set(resource->url(), resource);
     131   
     132    CheckCacheObjectStatus(this, resource);
     133    return resource;
    102134}
    103135
    104 CachedCSSStyleSheet *DocLoader::requestCSSStyleSheet(const String& url, const String& charset)
     136void DocLoader::setAutoLoadImages(bool enable)
    105137{
    106     KURL fullURL = m_doc->completeURL(url.deprecatedString());
    107 
    108     if (CheckIfReloading(this))
    109         setCachePolicy(CachePolicyReload);
    110 
    111     bool reload = needReload(fullURL);
    112 
    113     CachedCSSStyleSheet* cachedObject = Cache::requestCSSStyleSheet(this, url, reload, m_expireDate, charset);
    114     CheckCacheObjectStatus(this, cachedObject);
    115     return cachedObject;
    116 }
    117 
    118 CachedScript* DocLoader::requestScript(const String& url, const String& charset)
    119 {
    120     KURL fullURL = m_doc->completeURL(url.deprecatedString());
    121 
    122     if (CheckIfReloading(this))
    123         setCachePolicy(CachePolicyReload);
    124 
    125     bool reload = needReload(fullURL);
    126 
    127     CachedScript *cachedObject = Cache::requestScript(this, url, reload, m_expireDate, charset);
    128     CheckCacheObjectStatus(this, cachedObject);
    129     return cachedObject;
    130 }
    131 
    132 #ifdef XSLT_SUPPORT
    133 CachedXSLStyleSheet* DocLoader::requestXSLStyleSheet(const String& url)
    134 {
    135     KURL fullURL = m_doc->completeURL(url.deprecatedString());
    136    
    137     if (CheckIfReloading(this))
    138         setCachePolicy(CachePolicyReload);
    139    
    140     bool reload = needReload(fullURL);
    141    
    142     CachedXSLStyleSheet *cachedObject = Cache::requestXSLStyleSheet(this, url, reload, m_expireDate);
    143     CheckCacheObjectStatus(this, cachedObject);
    144     return cachedObject;
    145 }
    146 #endif
    147 
    148 #ifdef XBL_SUPPORT
    149 CachedXBLDocument* DocLoader::requestXBLDocument(const String& url)
    150 {
    151     KURL fullURL = m_doc->completeURL(url.deprecatedString());
    152    
    153     // FIXME: Is this right for XBL?
    154     if (m_frame && m_frame->onlyLocalReferences() && fullURL.protocol() != "file") return 0;
    155    
    156     if (CheckIfReloading(this))
    157         setCachePolicy(CachePolicyReload);
    158    
    159     bool reload = needReload(fullURL);
    160    
    161     CachedXBLDocument *cachedObject = Cache::requestXBLDocument(this, url, reload, m_expireDate);
    162     CheckCacheObjectStatus(this, cachedObject);
    163     return cachedObject;
    164 }
    165 #endif
    166 
    167 void DocLoader::setAutoloadImages(bool enable)
    168 {
    169     if (enable == m_bautoloadImages)
     138    if (enable == m_autoLoadImages)
    170139        return;
    171140
    172     m_bautoloadImages = enable;
     141    m_autoLoadImages = enable;
    173142
    174     if (!m_bautoloadImages)
     143    if (!m_autoLoadImages)
    175144        return;
    176145
    177     HashMap<String, CachedResource*>::iterator end = m_docObjects.end();
    178     for (HashMap<String, CachedResource*>::iterator it = m_docObjects.begin(); it != end; ++it) {
    179         CachedResource* co = it->second;
    180         if (co->type() == CachedResource::ImageResource) {
    181             CachedImage *img = const_cast<CachedImage*>(static_cast<const CachedImage *>(co));
     146    HashMap<String, CachedResource*>::iterator end = m_docResources.end();
     147    for (HashMap<String, CachedResource*>::iterator it = m_docResources.begin(); it != end; ++it) {
     148        CachedResource* resource = it->second;
     149        if (resource->type() == CachedResource::ImageResource) {
     150            CachedImage* image = const_cast<CachedImage*>(static_cast<const CachedImage *>(resource));
    182151
    183             CachedResource::Status status = img->status();
     152            CachedResource::Status status = image->status();
    184153            if (status != CachedResource::Unknown)
    185154                continue;
    186155
    187             Cache::loader()->load(this, img, true);
     156            cache()->loader()->load(this, image, true);
    188157        }
    189158    }
     
    195164}
    196165
    197 void DocLoader::removeCachedObject(CachedResource* o) const
     166void DocLoader::removeCachedResource(CachedResource* resource) const
    198167{
    199     m_docObjects.remove(o->url());
     168    m_docResources.remove(resource->url());
    200169}
    201170
  • trunk/WebCore/loader/DocLoader.h

    r16689 r17131  
    2828#define DocLoader_h
    2929
     30#include "CachedResource.h"
    3031#include "CachePolicy.h"
    3132#include "Settings.h"
     
    3536
    3637namespace WebCore {
    37     class CachedCSSStyleSheet;
    38     class CachedImage;
    39     class CachedResource;
    40     class CachedScript;
    41     class CachedXSLStyleSheet;
    42     class Document;
    43     class Frame;
    44     class HTMLImageLoader;
    45     class KURL;
    46    
    47     /**
    48      * Manages the loading of scripts/images/stylesheets for a particular document
    49      */
    50     class DocLoader
    51     {
    52     public:
    53         DocLoader(Frame*, Document*);
    54         ~DocLoader();
    5538
    56         CachedImage* requestImage(const String& url);
    57         CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset);
    58         CachedScript* requestScript(const String& url, const String& charset);
     39class CachedCSSStyleSheet;
     40class CachedImage;
     41class CachedScript;
     42class CachedXSLStyleSheet;
     43class Document;
     44class Frame;
     45class HTMLImageLoader;
     46class KURL;
     47
     48// The DocLoader manages the loading of scripts/images/stylesheets for a single document.
     49class DocLoader
     50{
     51friend class Cache;
     52friend class HTMLImageLoader;
     53
     54public:
     55    DocLoader(Frame*, Document*);
     56    ~DocLoader();
     57
     58    CachedImage* requestImage(const String& url);
     59    CachedCSSStyleSheet* requestCSSStyleSheet(const String& url, const String& charset);
     60    CachedScript* requestScript(const String& url, const String& charset);
    5961
    6062#ifdef XSLT_SUPPORT
    61         CachedXSLStyleSheet* requestXSLStyleSheet(const String& url);
     63    CachedXSLStyleSheet* requestXSLStyleSheet(const String& url);
    6264#endif
    6365#ifdef XBL_SUPPORT
    64         CachedXBLDocument* requestXBLDocument(const String &url);
     66    CachedXBLDocument* requestXBLDocument(const String &url);
    6567#endif
    6668
    67         CachedResource* cachedObject(const String& url) const { return m_docObjects.get(url); }
    68         const HashMap<String, CachedResource*>& allCachedObjects() const { return m_docObjects; }
     69    CachedResource* cachedResource(const String& url) const { return m_docResources.get(url); }
     70    const HashMap<String, CachedResource*>& allCachedResources() const { return m_docResources; }
    6971
    70         bool autoloadImages() const { return m_bautoloadImages; }
    71         CachePolicy cachePolicy() const { return m_cachePolicy; }
    72         time_t expireDate() const { return m_expireDate; }
    73         Frame* frame() const { return m_frame; }
    74         Document* doc() const { return m_doc; }
     72    bool autoLoadImages() const { return m_autoLoadImages; }
     73    void setAutoLoadImages(bool);
     74   
     75    CachePolicy cachePolicy() const { return m_cachePolicy; }
     76    void setCachePolicy(CachePolicy);
     77   
     78    time_t expireDate() const { return m_expireDate; }
     79    void setExpireDate(time_t);
     80   
     81    Frame* frame() const { return m_frame; }
     82    Document* doc() const { return m_doc; }
    7583
    76         void setExpireDate(time_t);
    77         void setAutoloadImages(bool);
    78         void setCachePolicy(CachePolicy);
    79         void removeCachedObject(CachedResource*) const;
     84    void removeCachedResource(CachedResource*) const;
    8085
    81         void setLoadInProgress(bool);
    82         bool loadInProgress() const { return m_loadInProgress; }
     86    void setLoadInProgress(bool);
     87    bool loadInProgress() const { return m_loadInProgress; }
    8388
    84     private:
    85         bool needReload(const KURL &fullUrl);
     89private:
     90    CachedResource* requestResource(CachedResource::Type, const String& url, const String* charset = 0);
    8691
    87         friend class Cache;
    88         friend class Document;
    89         friend class HTMLImageLoader;
     92    void checkForReload(const KURL&);
    9093
    91         HashSet<String> m_reloadedURLs;
    92         mutable HashMap<String, CachedResource*> m_docObjects;
    93         time_t m_expireDate;
    94         CachePolicy m_cachePolicy;
    95         bool m_bautoloadImages : 1;
    96         Frame* m_frame;
    97         Document *m_doc;
    98         bool m_loadInProgress;
    99     };
     94    Cache* m_cache;
     95    HashSet<String> m_reloadedURLs;
     96    mutable HashMap<String, CachedResource*> m_docResources;
     97    time_t m_expireDate;
     98    CachePolicy m_cachePolicy;
     99    bool m_autoLoadImages : 1;
     100    Frame* m_frame;
     101    Document *m_doc;
     102    bool m_loadInProgress;
     103};
    100104
    101105}
  • trunk/WebCore/loader/ImageDocument.cpp

    r15766 r17131  
    112112        Vector<char>& buffer = cachedImage->bufferData(0, 0, 0);
    113113        cachedImage->data(buffer, true);
     114        cachedImage->finish();
    114115
    115116        // FIXME: Need code to set the title for platforms other than Mac OS X.
  • trunk/WebCore/loader/loader.cpp

    r17070 r17131  
    104104        object->error();
    105105        docLoader->setLoadInProgress(false);
    106         Cache::remove(object);
     106        cache()->remove(object);
    107107    } else {
    108108        docLoader->setLoadInProgress(true);
     
    196196    while (pIt.current()) {
    197197        if (pIt.current()->docLoader() == dl) {
    198             Cache::remove(pIt.current()->cachedObject());
     198            cache()->remove(pIt.current()->cachedObject());
    199199            m_requestsPending.remove(pIt);
    200200        } else
     
    215215        Request* r = m_requestsLoading.get(job);
    216216        m_requestsLoading.remove(job);
    217         Cache::remove(r->cachedObject());
     217        cache()->remove(r->cachedObject());
    218218        job->kill();
    219219    }
     
    222222    while (bdIt.current()) {
    223223        if (bdIt.current()->docLoader() == dl) {
    224             Cache::remove(bdIt.current()->cachedObject());
     224            cache()->remove(bdIt.current()->cachedObject());
    225225            m_requestsBackgroundDecoding.remove(bdIt);
    226226        } else
  • trunk/WebCore/loader/mac/LoaderFunctionsMac.mm

    r17092 r17131  
    170170int NumberOfPendingOrLoadingRequests(DocLoader *dl)
    171171{
    172     return Cache::loader()->numRequests(dl);
     172    return cache()->loader()->numRequests(dl);
    173173}
    174174
     
    189189        return;
    190190    switch (cachedObject->status()) {
    191     case CachedResource::Persistent:
    192191    case CachedResource::Cached:
    193     case CachedResource::Uncacheable:
    194192        break;
    195193    case CachedResource::NotCached:
  • trunk/WebCore/page/Frame.cpp

    r17111 r17131  
    124124class UserStyleSheetLoader : public CachedResourceClient {
    125125public:
    126     UserStyleSheetLoader(Frame* frame, const String& url, DocLoader* dl)
     126    UserStyleSheetLoader(Frame* frame, const String& url, DocLoader* docLoader)
    127127        : m_frame(frame)
    128         , m_cachedSheet(Cache::requestCSSStyleSheet(dl, url, false, 0, ""))
     128        , m_cachedSheet(docLoader->requestCSSStyleSheet(url, ""))
    129129    {
    130130        m_cachedSheet->ref(this);
     
    163163{
    164164    AtomicString::init();
    165     Cache::init();
    166165    EventNames::init();
    167166    HTMLNames::init();
     
    338337  if (Document *doc = d->m_doc.get()) {
    339338    if (DocLoader *docLoader = doc->docLoader())
    340       Cache::loader()->cancelRequests(docLoader);
     339      cache()->loader()->cancelRequests(docLoader);
    341340      XMLHttpRequest::cancelRequests(doc);
    342341  }
     
    443442}
    444443
    445 void Frame::setAutoloadImages(bool enable)
    446 {
    447   if (d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable)
     444void Frame::setAutoLoadImages(bool enable)
     445{
     446  if (d->m_doc && d->m_doc->docLoader()->autoLoadImages() == enable)
    448447    return;
    449448
    450449  if (d->m_doc)
    451     d->m_doc->docLoader()->setAutoloadImages(enable);
    452 }
    453 
    454 bool Frame::autoloadImages() const
     450    d->m_doc->docLoader()->setAutoLoadImages(enable);
     451}
     452
     453bool Frame::autoLoadImages() const
    455454{
    456455  if (d->m_doc)
    457     return d->m_doc->docLoader()->autoloadImages();
     456    return d->m_doc->docLoader()->autoLoadImages();
    458457
    459458  return true;
     
    673672  updatePolicyBaseURL();
    674673
    675   setAutoloadImages(d->m_settings->autoLoadImages());
     674  setAutoLoadImages(d->m_settings->autoLoadImages());
    676675  const KURL& userStyleSheet = d->m_settings->userStyleSheetLocation();
    677676
     
    901900  int requests = 0;
    902901  if (d->m_doc && d->m_doc->docLoader())
    903       requests = Cache::loader()->numRequests(d->m_doc->docLoader());
     902      requests = cache()->loader()->numRequests(d->m_doc->docLoader());
    904903
    905904  if (requests > 0)
     
    17551754void Frame::reparseConfiguration()
    17561755{
    1757     setAutoloadImages(d->m_settings->autoLoadImages());
     1756    setAutoLoadImages(d->m_settings->autoLoadImages());
    17581757       
    17591758    d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
  • trunk/WebCore/page/Frame.h

    r17092 r17131  
    165165   * @note Request will be ignored if called before @ref begin().
    166166   */
    167   void setAutoloadImages(bool enable);
     167  void setAutoLoadImages(bool enable);
    168168  /**
    169169   * Returns whether images contained in the document are loaded automatically
     
    172172   * was called.
    173173   */
    174   bool autoloadImages() const;
     174  bool autoLoadImages() const;
    175175
    176176  KURL baseURL() const;
  • trunk/WebCore/xml/XSLTProcessor.cpp

    r16803 r17131  
    9191            void *oldErrorContext = xmlGenericErrorContext;
    9292           
    93             Vector<char> data = ServeSynchronousRequest(Cache::loader(), globalDocLoader, loader.get(), finalURL, headers);
     93            Vector<char> data = ServeSynchronousRequest(cache()->loader(), globalDocLoader, loader.get(), finalURL, headers);
    9494       
    9595            xmlSetGenericErrorFunc(0, parseErrorFunc);
  • trunk/WebCore/xml/xmlhttprequest.cpp

    r16803 r17131  
    334334            // avoid deadlock in case the loader wants to use JS on a background thread
    335335            KJS::JSLock::DropAllLocks dropLocks;
    336             data = ServeSynchronousRequest(Cache::loader(), m_doc->docLoader(), m_loader.get(), finalURL, headers);
     336            data = ServeSynchronousRequest(cache()->loader(), m_doc->docLoader(), m_loader.get(), finalURL, headers);
    337337        }
    338338
Note: See TracChangeset for help on using the changeset viewer.