Index: Source/wtf/Vector.h |
diff --git a/Source/wtf/Vector.h b/Source/wtf/Vector.h |
index caf5658172941b04f64a5e7011b149e731326873..5f6531768902ce8c58e006e8519c16227bef0c07 100644 |
--- a/Source/wtf/Vector.h |
+++ b/Source/wtf/Vector.h |
@@ -313,10 +313,6 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
{ |
} |
- ~VectorBufferBase() |
- { |
- } |
- |
T* m_buffer; |
unsigned m_capacity; |
unsigned m_size; |
@@ -342,10 +338,6 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
allocateBuffer(capacity); |
} |
- ~VectorBuffer() |
- { |
- } |
- |
void destruct() |
{ |
deallocateBuffer(m_buffer); |
@@ -407,10 +399,6 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
Base::allocateBuffer(capacity); |
} |
- ~VectorBuffer() |
- { |
- } |
- |
void destruct() |
{ |
deallocateBuffer(m_buffer); |
@@ -493,8 +481,49 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; |
}; |
+ template<typename T, size_t inlineCapacity, typename Allocator> |
+ class Vector; |
+ |
+ // VectorDestructorBase defines the destructor of a vector. This base is used in order to |
+ // completely avoid creating a destructor for a vector that does not need to be destructed. |
+ // By doing so, the clang compiler will have correct information about whether or not a |
+ // vector has a trivial destructor and we use that in a compiler plugin to ensure the |
+ // correctness of non-finalized garbage-collected classes and the use of VectorTraits::needsDestruction. |
+ |
+ // All non-GC managed vectors needs a destructor. This destructor will simply call finalize on the actual vector type. |
+ template<typename Derived, typename Elements, bool hasInlineCapacity, bool isGarbageCollected> |
+ class VectorDestructorBase { |
+ public: |
+ ~VectorDestructorBase() { static_cast<Derived*>(this)->finalize(); } |
+ }; |
+ |
+ // Heap-allocated vectors with no inlineCapacity never need a destructor. |
+ template<typename Derived, typename Elements> |
+ class VectorDestructorBase<Derived, Elements, false, true> { }; |
+ |
+ // Heap-allocator vectors with inlineCapacity need a destructor if the inline elements do. |
+ // The use of VectorTraits<Elements>::needsDestruction is delayed until we know that |
+ // inlineCapacity is non-zero to allow classes that recursively refer to themselves in vector |
+ // members. If inlineCapacity is non-zero doing so would have undefined meaning, so in this |
+ // case we can use HeapVectorWithInlineCapacityDestructorBase to define a destructor |
+ // depending on the value of VectorTraits<Elements>::needsDestruction. |
+ template<typename Derived, bool elementsNeedsDestruction> |
+ class HeapVectorWithInlineCapacityDestructorBase; |
+ |
+ template<typename Derived> |
+ class HeapVectorWithInlineCapacityDestructorBase<Derived, true> { |
+ public: |
+ ~HeapVectorWithInlineCapacityDestructorBase() { static_cast<Derived*>(this)->finalize(); } |
+ }; |
+ |
+ template<typename Derived> |
+ class HeapVectorWithInlineCapacityDestructorBase<Derived, false> { }; |
+ |
+ template<typename Derived, typename Elements> |
+ class VectorDestructorBase<Derived, Elements, true, true> : public HeapVectorWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruction> { }; |
+ |
template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator> |
- class Vector : private VectorBuffer<T, inlineCapacity, Allocator> { |
+ class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public VectorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0), Allocator::isGarbageCollected> { |
private: |
typedef VectorBuffer<T, inlineCapacity, Allocator> Base; |
typedef VectorTypeOperations<T> TypeOperations; |
@@ -536,7 +565,7 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
// On-GC-heap vectors: Destructor should be called for inline buffers |
// (if any) but destructor shouldn't be called for vector backing since |
// it is managed by the traced GC heap. |
- ~Vector() |
+ void finalize() |
{ |
if (!inlineCapacity) { |
if (LIKELY(!Base::buffer())) |
@@ -550,11 +579,6 @@ static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE; |
Base::destruct(); |
} |
- void finalize() |
- { |
- this->~Vector(); |
- } |
- |
void clearUnusedSlots(T* from, T* to) |
{ |
VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value || VectorTraits<T>::isWeak), T>::clear(from, to); |