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

Unified 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, 6 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 side-by-side diff with in-line comments
Download patch
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..317f93e8c564ad3cfdcdebae29f509ec50b79bcb 100644
--- a/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
+++ b/third_party/WebKit/Source/platform/graphics/ContiguousContainer.cpp
@@ -18,6 +18,15 @@ namespace blink {
// initial buffer.
static const unsigned kDefaultInitialBufferSize = 32;
+static inline char* alignAddress(char* address, size_t alignment)
+{
+ char* aligned = reinterpret_cast<char*>(alignment * ((reinterpret_cast<size_t>(address) + alignment - 1) / alignment));
+ DCHECK_EQ(0u, reinterpret_cast<size_t>(aligned) % alignment);
+ DCHECK(aligned >= address);
+ DCHECK(aligned < address + alignment);
+ return aligned;
+}
+
class ContiguousContainerBase::Buffer {
WTF_MAKE_NONCOPYABLE(Buffer);
USING_FAST_MALLOC(Buffer);
@@ -38,17 +47,19 @@ 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, size_t alignment)
{
- ASSERT(unusedCapacity() >= objectSize);
+ char* alignedAddress = alignAddress(m_end, alignment);
+ 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);
+ if (isEmpty())
+ m_firstObject = alignedAddress;
+ m_end = alignedAddress + objectSize;
+ return alignedAddress;
}
void deallocateLastObject(void* object)
@@ -57,11 +68,20 @@ public:
ANNOTATE_CHANGE_SIZE(
m_begin, m_capacity, usedCapacity(), static_cast<char*>(object) - m_begin);
m_end = static_cast<char*>(object);
+ if (m_end == m_firstObject) {
+ // We have deallocated the first object in this buffer. Reset m_end so that
+ // isEmpty() can return correct value.
+ m_end = m_begin;
+ }
+ // Otherwise 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.
}
private:
- // m_begin <= m_end <= m_begin + m_capacity
+ // m_begin <= m_firstObject <= m_end <= m_begin + m_capacity
char* m_begin;
+ // Because of alignment, the first object may be allocated after m_begin.
+ char* m_firstObject;
char* m_end;
size_t m_capacity;
};
@@ -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, size_t alignment, 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, alignment);
+ 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, alignment);
+ DCHECK(element);
}
-
- void* element = bufferForAlloc->allocate(objectSize);
m_elements.append(element);
return element;
}

Powered by Google App Engine
This is Rietveld 408576698