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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "cc/base/contiguous_container.h" 5 #include "cc/base/contiguous_container.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 namespace cc { 11 namespace cc {
12 12
13 namespace {
14
13 // Default number of max-sized elements to allocate space for, if there is no 15 // Default number of max-sized elements to allocate space for, if there is no
14 // initial buffer. 16 // initial buffer.
15 static const unsigned kDefaultInitialBufferSize = 32; 17 const unsigned kDefaultInitialBufferSize = 32;
18
19 inline char* AlignAddress(char* address, unsigned log2_alignment) {
20 char* aligned = reinterpret_cast<char*>(
21 (((reinterpret_cast<size_t>(address) - 1) >> log2_alignment) + 1)
22 << log2_alignment);
23 DCHECK_EQ(0u, reinterpret_cast<size_t>(aligned) % (1 << log2_alignment));
24 DCHECK(aligned >= address);
25 DCHECK(aligned < address + (1 << log2_alignment));
26 return aligned;
27 }
28
29 } // namespace
16 30
17 class ContiguousContainerBase::Buffer { 31 class ContiguousContainerBase::Buffer {
18 public: 32 public:
19 explicit Buffer(size_t buffer_size) 33 explicit Buffer(size_t buffer_size)
20 : data_(new char[buffer_size]), end_(begin()), capacity_(buffer_size) {} 34 : data_(new char[buffer_size]), end_(begin()), capacity_(buffer_size) {}
21 35
22 ~Buffer() {} 36 ~Buffer() {}
23 37
24 size_t Capacity() const { return capacity_; } 38 size_t Capacity() const { return capacity_; }
25 size_t UsedCapacity() const { return end_ - begin(); } 39 size_t UsedCapacity() const { return end_ - begin(); }
26 size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); } 40 size_t UnusedCapacity() const { return Capacity() - UsedCapacity(); }
27 bool empty() const { return UsedCapacity() == 0; } 41 bool empty() const { return UsedCapacity() == 0; }
28 42
29 void* Allocate(size_t object_size) { 43 void* Allocate(size_t object_size, unsigned log2_alignment) {
30 DCHECK_GE(UnusedCapacity(), object_size); 44 char* aligned_address;
31 void* result = end_; 45 if (empty()) {
32 end_ += object_size; 46 // begin()'s alignment must be suitable for all possible types.
33 return result; 47 DCHECK_EQ(begin(), AlignAddress(begin(), log2_alignment));
48 DCHECK(object_size <= capacity_);
49 aligned_address = begin();
50 } else {
51 aligned_address = AlignAddress(end_, log2_alignment);
52 if (aligned_address - begin() + object_size > capacity_)
53 return nullptr;
54 }
55 end_ = aligned_address + object_size;
56 return aligned_address;
34 } 57 }
35 58
36 void DeallocateLastObject(void* object) { 59 void DeallocateLastObject(void* object) {
37 DCHECK_LE(begin(), object); 60 DCHECK_LE(begin(), object);
38 DCHECK_LT(object, end_); 61 DCHECK_LT(object, end_);
39 end_ = static_cast<char*>(object); 62 end_ = static_cast<char*>(object);
63 // We may leave a gap between the end of the previous object (which we
64 // don't know) and end_ because of alignment of the deallocated object.
40 } 65 }
41 66
42 private: 67 private:
43 char* begin() { return &data_[0]; } 68 char* begin() { return &data_[0]; }
44 const char* begin() const { return &data_[0]; } 69 const char* begin() const { return &data_[0]; }
45 70
46 // begin() <= end_ <= begin() + capacity_ 71 // begin() <= end_ <= begin() + capacity_
47 std::unique_ptr<char[]> data_; 72 std::unique_ptr<char[]> data_;
48 char* end_; 73 char* end_;
49 size_t capacity_; 74 size_t capacity_;
(...skipping 23 matching lines...) Expand all
73 for (const auto& buffer : buffers_) 98 for (const auto& buffer : buffers_)
74 used_capacity += buffer->UsedCapacity(); 99 used_capacity += buffer->UsedCapacity();
75 return used_capacity; 100 return used_capacity;
76 } 101 }
77 102
78 size_t ContiguousContainerBase::MemoryUsageInBytes() const { 103 size_t ContiguousContainerBase::MemoryUsageInBytes() const {
79 return sizeof(*this) + GetCapacityInBytes() + 104 return sizeof(*this) + GetCapacityInBytes() +
80 elements_.capacity() * sizeof(elements_[0]); 105 elements_.capacity() * sizeof(elements_[0]);
81 } 106 }
82 107
83 void* ContiguousContainerBase::Allocate(size_t object_size) { 108 void* ContiguousContainerBase::Allocate(size_t object_size,
109 unsigned log2_alignment) {
84 DCHECK_LE(object_size, max_object_size_); 110 DCHECK_LE(object_size, max_object_size_);
85 111
86 Buffer* buffer_for_alloc = nullptr; 112 void* element = buffers_.empty() ? nullptr : buffers_[end_index_]->Allocate(
87 if (!buffers_.empty()) { 113 object_size, log2_alignment);
88 Buffer* end_buffer = buffers_[end_index_].get(); 114 if (!element) {
89 if (end_buffer->UnusedCapacity() >= object_size) 115 Buffer* buffer_for_alloc;
90 buffer_for_alloc = end_buffer; 116 if (end_index_ + 1 < buffers_.size()) {
91 else if (end_index_ + 1 < buffers_.size())
92 buffer_for_alloc = buffers_[++end_index_].get(); 117 buffer_for_alloc = buffers_[++end_index_].get();
118 } else {
119 size_t new_buffer_size =
120 buffers_.empty() ? kDefaultInitialBufferSize * max_object_size_
121 : 2 * buffers_.back()->Capacity();
122 buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size);
123 }
124 element = buffer_for_alloc->Allocate(object_size, log2_alignment);
125 DCHECK(element);
93 } 126 }
94
95 if (!buffer_for_alloc) {
96 size_t new_buffer_size = buffers_.empty()
97 ? kDefaultInitialBufferSize * max_object_size_
98 : 2 * buffers_.back()->Capacity();
99 buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size);
100 }
101
102 void* element = buffer_for_alloc->Allocate(object_size);
103 elements_.push_back(element); 127 elements_.push_back(element);
104 return element; 128 return element;
105 } 129 }
106 130
107 void ContiguousContainerBase::RemoveLast() { 131 void ContiguousContainerBase::RemoveLast() {
108 void* object = elements_.back(); 132 void* object = elements_.back();
109 elements_.pop_back(); 133 elements_.pop_back();
110 134
111 Buffer* end_buffer = buffers_[end_index_].get(); 135 Buffer* end_buffer = buffers_[end_index_].get();
112 end_buffer->DeallocateLastObject(object); 136 end_buffer->DeallocateLastObject(object);
(...skipping 24 matching lines...) Expand all
137 size_t buffer_size) { 161 size_t buffer_size) {
138 DCHECK(buffers_.empty() || end_index_ == buffers_.size() - 1); 162 DCHECK(buffers_.empty() || end_index_ == buffers_.size() - 1);
139 std::unique_ptr<Buffer> new_buffer(new Buffer(buffer_size)); 163 std::unique_ptr<Buffer> new_buffer(new Buffer(buffer_size));
140 Buffer* buffer_to_return = new_buffer.get(); 164 Buffer* buffer_to_return = new_buffer.get();
141 buffers_.push_back(std::move(new_buffer)); 165 buffers_.push_back(std::move(new_buffer));
142 end_index_ = buffers_.size() - 1; 166 end_index_ = buffers_.size() - 1;
143 return buffer_to_return; 167 return buffer_to_return;
144 } 168 }
145 169
146 } // namespace cc 170 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698