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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ContiguousContainer.h

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
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 #ifndef ContiguousContainer_h 5 #ifndef ContiguousContainer_h
6 #define ContiguousContainer_h 6 #define ContiguousContainer_h
7 7
8 #include "platform/PlatformExport.h" 8 #include "platform/PlatformExport.h"
9 #include "wtf/Alignment.h" 9 #include "wtf/Alignment.h"
10 #include "wtf/Allocator.h" 10 #include "wtf/Allocator.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 ContiguousContainerBase& operator=(ContiguousContainerBase&&); 48 ContiguousContainerBase& operator=(ContiguousContainerBase&&);
49 49
50 size_t size() const { return m_elements.size(); } 50 size_t size() const { return m_elements.size(); }
51 bool isEmpty() const { return !size(); } 51 bool isEmpty() const { return !size(); }
52 size_t capacityInBytes() const; 52 size_t capacityInBytes() const;
53 size_t usedCapacityInBytes() const; 53 size_t usedCapacityInBytes() const;
54 size_t memoryUsageInBytes() const; 54 size_t memoryUsageInBytes() const;
55 55
56 // These do not invoke constructors or destructors. 56 // These do not invoke constructors or destructors.
57 void reserveInitialCapacity(size_t, const char* typeName); 57 void reserveInitialCapacity(size_t, const char* typeName);
58 void* allocate(size_t objectSize, const char* typeName); 58 void* allocate(size_t objectSize, size_t alignment, const char* typeName);
59 void removeLast(); 59 void removeLast();
60 void clear(); 60 void clear();
61 void swap(ContiguousContainerBase&); 61 void swap(ContiguousContainerBase&);
62 62
63 Vector<void*> m_elements; 63 Vector<void*> m_elements;
64 64
65 private: 65 private:
66 class Buffer; 66 class Buffer;
67 67
68 Buffer* allocateNewBufferForNextAllocation(size_t, const char* typeName); 68 Buffer* allocateNewBufferForNextAllocation(size_t, const char* typeName);
69 69
70 Vector<std::unique_ptr<Buffer>> m_buffers; 70 Vector<std::unique_ptr<Buffer>> m_buffers;
71 unsigned m_endIndex; 71 unsigned m_endIndex;
72 size_t m_maxObjectSize; 72 size_t m_maxObjectSize;
73 }; 73 };
74 74
75 // For most cases, no alignment stricter than pointer alignment is required. If 75 template <class BaseElementType>
76 // one of the derived classes has stronger alignment requirements (and the
77 // static_assert fires), set alignment to the LCM of the derived class
78 // alignments. For small structs without pointers, it may be possible to reduce
79 // alignment for tighter packing.
80
81 template <class BaseElementType, unsigned alignment = sizeof(void*)>
82 class ContiguousContainer : public ContiguousContainerBase { 76 class ContiguousContainer : public ContiguousContainerBase {
83 private: 77 private:
84 // Declares itself as a forward iterator, but also supports a few more 78 // Declares itself as a forward iterator, but also supports a few more
85 // things. The whole random access iterator interface is a bit much. 79 // things. The whole random access iterator interface is a bit much.
86 template <typename BaseIterator, typename ValueType> 80 template <typename BaseIterator, typename ValueType>
87 class IteratorWrapper : public std::iterator<std::forward_iterator_tag, Valu eType> { 81 class IteratorWrapper : public std::iterator<std::forward_iterator_tag, Valu eType> {
88 DISALLOW_NEW(); 82 DISALLOW_NEW();
89 public: 83 public:
90 IteratorWrapper() {} 84 IteratorWrapper() {}
91 bool operator==(const IteratorWrapper& other) const { return m_it == oth er.m_it; } 85 bool operator==(const IteratorWrapper& other) const { return m_it == oth er.m_it; }
92 bool operator!=(const IteratorWrapper& other) const { return m_it != oth er.m_it; } 86 bool operator!=(const IteratorWrapper& other) const { return m_it != oth er.m_it; }
93 ValueType& operator*() const { return *static_cast<ValueType*>(*m_it); } 87 ValueType& operator*() const { return *static_cast<ValueType*>(*m_it); }
94 ValueType* operator->() const { return &operator*(); } 88 ValueType* operator->() const { return &operator*(); }
95 IteratorWrapper operator+(std::ptrdiff_t n) const { return IteratorWrapp er(m_it + n); } 89 IteratorWrapper operator+(std::ptrdiff_t n) const { return IteratorWrapp er(m_it + n); }
96 IteratorWrapper operator++(int) { IteratorWrapper tmp = *this; ++m_it; r eturn tmp; } 90 IteratorWrapper operator++(int) { IteratorWrapper tmp = *this; ++m_it; r eturn tmp; }
97 std::ptrdiff_t operator-(const IteratorWrapper& other) const { return m_ it - other.m_it; } 91 std::ptrdiff_t operator-(const IteratorWrapper& other) const { return m_ it - other.m_it; }
98 IteratorWrapper& operator++() { ++m_it; return *this; } 92 IteratorWrapper& operator++() { ++m_it; return *this; }
99 private: 93 private:
100 explicit IteratorWrapper(const BaseIterator& it) : m_it(it) {} 94 explicit IteratorWrapper(const BaseIterator& it) : m_it(it) {}
101 BaseIterator m_it; 95 BaseIterator m_it;
102 friend class ContiguousContainer; 96 friend class ContiguousContainer;
103 }; 97 };
104 98
105 public: 99 public:
106 using iterator = IteratorWrapper<Vector<void*>::iterator, BaseElementType>; 100 using iterator = IteratorWrapper<Vector<void*>::iterator, BaseElementType>;
107 using const_iterator = IteratorWrapper<Vector<void*>::const_iterator, const BaseElementType>; 101 using const_iterator = IteratorWrapper<Vector<void*>::const_iterator, const BaseElementType>;
108 using reverse_iterator = IteratorWrapper<Vector<void*>::reverse_iterator, Ba seElementType>; 102 using reverse_iterator = IteratorWrapper<Vector<void*>::reverse_iterator, Ba seElementType>;
109 using const_reverse_iterator = IteratorWrapper<Vector<void*>::const_reverse_ iterator, const BaseElementType>; 103 using const_reverse_iterator = IteratorWrapper<Vector<void*>::const_reverse_ iterator, const BaseElementType>;
110 104
111 explicit ContiguousContainer(size_t maxObjectSize) : ContiguousContainerBase (align(maxObjectSize)) {} 105 explicit ContiguousContainer(size_t maxObjectSize) : ContiguousContainerBase (maxObjectSize) {}
112 106
113 ContiguousContainer(size_t maxObjectSize, size_t initialSizeBytes) 107 ContiguousContainer(size_t maxObjectSize, size_t initialSizeBytes)
114 : ContiguousContainer(maxObjectSize) 108 : ContiguousContainer(maxObjectSize)
115 { 109 {
116 reserveInitialCapacity(std::max(maxObjectSize, initialSizeBytes), WTF_HE AP_PROFILER_TYPE_NAME(BaseElementType)); 110 reserveInitialCapacity(std::max(maxObjectSize, initialSizeBytes), WTF_HE AP_PROFILER_TYPE_NAME(BaseElementType));
117 } 111 }
118 112
119 ContiguousContainer(ContiguousContainer&& source) 113 ContiguousContainer(ContiguousContainer&& source)
120 : ContiguousContainerBase(std::move(source)) {} 114 : ContiguousContainerBase(std::move(source)) {}
121 115
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 BaseElementType& last() { return *rbegin(); } 151 BaseElementType& last() { return *rbegin(); }
158 const BaseElementType& last() const { return *rbegin(); } 152 const BaseElementType& last() const { return *rbegin(); }
159 BaseElementType& operator[](size_t index) { return *(begin() + index); } 153 BaseElementType& operator[](size_t index) { return *(begin() + index); }
160 const BaseElementType& operator[](size_t index) const { return *(begin() + i ndex); } 154 const BaseElementType& operator[](size_t index) const { return *(begin() + i ndex); }
161 155
162 template <class DerivedElementType, typename... Args> 156 template <class DerivedElementType, typename... Args>
163 DerivedElementType& allocateAndConstruct(Args&&... args) 157 DerivedElementType& allocateAndConstruct(Args&&... args)
164 { 158 {
165 static_assert(WTF::IsSubclass<DerivedElementType, BaseElementType>::valu e, 159 static_assert(WTF::IsSubclass<DerivedElementType, BaseElementType>::valu e,
166 "Must use subclass of BaseElementType."); 160 "Must use subclass of BaseElementType.");
167 static_assert(alignment % WTF_ALIGN_OF(DerivedElementType) == 0, 161 return *new (allocate(sizeof(DerivedElementType), WTF_ALIGN_OF(DerivedEl ementType)))
168 "Derived type requires stronger alignment."); 162 DerivedElementType(std::forward<Args>(args)...);
169 size_t allocSize = align(sizeof(DerivedElementType));
170 return *new (allocate(allocSize)) DerivedElementType(std::forward<Args>( args)...);
171 } 163 }
172 164
173 void removeLast() 165 void removeLast()
174 { 166 {
175 ASSERT(!isEmpty()); 167 ASSERT(!isEmpty());
176 last().~BaseElementType(); 168 last().~BaseElementType();
177 ContiguousContainerBase::removeLast(); 169 ContiguousContainerBase::removeLast();
178 } 170 }
179 171
180 void clear() 172 void clear()
181 { 173 {
182 for (auto& element : *this) { 174 for (auto& element : *this) {
183 (void)element; // MSVC incorrectly reports this variable as unused. 175 (void)element; // MSVC incorrectly reports this variable as unused.
184 element.~BaseElementType(); 176 element.~BaseElementType();
185 } 177 }
186 ContiguousContainerBase::clear(); 178 ContiguousContainerBase::clear();
187 } 179 }
188 180
189 void swap(ContiguousContainer& other) { ContiguousContainerBase::swap(other) ; } 181 void swap(ContiguousContainer& other) { ContiguousContainerBase::swap(other) ; }
190 182
191 // Appends a new element using memcpy, then default-constructs a base 183 // Appends a new element using memcpy, then default-constructs a base
192 // element in its place. Use with care. 184 // element in its place. Use with care.
193 BaseElementType& appendByMoving(BaseElementType& item, size_t size) 185 BaseElementType& appendByMoving(BaseElementType& item, size_t size, size_t a lignment)
194 { 186 {
195 ASSERT(size >= sizeof(BaseElementType)); 187 ASSERT(size >= sizeof(BaseElementType));
196 void* newItem = allocate(size); 188 void* newItem = allocate(size, alignment);
197 memcpy(newItem, static_cast<void*>(&item), size); 189 memcpy(newItem, static_cast<void*>(&item), size);
198 new (&item) BaseElementType; 190 new (&item) BaseElementType;
199 return *static_cast<BaseElementType*>(newItem); 191 return *static_cast<BaseElementType*>(newItem);
200 } 192 }
201 193
202 private: 194 private:
203 void* allocate(size_t objectSize) 195 FRIEND_TEST_ALL_PREFIXES(ContiguousContainerTest, Alignment);
196
197 void* allocate(size_t objectSize, size_t alignment)
204 { 198 {
205 return ContiguousContainerBase::allocate(objectSize, WTF_HEAP_PROFILER_T YPE_NAME(BaseElementType)); 199 return ContiguousContainerBase::allocate(objectSize, alignment, WTF_HEAP _PROFILER_TYPE_NAME(BaseElementType));
206 }
207
208 static size_t align(size_t size)
209 {
210 size_t alignedSize = alignment * ((size + alignment - 1) / alignment);
211 ASSERT(alignedSize % alignment == 0);
212 ASSERT(alignedSize >= size);
213 ASSERT(alignedSize < size + alignment);
214 return alignedSize;
215 } 200 }
216 }; 201 };
217 202
218 } // namespace blink 203 } // namespace blink
219 204
220 #endif // ContiguousContainer_h 205 #endif // ContiguousContainer_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698