| Index: chrome/browser/renderer_host/backing_store_manager.cc
 | 
| diff --git a/chrome/browser/renderer_host/backing_store_manager.cc b/chrome/browser/renderer_host/backing_store_manager.cc
 | 
| index 3ff2e76b5ddebe1bdfeb171a0bdb9b3eacb4b59c..7b16a43464cc9264dceb817c2ebe787a807e6a17 100644
 | 
| --- a/chrome/browser/renderer_host/backing_store_manager.cc
 | 
| +++ b/chrome/browser/renderer_host/backing_store_manager.cc
 | 
| @@ -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 @@ typedef OwningMRUCache<RenderWidgetHost*, BackingStore*> BackingStoreCache;
 | 
|  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 @@ void BackingStoreManager::RemoveBackingStore(RenderWidgetHost* host) {
 | 
|    BackingStoreCache::iterator it = cache->Peek(host);
 | 
|    if (it == cache->end())
 | 
|      return;
 | 
| -
 | 
|    cache->Erase(it);
 | 
|  
 | 
|    if (cache->empty()) {
 | 
| @@ -118,3 +142,12 @@ void BackingStoreManager::RemoveBackingStore(RenderWidgetHost* host) {
 | 
|      cache = NULL;
 | 
|    }
 | 
|  }
 | 
| +
 | 
| +// static
 | 
| +bool BackingStoreManager::ExpireBackingStoreForTest(RenderWidgetHost* host) {
 | 
| +  BackingStoreCache::iterator it = cache->Peek(host);
 | 
| +  if (it == cache->end())
 | 
| +    return false;
 | 
| +  ExpireBackingStoreAt(it);
 | 
| +  return true;
 | 
| +}
 | 
| 
 |