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 |