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

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

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 #include "platform/graphics/ContiguousContainer.h" 5 #include "platform/graphics/ContiguousContainer.h"
6 6
7 #include "wtf/Allocator.h" 7 #include "wtf/Allocator.h"
8 #include "wtf/ContainerAnnotations.h" 8 #include "wtf/ContainerAnnotations.h"
9 #include "wtf/PtrUtil.h" 9 #include "wtf/PtrUtil.h"
10 #include "wtf/allocator/PartitionAlloc.h" 10 #include "wtf/allocator/PartitionAlloc.h"
11 #include "wtf/allocator/Partitions.h" 11 #include "wtf/allocator/Partitions.h"
12 #include <algorithm> 12 #include <algorithm>
13 #include <memory> 13 #include <memory>
14 14
15 namespace blink { 15 namespace blink {
16 16
17 // Default number of max-sized elements to allocate space for, if there is no 17 // Default number of max-sized elements to allocate space for, if there is no
18 // initial buffer. 18 // initial buffer.
19 static const unsigned kDefaultInitialBufferSize = 32; 19 static const unsigned kDefaultInitialBufferSize = 32;
20 20
21 static inline char* alignAddress(char* address, size_t alignment)
22 {
23 char* aligned = reinterpret_cast<char*>(alignment * ((reinterpret_cast<size_ t>(address) + alignment - 1) / alignment));
24 DCHECK_EQ(0u, reinterpret_cast<size_t>(aligned) % alignment);
25 DCHECK(aligned >= address);
26 DCHECK(aligned < address + alignment);
27 return aligned;
28 }
29
21 class ContiguousContainerBase::Buffer { 30 class ContiguousContainerBase::Buffer {
22 WTF_MAKE_NONCOPYABLE(Buffer); 31 WTF_MAKE_NONCOPYABLE(Buffer);
23 USING_FAST_MALLOC(Buffer); 32 USING_FAST_MALLOC(Buffer);
24 public: 33 public:
25 Buffer(size_t bufferSize, const char* typeName) 34 Buffer(size_t bufferSize, const char* typeName)
26 { 35 {
27 m_capacity = WTF::Partitions::bufferActualSize(bufferSize); 36 m_capacity = WTF::Partitions::bufferActualSize(bufferSize);
28 m_begin = m_end = static_cast<char*>( 37 m_begin = m_end = static_cast<char*>(
29 WTF::Partitions::bufferMalloc(m_capacity, typeName)); 38 WTF::Partitions::bufferMalloc(m_capacity, typeName));
30 ANNOTATE_NEW_BUFFER(m_begin, m_capacity, 0); 39 ANNOTATE_NEW_BUFFER(m_begin, m_capacity, 0);
31 } 40 }
32 41
33 ~Buffer() 42 ~Buffer()
34 { 43 {
35 ANNOTATE_DELETE_BUFFER(m_begin, m_capacity, usedCapacity()); 44 ANNOTATE_DELETE_BUFFER(m_begin, m_capacity, usedCapacity());
36 WTF::Partitions::bufferFree(m_begin); 45 WTF::Partitions::bufferFree(m_begin);
37 } 46 }
38 47
39 size_t capacity() const { return m_capacity; } 48 size_t capacity() const { return m_capacity; }
40 size_t usedCapacity() const { return m_end - m_begin; } 49 size_t usedCapacity() const { return m_end - m_begin; }
41 size_t unusedCapacity() const { return capacity() - usedCapacity(); }
42 bool isEmpty() const { return usedCapacity() == 0; } 50 bool isEmpty() const { return usedCapacity() == 0; }
43 51
44 void* allocate(size_t objectSize) 52 void* allocate(size_t objectSize, size_t alignment)
45 { 53 {
46 ASSERT(unusedCapacity() >= objectSize); 54 char* alignedAddress = alignAddress(m_end, alignment);
55 if (alignedAddress - m_begin + objectSize > m_capacity)
56 return nullptr;
47 ANNOTATE_CHANGE_SIZE( 57 ANNOTATE_CHANGE_SIZE(
48 m_begin, m_capacity, usedCapacity(), usedCapacity() + objectSize); 58 m_begin, m_capacity, usedCapacity(), usedCapacity() + (alignedAddres s - m_end) + objectSize);
49 void* result = m_end; 59 if (isEmpty())
50 m_end += objectSize; 60 m_firstObject = alignedAddress;
51 return result; 61 m_end = alignedAddress + objectSize;
62 return alignedAddress;
52 } 63 }
53 64
54 void deallocateLastObject(void* object) 65 void deallocateLastObject(void* object)
55 { 66 {
56 RELEASE_ASSERT(m_begin <= object && object < m_end); 67 RELEASE_ASSERT(m_begin <= object && object < m_end);
57 ANNOTATE_CHANGE_SIZE( 68 ANNOTATE_CHANGE_SIZE(
58 m_begin, m_capacity, usedCapacity(), static_cast<char*>(object) - m_ begin); 69 m_begin, m_capacity, usedCapacity(), static_cast<char*>(object) - m_ begin);
59 m_end = static_cast<char*>(object); 70 m_end = static_cast<char*>(object);
71 if (m_end == m_firstObject) {
72 // We have deallocated the first object in this buffer. Reset m_end so that
73 // isEmpty() can return correct value.
74 m_end = m_begin;
75 }
76 // Otherwise we may leave a gap between the end of the previous object ( which we
77 // don't know) and m_end because of alignment of the deallocated object.
60 } 78 }
61 79
62 private: 80 private:
63 // m_begin <= m_end <= m_begin + m_capacity 81 // m_begin <= m_firstObject <= m_end <= m_begin + m_capacity
64 char* m_begin; 82 char* m_begin;
83 // Because of alignment, the first object may be allocated after m_begin.
84 char* m_firstObject;
65 char* m_end; 85 char* m_end;
66 size_t m_capacity; 86 size_t m_capacity;
67 }; 87 };
68 88
69 ContiguousContainerBase::ContiguousContainerBase(size_t maxObjectSize) 89 ContiguousContainerBase::ContiguousContainerBase(size_t maxObjectSize)
70 : m_endIndex(0) 90 : m_endIndex(0)
71 , m_maxObjectSize(maxObjectSize) 91 , m_maxObjectSize(maxObjectSize)
72 { 92 {
73 } 93 }
74 94
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 { 128 {
109 return sizeof(*this) + capacityInBytes() 129 return sizeof(*this) + capacityInBytes()
110 + m_elements.capacity() * sizeof(m_elements[0]); 130 + m_elements.capacity() * sizeof(m_elements[0]);
111 } 131 }
112 132
113 void ContiguousContainerBase::reserveInitialCapacity(size_t bufferSize, const ch ar* typeName) 133 void ContiguousContainerBase::reserveInitialCapacity(size_t bufferSize, const ch ar* typeName)
114 { 134 {
115 allocateNewBufferForNextAllocation(bufferSize, typeName); 135 allocateNewBufferForNextAllocation(bufferSize, typeName);
116 } 136 }
117 137
118 void* ContiguousContainerBase::allocate(size_t objectSize, const char* typeName) 138 void* ContiguousContainerBase::allocate(size_t objectSize, size_t alignment, con st char* typeName)
119 { 139 {
120 ASSERT(objectSize <= m_maxObjectSize); 140 DCHECK(objectSize <= m_maxObjectSize);
121 141
122 Buffer* bufferForAlloc = nullptr; 142 void* element = m_buffers.isEmpty() ? nullptr : m_buffers[m_endIndex]->alloc ate(objectSize, alignment);
123 if (!m_buffers.isEmpty()) { 143 if (!element) {
124 Buffer* endBuffer = m_buffers[m_endIndex].get(); 144 Buffer* bufferForAlloc;
125 if (endBuffer->unusedCapacity() >= objectSize) 145 if (m_endIndex + 1 < m_buffers.size()) {
126 bufferForAlloc = endBuffer;
127 else if (m_endIndex + 1 < m_buffers.size())
128 bufferForAlloc = m_buffers[++m_endIndex].get(); 146 bufferForAlloc = m_buffers[++m_endIndex].get();
147 } else {
148 size_t newBufferSize = m_buffers.isEmpty()
149 ? kDefaultInitialBufferSize * m_maxObjectSize
150 : 2 * m_buffers.last()->capacity();
151 bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize, t ypeName);
152 }
153 element = bufferForAlloc->allocate(objectSize, alignment);
154 DCHECK(element);
129 } 155 }
130
131 if (!bufferForAlloc) {
132 size_t newBufferSize = m_buffers.isEmpty()
133 ? kDefaultInitialBufferSize * m_maxObjectSize
134 : 2 * m_buffers.last()->capacity();
135 bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize, typeN ame);
136 }
137
138 void* element = bufferForAlloc->allocate(objectSize);
139 m_elements.append(element); 156 m_elements.append(element);
140 return element; 157 return element;
141 } 158 }
142 159
143 void ContiguousContainerBase::removeLast() 160 void ContiguousContainerBase::removeLast()
144 { 161 {
145 void* object = m_elements.last(); 162 void* object = m_elements.last();
146 m_elements.removeLast(); 163 m_elements.removeLast();
147 164
148 Buffer* endBuffer = m_buffers[m_endIndex].get(); 165 Buffer* endBuffer = m_buffers[m_endIndex].get();
(...skipping 27 matching lines...) Expand all
176 { 193 {
177 ASSERT(m_buffers.isEmpty() || m_endIndex == m_buffers.size() - 1); 194 ASSERT(m_buffers.isEmpty() || m_endIndex == m_buffers.size() - 1);
178 std::unique_ptr<Buffer> newBuffer = wrapUnique(new Buffer(bufferSize, typeNa me)); 195 std::unique_ptr<Buffer> newBuffer = wrapUnique(new Buffer(bufferSize, typeNa me));
179 Buffer* bufferToReturn = newBuffer.get(); 196 Buffer* bufferToReturn = newBuffer.get();
180 m_buffers.append(std::move(newBuffer)); 197 m_buffers.append(std::move(newBuffer));
181 m_endIndex = m_buffers.size() - 1; 198 m_endIndex = m_buffers.size() - 1;
182 return bufferToReturn; 199 return bufferToReturn;
183 } 200 }
184 201
185 } // namespace blink 202 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698