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

Unified Diff: Source/wtf/Vector.h

Issue 189543014: Ensure proper finalization of garbage-collected types. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase and sign error in Vector Created 6 years, 9 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
« no previous file with comments | « Source/wtf/HashTable.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « Source/wtf/HashTable.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698