summaryrefslogtreecommitdiffstats
path: root/base/memory/discardable_memory_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/memory/discardable_memory_manager.cc')
-rw-r--r--base/memory/discardable_memory_manager.cc148
1 files changed, 66 insertions, 82 deletions
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc
index 87d3270..1dff3e4d 100644
--- a/base/memory/discardable_memory_manager.cc
+++ b/base/memory/discardable_memory_manager.cc
@@ -9,25 +9,23 @@
#include "base/containers/mru_cache.h"
#include "base/debug/trace_event.h"
#include "base/synchronization/lock.h"
-#include "base/sys_info.h"
namespace base {
namespace internal {
-
namespace {
// This is admittedly pretty magical. It's approximately enough memory for four
// 2560x1600 images.
-static const size_t kDefaultDiscardableMemoryLimit = 64 * 1024 * 1024;
+static const size_t kDefaultMemoryLimit = 64 * 1024 * 1024;
static const size_t kDefaultBytesToKeepUnderModeratePressure =
- kDefaultDiscardableMemoryLimit / 4;
+ kDefaultMemoryLimit / 4;
} // namespace
DiscardableMemoryManager::DiscardableMemoryManager()
: allocations_(AllocationMap::NO_AUTO_EVICT),
bytes_allocated_(0),
- discardable_memory_limit_(kDefaultDiscardableMemoryLimit),
+ memory_limit_(kDefaultMemoryLimit),
bytes_to_keep_under_moderate_pressure_(
kDefaultBytesToKeepUnderModeratePressure) {
BytesAllocatedChanged();
@@ -42,10 +40,8 @@ void DiscardableMemoryManager::RegisterMemoryPressureListener() {
AutoLock lock(lock_);
DCHECK(base::MessageLoop::current());
DCHECK(!memory_pressure_listener_);
- memory_pressure_listener_.reset(
- new MemoryPressureListener(
- base::Bind(&DiscardableMemoryManager::OnMemoryPressure,
- Unretained(this))));
+ memory_pressure_listener_.reset(new MemoryPressureListener(base::Bind(
+ &DiscardableMemoryManager::OnMemoryPressure, Unretained(this))));
}
void DiscardableMemoryManager::UnregisterMemoryPressureListener() {
@@ -54,9 +50,9 @@ void DiscardableMemoryManager::UnregisterMemoryPressureListener() {
memory_pressure_listener_.reset();
}
-void DiscardableMemoryManager::SetDiscardableMemoryLimit(size_t bytes) {
+void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) {
AutoLock lock(lock_);
- discardable_memory_limit_ = bytes;
+ memory_limit_ = bytes;
EnforcePolicyWithLockAcquired();
}
@@ -66,90 +62,77 @@ void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure(
bytes_to_keep_under_moderate_pressure_ = bytes;
}
-void DiscardableMemoryManager::Register(
- const DiscardableMemory* discardable, size_t bytes) {
+void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) {
AutoLock lock(lock_);
// A registered memory listener is currently required. This DCHECK can be
// moved or removed if we decide that it's useful to relax this condition.
// TODO(reveman): Enable this DCHECK when skia and blink are able to
// register memory pressure listeners. crbug.com/333907
// DCHECK(memory_pressure_listener_);
- DCHECK(allocations_.Peek(discardable) == allocations_.end());
- allocations_.Put(discardable, Allocation(bytes));
+ DCHECK(allocations_.Peek(allocation) == allocations_.end());
+ allocations_.Put(allocation, AllocationInfo(bytes));
}
-void DiscardableMemoryManager::Unregister(
- const DiscardableMemory* discardable) {
+void DiscardableMemoryManager::Unregister(Allocation* allocation) {
AutoLock lock(lock_);
- AllocationMap::iterator it = allocations_.Peek(discardable);
- if (it == allocations_.end())
- return;
-
- if (it->second.memory) {
- size_t bytes = it->second.bytes;
- DCHECK_LE(bytes, bytes_allocated_);
- bytes_allocated_ -= bytes;
+ AllocationMap::iterator it = allocations_.Peek(allocation);
+ DCHECK(it != allocations_.end());
+ const AllocationInfo& info = it->second;
+
+ if (info.purgable) {
+ size_t bytes_purgable = info.bytes;
+ DCHECK_LE(bytes_purgable, bytes_allocated_);
+ bytes_allocated_ -= bytes_purgable;
BytesAllocatedChanged();
- free(it->second.memory);
}
allocations_.Erase(it);
}
-scoped_ptr<uint8, FreeDeleter> DiscardableMemoryManager::Acquire(
- const DiscardableMemory* discardable,
- bool* purged) {
+bool DiscardableMemoryManager::AcquireLock(Allocation* allocation,
+ bool* purged) {
AutoLock lock(lock_);
- // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
+ // Note: |allocations_| is an MRU cache, and use of |Get| here updates that
// cache.
- AllocationMap::iterator it = allocations_.Get(discardable);
- CHECK(it != allocations_.end());
-
- if (it->second.memory) {
- scoped_ptr<uint8, FreeDeleter> memory(it->second.memory);
- it->second.memory = NULL;
- *purged = false;
- return memory.Pass();
- }
+ AllocationMap::iterator it = allocations_.Get(allocation);
+ DCHECK(it != allocations_.end());
+ AllocationInfo* info = &it->second;
+
+ if (!info->bytes)
+ return false;
- size_t bytes = it->second.bytes;
- if (!bytes)
- return scoped_ptr<uint8, FreeDeleter>();
+ size_t bytes_required = info->purgable ? 0u : info->bytes;
- if (discardable_memory_limit_) {
+ if (memory_limit_) {
size_t limit = 0;
- if (bytes < discardable_memory_limit_)
- limit = discardable_memory_limit_ - bytes;
+ if (bytes_required < memory_limit_)
+ limit = memory_limit_ - bytes_required;
PurgeLRUWithLockAcquiredUntilUsageIsWithin(limit);
}
// Check for overflow.
- if (std::numeric_limits<size_t>::max() - bytes < bytes_allocated_)
- return scoped_ptr<uint8, FreeDeleter>();
-
- scoped_ptr<uint8, FreeDeleter> memory(static_cast<uint8*>(malloc(bytes)));
- if (!memory)
- return scoped_ptr<uint8, FreeDeleter>();
-
- bytes_allocated_ += bytes;
- BytesAllocatedChanged();
+ if (std::numeric_limits<size_t>::max() - bytes_required < bytes_allocated_)
+ return false;
- *purged = true;
- return memory.Pass();
+ *purged = !allocation->AllocateAndAcquireLock(info->bytes);
+ info->purgable = false;
+ if (bytes_required) {
+ bytes_allocated_ += bytes_required;
+ BytesAllocatedChanged();
+ }
+ return true;
}
-void DiscardableMemoryManager::Release(
- const DiscardableMemory* discardable,
- scoped_ptr<uint8, FreeDeleter> memory) {
+void DiscardableMemoryManager::ReleaseLock(Allocation* allocation) {
AutoLock lock(lock_);
- // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
+ // Note: |allocations_| is an MRU cache, and use of |Get| here updates that
// cache.
- AllocationMap::iterator it = allocations_.Get(discardable);
- CHECK(it != allocations_.end());
-
- DCHECK(!it->second.memory);
- it->second.memory = memory.release();
+ AllocationMap::iterator it = allocations_.Get(allocation);
+ DCHECK(it != allocations_.end());
+ AllocationInfo* info = &it->second;
+ allocation->ReleaseLock();
+ info->purgable = true;
EnforcePolicyWithLockAcquired();
}
@@ -159,17 +142,17 @@ void DiscardableMemoryManager::PurgeAll() {
}
bool DiscardableMemoryManager::IsRegisteredForTest(
- const DiscardableMemory* discardable) const {
+ Allocation* allocation) const {
AutoLock lock(lock_);
- AllocationMap::const_iterator it = allocations_.Peek(discardable);
+ AllocationMap::const_iterator it = allocations_.Peek(allocation);
return it != allocations_.end();
}
bool DiscardableMemoryManager::CanBePurgedForTest(
- const DiscardableMemory* discardable) const {
+ Allocation* allocation) const {
AutoLock lock(lock_);
- AllocationMap::const_iterator it = allocations_.Peek(discardable);
- return it != allocations_.end() && it->second.memory;
+ AllocationMap::const_iterator it = allocations_.Peek(allocation);
+ return it != allocations_.end() && it->second.purgable;
}
size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
@@ -203,7 +186,8 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
TRACE_EVENT1(
"base",
"DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin",
- "limit", limit);
+ "limit",
+ limit);
lock_.AssertAcquired();
@@ -211,16 +195,19 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
for (AllocationMap::reverse_iterator it = allocations_.rbegin();
it != allocations_.rend();
++it) {
+ Allocation* allocation = it->first;
+ AllocationInfo* info = &it->second;
+
if (bytes_allocated_ <= limit)
break;
- if (!it->second.memory)
+ if (!info->purgable)
continue;
- size_t bytes = it->second.bytes;
- DCHECK_LE(bytes, bytes_allocated_);
- bytes_allocated_ -= bytes;
- free(it->second.memory);
- it->second.memory = NULL;
+ size_t bytes_purgable = info->bytes;
+ DCHECK_LE(bytes_purgable, bytes_allocated_);
+ bytes_allocated_ -= bytes_purgable;
+ info->purgable = false;
+ allocation->Purge();
}
if (bytes_allocated_ != bytes_allocated_before_purging)
@@ -228,14 +215,11 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
}
void DiscardableMemoryManager::EnforcePolicyWithLockAcquired() {
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_);
+ PurgeLRUWithLockAcquiredUntilUsageIsWithin(memory_limit_);
}
void DiscardableMemoryManager::BytesAllocatedChanged() const {
- TRACE_COUNTER_ID1("base",
- "DiscardableMemoryUsage",
- this,
- bytes_allocated_);
+ TRACE_COUNTER_ID1("base", "DiscardableMemoryUsage", this, bytes_allocated_);
}
} // namespace internal