Index: Source/wtf/Vector.h |
diff --git a/Source/wtf/Vector.h b/Source/wtf/Vector.h |
index f353c01cd4140420a5b574bca4c90a2ba1aaa8f1..88e532fd3d5f3e95248dd538628f268b59b42657 100644 |
--- a/Source/wtf/Vector.h |
+++ b/Source/wtf/Vector.h |
@@ -79,6 +79,9 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
template<typename T> |
struct VectorUnusedSlotClearer<false, T> { |
static void clear(T*, T*) { } |
+#if ENABLE(ASSERT) |
+ static void checkCleared(const T*, const T*) { } |
+#endif |
}; |
template<typename T> |
@@ -89,6 +92,17 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
// do not visit them (or at least it does not matter if they do). |
memset(begin, 0, sizeof(T) * (end - begin)); |
} |
+ |
+#if ENABLE(ASSERT) |
+ static void checkCleared(const T* begin, const T* end) |
+ { |
+ const unsigned char* unusedArea = reinterpret_cast<const unsigned char*>(begin); |
+ const unsigned char* endAddress = reinterpret_cast<const unsigned char*>(end); |
+ ASSERT(endAddress >= unusedArea); |
+ for (int i = 0; i < endAddress - unusedArea; ++i) |
+ ASSERT(!unusedArea[i]); |
+ } |
+#endif |
}; |
template <bool canInitializeWithMemset, typename T> |
@@ -331,6 +345,13 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::clear(from, to); |
} |
+ void checkUnusedSlots(const T* from, const T* to) |
+ { |
+#if ENABLE(ASSERT) && !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
+ VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T>>::value), T>::checkCleared(from, to); |
+#endif |
+ } |
+ |
protected: |
VectorBufferBase() |
: m_buffer(0) |
@@ -419,6 +440,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
using Base::capacity; |
using Base::clearUnusedSlots; |
+ using Base::checkUnusedSlots; |
bool hasOutOfLineBuffer() const |
{ |
@@ -539,11 +561,13 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size); |
TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_size, other.inlineBuffer()); |
TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer() + m_size, other.inlineBuffer() + other.m_size); |
+ Base::clearUnusedSlots(inlineBuffer() + other.m_size, inlineBuffer() + m_size); |
ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size); |
} else { |
ANNOTATE_CHANGE_SIZE(inlineBuffer(), inlineCapacity, m_size, other.m_size); |
TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer()); |
TypeOperations::move(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size, inlineBuffer() + m_size); |
+ Base::clearUnusedSlots(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size); |
ANNOTATE_CHANGE_SIZE(other.inlineBuffer(), inlineCapacity, other.m_size, m_size); |
} |
} else if (buffer() == inlineBuffer()) { |
@@ -552,6 +576,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
other.m_buffer = other.inlineBuffer(); |
ANNOTATE_NEW_BUFFER(other.m_buffer, inlineCapacity, m_size); |
TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer()); |
+ Base::clearUnusedSlots(inlineBuffer(), inlineBuffer() + m_size); |
std::swap(m_capacity, other.m_capacity); |
} else if (other.buffer() == other.inlineBuffer()) { |
ANNOTATE_DELETE_BUFFER(other.m_buffer, inlineCapacity, other.m_size); |
@@ -559,6 +584,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
m_buffer = inlineBuffer(); |
ANNOTATE_NEW_BUFFER(m_buffer, inlineCapacity, other.m_size); |
TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer()); |
+ Base::clearUnusedSlots(other.inlineBuffer(), other.inlineBuffer() + other.m_size); |
std::swap(m_capacity, other.m_capacity); |
} else { |
std::swap(m_buffer, other.m_buffer); |
@@ -779,6 +805,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
using Base::allocateBuffer; |
using Base::allocationSize; |
using Base::clearUnusedSlots; |
+ using Base::checkUnusedSlots; |
}; |
template<typename T, size_t inlineCapacity, typename Allocator> |
@@ -970,6 +997,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
{ |
if (size <= m_size) { |
TypeOperations::destruct(begin() + size, end()); |
+ clearUnusedSlots(begin() + size, end()); |
ANNOTATE_CHANGE_SIZE(begin(), capacity(), m_size, size); |
} else { |
if (size > capacity()) |
@@ -1026,6 +1054,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
Base::allocateExpandedBuffer(newCapacity); |
ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
TypeOperations::move(oldBuffer, oldEnd, begin()); |
+ clearUnusedSlots(oldBuffer, oldEnd); |
ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
Base::deallocateBuffer(oldBuffer); |
} |
@@ -1066,6 +1095,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
if (begin() != oldBuffer) { |
ANNOTATE_NEW_BUFFER(begin(), capacity(), m_size); |
TypeOperations::move(oldBuffer, oldEnd, begin()); |
+ clearUnusedSlots(oldBuffer, oldEnd); |
ANNOTATE_DELETE_BUFFER(oldBuffer, oldCapacity, m_size); |
} |
} else { |
@@ -1287,6 +1317,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
if (ShouldBeTraced<VectorTraits<T>>::value) { |
for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; bufferEntry++) |
Allocator::template trace<VisitorDispatcher, T, VectorTraits<T>>(visitor, *const_cast<T*>(bufferEntry)); |
+ checkUnusedSlots(buffer() + size(), buffer() + capacity()); |
} |
if (this->hasOutOfLineBuffer()) |
Allocator::markNoTracing(visitor, buffer()); |