| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |