Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1043)

Unified Diff: content/common/discardable_shared_memory_heap.cc

Issue 807303002: base: Add free list implementation to browser-wide discardable memory system. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@discardable-shared-memory-ashmem
Patch Set: rebase Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/common/discardable_shared_memory_heap.cc
diff --git a/content/common/discardable_shared_memory_heap.cc b/content/common/discardable_shared_memory_heap.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2e28da35d9715119961ebf3dd1526df58631b655
--- /dev/null
+++ b/content/common/discardable_shared_memory_heap.cc
@@ -0,0 +1,169 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/discardable_shared_memory_heap.h"
+
+#include "base/memory/discardable_shared_memory.h"
+
+namespace content {
+namespace {
+
+bool IsPowerOfTwo(size_t x) {
+ return (x & (x - 1)) == 0;
+}
+
+bool IsInFreeList(DiscardableSharedMemoryHeap::Span* span) {
+ return span->previous() || span->next();
+}
+
+} // namespace
+
+DiscardableSharedMemoryHeap::Span::Span(
+ linked_ptr<base::DiscardableSharedMemory> shared_memory,
+ size_t start,
+ size_t length)
+ : shared_memory_(shared_memory), start_(start), length_(length) {
+}
+
+DiscardableSharedMemoryHeap::Span::~Span() {
+}
+
+DiscardableSharedMemoryHeap::DiscardableSharedMemoryHeap(size_t block_size)
+ : block_size_(block_size) {
+ DCHECK_NE(block_size_, 0u);
+ DCHECK(IsPowerOfTwo(block_size_));
+}
+
+DiscardableSharedMemoryHeap::~DiscardableSharedMemoryHeap() {
+ while (!free_spans_.empty())
+ RemoveFromFreeList(free_spans_.tail()->value());
+}
+
+scoped_ptr<DiscardableSharedMemoryHeap::Span> DiscardableSharedMemoryHeap::Grow(
+ scoped_ptr<base::DiscardableSharedMemory> memory,
+ size_t size) {
+ linked_ptr<base::DiscardableSharedMemory> shared_memory(memory.release());
+
+ // Memory must be aligned to block size.
+ DCHECK_EQ(
+ reinterpret_cast<size_t>(shared_memory->memory()) & (block_size_ - 1),
+ 0u);
+ DCHECK_EQ(size & (block_size_ - 1), 0u);
+
+ scoped_ptr<Span> span(
+ new Span(shared_memory,
+ reinterpret_cast<size_t>(shared_memory->memory()) / block_size_,
+ size / block_size_));
+ RegisterSpan(span.get());
+ return span.Pass();
+}
+
+void DiscardableSharedMemoryHeap::MergeIntoFreeList(scoped_ptr<Span> span) {
+ // Merge with previous span if possible.
+ SpanMap::iterator prev_it = spans_.find(span->start_ - 1);
+ if (prev_it != spans_.end() && IsInFreeList(prev_it->second)) {
+ scoped_ptr<Span> prev = RemoveFromFreeList(prev_it->second);
+ DCHECK_EQ(prev->start_ + prev->length_, span->start_);
+ span->start_ -= prev->length_;
+ span->length_ += prev->length_;
+ spans_[span->start_] = span.get();
+ }
+
+ // Merge with next span if possible.
+ SpanMap::iterator next_it = spans_.find(span->start_ + span->length_);
+ if (next_it != spans_.end() && IsInFreeList(next_it->second)) {
+ scoped_ptr<Span> next = RemoveFromFreeList(next_it->second);
+ DCHECK_EQ(next->start_, span->start_ + span->length_);
+ span->length_ += next->length_;
+ spans_[span->start_ + span->length_ - 1] = span.get();
+ }
+
+ free_spans_.Append(span.release());
+}
+
+scoped_ptr<DiscardableSharedMemoryHeap::Span>
+DiscardableSharedMemoryHeap::Split(Span* span, size_t blocks) {
+ DCHECK(blocks);
+ DCHECK_LT(blocks, span->length_);
+
+ scoped_ptr<Span> leftover(new Span(
+ span->shared_memory_, span->start_ + blocks, span->length_ - blocks));
+ RegisterSpan(leftover.get());
+ spans_[span->start_ + blocks - 1] = span;
+ span->length_ = blocks;
+ return leftover.Pass();
+}
+
+scoped_ptr<DiscardableSharedMemoryHeap::Span>
+DiscardableSharedMemoryHeap::SearchFreeList(size_t blocks) {
+ DCHECK(blocks);
+
+ // Search through list to find best span.
+ Span* best = NULL;
Avi (use Gerrit) 2014/12/18 20:49:06 nullptr
reveman 2014/12/18 21:30:44 Done.
+
+ // This implements address-ordered best-fit.
+ for (Span* span = free_spans_.head()->value(); span != free_spans_.end();
+ span = span->next()->value()) {
+ // Skip span if it's not large enough.
+ if (span->length_ < blocks)
+ continue;
+
+ if (best) {
+ // Skip span if |best| is a better fit.
+ if (span->length_ > best->length_)
+ continue;
+
+ // Skip span if |best| starts at a lower address.
+ if ((span->length_ == best->length_) && (span->start_ > best->start_))
+ continue;
+ }
+
+ best = span;
+ }
+
+ return best ? Carve(best, blocks) : scoped_ptr<Span>();
+}
+
+void DiscardableSharedMemoryHeap::DeleteSpan(scoped_ptr<Span> span) {
+ DCHECK(!IsInFreeList(span.get()));
+ spans_.erase(span->start_);
+ if (span->length_ > 1)
+ spans_.erase(span->start_ + span->length_ - 1);
+}
+
+scoped_ptr<DiscardableSharedMemoryHeap::Span>
+DiscardableSharedMemoryHeap::RemoveFromFreeList(Span* span) {
+ span->RemoveFromList();
+ return make_scoped_ptr(span);
+}
+
+scoped_ptr<DiscardableSharedMemoryHeap::Span>
+DiscardableSharedMemoryHeap::Carve(Span* span, size_t blocks) {
+ scoped_ptr<Span> serving = RemoveFromFreeList(span);
+
+ const int extra = serving->length_ - blocks;
+ if (extra) {
+ scoped_ptr<Span> leftover(
+ new Span(serving->shared_memory_, serving->start_ + blocks, extra));
+ RegisterSpan(leftover.get());
+
+ // No need to coalesced as the previous span of |leftover| was just split
Avi (use Gerrit) 2014/12/18 20:49:06 s/coalesced/coalesce/
reveman 2014/12/18 21:30:44 Done.
+ // and the next span of |leftover| was not previously coalesced with
+ // |span|.
+ free_spans_.Append(leftover.release());
+
+ serving->length_ = blocks;
+ spans_[serving->start_ + blocks - 1] = serving.get();
+ }
+
+ return serving.Pass();
+}
+
+void DiscardableSharedMemoryHeap::RegisterSpan(Span* span) {
+ spans_[span->start_] = span;
+ if (span->length_ > 1)
+ spans_[span->start_ + span->length_ - 1] = span;
+}
+
+} // namespace content
« no previous file with comments | « content/common/discardable_shared_memory_heap.h ('k') | content/common/discardable_shared_memory_heap_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698