diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index ed5066747c2c..9cbbd96a346c 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3247,14 +3247,6 @@ nsIDocument::TakeFrameRequestCallbacks(FrameRequestCallbackList& aCallbacks) mFrameRequestCallbacks.Clear(); } -PLDHashOperator RequestDiscardEnumerator(imgIRequest* aKey, - PRUint32 aData, - void* userArg) -{ - aKey->RequestDiscard(); - return PL_DHASH_NEXT; -} - void nsDocument::DeleteShell() { @@ -3263,11 +3255,6 @@ nsDocument::DeleteShell() RevokeAnimationFrameNotifications(); } - // When our shell goes away, request that all our images be immediately - // discarded, so we don't carry around decoded image data for a document we - // no longer intend to paint. - mImageTracker.EnumerateRead(RequestDiscardEnumerator, nsnull); - mPresShell = nsnull; } @@ -8322,32 +8309,26 @@ nsDocument::RemoveImage(imgIRequest* aImage) // If the count is now zero, remove from the tracker. // Otherwise, set the new value. - if (count != 0) { + if (count == 0) { + mImageTracker.Remove(aImage); + } else { mImageTracker.Put(aImage, count); - return NS_OK; } - mImageTracker.Remove(aImage); - nsresult rv = NS_OK; - // Now that we're no longer tracking this image, unlock it if we'd - // previously locked it. - if (mLockingImages) { + // If we removed the image from the tracker and we're locking images, unlock + // this image. + if (count == 0 && mLockingImages) rv = aImage->UnlockImage(); - } - // If we're animating images, remove our request to animate this one. - if (mAnimatingImages) { + // If we removed the image from the tracker and we're animating images, + // remove our request to animate this image. + if (count == 0 && mAnimatingImages) { nsresult rv2 = aImage->DecrementAnimationConsumers(); rv = NS_SUCCEEDED(rv) ? rv2 : rv; } - // Request that the image be discarded if nobody else holds a lock on it. - // Do this even if !mLockingImages, because even if we didn't just unlock - // this image, it might still be a candidate for discarding. - aImage->RequestDiscard(); - return rv; } diff --git a/image/public/imgIContainer.idl b/image/public/imgIContainer.idl index 14d22f2c554b..5a632215103f 100644 --- a/image/public/imgIContainer.idl +++ b/image/public/imgIContainer.idl @@ -93,7 +93,7 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter); * * Internally, imgIContainer also manages animation of images. */ -[scriptable, uuid(8bf87433-be67-413b-9497-00071c5002bd)] +[scriptable, uuid(2506249c-e0a1-4d8f-846c-2d478247f8d8)] interface imgIContainer : nsISupports { /** @@ -283,12 +283,6 @@ interface imgIContainer : nsISupports */ void unlockImage(); - /** - * If this image is unlocked, discard its decoded data. If the image is - * locked or has already been discarded, do nothing. - */ - void requestDiscard(); - /** * Indicates that this imgIContainer has been triggered to update * its internal animation state. Likely this should only be called diff --git a/image/public/imgIRequest.idl b/image/public/imgIRequest.idl index 080e2f9661ba..9d3cfb75b925 100644 --- a/image/public/imgIRequest.idl +++ b/image/public/imgIRequest.idl @@ -52,7 +52,7 @@ interface nsIPrincipal; * @version 0.1 * @see imagelib2 */ -[scriptable, uuid(d35a9adb-8328-4b64-b06f-72a165acd080)] +[scriptable, uuid(c3bf4e2a-f64b-4ac1-a84e-18631b1802ab)] interface imgIRequest : nsIRequest { /** @@ -194,12 +194,6 @@ interface imgIRequest : nsIRequest */ void unlockImage(); - /** - * If this image is unlocked, discard the image's decoded data. If the image - * is locked or is already discarded, do nothing. - */ - void requestDiscard(); - /** * If this request is for an animated image, the method creates a new * request which contains the current frame of the image. diff --git a/image/src/DiscardTracker.cpp b/image/src/DiscardTracker.cpp index 473c50110dec..fcd85dc4bf3b 100644 --- a/image/src/DiscardTracker.cpp +++ b/image/src/DiscardTracker.cpp @@ -1,7 +1,39 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bobby Holley + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #include "nsComponentManagerUtils.h" #include "nsITimer.h" @@ -12,95 +44,77 @@ namespace mozilla { namespace image { -static const char* sDiscardTimeoutPref = "image.mem.min_discard_timeout_ms"; - -/* static */ LinkedList DiscardTracker::sDiscardableImages; -/* static */ nsCOMPtr DiscardTracker::sTimer; -/* static */ bool DiscardTracker::sInitialized = false; -/* static */ bool DiscardTracker::sTimerOn = false; -/* static */ bool DiscardTracker::sDiscardRunnablePending = false; -/* static */ PRUint64 DiscardTracker::sCurrentDecodedImageBytes = 0; -/* static */ PRUint32 DiscardTracker::sMinDiscardTimeoutMs = 10000; -/* static */ PRUint32 DiscardTracker::sMaxDecodedImageKB = 42 * 1024; +static bool sInitialized = false; +static bool sTimerOn = false; +static PRUint32 sMinDiscardTimeoutMs = 10000; /* Default if pref unreadable. */ +static nsITimer *sTimer = nsnull; +static struct DiscardTrackerNode sHead, sSentinel, sTail; /* - * When we notice we're using too much memory for decoded images, we enqueue a - * DiscardRunnable, which runs this code. + * Puts an image in the back of the tracker queue. If the image is already + * in the tracker, this removes it first. */ -NS_IMETHODIMP -DiscardTracker::DiscardRunnable::Run() -{ - sDiscardRunnablePending = false; - DiscardTracker::DiscardNow(); - return NS_OK; -} - -int -DiscardTimeoutChangedCallback(const char* aPref, void *aClosure) -{ - DiscardTracker::ReloadTimeout(); - return 0; -} - nsresult -DiscardTracker::Reset(Node *node) +DiscardTracker::Reset(DiscardTrackerNode *node) { - // We shouldn't call Reset() with a null |img| pointer, on images which can't - // be discarded, or on animated images (which should be marked as - // non-discardable, anyway). - MOZ_ASSERT(node->img); - MOZ_ASSERT(node->img->CanDiscard()); - MOZ_ASSERT(!node->img->mAnim); - - // Initialize the first time through. nsresult rv; +#ifdef DEBUG + bool isSentinel = (node == &sSentinel); + + // Sanity check the node. + NS_ABORT_IF_FALSE(isSentinel || node->curr, "Node doesn't point to anything!"); + + // We should not call this function if we can't discard + NS_ABORT_IF_FALSE(isSentinel || node->curr->CanDiscard(), + "trying to reset discarding but can't discard!"); + + // As soon as an image becomes animated it is set non-discardable + NS_ABORT_IF_FALSE(isSentinel || !node->curr->mAnim, + "Trying to reset discarding on animated image!"); +#endif + + // Initialize the first time through if (NS_UNLIKELY(!sInitialized)) { rv = Initialize(); NS_ENSURE_SUCCESS(rv, rv); } - // Insert the node at the front of the list and note when it was inserted. - bool wasInList = node->isInList(); - if (wasInList) { - node->remove(); - } - node->timestamp = TimeStamp::Now(); - sDiscardableImages.insertFront(node); + // Remove the node if it's in the list. + Remove(node); - // If the node wasn't already in the list of discardable images, then we may - // need to discard some images to stay under the sMaxDecodedImageKB limit. - // Call MaybeDiscardSoon to do this check. - if (!wasInList) { - MaybeDiscardSoon(); - } + // Append it to the list. + node->prev = sTail.prev; + node->next = &sTail; + node->prev->next = sTail.prev = node; - // Make sure the timer is running. - rv = EnableTimer(); + // Make sure the timer is running + rv = TimerOn(); NS_ENSURE_SUCCESS(rv,rv); return NS_OK; } -void -DiscardTracker::Remove(Node *node) -{ - if (node->isInList()) - node->remove(); - - if (sDiscardableImages.isEmpty()) - DisableTimer(); -} - -/** - * Shut down the tracker, deallocating the timer. +/* + * Removes a node from the tracker. No-op if the node is currently untracked. */ void -DiscardTracker::Shutdown() +DiscardTracker::Remove(DiscardTrackerNode *node) { - if (sTimer) { - sTimer->Cancel(); - sTimer = NULL; + NS_ABORT_IF_FALSE(node != nsnull, "Can't pass null node"); + + // If we're not in a list, we have nothing to do. + if ((node->prev == nsnull) || (node->next == nsnull)) { + NS_ABORT_IF_FALSE(node->prev == node->next, + "Node is half in a list!"); + return; } + + // Connect around ourselves + node->prev->next = node->next; + node->next->prev = node->prev; + + // Clean up the node we removed. + node->prev = node->next = nsnull; } /* @@ -112,23 +126,31 @@ DiscardTracker::DiscardAll() if (!sInitialized) return; - sDiscardableImages.clear(); + // Remove the sentinel from the list so that the only elements in the list + // which don't track an image are the head and tail. + Remove(&sSentinel); - // The list is empty, so there's no need to leave the timer on. - DisableTimer(); + // Discard all tracked images. + for (DiscardTrackerNode *node = sHead.next; + node != &sTail; node = sHead.next) { + NS_ABORT_IF_FALSE(node->curr, "empty node!"); + Remove(node); + node->curr->Discard(); + } + + // Add the sentinel back to the (now empty) list. + Reset(&sSentinel); + + // Because the sentinel is the only element in the list, the next timer event + // would be a no-op. Disable the timer as an optimization. + TimerOff(); } -void -DiscardTracker::InformAllocation(PRUint64 bytes) +static int +DiscardTimeoutChangedCallback(const char* aPref, void *aClosure) { - // This function is called back e.g. from RasterImage::Discard(); be careful! - - sCurrentDecodedImageBytes += bytes; - MOZ_ASSERT(sCurrentDecodedImageBytes >= 0); - - // If we're using too much memory for decoded images, MaybeDiscardSoon will - // enqueue a callback to discard some images. - MaybeDiscardSoon(); + DiscardTracker::ReloadTimeout(); + return 0; } /** @@ -137,57 +159,82 @@ DiscardTracker::InformAllocation(PRUint64 bytes) nsresult DiscardTracker::Initialize() { + nsresult rv; + + // Set up the list. Head<->Sentinel<->Tail + sHead.curr = sTail.curr = sSentinel.curr = nsnull; + sHead.prev = sTail.next = nsnull; + sHead.next = sTail.prev = &sSentinel; + sSentinel.prev = &sHead; + sSentinel.next = &sTail; + // Watch the timeout pref for changes. Preferences::RegisterCallback(DiscardTimeoutChangedCallback, - sDiscardTimeoutPref); + DISCARD_TIMEOUT_PREF); - Preferences::AddUintVarCache(&sMaxDecodedImageKB, - "image.mem.max_decoded_image_kb", - 50 * 1024); - - // Create the timer. - sTimer = do_CreateInstance("@mozilla.org/timer;1"); - - // Read the timeout pref and start the timer. ReloadTimeout(); + // Create and start the timer + nsCOMPtr t = do_CreateInstance("@mozilla.org/timer;1"); + NS_ENSURE_TRUE(t, NS_ERROR_OUT_OF_MEMORY); + t.forget(&sTimer); + rv = TimerOn(); + NS_ENSURE_SUCCESS(rv, rv); + // Mark us as initialized sInitialized = true; return NS_OK; } +/** + * Shut down the tracker, deallocating the timer. + */ +void +DiscardTracker::Shutdown() +{ + if (sTimer) { + sTimer->Cancel(); + NS_RELEASE(sTimer); + sTimer = nsnull; + } +} + /** * Read the discard timeout from about:config. */ void DiscardTracker::ReloadTimeout() { - // Read the timeout pref. - PRInt32 discardTimeout; - nsresult rv = Preferences::GetInt(sDiscardTimeoutPref, &discardTimeout); + nsresult rv; - // If we got something bogus, return. + // read the timeout pref + PRInt32 discardTimeout; + rv = Preferences::GetInt(DISCARD_TIMEOUT_PREF, &discardTimeout); + + // If we got something bogus, return if (!NS_SUCCEEDED(rv) || discardTimeout <= 0) return; - // If the value didn't change, return. + // If the value didn't change, return if ((PRUint32) discardTimeout == sMinDiscardTimeoutMs) return; - // Update the value. + // Update the value sMinDiscardTimeoutMs = (PRUint32) discardTimeout; - // Restart the timer so the new timeout takes effect. - DisableTimer(); - EnableTimer(); + // If the timer's on, restart the clock to make changes take effect + if (sTimerOn) { + TimerOff(); + TimerOn(); + } } /** * Enables the timer. No-op if the timer is already running. */ nsresult -DiscardTracker::EnableTimer() +DiscardTracker::TimerOn() { // Nothing to do if the timer's already on. if (sTimerOn) @@ -205,7 +252,7 @@ DiscardTracker::EnableTimer() * Disables the timer. No-op if the timer isn't running. */ void -DiscardTracker::DisableTimer() +DiscardTracker::TimerOff() { // Nothing to do if the timer's already off. if (!sTimerOn) @@ -217,59 +264,29 @@ DiscardTracker::DisableTimer() } /** - * Routine activated when the timer fires. This discards everything that's - * older than sMinDiscardTimeoutMs, and tries to discard enough images so that - * we go under sMaxDecodedImageKB. + * Routine activated when the timer fires. This discards everything + * in front of sentinel, and resets the sentinel to the back of the + * list. */ void DiscardTracker::TimerCallback(nsITimer *aTimer, void *aClosure) { - DiscardNow(); -} + DiscardTrackerNode *node; -void -DiscardTracker::DiscardNow() -{ - // Assuming the list is ordered with oldest discard tracker nodes at the back - // and newest ones at the front, iterate from back to front discarding nodes - // until we encounter one which is new enough to keep and until we go under - // our sMaxDecodedImageKB limit. - - TimeStamp now = TimeStamp::Now(); - Node* node; - while ((node = sDiscardableImages.getLast())) { - if ((now - node->timestamp).ToMilliseconds() > sMinDiscardTimeoutMs || - sCurrentDecodedImageBytes > sMaxDecodedImageKB * 1024) { - - // Discarding the image should cause sCurrentDecodedImageBytes to - // decrease via a call to InformAllocation(). - node->img->Discard(); - - // Careful: Discarding may have caused the node to have been removed - // from the list. - Remove(node); - } - else { - break; - } + // Remove and discard everything before the sentinel + for (node = sSentinel.prev; node != &sHead; node = sSentinel.prev) { + NS_ABORT_IF_FALSE(node->curr, "empty node!"); + Remove(node); + node->curr->Discard(); } - // If the list is empty, disable the timer. - if (sDiscardableImages.isEmpty()) - DisableTimer(); -} + // Append the sentinel to the back of the list + Reset(&sSentinel); -void -DiscardTracker::MaybeDiscardSoon() -{ - // Are we carrying around too much decoded image data? If so, enqueue an - // event to try to get us down under our limit. - if (sCurrentDecodedImageBytes > sMaxDecodedImageKB * 1024 && - !sDiscardableImages.isEmpty() && !sDiscardRunnablePending) { - sDiscardRunnablePending = true; - nsRefPtr runnable = new DiscardRunnable(); - NS_DispatchToCurrentThread(runnable); - } + // If there's nothing in front of the sentinel, the next callback + // is guaranteed to be a no-op. Disable the timer as an optimization. + if (sSentinel.prev == &sHead) + TimerOff(); } } // namespace image diff --git a/image/src/DiscardTracker.h b/image/src/DiscardTracker.h index 4d6b4c94092c..c1f7b8be6f3e 100644 --- a/image/src/DiscardTracker.h +++ b/image/src/DiscardTracker.h @@ -1,113 +1,87 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bobby Holley + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ #ifndef mozilla_imagelib_DiscardTracker_h_ #define mozilla_imagelib_DiscardTracker_h_ -#include "mozilla/LinkedList.h" -#include "mozilla/TimeStamp.h" +#define DISCARD_TIMEOUT_PREF "image.mem.min_discard_timeout_ms" class nsITimer; namespace mozilla { namespace image { - class RasterImage; +// Struct to make a RasterImage insertable into the tracker list. This +// is embedded within each RasterImage object, and we do 'this->curr = this' +// on RasterImage construction. Thus, a RasterImage must always call +// DiscardTracker::Remove() in its destructor to avoid having the tracker +// point to bogus memory. +struct DiscardTrackerNode +{ + // Pointer to the RasterImage that this node tracks + RasterImage *curr; + + // Pointers to the previous and next nodes in the list + DiscardTrackerNode *prev, *next; +}; + /** - * This static class maintains a linked list of RasterImage objects which are - * eligible for discarding. - * - * When Reset() is called, the node is removed from its position in the list - * (if it was there before) and appended to the beginnings of the list. - * - * Periodically (on a timer and when we notice that we're using more memory - * than we'd like for decoded images), we go through the list and discard - * decoded data from images at the end of the list. + * This static class maintains a linked list of RasterImage nodes. When Reset() + * is called, the node is removed from its position in the list (if it was there + * before) and appended to the end. When Remove() is called, the node is removed + * from the list. The timer fires once every MIN_DISCARD_TIMEOUT_MS ms. When it + * does, it calls Discard() on each container preceding it, and then appends + * itself to the end of the list. Thus, the discard timeout varies between + * MIN_DISCARD_TIMEOUT_MS and 2*MIN_DISCARD_TIMEOUT_MS. */ class DiscardTracker { public: - /** - * The DiscardTracker keeps a linked list of Node objects. Each object - * points to a RasterImage and contains a timestamp indicating when the - * node was inserted into the tracker. - * - * This structure is embedded within each RasterImage object, and we do - * |mDiscardTrackerNode.img = this| on RasterImage construction. Thus, a - * RasterImage must always call DiscardTracker::Remove() in its destructor - * to avoid having the tracker point to bogus memory. - */ - struct Node : public LinkedListElement - { - RasterImage *img; - TimeStamp timestamp; - }; - - /** - * Add an image to the front of the tracker's list, or move it to the front - * if it's already in the list. - */ - static nsresult Reset(struct Node* node); - - /** - * Remove a node from the tracker; do nothing if the node is currently - * untracked. - */ - static void Remove(struct Node* node); - - /** - * Shut the discard tracker down. This should be called on XPCOM shutdown - * so we destroy the discard timer's nsITimer. - */ + static nsresult Reset(struct DiscardTrackerNode *node); + static void Remove(struct DiscardTrackerNode *node); static void Shutdown(); - - /** - * Discard the decoded image data for all images tracked by the discard - * tracker. - */ - static void DiscardAll(); - - /** - * Inform the discard tracker that we've allocated or deallocated some - * memory for a decoded image. We use this to determine when we've - * allocated too much memory and should discard some images. - */ - static void InformAllocation(PRUint64 bytes); - - private: - /** - * This is called when the discard timer fires; it calls into DiscardNow(). - */ - friend int DiscardTimeoutChangedCallback(const char* aPref, void *aClosure); - - /** - * When run, this runnable sets sDiscardRunnablePending to false and calls - * DiscardNow(). - */ - class DiscardRunnable : public nsRunnable - { - NS_IMETHOD Run(); - }; - - static nsresult Initialize(); static void ReloadTimeout(); - static nsresult EnableTimer(); - static void DisableTimer(); - static void MaybeDiscardSoon(); + static void DiscardAll(); + private: + static nsresult Initialize(); + static nsresult TimerOn(); + static void TimerOff(); static void TimerCallback(nsITimer *aTimer, void *aClosure); - static void DiscardNow(); - - static LinkedList sDiscardableImages; - static nsCOMPtr sTimer; - static bool sInitialized; - static bool sTimerOn; - static bool sDiscardRunnablePending; - static PRUint64 sCurrentDecodedImageBytes; - static PRUint32 sMinDiscardTimeoutMs; - static PRUint32 sMaxDecodedImageKB; }; } // namespace image diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index d7df5408b477..6f7787455803 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -214,7 +214,8 @@ RasterImage::RasterImage(imgStatusTracker* aStatusTracker) : mAnimationFinished(false) { // Set up the discard tracker node. - mDiscardTrackerNode.img = this; + mDiscardTrackerNode.curr = this; + mDiscardTrackerNode.prev = mDiscardTrackerNode.next = nsnull; Telemetry::GetHistogramById(Telemetry::IMAGE_DECODE_COUNT)->Add(0); // Statistics @@ -2181,7 +2182,8 @@ RasterImage::Discard(bool force) if (observer) observer->OnDiscard(nsnull); - DiscardTracker::Remove(&mDiscardTrackerNode); + if (force) + DiscardTracker::Remove(&mDiscardTrackerNode); // Log PR_LOG(gCompressedImageAccountingLog, PR_LOG_DEBUG, @@ -2219,7 +2221,7 @@ RasterImage::CanForciblyDiscard() { // discarding this image. Mainly for assertions. bool RasterImage::DiscardingActive() { - return mDiscardTrackerNode.isInList(); + return !!(mDiscardTrackerNode.prev || mDiscardTrackerNode.next); } // Helper method to determine if we're storing the source data in a buffer @@ -2694,18 +2696,6 @@ RasterImage::UnlockImage() return NS_OK; } -//****************************************************************************** -/* void requestDiscard() */ -NS_IMETHODIMP -RasterImage::RequestDiscard() -{ - if (CanDiscard()) { - Discard(); - } - - return NS_OK; -} - // Flushes up to aMaxBytes to the decoder. nsresult RasterImage::DecodeSomeData(PRUint32 aMaxBytes) diff --git a/image/src/RasterImage.h b/image/src/RasterImage.h index a3f9a5c41b2f..16d86344a0e6 100644 --- a/image/src/RasterImage.h +++ b/image/src/RasterImage.h @@ -198,7 +198,6 @@ public: NS_SCRIPTABLE NS_IMETHOD RequestDecode(void); NS_SCRIPTABLE NS_IMETHOD LockImage(void); NS_SCRIPTABLE NS_IMETHOD UnlockImage(void); - NS_SCRIPTABLE NS_IMETHOD RequestDiscard(void); NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void); NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime); // END NS_DECL_IMGICONTAINER @@ -635,7 +634,7 @@ private: // data // Discard members PRUint32 mLockCount; - DiscardTracker::Node mDiscardTrackerNode; + DiscardTrackerNode mDiscardTrackerNode; // Source data members FallibleTArray mSourceData; diff --git a/image/src/VectorImage.cpp b/image/src/VectorImage.cpp index 530602d1b085..f263f29d5034 100644 --- a/image/src/VectorImage.cpp +++ b/image/src/VectorImage.cpp @@ -626,15 +626,6 @@ VectorImage::UnlockImage() return NS_OK; } -//****************************************************************************** -/* void requestDiscard() */ -NS_IMETHODIMP -VectorImage::RequestDiscard() -{ - // This method is for image-discarding, which only applies to RasterImages. - return NS_OK; -} - //****************************************************************************** /* void resetAnimation (); */ NS_IMETHODIMP diff --git a/image/src/VectorImage.h b/image/src/VectorImage.h index a10a347eacc7..bd1e9b4ad497 100644 --- a/image/src/VectorImage.h +++ b/image/src/VectorImage.h @@ -81,7 +81,6 @@ public: NS_SCRIPTABLE NS_IMETHOD RequestDecode(void); NS_SCRIPTABLE NS_IMETHOD LockImage(void); NS_SCRIPTABLE NS_IMETHOD UnlockImage(void); - NS_SCRIPTABLE NS_IMETHOD RequestDiscard(void); NS_SCRIPTABLE NS_IMETHOD ResetAnimation(void); NS_IMETHOD_(void) RequestRefresh(const mozilla::TimeStamp& aTime); // END NS_DECL_IMGICONTAINER diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index 62eeed50c2f2..7946220d1684 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -37,7 +37,6 @@ * ***** END LICENSE BLOCK ***** */ #include "imgFrame.h" -#include "DiscardTracker.h" #include @@ -68,8 +67,6 @@ static PRUint32 gTotalDDBSize = 0; #endif -using namespace mozilla::image; - // Returns true if an image of aWidth x aHeight is allowed and legal. static bool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) { @@ -150,7 +147,6 @@ imgFrame::imgFrame() : , mIsDDBSurface(false) #endif , mLocked(false) - , mInformedDiscardTracker(false) { static bool hasCheckedOptimize = false; if (!hasCheckedOptimize) { @@ -170,10 +166,6 @@ imgFrame::~imgFrame() gTotalDDBSize -= mSize.width * mSize.height * 4; } #endif - - if (mInformedDiscardTracker) { - DiscardTracker::InformAllocation(-4 * mSize.height * mSize.width); - } } nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, @@ -235,14 +227,6 @@ nsresult imgFrame::Init(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, #endif } - // Inform the discard tracker that we've allocated some memory, but only if - // we're not a paletted image (paletted images are not usually large and are - // used only for animated frames, which we don't discard). - if (!mPalettedImageData) { - DiscardTracker::InformAllocation(4 * mSize.width * mSize.height); - mInformedDiscardTracker = true; - } - return NS_OK; } @@ -287,14 +271,6 @@ nsresult imgFrame::Optimize() #ifdef XP_MACOSX mQuartzSurface = nsnull; #endif - - // We just dumped most of our allocated memory, so tell the discard - // tracker that we're not using any at all. - if (mInformedDiscardTracker) { - DiscardTracker::InformAllocation(-4 * mSize.width * mSize.height); - mInformedDiscardTracker = false; - } - return NS_OK; } } diff --git a/image/src/imgFrame.h b/image/src/imgFrame.h index b4f35b544325..ce6013ad80c8 100644 --- a/image/src/imgFrame.h +++ b/image/src/imgFrame.h @@ -195,9 +195,6 @@ private: // data /** Indicates if the image data is currently locked */ bool mLocked; - /** Have we called DiscardTracker::InformAllocation()? */ - bool mInformedDiscardTracker; - #ifdef XP_WIN bool mIsDDBSurface; #endif diff --git a/image/src/imgRequestProxy.cpp b/image/src/imgRequestProxy.cpp index 32edcc9360a4..477ee29343a6 100644 --- a/image/src/imgRequestProxy.cpp +++ b/image/src/imgRequestProxy.cpp @@ -370,16 +370,6 @@ imgRequestProxy::UnlockImage() return NS_OK; } -/* void requestDiscard (); */ -NS_IMETHODIMP -imgRequestProxy::RequestDiscard() -{ - if (mImage) { - return mImage->RequestDiscard(); - } - return NS_OK; -} - NS_IMETHODIMP imgRequestProxy::IncrementAnimationConsumers() { diff --git a/image/test/mochitest/Makefile.in b/image/test/mochitest/Makefile.in index 39548c1d5a6f..e673798cdff6 100644 --- a/image/test/mochitest/Makefile.in +++ b/image/test/mochitest/Makefile.in @@ -88,7 +88,6 @@ _TEST_FILES = imgutils.js \ test_bug671906.html \ test_error_events.html \ error-early.png \ - test_drawDiscardedImage.html \ $(NULL) # Tests disabled due to intermittent orange diff --git a/image/test/mochitest/test_drawDiscardedImage.html b/image/test/mochitest/test_drawDiscardedImage.html deleted file mode 100644 index 7c99ba50461a..000000000000 --- a/image/test/mochitest/test_drawDiscardedImage.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - Test for Bug 731419 - Draw an ostensibly discarded image to a canvas - - - - - - - - - - - - - - - - - diff --git a/mfbt/LinkedList.h b/mfbt/LinkedList.h index 640a6519ee70..70244b89671c 100644 --- a/mfbt/LinkedList.h +++ b/mfbt/LinkedList.h @@ -355,18 +355,6 @@ public: return !sentinel.isInList(); } - /* - * Remove all the elements from the list. - * - * This runs in time linear to the list's length, because we have to mark - * each element as not in the list. - */ - void clear() - { - while (popFirst()) - continue; - } - /* * In a debug build, make sure that the list is sane (no cycles, consistent * next/prev pointers, only one sentinel). Has no effect in release builds. diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index b8be48c1e17d..d279ae138538 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3333,10 +3333,6 @@ pref("image.mem.max_ms_before_yield", 5); // The maximum source data size for which we auto sync decode pref("image.mem.max_bytes_for_sync_decode", 150000); -// The maximum amount of decoded image data we'll willingly keep around (we -// might keep around more than this, but we'll try to get down to this value). -pref("image.mem.max_decoded_image_kb", 50 * 1024); - // WebGL prefs pref("webgl.force-enabled", false); pref("webgl.disabled", false);