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

Unified Diff: cc/base/contiguous_container.cc

Issue 2119033003: Fix alignment issue of ContiguousContainer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 4 years, 5 months 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: cc/base/contiguous_container.cc
diff --git a/cc/base/contiguous_container.cc b/cc/base/contiguous_container.cc
index d6280b43290b8d4d9547f56a1a62b070caf63e66..92b61c42e7854b0e3c46f41bdf5242b0a1492319 100644
--- a/cc/base/contiguous_container.cc
+++ b/cc/base/contiguous_container.cc
@@ -10,9 +10,23 @@
namespace cc {
+namespace {
+
// Default number of max-sized elements to allocate space for, if there is no
// initial buffer.
-static const unsigned kDefaultInitialBufferSize = 32;
+const unsigned kDefaultInitialBufferSize = 32;
+
+inline char* AlignAddress(char* address, unsigned log2_alignment) {
+ char* aligned = reinterpret_cast<char*>(
+ (((reinterpret_cast<size_t>(address) - 1) >> log2_alignment) + 1)
+ << log2_alignment);
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(aligned) % (1 << log2_alignment));
+ DCHECK(aligned >= address);
+ DCHECK(aligned < address + (1 << log2_alignment));
+ return aligned;
+}
+
+} // namespace
class ContiguousContainerBase::Buffer {
public:
@@ -26,17 +40,28 @@ class ContiguousContainerBase::Buffer {
size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); }
bool empty() const { return UsedCapacity() == 0; }
- void* Allocate(size_t object_size) {
- DCHECK_GE(UnusedCapacity(), object_size);
- void* result = end_;
- end_ += object_size;
- return result;
+ void* Allocate(size_t object_size, unsigned log2_alignment) {
+ char* aligned_address;
+ if (empty()) {
+ // begin()'s alignment must be suitable for all possible types.
+ DCHECK_EQ(begin(), AlignAddress(begin(), log2_alignment));
+ DCHECK(object_size <= capacity_);
+ aligned_address = begin();
+ } else {
+ aligned_address = AlignAddress(end_, log2_alignment);
+ if (aligned_address - begin() + object_size > capacity_)
+ return nullptr;
+ }
+ end_ = aligned_address + object_size;
+ return aligned_address;
}
void DeallocateLastObject(void* object) {
DCHECK_LE(begin(), object);
DCHECK_LT(object, end_);
end_ = static_cast<char*>(object);
+ // We may leave a gap between the end of the previous object (which we
+ // don't know) and end_ because of alignment of the deallocated object.
}
private:
@@ -80,26 +105,25 @@ size_t ContiguousContainerBase::MemoryUsageInBytes() const {
elements_.capacity() * sizeof(elements_[0]);
}
-void* ContiguousContainerBase::Allocate(size_t object_size) {
+void* ContiguousContainerBase::Allocate(size_t object_size,
+ unsigned log2_alignment) {
DCHECK_LE(object_size, max_object_size_);
- Buffer* buffer_for_alloc = nullptr;
- if (!buffers_.empty()) {
- Buffer* end_buffer = buffers_[end_index_].get();
- if (end_buffer->UnusedCapacity() >= object_size)
- buffer_for_alloc = end_buffer;
- else if (end_index_ + 1 < buffers_.size())
+ void* element = buffers_.empty() ? nullptr : buffers_[end_index_]->Allocate(
+ object_size, log2_alignment);
+ if (!element) {
+ Buffer* buffer_for_alloc;
+ if (end_index_ + 1 < buffers_.size()) {
buffer_for_alloc = buffers_[++end_index_].get();
+ } else {
+ size_t new_buffer_size =
+ buffers_.empty() ? kDefaultInitialBufferSize * max_object_size_
+ : 2 * buffers_.back()->Capacity();
+ buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size);
+ }
+ element = buffer_for_alloc->Allocate(object_size, log2_alignment);
+ DCHECK(element);
}
-
- if (!buffer_for_alloc) {
- size_t new_buffer_size = buffers_.empty()
- ? kDefaultInitialBufferSize * max_object_size_
- : 2 * buffers_.back()->Capacity();
- buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size);
- }
-
- void* element = buffer_for_alloc->Allocate(object_size);
elements_.push_back(element);
return element;
}

Powered by Google App Engine
This is Rietveld 408576698