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

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: 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
« no previous file with comments | « cc/base/contiguous_container.h ('k') | cc/base/contiguous_container_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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, size_t alignment) {
20 char* aligned = reinterpret_cast<char*>(
21 alignment *
22 ((reinterpret_cast<size_t>(address) + alignment - 1) / alignment));
23 DCHECK(reinterpret_cast<size_t>(aligned) % alignment == 0);
24 DCHECK(aligned >= address);
25 DCHECK(aligned < address + 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, size_t alignment) {
30 DCHECK_GE(UnusedCapacity(), object_size); 44 char* aligned_address = AlignAddress(end_, alignment);
31 void* result = end_; 45 if (aligned_address - begin() + object_size > Capacity())
32 end_ += object_size; 46 return nullptr;
33 return result; 47 if (empty())
48 first_object_ = aligned_address;
49 end_ = aligned_address + object_size;
50 return aligned_address;
34 } 51 }
35 52
36 void DeallocateLastObject(void* object) { 53 void DeallocateLastObject(void* object) {
37 DCHECK_LE(begin(), object); 54 DCHECK_LE(begin(), object);
38 DCHECK_LT(object, end_); 55 DCHECK_LT(object, end_);
39 end_ = static_cast<char*>(object); 56 end_ = static_cast<char*>(object);
57 if (end_ == first_object_) {
58 // We have deallocated the first object in this buffer. Reset en_ so that
59 // empty() can return correct value.
60 end_ = begin();
61 }
62 // Otherwise we may leave a gap between the end of the previous object
63 // (which we don't know) and end_ because of alignment of the deallocated
64 // 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() <= first_object_ <= end_ <= begin() + capacity_
47 std::unique_ptr<char[]> data_; 72 std::unique_ptr<char[]> data_;
73 // Because of alignment, the first object may be allocated after begin().
74 char* first_object_;
48 char* end_; 75 char* end_;
49 size_t capacity_; 76 size_t capacity_;
50 }; 77 };
51 78
52 ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size) 79 ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size)
53 : end_index_(0), max_object_size_(max_object_size) {} 80 : end_index_(0), max_object_size_(max_object_size) {}
54 81
55 ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size, 82 ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size,
56 size_t initial_size_bytes) 83 size_t initial_size_bytes)
57 : ContiguousContainerBase(max_object_size) { 84 : ContiguousContainerBase(max_object_size) {
(...skipping 15 matching lines...) Expand all
73 for (const auto& buffer : buffers_) 100 for (const auto& buffer : buffers_)
74 used_capacity += buffer->UsedCapacity(); 101 used_capacity += buffer->UsedCapacity();
75 return used_capacity; 102 return used_capacity;
76 } 103 }
77 104
78 size_t ContiguousContainerBase::MemoryUsageInBytes() const { 105 size_t ContiguousContainerBase::MemoryUsageInBytes() const {
79 return sizeof(*this) + GetCapacityInBytes() + 106 return sizeof(*this) + GetCapacityInBytes() +
80 elements_.capacity() * sizeof(elements_[0]); 107 elements_.capacity() * sizeof(elements_[0]);
81 } 108 }
82 109
83 void* ContiguousContainerBase::Allocate(size_t object_size) { 110 void* ContiguousContainerBase::Allocate(size_t object_size, size_t alignment) {
84 DCHECK_LE(object_size, max_object_size_); 111 DCHECK_LE(object_size, max_object_size_);
85 112
86 Buffer* buffer_for_alloc = nullptr; 113 void* element = buffers_.empty() ? nullptr : buffers_[end_index_]->Allocate(
87 if (!buffers_.empty()) { 114 object_size, alignment);
88 Buffer* end_buffer = buffers_[end_index_].get(); 115 if (!element) {
89 if (end_buffer->UnusedCapacity() >= object_size) 116 Buffer* buffer_for_alloc;
90 buffer_for_alloc = end_buffer; 117 if (end_index_ + 1 < buffers_.size()) {
91 else if (end_index_ + 1 < buffers_.size())
92 buffer_for_alloc = buffers_[++end_index_].get(); 118 buffer_for_alloc = buffers_[++end_index_].get();
119 } else {
120 size_t new_buffer_size =
121 buffers_.empty() ? kDefaultInitialBufferSize * max_object_size_
122 : 2 * buffers_.back()->Capacity();
123 buffer_for_alloc = AllocateNewBufferForNextAllocation(new_buffer_size);
124 }
125 element = buffer_for_alloc->Allocate(object_size, alignment);
126 DCHECK(element);
93 } 127 }
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); 128 elements_.push_back(element);
104 return element; 129 return element;
105 } 130 }
106 131
107 void ContiguousContainerBase::RemoveLast() { 132 void ContiguousContainerBase::RemoveLast() {
108 void* object = elements_.back(); 133 void* object = elements_.back();
109 elements_.pop_back(); 134 elements_.pop_back();
110 135
111 Buffer* end_buffer = buffers_[end_index_].get(); 136 Buffer* end_buffer = buffers_[end_index_].get();
112 end_buffer->DeallocateLastObject(object); 137 end_buffer->DeallocateLastObject(object);
(...skipping 24 matching lines...) Expand all
137 size_t buffer_size) { 162 size_t buffer_size) {
138 DCHECK(buffers_.empty() || end_index_ == buffers_.size() - 1); 163 DCHECK(buffers_.empty() || end_index_ == buffers_.size() - 1);
139 std::unique_ptr<Buffer> new_buffer(new Buffer(buffer_size)); 164 std::unique_ptr<Buffer> new_buffer(new Buffer(buffer_size));
140 Buffer* buffer_to_return = new_buffer.get(); 165 Buffer* buffer_to_return = new_buffer.get();
141 buffers_.push_back(std::move(new_buffer)); 166 buffers_.push_back(std::move(new_buffer));
142 end_index_ = buffers_.size() - 1; 167 end_index_ = buffers_.size() - 1;
143 return buffer_to_return; 168 return buffer_to_return;
144 } 169 }
145 170
146 } // namespace cc 171 } // namespace cc
OLDNEW
« no previous file with comments | « cc/base/contiguous_container.h ('k') | cc/base/contiguous_container_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698