Index: chrome/browser/renderer_host/backing_store_manager.cc |
=================================================================== |
--- chrome/browser/renderer_host/backing_store_manager.cc (revision 17971) |
+++ chrome/browser/renderer_host/backing_store_manager.cc (working copy) |
@@ -7,6 +7,7 @@ |
#include "base/sys_info.h" |
#include "chrome/browser/renderer_host/backing_store.h" |
#include "chrome/browser/renderer_host/render_widget_host.h" |
+#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h" |
#include "chrome/common/chrome_constants.h" |
namespace { |
@@ -15,35 +16,59 @@ |
static BackingStoreCache* cache = NULL; |
// Returns the size of the backing store cache. |
-static int GetBackingStoreCacheSize() { |
+static size_t GetBackingStoreCacheSize() { |
// This uses a similar approach to GetMaxRendererProcessCount. The goal |
// is to reduce memory pressure and swapping on low-resource machines. |
- static const int kMaxDibCountByRamTier[] = { |
+ static const size_t kMaxDibCountByRamTier[] = { |
2, // less than 256MB |
3, // 256MB |
4, // 512MB |
5 // 768MB and above |
}; |
- static int max_size = kMaxDibCountByRamTier[ |
+ static size_t max_size = kMaxDibCountByRamTier[ |
std::min(base::SysInfo::AmountOfPhysicalMemoryMB() / 256, |
static_cast<int>(arraysize(kMaxDibCountByRamTier)) - 1)]; |
return max_size; |
} |
+// Expires the given backing store from the cache. |
+void ExpireBackingStoreAt(BackingStoreCache::iterator backing_store) { |
+ RenderWidgetHost* rwh = backing_store->second->render_widget_host(); |
+ if (rwh->painting_observer()) { |
+ rwh->painting_observer()->WidgetWillDestroyBackingStore( |
+ backing_store->first, |
+ backing_store->second); |
+ } |
+ cache->Erase(backing_store); |
+} |
+ |
// Creates the backing store for the host based on the dimensions passed in. |
// Removes the existing backing store if there is one. |
BackingStore* CreateBackingStore(RenderWidgetHost* host, |
const gfx::Size& backing_store_size) { |
+ // Remove any existing backing store in case we're replacing it. |
BackingStoreManager::RemoveBackingStore(host); |
+ size_t max_cache_size = GetBackingStoreCacheSize(); |
+ if (max_cache_size > 0 && !cache) |
+ cache = new BackingStoreCache(BackingStoreCache::NO_AUTO_EVICT); |
+ |
+ if (cache->size() >= max_cache_size) { |
+ // Need to remove an old backing store to make room for the new one. We |
+ // don't want to do this when the backing store is being replace by a new |
+ // one for the same tab, but this case won't get called then: we'll have |
+ // removed the onld one in the RemoveBackingStore above, and the cache |
+ // won't be over-sized. |
+ // |
+ // Crazy C++ alert: rbegin.base() is a forward iterator pointing to end(), |
+ // so we need to do -- to move one back to the actual last item. |
+ ExpireBackingStoreAt(--cache->rbegin().base()); |
+ } |
+ |
BackingStore* backing_store = host->AllocBackingStore(backing_store_size); |
- int backing_store_cache_size = GetBackingStoreCacheSize(); |
- if (backing_store_cache_size > 0) { |
- if (!cache) |
- cache = new BackingStoreCache(backing_store_cache_size); |
+ if (max_cache_size > 0) |
cache->Put(host, backing_store); |
- } |
return backing_store; |
} |
@@ -110,7 +135,6 @@ |
BackingStoreCache::iterator it = cache->Peek(host); |
if (it == cache->end()) |
return; |
- |
cache->Erase(it); |
if (cache->empty()) { |
@@ -118,3 +142,12 @@ |
cache = NULL; |
} |
} |
+ |
+// static |
+bool BackingStoreManager::ExpireBackingStoreForTest(RenderWidgetHost* host) { |
+ BackingStoreCache::iterator it = cache->Peek(host); |
+ if (it == cache->end()) |
+ return false; |
+ ExpireBackingStoreAt(it); |
+ return true; |
+} |