| Index: content/child/child_discardable_shared_memory_manager.cc
|
| diff --git a/content/child/child_discardable_shared_memory_manager.cc b/content/child/child_discardable_shared_memory_manager.cc
|
| index cf4e488dcba6f12cf21cf7f70a1b0a0f821a65e6..bfe2ef9bee301af6a06e3298f611b94c045719b6 100644
|
| --- a/content/child/child_discardable_shared_memory_manager.cc
|
| +++ b/content/child/child_discardable_shared_memory_manager.cc
|
| @@ -52,12 +52,14 @@ class DiscardableMemoryShmemChunkImpl
|
|
|
| ChildDiscardableSharedMemoryManager::ChildDiscardableSharedMemoryManager(
|
| ThreadSafeSender* sender)
|
| - : heap_(base::GetPageSize()), sender_(sender), bytes_allocated_(0) {
|
| + : heap_(base::GetPageSize()), sender_(sender) {
|
| }
|
|
|
| ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() {
|
| - if (bytes_allocated_)
|
| - BytesAllocatedChanged(0);
|
| + // TODO(reveman): Determine if this DCHECK can be enabled. crbug.com/430533
|
| + // DCHECK_EQ(heap_.GetSize(), heap_.GetFreeListSize());
|
| + if (heap_.GetSize())
|
| + MemoryUsageChanged(0, 0);
|
| }
|
|
|
| scoped_ptr<base::DiscardableMemoryShmemChunk>
|
| @@ -76,6 +78,7 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
|
| // Round up to multiple of page size.
|
| size_t pages = (size + base::GetPageSize() - 1) / base::GetPageSize();
|
|
|
| + size_t heap_size_prior_to_releasing_purged_memory = heap_.GetSize();
|
| for (;;) {
|
| // Search free list for available space.
|
| scoped_ptr<DiscardableSharedMemoryHeap::Span> free_span =
|
| @@ -91,28 +94,27 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
|
| free_span->length() * base::GetPageSize()) ==
|
| base::DiscardableSharedMemory::FAILED) {
|
| DCHECK(!free_span->shared_memory()->IsMemoryResident());
|
| - // We have to release free memory before |free_span| can be destroyed.
|
| - size_t bytes_released = heap_.ReleaseFreeMemory();
|
| - DCHECK_NE(bytes_released, 0u);
|
| - DCHECK_LE(bytes_released, bytes_allocated_);
|
| - bytes_allocated_ -= bytes_released;
|
| - BytesAllocatedChanged(bytes_allocated_);
|
| + // We have to release purged memory before |free_span| can be destroyed.
|
| + heap_.ReleasePurgedMemory();
|
| DCHECK(!free_span->shared_memory());
|
| continue;
|
| }
|
|
|
| + // Memory usage is guaranteed to have changed after having removed
|
| + // at least one span from the free list.
|
| + MemoryUsageChanged(heap_.GetSize(), heap_.GetFreeListSize());
|
| +
|
| return make_scoped_ptr(
|
| new DiscardableMemoryShmemChunkImpl(this, free_span.Pass()));
|
| }
|
|
|
| - // Release free memory and free up the address space. Failing to do this
|
| - // can result in the child process running out of address space.
|
| - size_t bytes_released = heap_.ReleaseFreeMemory();
|
| - if (bytes_released) {
|
| - DCHECK_LE(bytes_released, bytes_allocated_);
|
| - bytes_allocated_ -= bytes_released;
|
| - BytesAllocatedChanged(bytes_allocated_);
|
| - }
|
| + // Release purged memory to free up the address space before we attempt to
|
| + // allocate more memory.
|
| + heap_.ReleasePurgedMemory();
|
| +
|
| + // Make sure crash keys are up to date in case allocation fails.
|
| + if (heap_.GetSize() != heap_size_prior_to_releasing_purged_memory)
|
| + MemoryUsageChanged(heap_.GetSize(), heap_.GetFreeListSize());
|
|
|
| size_t pages_to_allocate =
|
| std::max(kAllocationSize / base::GetPageSize(), pages);
|
| @@ -122,11 +124,6 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
|
| scoped_ptr<base::DiscardableSharedMemory> shared_memory(
|
| AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes));
|
|
|
| - // Note: use mapped size rather than |allocation_size_in_bytes| as
|
| - // the latter only represent the amount of memory available for usage.
|
| - bytes_allocated_ += shared_memory->mapped_size();
|
| - BytesAllocatedChanged(bytes_allocated_);
|
| -
|
| // Create span for allocated memory.
|
| scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(
|
| heap_.Grow(shared_memory.Pass(), allocation_size_in_bytes));
|
| @@ -142,6 +139,8 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
|
| heap_.MergeIntoFreeList(leftover.Pass());
|
| }
|
|
|
| + MemoryUsageChanged(heap_.GetSize(), heap_.GetFreeListSize());
|
| +
|
| return make_scoped_ptr(
|
| new DiscardableMemoryShmemChunkImpl(this, new_span.Pass()));
|
| }
|
| @@ -149,12 +148,14 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
|
| void ChildDiscardableSharedMemoryManager::ReleaseFreeMemory() {
|
| base::AutoLock lock(lock_);
|
|
|
| - size_t bytes_released = heap_.ReleaseFreeMemory();
|
| - if (bytes_released) {
|
| - DCHECK_LE(bytes_released, bytes_allocated_);
|
| - bytes_allocated_ -= bytes_released;
|
| - BytesAllocatedChanged(bytes_allocated_);
|
| - }
|
| + size_t heap_size_prior_to_releasing_memory = heap_.GetSize();
|
| +
|
| + // Release both purged and free memory.
|
| + heap_.ReleasePurgedMemory();
|
| + heap_.ReleaseFreeMemory();
|
| +
|
| + if (heap_.GetSize() != heap_size_prior_to_releasing_memory)
|
| + MemoryUsageChanged(heap_.GetSize(), heap_.GetFreeListSize());
|
| }
|
|
|
| bool ChildDiscardableSharedMemoryManager::LockSpan(
|
| @@ -208,6 +209,9 @@ void ChildDiscardableSharedMemoryManager::ReleaseSpan(
|
| span->shared_memory()->Purge(base::Time::Now());
|
|
|
| heap_.MergeIntoFreeList(span.Pass());
|
| +
|
| + // Bytes of free memory changed.
|
| + MemoryUsageChanged(heap_.GetSize(), heap_.GetFreeListSize());
|
| }
|
|
|
| scoped_ptr<base::DiscardableSharedMemory>
|
| @@ -230,14 +234,19 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
|
| return memory.Pass();
|
| }
|
|
|
| -void ChildDiscardableSharedMemoryManager::BytesAllocatedChanged(
|
| - size_t new_bytes_allocated) const {
|
| - TRACE_COUNTER_ID1("renderer", "DiscardableMemoryUsage", this,
|
| - new_bytes_allocated);
|
| +void ChildDiscardableSharedMemoryManager::MemoryUsageChanged(
|
| + size_t new_bytes_total,
|
| + size_t new_bytes_free) const {
|
| + TRACE_COUNTER2("renderer", "DiscardableMemoryUsage", "allocated",
|
| + new_bytes_total - new_bytes_free, "free", new_bytes_free);
|
|
|
| static const char kDiscardableMemoryUsageKey[] = "dm-usage";
|
| base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey,
|
| - base::Uint64ToString(new_bytes_allocated));
|
| + base::Uint64ToString(new_bytes_total));
|
| +
|
| + static const char kDiscardableMemoryUsageFreeKey[] = "dm-usage-free";
|
| + base::debug::SetCrashKeyValue(kDiscardableMemoryUsageFreeKey,
|
| + base::Uint64ToString(new_bytes_free));
|
| }
|
|
|
| } // namespace content
|
|
|