Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/discardable_memory_provider.h" | 5 #include "base/memory/discardable_memory_provider.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/containers/hash_tables.h" | 8 #include "base/containers/hash_tables.h" |
| 9 #include "base/containers/mru_cache.h" | 9 #include "base/containers/mru_cache.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 static const size_t kDefaultBytesToReclaimUnderModeratePressure = | 22 static const size_t kDefaultBytesToReclaimUnderModeratePressure = |
| 23 kDefaultDiscardableMemoryLimit / 2; | 23 kDefaultDiscardableMemoryLimit / 2; |
| 24 | 24 |
| 25 } // namespace | 25 } // namespace |
| 26 | 26 |
| 27 DiscardableMemoryProvider::DiscardableMemoryProvider() | 27 DiscardableMemoryProvider::DiscardableMemoryProvider() |
| 28 : allocations_(AllocationMap::NO_AUTO_EVICT), | 28 : allocations_(AllocationMap::NO_AUTO_EVICT), |
| 29 bytes_allocated_(0), | 29 bytes_allocated_(0), |
| 30 discardable_memory_limit_(kDefaultDiscardableMemoryLimit), | 30 discardable_memory_limit_(kDefaultDiscardableMemoryLimit), |
| 31 bytes_to_reclaim_under_moderate_pressure_( | 31 bytes_to_reclaim_under_moderate_pressure_( |
| 32 kDefaultBytesToReclaimUnderModeratePressure), | 32 kDefaultBytesToReclaimUnderModeratePressure) { |
| 33 memory_pressure_listener_( | |
| 34 base::Bind(&DiscardableMemoryProvider::NotifyMemoryPressure, | |
| 35 Unretained(this))) { | |
| 36 } | 33 } |
| 37 | 34 |
| 38 DiscardableMemoryProvider::~DiscardableMemoryProvider() { | 35 DiscardableMemoryProvider::~DiscardableMemoryProvider() { |
| 39 DCHECK(allocations_.empty()); | 36 DCHECK(allocations_.empty()); |
| 40 DCHECK_EQ(0u, bytes_allocated_); | 37 DCHECK_EQ(0u, bytes_allocated_); |
| 41 } | 38 } |
| 42 | 39 |
| 43 void DiscardableMemoryProvider::NotifyMemoryPressure( | 40 void DiscardableMemoryProvider::RegisterMemoryPressureListener() { |
| 44 MemoryPressureListener::MemoryPressureLevel pressure_level) { | 41 AutoLock lock(lock_); |
| 45 switch (pressure_level) { | 42 DCHECK(base::MessageLoop::current()); |
| 46 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: | 43 DCHECK(!memory_pressure_listener_); |
| 47 Purge(); | 44 memory_pressure_listener_.reset( |
| 48 return; | 45 new MemoryPressureListener( |
| 49 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: | 46 base::Bind(&DiscardableMemoryProvider::OnMemoryPressure, |
| 50 PurgeAll(); | 47 Unretained(this)))); |
| 51 return; | 48 } |
| 52 } | |
| 53 | 49 |
| 54 NOTREACHED(); | 50 void DiscardableMemoryProvider::UnregisterMemoryPressureListener() { |
| 51 AutoLock lock(lock_); | |
| 52 DCHECK(memory_pressure_listener_); | |
| 53 memory_pressure_listener_.reset(); | |
| 55 } | 54 } |
| 56 | 55 |
| 57 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { | 56 void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) { |
| 58 AutoLock lock(lock_); | 57 AutoLock lock(lock_); |
| 59 discardable_memory_limit_ = bytes; | 58 discardable_memory_limit_ = bytes; |
| 60 EnforcePolicyWithLockAcquired(); | 59 EnforcePolicyWithLockAcquired(); |
| 61 } | 60 } |
| 62 | 61 |
| 63 void DiscardableMemoryProvider::SetBytesToReclaimUnderModeratePressure( | 62 void DiscardableMemoryProvider::SetBytesToReclaimUnderModeratePressure( |
| 64 size_t bytes) { | 63 size_t bytes) { |
| 65 AutoLock lock(lock_); | 64 AutoLock lock(lock_); |
| 66 bytes_to_reclaim_under_moderate_pressure_ = bytes; | 65 bytes_to_reclaim_under_moderate_pressure_ = bytes; |
| 67 } | 66 } |
| 68 | 67 |
| 69 void DiscardableMemoryProvider::Register( | 68 void DiscardableMemoryProvider::Register( |
| 70 const DiscardableMemory* discardable, size_t bytes) { | 69 const DiscardableMemory* discardable, size_t bytes) { |
| 71 AutoLock lock(lock_); | 70 AutoLock lock(lock_); |
| 71 // A registered memory listener is currently required. This DCHECK can be | |
| 72 // moved or removed if we decide that it's useful to relax this condition. | |
| 73 // TODO(reveman): Enable this DCHECK when skia and blink are able to | |
| 74 // register memory pressure listeners. crbug.com/333907 | |
| 75 // DCHECK(memory_pressure_listener_); | |
|
reveman
2014/01/13 18:22:28
Disabled this DCHECK for now as it's causing webki
| |
| 72 DCHECK(allocations_.Peek(discardable) == allocations_.end()); | 76 DCHECK(allocations_.Peek(discardable) == allocations_.end()); |
| 73 allocations_.Put(discardable, Allocation(bytes)); | 77 allocations_.Put(discardable, Allocation(bytes)); |
| 74 } | 78 } |
| 75 | 79 |
| 76 void DiscardableMemoryProvider::Unregister( | 80 void DiscardableMemoryProvider::Unregister( |
| 77 const DiscardableMemory* discardable) { | 81 const DiscardableMemory* discardable) { |
| 78 AutoLock lock(lock_); | 82 AutoLock lock(lock_); |
| 79 AllocationMap::iterator it = allocations_.Peek(discardable); | 83 AllocationMap::iterator it = allocations_.Peek(discardable); |
| 80 if (it == allocations_.end()) | 84 if (it == allocations_.end()) |
| 81 return; | 85 return; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 AutoLock lock(lock_); | 166 AutoLock lock(lock_); |
| 163 AllocationMap::const_iterator it = allocations_.Peek(discardable); | 167 AllocationMap::const_iterator it = allocations_.Peek(discardable); |
| 164 return it != allocations_.end() && it->second.memory; | 168 return it != allocations_.end() && it->second.memory; |
| 165 } | 169 } |
| 166 | 170 |
| 167 size_t DiscardableMemoryProvider::GetBytesAllocatedForTest() const { | 171 size_t DiscardableMemoryProvider::GetBytesAllocatedForTest() const { |
| 168 AutoLock lock(lock_); | 172 AutoLock lock(lock_); |
| 169 return bytes_allocated_; | 173 return bytes_allocated_; |
| 170 } | 174 } |
| 171 | 175 |
| 176 void DiscardableMemoryProvider::OnMemoryPressure( | |
| 177 MemoryPressureListener::MemoryPressureLevel pressure_level) { | |
| 178 switch (pressure_level) { | |
| 179 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: | |
| 180 Purge(); | |
| 181 return; | |
| 182 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: | |
| 183 PurgeAll(); | |
| 184 return; | |
| 185 } | |
| 186 | |
| 187 NOTREACHED(); | |
| 188 } | |
| 189 | |
| 172 void DiscardableMemoryProvider::Purge() { | 190 void DiscardableMemoryProvider::Purge() { |
| 173 AutoLock lock(lock_); | 191 AutoLock lock(lock_); |
| 174 | 192 |
| 175 if (bytes_to_reclaim_under_moderate_pressure_ == 0) | 193 if (bytes_to_reclaim_under_moderate_pressure_ == 0) |
| 176 return; | 194 return; |
| 177 | 195 |
| 178 size_t limit = 0; | 196 size_t limit = 0; |
| 179 if (bytes_to_reclaim_under_moderate_pressure_ < bytes_allocated_) | 197 if (bytes_to_reclaim_under_moderate_pressure_ < bytes_allocated_) |
| 180 limit = bytes_allocated_ - bytes_to_reclaim_under_moderate_pressure_; | 198 limit = bytes_allocated_ - bytes_to_reclaim_under_moderate_pressure_; |
| 181 | 199 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 206 it->second.memory = NULL; | 224 it->second.memory = NULL; |
| 207 } | 225 } |
| 208 } | 226 } |
| 209 | 227 |
| 210 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { | 228 void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() { |
| 211 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); | 229 PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_); |
| 212 } | 230 } |
| 213 | 231 |
| 214 } // namespace internal | 232 } // namespace internal |
| 215 } // namespace base | 233 } // namespace base |
| OLD | NEW |