Fix a regression where the cache size overflows because of a double
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Mar 2007 02:00:25 +0000 (02:00 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Mar 2007 02:00:25 +0000 (02:00 +0000)
        subtraction per resource when they got removed from the cache.  Add an
        assert to adjustSize to detect this case in the future.

        Fix ImageSourceCG so that when we flush decoded data from our cache that
        we also flush it from the ImageSource.

        Reviewed by mjs

        * loader/Cache.cpp:
        (WebCore::Cache::adjustSize):
        * platform/graphics/BitmapImage.cpp:
        (WebCore::BitmapImage::~BitmapImage):
        (WebCore::BitmapImage::destroyDecodedData):
        * platform/graphics/Image.h:
        * platform/graphics/ImageSource.h:
        * platform/graphics/cg/ImageSourceCG.cpp:
        (WebCore::ImageSource::setData):
        (WebCore::ImageSource::destroyFrameAtIndex):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@20044 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/loader/Cache.cpp
WebCore/platform/graphics/BitmapImage.cpp
WebCore/platform/graphics/Image.h
WebCore/platform/graphics/ImageSource.h
WebCore/platform/graphics/cg/ImageSourceCG.cpp

index 7971bd9..de82946 100644 (file)
@@ -1,3 +1,25 @@
+2007-03-07  David Hyatt  <hyatt@apple.com>
+
+        Fix a regression where the cache size overflows because of a double
+        subtraction per resource when they got removed from the cache.  Add an
+        assert to adjustSize to detect this case in the future.
+
+        Fix ImageSourceCG so that when we flush decoded data from our cache that
+        we also flush it from the ImageSource.
+
+        Reviewed by mjs
+
+        * loader/Cache.cpp:
+        (WebCore::Cache::adjustSize):
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::~BitmapImage):
+        (WebCore::BitmapImage::destroyDecodedData):
+        * platform/graphics/Image.h:
+        * platform/graphics/ImageSource.h:
+        * platform/graphics/cg/ImageSourceCG.cpp:
+        (WebCore::ImageSource::setData):
+        (WebCore::ImageSource::destroyFrameAtIndex):
+
 2007-03-07  Mitz Pettel  <mitz@webkit.org>
 
         Reviewed by Darin.
index fa34fd8..979cc08 100644 (file)
@@ -130,7 +130,7 @@ void Cache::prune()
     unsigned unreferencedResourcesSize = m_currentSize - m_liveResourcesSize;
     if (unreferencedResourcesSize < m_maximumSize)
         return;
-
+    
     // Our first pass over the objects in the cache will destroy any decoded data in unreferenced objects.
     unsigned size = m_lruLists.size();
     for (int i = size - 1; i >= 0; i--) {
@@ -346,9 +346,12 @@ void Cache::resourceAccessed(CachedResource* resource)
 
 void Cache::adjustSize(bool live, int delta)
 {
+    ASSERT(delta >= 0 || ((int)m_currentSize + delta >= 0));
     m_currentSize += delta;
-    if (live)
+    if (live) {
+        ASSERT(delta >= 0 || ((int)m_liveResourcesSize + delta >= 0));
         m_liveResourcesSize += delta;
+    }
 }
 
 Cache::Statistics Cache::getStatistics()
index 3550f31..4e76920 100644 (file)
@@ -56,6 +56,8 @@ BitmapImage::BitmapImage(ImageObserver* observer)
 
 BitmapImage::~BitmapImage()
 {
+    // Null out the image observer so that we don't incorrectly communicate that decoded data is being destroyed during destruction.
+    m_imageObserver = 0;
     destroyDecodedData();
     stopAnimation();
 }
@@ -70,6 +72,7 @@ void BitmapImage::destroyDecodedData(bool incremental)
             if (m_frames[i].m_frame) {
                 sizeChange -= frameSize;
                 m_frames[i].clear();
+                m_source.destroyFrameAtIndex(i);
             }
         }
 
index 0f4b5a6..994a585 100644 (file)
@@ -144,6 +144,7 @@ private:
     static void drawPatternCallback(void* info, CGContext*);
 #endif
     
+protected:
     Vector<char> m_data; // The encoded raw data for the image. 
     ImageObserver* m_imageObserver;
 };
index 2543278..da911e1 100644 (file)
@@ -78,7 +78,10 @@ public:
     int repetitionCount();
     
     size_t frameCount() const;
+    
     NativeImagePtr createFrameAtIndex(size_t);
+    void destroyFrameAtIndex(size_t);
+    
     float frameDurationAtIndex(size_t);
     bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
 
index 2326d77..39c8ad5 100644 (file)
@@ -67,7 +67,7 @@ bool ImageSource::initialized() const
 void ImageSource::setData(NativeBytePtr data, bool allDataReceived)
 {
     if (!m_decoder)
-        m_decoder = CGImageSourceCreateIncremental(imageSourceOptions());
+        m_decoder = CGImageSourceCreateIncremental(NULL);
     CGImageSourceUpdateData(m_decoder, data, allDataReceived);
 }
 
@@ -139,6 +139,15 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index)
     return CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions());
 }
 
+void ImageSource::destroyFrameAtIndex(size_t index)
+{
+    // FIXME: Image I/O has no API for flushing frames from its internal cache.  The best we can do is tell it to create
+    // a new image with NULL options.  This will cause the cache/no-cache flags to mismatch, and it will then drop
+    // its reference to the old decoded image.
+    CGImageRef image = CGImageSourceCreateImageAtIndex(m_decoder, index, NULL);
+    CFRelease(image);
+}
+
 float ImageSource::frameDurationAtIndex(size_t index)
 {
     float duration = 0;