Chromium Code Reviews| Index: third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp |
| diff --git a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp |
| index cb42fefa480b0aa32f03d22131e9d8205945ed00..82959c78bb0f180620b1a97d6171d69508d6da16 100644 |
| --- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp |
| +++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp |
| @@ -18,6 +18,16 @@ namespace blink { |
| // initial buffer. |
| static const unsigned kDefaultInitialBufferSize = 32; |
| +static inline char* alignAddress(char* address, unsigned log2Alignment) |
| +{ |
| + char* aligned = reinterpret_cast<char*>( |
| + (((reinterpret_cast<size_t>(address) - 1) >> log2Alignment) + 1) << log2Alignment); |
|
jbroman
2016/07/04 19:21:35
why size_t and not uintptr_t?
|
| + DCHECK_EQ(0u, reinterpret_cast<size_t>(aligned) % (1 << log2Alignment)); |
| + DCHECK(aligned >= address); |
| + DCHECK(aligned < address + (1 << log2Alignment)); |
| + return aligned; |
| +} |
| + |
| class ContiguousContainerBase::Buffer { |
| WTF_MAKE_NONCOPYABLE(Buffer); |
| USING_FAST_MALLOC(Buffer); |
| @@ -38,17 +48,25 @@ public: |
| size_t capacity() const { return m_capacity; } |
| size_t usedCapacity() const { return m_end - m_begin; } |
| - size_t unusedCapacity() const { return capacity() - usedCapacity(); } |
| bool isEmpty() const { return usedCapacity() == 0; } |
| - void* allocate(size_t objectSize) |
| + void* allocate(size_t objectSize, unsigned log2Alignment) |
| { |
| - ASSERT(unusedCapacity() >= objectSize); |
| + char* alignedAddress; |
| + if (isEmpty()) { |
| + // m_begin's alignment must be suitable for all possible types. |
| + DCHECK(m_begin == alignAddress(m_begin, log2Alignment)); |
| + DCHECK(objectSize <= m_capacity); |
| + alignedAddress = m_begin; |
| + } else { |
| + alignedAddress = alignAddress(m_end, log2Alignment); |
| + if (alignedAddress - m_begin + objectSize > m_capacity) |
| + return nullptr; |
| + } |
| ANNOTATE_CHANGE_SIZE( |
| - m_begin, m_capacity, usedCapacity(), usedCapacity() + objectSize); |
| - void* result = m_end; |
| - m_end += objectSize; |
| - return result; |
| + m_begin, m_capacity, usedCapacity(), usedCapacity() + (alignedAddress - m_end) + objectSize); |
| + m_end = alignedAddress + objectSize; |
| + return alignedAddress; |
| } |
| void deallocateLastObject(void* object) |
| @@ -57,6 +75,8 @@ public: |
| ANNOTATE_CHANGE_SIZE( |
| m_begin, m_capacity, usedCapacity(), static_cast<char*>(object) - m_begin); |
| m_end = static_cast<char*>(object); |
| + // We may leave a gap between the end of the previous object (which we don't know) |
| + // and m_end because of alignment of the deallocated object. |
|
jbroman
2016/07/04 19:21:35
...which seems weird to me.
|
| } |
| private: |
| @@ -115,27 +135,24 @@ void ContiguousContainerBase::reserveInitialCapacity(size_t bufferSize, const ch |
| allocateNewBufferForNextAllocation(bufferSize, typeName); |
| } |
| -void* ContiguousContainerBase::allocate(size_t objectSize, const char* typeName) |
| +void* ContiguousContainerBase::allocate(size_t objectSize, unsigned log2Alignment, const char* typeName) |
| { |
| - ASSERT(objectSize <= m_maxObjectSize); |
| - |
| - Buffer* bufferForAlloc = nullptr; |
| - if (!m_buffers.isEmpty()) { |
| - Buffer* endBuffer = m_buffers[m_endIndex].get(); |
| - if (endBuffer->unusedCapacity() >= objectSize) |
| - bufferForAlloc = endBuffer; |
| - else if (m_endIndex + 1 < m_buffers.size()) |
| - bufferForAlloc = m_buffers[++m_endIndex].get(); |
| - } |
| + DCHECK(objectSize <= m_maxObjectSize); |
| - if (!bufferForAlloc) { |
| - size_t newBufferSize = m_buffers.isEmpty() |
| - ? kDefaultInitialBufferSize * m_maxObjectSize |
| - : 2 * m_buffers.last()->capacity(); |
| - bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize, typeName); |
| + void* element = m_buffers.isEmpty() ? nullptr : m_buffers[m_endIndex]->allocate(objectSize, log2Alignment); |
| + if (!element) { |
| + Buffer* bufferForAlloc; |
| + if (m_endIndex + 1 < m_buffers.size()) { |
| + bufferForAlloc = m_buffers[++m_endIndex].get(); |
| + } else { |
| + size_t newBufferSize = m_buffers.isEmpty() |
| + ? kDefaultInitialBufferSize * m_maxObjectSize |
| + : 2 * m_buffers.last()->capacity(); |
| + bufferForAlloc = allocateNewBufferForNextAllocation(newBufferSize, typeName); |
| + } |
| + element = bufferForAlloc->allocate(objectSize, log2Alignment); |
| + DCHECK(element); |
| } |
| - |
| - void* element = bufferForAlloc->allocate(objectSize); |
| m_elements.append(element); |
| return element; |
| } |