Home | History | Annotate | Download | only in wtf
      1 /*
      2  *  Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  *  This library is free software; you can redistribute it and/or
      5  *  modify it under the terms of the GNU Library General Public
      6  *  License as published by the Free Software Foundation; either
      7  *  version 2 of the License, or (at your option) any later version.
      8  *
      9  *  This library is distributed in the hope that it will be useful,
     10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  *  Library General Public License for more details.
     13  *
     14  *  You should have received a copy of the GNU Library General Public License
     15  *  along with this library; see the file COPYING.LIB.  If not, write to
     16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  *  Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #ifndef WTF_Vector_h
     22 #define WTF_Vector_h
     23 
     24 #include "wtf/Alignment.h"
     25 #include "wtf/DefaultAllocator.h"
     26 #include "wtf/FastAllocBase.h"
     27 #include "wtf/Noncopyable.h"
     28 #include "wtf/NotFound.h"
     29 #include "wtf/StdLibExtras.h"
     30 #include "wtf/VectorTraits.h"
     31 #include "wtf/WTF.h"
     32 #include <string.h>
     33 #include <utility>
     34 
     35 namespace WTF {
     36 
     37 #if defined(MEMORY_SANITIZER_INITIAL_SIZE)
     38 static const size_t kInitialVectorSize = 1;
     39 #else
     40 #ifndef WTF_VECTOR_INITIAL_SIZE
     41 #define WTF_VECTOR_INITIAL_SIZE 4
     42 #endif
     43 static const size_t kInitialVectorSize = WTF_VECTOR_INITIAL_SIZE;
     44 #endif
     45 
     46     template<typename T, size_t inlineBuffer, typename Allocator>
     47     class Deque;
     48 
     49     template <bool needsDestruction, typename T>
     50     struct VectorDestructor;
     51 
     52     template<typename T>
     53     struct VectorDestructor<false, T>
     54     {
     55         static void destruct(T*, T*) {}
     56     };
     57 
     58     template<typename T>
     59     struct VectorDestructor<true, T>
     60     {
     61         static void destruct(T* begin, T* end)
     62         {
     63             for (T* cur = begin; cur != end; ++cur)
     64                 cur->~T();
     65         }
     66     };
     67 
     68     template <bool unusedSlotsMustBeZeroed, typename T>
     69     struct VectorUnusedSlotClearer;
     70 
     71     template<typename T>
     72     struct VectorUnusedSlotClearer<false, T> {
     73         static void clear(T*, T*) { }
     74     };
     75 
     76     template<typename T>
     77     struct VectorUnusedSlotClearer<true, T> {
     78         static void clear(T* begin, T* end)
     79         {
     80             // We clear out unused slots so that the visitor and the finalizer
     81             // do not visit them (or at least it does not matter if they do).
     82             memset(begin, 0, sizeof(T) * (end - begin));
     83         }
     84     };
     85 
     86     template <bool canInitializeWithMemset, typename T>
     87     struct VectorInitializer;
     88 
     89     template<typename T>
     90     struct VectorInitializer<false, T>
     91     {
     92         static void initialize(T* begin, T* end)
     93         {
     94             for (T* cur = begin; cur != end; ++cur)
     95                 new (NotNull, cur) T;
     96         }
     97     };
     98 
     99     template<typename T>
    100     struct VectorInitializer<true, T>
    101     {
    102         static void initialize(T* begin, T* end)
    103         {
    104             memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin));
    105         }
    106     };
    107 
    108     template <bool canMoveWithMemcpy, typename T>
    109     struct VectorMover;
    110 
    111     template<typename T>
    112     struct VectorMover<false, T>
    113     {
    114         static void move(const T* src, const T* srcEnd, T* dst)
    115         {
    116             while (src != srcEnd) {
    117                 new (NotNull, dst) T(*src);
    118                 src->~T();
    119                 ++dst;
    120                 ++src;
    121             }
    122         }
    123         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
    124         {
    125             if (src > dst)
    126                 move(src, srcEnd, dst);
    127             else {
    128                 T* dstEnd = dst + (srcEnd - src);
    129                 while (src != srcEnd) {
    130                     --srcEnd;
    131                     --dstEnd;
    132                     new (NotNull, dstEnd) T(*srcEnd);
    133                     srcEnd->~T();
    134                 }
    135             }
    136         }
    137         static void swap(T* src, T* srcEnd, T* dst)
    138         {
    139             std::swap_ranges(src, srcEnd, dst);
    140         }
    141     };
    142 
    143     template<typename T>
    144     struct VectorMover<true, T>
    145     {
    146         static void move(const T* src, const T* srcEnd, T* dst)
    147         {
    148             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
    149         }
    150         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
    151         {
    152             memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
    153         }
    154         static void swap(T* src, T* srcEnd, T* dst)
    155         {
    156             std::swap_ranges(reinterpret_cast<char*>(src), reinterpret_cast<char*>(srcEnd), reinterpret_cast<char*>(dst));
    157         }
    158     };
    159 
    160     template <bool canCopyWithMemcpy, typename T>
    161     struct VectorCopier;
    162 
    163     template<typename T>
    164     struct VectorCopier<false, T>
    165     {
    166         template<typename U>
    167         static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
    168         {
    169             while (src != srcEnd) {
    170                 new (NotNull, dst) T(*src);
    171                 ++dst;
    172                 ++src;
    173             }
    174         }
    175     };
    176 
    177     template<typename T>
    178     struct VectorCopier<true, T>
    179     {
    180         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
    181         {
    182             memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src));
    183         }
    184         template<typename U>
    185         static void uninitializedCopy(const U* src, const U* srcEnd, T* dst)
    186         {
    187             VectorCopier<false, T>::uninitializedCopy(src, srcEnd, dst);
    188         }
    189     };
    190 
    191     template <bool canFillWithMemset, typename T>
    192     struct VectorFiller;
    193 
    194     template<typename T>
    195     struct VectorFiller<false, T>
    196     {
    197         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
    198         {
    199             while (dst != dstEnd) {
    200                 new (NotNull, dst) T(val);
    201                 ++dst;
    202             }
    203         }
    204     };
    205 
    206     template<typename T>
    207     struct VectorFiller<true, T>
    208     {
    209         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
    210         {
    211             COMPILE_ASSERT(sizeof(T) == sizeof(char), Size_of_type_should_be_equal_to_one);
    212 #if COMPILER(GCC) && defined(_FORTIFY_SOURCE)
    213             if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst)))
    214 #endif
    215                 memset(dst, val, dstEnd - dst);
    216         }
    217     };
    218 
    219     template<bool canCompareWithMemcmp, typename T>
    220     struct VectorComparer;
    221 
    222     template<typename T>
    223     struct VectorComparer<false, T>
    224     {
    225         static bool compare(const T* a, const T* b, size_t size)
    226         {
    227             if (LIKELY(a && b))
    228                 return std::equal(a, a + size, b);
    229             return !a && !b;
    230         }
    231     };
    232 
    233     template<typename T>
    234     struct VectorComparer<true, T>
    235     {
    236         static bool compare(const T* a, const T* b, size_t size)
    237         {
    238             return memcmp(a, b, sizeof(T) * size) == 0;
    239         }
    240     };
    241 
    242     template<typename T>
    243     struct VectorTypeOperations
    244     {
    245         static void destruct(T* begin, T* end)
    246         {
    247             VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end);
    248         }
    249 
    250         static void initialize(T* begin, T* end)
    251         {
    252             VectorInitializer<VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end);
    253         }
    254 
    255         static void move(const T* src, const T* srcEnd, T* dst)
    256         {
    257             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst);
    258         }
    259 
    260         static void moveOverlapping(const T* src, const T* srcEnd, T* dst)
    261         {
    262             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst);
    263         }
    264 
    265         static void swap(T* src, T* srcEnd, T* dst)
    266         {
    267             VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::swap(src, srcEnd, dst);
    268         }
    269 
    270         static void uninitializedCopy(const T* src, const T* srcEnd, T* dst)
    271         {
    272             VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst);
    273         }
    274 
    275         static void uninitializedFill(T* dst, T* dstEnd, const T& val)
    276         {
    277             VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val);
    278         }
    279 
    280         static bool compare(const T* a, const T* b, size_t size)
    281         {
    282             return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size);
    283         }
    284     };
    285 
    286     template<typename T, typename Allocator>
    287     class VectorBufferBase {
    288         WTF_MAKE_NONCOPYABLE(VectorBufferBase);
    289     public:
    290         void allocateBuffer(size_t newCapacity)
    291         {
    292             typedef typename Allocator::template VectorBackingHelper<T, VectorTraits<T> >::Type VectorBacking;
    293             ASSERT(newCapacity);
    294             size_t sizeToAllocate = allocationSize(newCapacity);
    295             m_buffer = Allocator::template backingMalloc<T*, VectorBacking>(sizeToAllocate);
    296             m_capacity = sizeToAllocate / sizeof(T);
    297         }
    298 
    299         size_t allocationSize(size_t capacity) const
    300         {
    301             return Allocator::Quantizer::template quantizedSize<T>(capacity);
    302         }
    303 
    304         T* buffer() { return m_buffer; }
    305         const T* buffer() const { return m_buffer; }
    306         size_t capacity() const { return m_capacity; }
    307 
    308         void clearUnusedSlots(T* from, T* to)
    309         {
    310             VectorUnusedSlotClearer<Allocator::isGarbageCollected && (VectorTraits<T>::needsDestruction || ShouldBeTraced<VectorTraits<T> >::value), T>::clear(from, to);
    311         }
    312 
    313     protected:
    314         VectorBufferBase()
    315             : m_buffer(0)
    316             , m_capacity(0)
    317         {
    318         }
    319 
    320         VectorBufferBase(T* buffer, size_t capacity)
    321             : m_buffer(buffer)
    322             , m_capacity(capacity)
    323         {
    324         }
    325 
    326         T* m_buffer;
    327         unsigned m_capacity;
    328         unsigned m_size;
    329     };
    330 
    331     template<typename T, size_t inlineCapacity, typename Allocator = DefaultAllocator>
    332     class VectorBuffer;
    333 
    334     template<typename T, typename Allocator>
    335     class VectorBuffer<T, 0, Allocator> : protected VectorBufferBase<T, Allocator> {
    336     private:
    337         typedef VectorBufferBase<T, Allocator> Base;
    338     public:
    339         VectorBuffer()
    340         {
    341         }
    342 
    343         VectorBuffer(size_t capacity)
    344         {
    345             // Calling malloc(0) might take a lock and may actually do an
    346             // allocation on some systems.
    347             if (capacity)
    348                 allocateBuffer(capacity);
    349         }
    350 
    351         void destruct()
    352         {
    353             deallocateBuffer(m_buffer);
    354             m_buffer = 0;
    355         }
    356 
    357         void deallocateBuffer(T* bufferToDeallocate)
    358         {
    359             Allocator::backingFree(bufferToDeallocate);
    360         }
    361 
    362         void resetBufferPointer()
    363         {
    364             m_buffer = 0;
    365             m_capacity = 0;
    366         }
    367 
    368         void swapVectorBuffer(VectorBuffer<T, 0, Allocator>& other)
    369         {
    370             std::swap(m_buffer, other.m_buffer);
    371             std::swap(m_capacity, other.m_capacity);
    372         }
    373 
    374         using Base::allocateBuffer;
    375         using Base::allocationSize;
    376 
    377         using Base::buffer;
    378         using Base::capacity;
    379 
    380         using Base::clearUnusedSlots;
    381 
    382         bool hasOutOfLineBuffer() const
    383         {
    384             // When inlineCapacity is 0 we have an out of line buffer if we have a buffer.
    385             return buffer();
    386         }
    387 
    388     protected:
    389         using Base::m_size;
    390 
    391     private:
    392         using Base::m_buffer;
    393         using Base::m_capacity;
    394     };
    395 
    396     template<typename T, size_t inlineCapacity, typename Allocator>
    397     class VectorBuffer : protected VectorBufferBase<T, Allocator> {
    398         WTF_MAKE_NONCOPYABLE(VectorBuffer);
    399     private:
    400         typedef VectorBufferBase<T, Allocator> Base;
    401     public:
    402         VectorBuffer()
    403             : Base(inlineBuffer(), inlineCapacity)
    404         {
    405         }
    406 
    407         VectorBuffer(size_t capacity)
    408             : Base(inlineBuffer(), inlineCapacity)
    409         {
    410             if (capacity > inlineCapacity)
    411                 Base::allocateBuffer(capacity);
    412         }
    413 
    414         void destruct()
    415         {
    416             deallocateBuffer(m_buffer);
    417             m_buffer = 0;
    418         }
    419 
    420         NEVER_INLINE void reallyDeallocateBuffer(T* bufferToDeallocate)
    421         {
    422             Allocator::backingFree(bufferToDeallocate);
    423         }
    424 
    425         void deallocateBuffer(T* bufferToDeallocate)
    426         {
    427             if (UNLIKELY(bufferToDeallocate != inlineBuffer()))
    428                 reallyDeallocateBuffer(bufferToDeallocate);
    429         }
    430 
    431         void resetBufferPointer()
    432         {
    433             m_buffer = inlineBuffer();
    434             m_capacity = inlineCapacity;
    435         }
    436 
    437         void allocateBuffer(size_t newCapacity)
    438         {
    439             // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks.
    440             if (newCapacity > inlineCapacity)
    441                 Base::allocateBuffer(newCapacity);
    442             else
    443                 resetBufferPointer();
    444         }
    445 
    446         size_t allocationSize(size_t capacity) const
    447         {
    448             if (capacity <= inlineCapacity)
    449                 return m_inlineBufferSize;
    450             return Base::allocationSize(capacity);
    451         }
    452 
    453         void swapVectorBuffer(VectorBuffer<T, inlineCapacity, Allocator>& other)
    454         {
    455             typedef VectorTypeOperations<T> TypeOperations;
    456 
    457             if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) {
    458                 ASSERT(m_capacity == other.m_capacity);
    459                 if (m_size > other.m_size) {
    460                     TypeOperations::swap(inlineBuffer(), inlineBuffer() + other.m_size, other.inlineBuffer());
    461                     TypeOperations::move(inlineBuffer() + other.m_size, inlineBuffer() + m_size, other.inlineBuffer() + other.m_size);
    462                 } else {
    463                     TypeOperations::swap(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
    464                     TypeOperations::move(other.inlineBuffer() + m_size, other.inlineBuffer() + other.m_size, inlineBuffer() + m_size);
    465                 }
    466             } else if (buffer() == inlineBuffer()) {
    467                 m_buffer = other.m_buffer;
    468                 other.m_buffer = other.inlineBuffer();
    469                 TypeOperations::move(inlineBuffer(), inlineBuffer() + m_size, other.inlineBuffer());
    470                 std::swap(m_capacity, other.m_capacity);
    471             } else if (other.buffer() == other.inlineBuffer()) {
    472                 other.m_buffer = m_buffer;
    473                 m_buffer = inlineBuffer();
    474                 TypeOperations::move(other.inlineBuffer(), other.inlineBuffer() + other.m_size, inlineBuffer());
    475                 std::swap(m_capacity, other.m_capacity);
    476             } else {
    477                 std::swap(m_buffer, other.m_buffer);
    478                 std::swap(m_capacity, other.m_capacity);
    479             }
    480         }
    481 
    482         using Base::buffer;
    483         using Base::capacity;
    484 
    485         bool hasOutOfLineBuffer() const
    486         {
    487             return buffer() && buffer() != inlineBuffer();
    488         }
    489 
    490     protected:
    491         using Base::m_size;
    492 
    493     private:
    494         using Base::m_buffer;
    495         using Base::m_capacity;
    496 
    497         static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T);
    498         T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); }
    499         const T* inlineBuffer() const { return reinterpret_cast_ptr<const T*>(m_inlineBuffer.buffer); }
    500 
    501         AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer;
    502         template<typename U, size_t inlineBuffer, typename V>
    503         friend class Deque;
    504     };
    505 
    506     template<typename T, size_t inlineCapacity, typename Allocator>
    507     class Vector;
    508 
    509     // VectorDestructorBase defines the destructor of a vector. This base is used in order to
    510     // completely avoid creating a destructor for a vector that does not need to be destructed.
    511     // By doing so, the clang compiler will have correct information about whether or not a
    512     // vector has a trivial destructor and we use that in a compiler plugin to ensure the
    513     // correctness of non-finalized garbage-collected classes and the use of VectorTraits::needsDestruction.
    514 
    515     // All non-GC managed vectors need a destructor. This destructor will simply call finalize on the actual vector type.
    516     template<typename Derived, typename Elements, bool hasInlineCapacity, bool isGarbageCollected>
    517     class VectorDestructorBase {
    518     public:
    519         ~VectorDestructorBase() { static_cast<Derived*>(this)->finalize(); }
    520     };
    521 
    522     // Heap-allocated vectors with no inlineCapacity never need a destructor.
    523     template<typename Derived, typename Elements>
    524     class VectorDestructorBase<Derived, Elements, false, true> { };
    525 
    526     // Heap-allocator vectors with inlineCapacity need a destructor if the inline elements do.
    527     // The use of VectorTraits<Elements>::needsDestruction is delayed until we know that
    528     // inlineCapacity is non-zero to allow classes that recursively refer to themselves in vector
    529     // members. If inlineCapacity is non-zero doing so would have undefined meaning, so in this
    530     // case we can use HeapVectorWithInlineCapacityDestructorBase to define a destructor
    531     // depending on the value of VectorTraits<Elements>::needsDestruction.
    532     template<typename Derived, bool elementsNeedsDestruction>
    533     class HeapVectorWithInlineCapacityDestructorBase;
    534 
    535     template<typename Derived>
    536     class HeapVectorWithInlineCapacityDestructorBase<Derived, true> {
    537     public:
    538         ~HeapVectorWithInlineCapacityDestructorBase() { static_cast<Derived*>(this)->finalize(); }
    539     };
    540 
    541     template<typename Derived>
    542     class HeapVectorWithInlineCapacityDestructorBase<Derived, false> { };
    543 
    544     template<typename Derived, typename Elements>
    545     class VectorDestructorBase<Derived, Elements, true, true> : public HeapVectorWithInlineCapacityDestructorBase<Derived, VectorTraits<Elements>::needsDestruction> { };
    546 
    547     template<typename T, size_t inlineCapacity = 0, typename Allocator = DefaultAllocator>
    548     class Vector : private VectorBuffer<T, inlineCapacity, Allocator>, public VectorDestructorBase<Vector<T, inlineCapacity, Allocator>, T, (inlineCapacity > 0), Allocator::isGarbageCollected> {
    549         WTF_USE_ALLOCATOR(Vector, Allocator);
    550     private:
    551         typedef VectorBuffer<T, inlineCapacity, Allocator> Base;
    552         typedef VectorTypeOperations<T> TypeOperations;
    553 
    554     public:
    555         typedef T ValueType;
    556 
    557         typedef T* iterator;
    558         typedef const T* const_iterator;
    559         typedef std::reverse_iterator<iterator> reverse_iterator;
    560         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
    561 
    562         Vector()
    563         {
    564             // Unused slots are initialized to zero so that the visitor and the
    565             // finalizer can visit them safely. canInitializeWithMemset tells us
    566             // that the class does not expect matching constructor and
    567             // destructor calls as long as the memory is zeroed.
    568             COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::needsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWithFinalizersCalledOnClearedMemory);
    569             COMPILE_ASSERT(!WTF::IsPolymorphic<T>::value || !VectorTraits<T>::canInitializeWithMemset, CantInitializeWithMemsetIfThereIsAVtable);
    570             m_size = 0;
    571         }
    572 
    573         explicit Vector(size_t size)
    574             : Base(size)
    575         {
    576             // Unused slots are initialized to zero so that the visitor and the
    577             // finalizer can visit them safely. canInitializeWithMemset tells us
    578             // that the class does not expect matching constructor and
    579             // destructor calls as long as the memory is zeroed.
    580             COMPILE_ASSERT(!Allocator::isGarbageCollected || !VectorTraits<T>::needsDestruction || VectorTraits<T>::canInitializeWithMemset, ClassHasProblemsWithFinalizersCalledOnClearedMemory);
    581             m_size = size;
    582             TypeOperations::initialize(begin(), end());
    583         }
    584 
    585         // Off-GC-heap vectors: Destructor should be called.
    586         // On-GC-heap vectors: Destructor should be called for inline buffers
    587         // (if any) but destructor shouldn't be called for vector backing since
    588         // it is managed by the traced GC heap.
    589         void finalize()
    590         {
    591             if (!inlineCapacity) {
    592                 if (LIKELY(!Base::buffer()))
    593                     return;
    594             }
    595             if (LIKELY(m_size) && !(Allocator::isGarbageCollected && this->hasOutOfLineBuffer())) {
    596                 TypeOperations::destruct(begin(), end());
    597                 m_size = 0; // Partial protection against use-after-free.
    598             }
    599 
    600             Base::destruct();
    601         }
    602 
    603         void finalizeGarbageCollectedObject()
    604         {
    605             finalize();
    606         }
    607 
    608         Vector(const Vector&);
    609         template<size_t otherCapacity>
    610         explicit Vector(const Vector<T, otherCapacity, Allocator>&);
    611 
    612         Vector& operator=(const Vector&);
    613         template<size_t otherCapacity>
    614         Vector& operator=(const Vector<T, otherCapacity, Allocator>&);
    615 
    616 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
    617         Vector(Vector&&);
    618         Vector& operator=(Vector&&);
    619 #endif
    620 
    621         size_t size() const { return m_size; }
    622         size_t capacity() const { return Base::capacity(); }
    623         bool isEmpty() const { return !size(); }
    624 
    625         T& at(size_t i)
    626         {
    627             RELEASE_ASSERT(i < size());
    628             return Base::buffer()[i];
    629         }
    630         const T& at(size_t i) const
    631         {
    632             RELEASE_ASSERT(i < size());
    633             return Base::buffer()[i];
    634         }
    635 
    636         T& operator[](size_t i) { return at(i); }
    637         const T& operator[](size_t i) const { return at(i); }
    638 
    639         T* data() { return Base::buffer(); }
    640         const T* data() const { return Base::buffer(); }
    641 
    642         iterator begin() { return data(); }
    643         iterator end() { return begin() + m_size; }
    644         const_iterator begin() const { return data(); }
    645         const_iterator end() const { return begin() + m_size; }
    646 
    647         reverse_iterator rbegin() { return reverse_iterator(end()); }
    648         reverse_iterator rend() { return reverse_iterator(begin()); }
    649         const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
    650         const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
    651 
    652         T& first() { return at(0); }
    653         const T& first() const { return at(0); }
    654         T& last() { return at(size() - 1); }
    655         const T& last() const { return at(size() - 1); }
    656 
    657         template<typename U> bool contains(const U&) const;
    658         template<typename U> size_t find(const U&) const;
    659         template<typename U> size_t reverseFind(const U&) const;
    660 
    661         void shrink(size_t size);
    662         void grow(size_t size);
    663         void resize(size_t size);
    664         void reserveCapacity(size_t newCapacity);
    665         void reserveInitialCapacity(size_t initialCapacity);
    666         void shrinkToFit() { shrinkCapacity(size()); }
    667         void shrinkToReasonableCapacity()
    668         {
    669             if (size() * 2 < capacity())
    670                 shrinkCapacity(size() + size() / 4 + 1);
    671         }
    672 
    673         void clear() { shrinkCapacity(0); }
    674 
    675         template<typename U> void append(const U*, size_t);
    676         template<typename U> void append(const U&);
    677         template<typename U> void uncheckedAppend(const U& val);
    678         template<typename U, size_t otherCapacity, typename V> void appendVector(const Vector<U, otherCapacity, V>&);
    679 
    680         template<typename U> void insert(size_t position, const U*, size_t);
    681         template<typename U> void insert(size_t position, const U&);
    682         template<typename U, size_t c, typename V> void insert(size_t position, const Vector<U, c, V>&);
    683 
    684         template<typename U> void prepend(const U*, size_t);
    685         template<typename U> void prepend(const U&);
    686         template<typename U, size_t c, typename V> void prepend(const Vector<U, c, V>&);
    687 
    688         void remove(size_t position);
    689         void remove(size_t position, size_t length);
    690 
    691         void removeLast()
    692         {
    693             ASSERT(!isEmpty());
    694             shrink(size() - 1);
    695         }
    696 
    697         Vector(size_t size, const T& val)
    698             : Base(size)
    699         {
    700             m_size = size;
    701             TypeOperations::uninitializedFill(begin(), end(), val);
    702         }
    703 
    704         void fill(const T&, size_t);
    705         void fill(const T& val) { fill(val, size()); }
    706 
    707         template<typename Iterator> void appendRange(Iterator start, Iterator end);
    708 
    709         void swap(Vector& other)
    710         {
    711             Base::swapVectorBuffer(other);
    712             std::swap(m_size, other.m_size);
    713         }
    714 
    715         void reverse();
    716 
    717         void trace(typename Allocator::Visitor*);
    718 
    719     private:
    720         void expandCapacity(size_t newMinCapacity);
    721         const T* expandCapacity(size_t newMinCapacity, const T*);
    722         template<typename U> U* expandCapacity(size_t newMinCapacity, U*);
    723         void shrinkCapacity(size_t newCapacity);
    724         template<typename U> void appendSlowCase(const U&);
    725 
    726         using Base::m_size;
    727         using Base::buffer;
    728         using Base::capacity;
    729         using Base::swapVectorBuffer;
    730         using Base::allocateBuffer;
    731         using Base::allocationSize;
    732         using Base::clearUnusedSlots;
    733     };
    734 
    735     template<typename T, size_t inlineCapacity, typename Allocator>
    736     Vector<T, inlineCapacity, Allocator>::Vector(const Vector& other)
    737         : Base(other.capacity())
    738     {
    739         m_size = other.size();
    740         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
    741     }
    742 
    743     template<typename T, size_t inlineCapacity, typename Allocator>
    744     template<size_t otherCapacity>
    745     Vector<T, inlineCapacity, Allocator>::Vector(const Vector<T, otherCapacity, Allocator>& other)
    746         : Base(other.capacity())
    747     {
    748         m_size = other.size();
    749         TypeOperations::uninitializedCopy(other.begin(), other.end(), begin());
    750     }
    751 
    752     template<typename T, size_t inlineCapacity, typename Allocator>
    753     Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, inlineCapacity, Allocator>& other)
    754     {
    755         if (UNLIKELY(&other == this))
    756             return *this;
    757 
    758         if (size() > other.size())
    759             shrink(other.size());
    760         else if (other.size() > capacity()) {
    761             clear();
    762             reserveCapacity(other.size());
    763             ASSERT(begin());
    764         }
    765 
    766         std::copy(other.begin(), other.begin() + size(), begin());
    767         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
    768         m_size = other.size();
    769 
    770         return *this;
    771     }
    772 
    773     inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; }
    774 
    775     template<typename T, size_t inlineCapacity, typename Allocator>
    776     template<size_t otherCapacity>
    777     Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(const Vector<T, otherCapacity, Allocator>& other)
    778     {
    779         // If the inline capacities match, we should call the more specific
    780         // template.  If the inline capacities don't match, the two objects
    781         // shouldn't be allocated the same address.
    782         ASSERT(!typelessPointersAreEqual(&other, this));
    783 
    784         if (size() > other.size())
    785             shrink(other.size());
    786         else if (other.size() > capacity()) {
    787             clear();
    788             reserveCapacity(other.size());
    789             ASSERT(begin());
    790         }
    791 
    792         std::copy(other.begin(), other.begin() + size(), begin());
    793         TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end());
    794         m_size = other.size();
    795 
    796         return *this;
    797     }
    798 
    799 #if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES)
    800     template<typename T, size_t inlineCapacity, typename Allocator>
    801     Vector<T, inlineCapacity, Allocator>::Vector(Vector<T, inlineCapacity, Allocator>&& other)
    802     {
    803         m_size = 0;
    804         // It's a little weird to implement a move constructor using swap but this way we
    805         // don't have to add a move constructor to VectorBuffer.
    806         swap(other);
    807     }
    808 
    809     template<typename T, size_t inlineCapacity, typename Allocator>
    810     Vector<T, inlineCapacity, Allocator>& Vector<T, inlineCapacity, Allocator>::operator=(Vector<T, inlineCapacity, Allocator>&& other)
    811     {
    812         swap(other);
    813         return *this;
    814     }
    815 #endif
    816 
    817     template<typename T, size_t inlineCapacity, typename Allocator>
    818     template<typename U>
    819     bool Vector<T, inlineCapacity, Allocator>::contains(const U& value) const
    820     {
    821         return find(value) != kNotFound;
    822     }
    823 
    824     template<typename T, size_t inlineCapacity, typename Allocator>
    825     template<typename U>
    826     size_t Vector<T, inlineCapacity, Allocator>::find(const U& value) const
    827     {
    828         const T* b = begin();
    829         const T* e = end();
    830         for (const T* iter = b; iter < e; ++iter) {
    831             if (*iter == value)
    832                 return iter - b;
    833         }
    834         return kNotFound;
    835     }
    836 
    837     template<typename T, size_t inlineCapacity, typename Allocator>
    838     template<typename U>
    839     size_t Vector<T, inlineCapacity, Allocator>::reverseFind(const U& value) const
    840     {
    841         const T* b = begin();
    842         const T* iter = end();
    843         while (iter > b) {
    844             --iter;
    845             if (*iter == value)
    846                 return iter - b;
    847         }
    848         return kNotFound;
    849     }
    850 
    851     template<typename T, size_t inlineCapacity, typename Allocator>
    852     void Vector<T, inlineCapacity, Allocator>::fill(const T& val, size_t newSize)
    853     {
    854         if (size() > newSize)
    855             shrink(newSize);
    856         else if (newSize > capacity()) {
    857             clear();
    858             reserveCapacity(newSize);
    859             ASSERT(begin());
    860         }
    861 
    862         std::fill(begin(), end(), val);
    863         TypeOperations::uninitializedFill(end(), begin() + newSize, val);
    864         m_size = newSize;
    865     }
    866 
    867     template<typename T, size_t inlineCapacity, typename Allocator>
    868     template<typename Iterator>
    869     void Vector<T, inlineCapacity, Allocator>::appendRange(Iterator start, Iterator end)
    870     {
    871         for (Iterator it = start; it != end; ++it)
    872             append(*it);
    873     }
    874 
    875     template<typename T, size_t inlineCapacity, typename Allocator>
    876     void Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity)
    877     {
    878         size_t oldCapacity = capacity();
    879         size_t expandedCapacity = oldCapacity;
    880         // We use a more aggressive expansion strategy for Vectors with inline storage.
    881         // This is because they are more likely to be on the stack, so the risk of heap bloat is minimized.
    882         // Furthermore, exceeding the inline capacity limit is not supposed to happen in the common case and may indicate a pathological condition or microbenchmark.
    883         if (inlineCapacity) {
    884             expandedCapacity *= 2;
    885             // Check for integer overflow, which could happen in the 32-bit build.
    886             RELEASE_ASSERT(expandedCapacity > oldCapacity);
    887         } else {
    888             // This cannot integer overflow.
    889             // On 64-bit, the "expanded" integer is 32-bit, and any encroachment above 2^32 will fail allocation in allocateBuffer().
    890             // On 32-bit, there's not enough address space to hold the old and new buffers.
    891             // In addition, our underlying allocator is supposed to always fail on > (2^31 - 1) allocations.
    892             expandedCapacity += (expandedCapacity / 4) + 1;
    893         }
    894         reserveCapacity(std::max(newMinCapacity, std::max(static_cast<size_t>(kInitialVectorSize), expandedCapacity)));
    895     }
    896 
    897     template<typename T, size_t inlineCapacity, typename Allocator>
    898     const T* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, const T* ptr)
    899     {
    900         if (ptr < begin() || ptr >= end()) {
    901             expandCapacity(newMinCapacity);
    902             return ptr;
    903         }
    904         size_t index = ptr - begin();
    905         expandCapacity(newMinCapacity);
    906         return begin() + index;
    907     }
    908 
    909     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
    910     inline U* Vector<T, inlineCapacity, Allocator>::expandCapacity(size_t newMinCapacity, U* ptr)
    911     {
    912         expandCapacity(newMinCapacity);
    913         return ptr;
    914     }
    915 
    916     template<typename T, size_t inlineCapacity, typename Allocator>
    917     inline void Vector<T, inlineCapacity, Allocator>::resize(size_t size)
    918     {
    919         if (size <= m_size)
    920             TypeOperations::destruct(begin() + size, end());
    921         else {
    922             if (size > capacity())
    923                 expandCapacity(size);
    924             TypeOperations::initialize(end(), begin() + size);
    925         }
    926 
    927         m_size = size;
    928     }
    929 
    930     template<typename T, size_t inlineCapacity, typename Allocator>
    931     void Vector<T, inlineCapacity, Allocator>::shrink(size_t size)
    932     {
    933         ASSERT(size <= m_size);
    934         TypeOperations::destruct(begin() + size, end());
    935         clearUnusedSlots(begin() + size, end());
    936         m_size = size;
    937     }
    938 
    939     template<typename T, size_t inlineCapacity, typename Allocator>
    940     void Vector<T, inlineCapacity, Allocator>::grow(size_t size)
    941     {
    942         ASSERT(size >= m_size);
    943         if (size > capacity())
    944             expandCapacity(size);
    945         TypeOperations::initialize(end(), begin() + size);
    946         m_size = size;
    947     }
    948 
    949     template<typename T, size_t inlineCapacity, typename Allocator>
    950     void Vector<T, inlineCapacity, Allocator>::reserveCapacity(size_t newCapacity)
    951     {
    952         if (UNLIKELY(newCapacity <= capacity()))
    953             return;
    954         T* oldBuffer = begin();
    955         T* oldEnd = end();
    956         Base::allocateBuffer(newCapacity);
    957         TypeOperations::move(oldBuffer, oldEnd, begin());
    958         Base::deallocateBuffer(oldBuffer);
    959     }
    960 
    961     template<typename T, size_t inlineCapacity, typename Allocator>
    962     inline void Vector<T, inlineCapacity, Allocator>::reserveInitialCapacity(size_t initialCapacity)
    963     {
    964         ASSERT(!m_size);
    965         ASSERT(capacity() == inlineCapacity);
    966         if (initialCapacity > inlineCapacity)
    967             Base::allocateBuffer(initialCapacity);
    968     }
    969 
    970     template<typename T, size_t inlineCapacity, typename Allocator>
    971     void Vector<T, inlineCapacity, Allocator>::shrinkCapacity(size_t newCapacity)
    972     {
    973         if (newCapacity >= capacity())
    974             return;
    975 
    976         if (newCapacity < size())
    977             shrink(newCapacity);
    978 
    979         T* oldBuffer = begin();
    980         if (newCapacity > 0) {
    981             // Optimization: if we're downsizing inside the same allocator bucket, we can exit with no additional work.
    982             if (Base::allocationSize(capacity()) == Base::allocationSize(newCapacity))
    983                 return;
    984 
    985             T* oldEnd = end();
    986             Base::allocateBuffer(newCapacity);
    987             if (begin() != oldBuffer)
    988                 TypeOperations::move(oldBuffer, oldEnd, begin());
    989         } else {
    990             Base::resetBufferPointer();
    991         }
    992 
    993         Base::deallocateBuffer(oldBuffer);
    994     }
    995 
    996     // Templatizing these is better than just letting the conversion happen implicitly,
    997     // because for instance it allows a PassRefPtr to be appended to a RefPtr vector
    998     // without refcount thrash.
    999 
   1000     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1001     void Vector<T, inlineCapacity, Allocator>::append(const U* data, size_t dataSize)
   1002     {
   1003         ASSERT(Allocator::isAllocationAllowed());
   1004         size_t newSize = m_size + dataSize;
   1005         if (newSize > capacity()) {
   1006             data = expandCapacity(newSize, data);
   1007             ASSERT(begin());
   1008         }
   1009         RELEASE_ASSERT(newSize >= m_size);
   1010         T* dest = end();
   1011         VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], dest);
   1012         m_size = newSize;
   1013     }
   1014 
   1015     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1016     ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::append(const U& val)
   1017     {
   1018         ASSERT(Allocator::isAllocationAllowed());
   1019         if (LIKELY(size() != capacity())) {
   1020             new (NotNull, end()) T(val);
   1021             ++m_size;
   1022             return;
   1023         }
   1024 
   1025         appendSlowCase(val);
   1026     }
   1027 
   1028     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1029     NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::appendSlowCase(const U& val)
   1030     {
   1031         ASSERT(size() == capacity());
   1032 
   1033         const U* ptr = &val;
   1034         ptr = expandCapacity(size() + 1, ptr);
   1035         ASSERT(begin());
   1036 
   1037         new (NotNull, end()) T(*ptr);
   1038         ++m_size;
   1039     }
   1040 
   1041     // This version of append saves a branch in the case where you know that the
   1042     // vector's capacity is large enough for the append to succeed.
   1043 
   1044     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1045     ALWAYS_INLINE void Vector<T, inlineCapacity, Allocator>::uncheckedAppend(const U& val)
   1046     {
   1047         ASSERT(size() < capacity());
   1048         const U* ptr = &val;
   1049         new (NotNull, end()) T(*ptr);
   1050         ++m_size;
   1051     }
   1052 
   1053     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t otherCapacity, typename OtherAllocator>
   1054     inline void Vector<T, inlineCapacity, Allocator>::appendVector(const Vector<U, otherCapacity, OtherAllocator>& val)
   1055     {
   1056         append(val.begin(), val.size());
   1057     }
   1058 
   1059     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1060     void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U* data, size_t dataSize)
   1061     {
   1062         ASSERT(Allocator::isAllocationAllowed());
   1063         RELEASE_ASSERT(position <= size());
   1064         size_t newSize = m_size + dataSize;
   1065         if (newSize > capacity()) {
   1066             data = expandCapacity(newSize, data);
   1067             ASSERT(begin());
   1068         }
   1069         RELEASE_ASSERT(newSize >= m_size);
   1070         T* spot = begin() + position;
   1071         TypeOperations::moveOverlapping(spot, end(), spot + dataSize);
   1072         VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(data, &data[dataSize], spot);
   1073         m_size = newSize;
   1074     }
   1075 
   1076     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1077     inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const U& val)
   1078     {
   1079         ASSERT(Allocator::isAllocationAllowed());
   1080         RELEASE_ASSERT(position <= size());
   1081         const U* data = &val;
   1082         if (size() == capacity()) {
   1083             data = expandCapacity(size() + 1, data);
   1084             ASSERT(begin());
   1085         }
   1086         T* spot = begin() + position;
   1087         TypeOperations::moveOverlapping(spot, end(), spot + 1);
   1088         new (NotNull, spot) T(*data);
   1089         ++m_size;
   1090     }
   1091 
   1092     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t c, typename OtherAllocator>
   1093     inline void Vector<T, inlineCapacity, Allocator>::insert(size_t position, const Vector<U, c, OtherAllocator>& val)
   1094     {
   1095         insert(position, val.begin(), val.size());
   1096     }
   1097 
   1098     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1099     void Vector<T, inlineCapacity, Allocator>::prepend(const U* data, size_t dataSize)
   1100     {
   1101         insert(0, data, dataSize);
   1102     }
   1103 
   1104     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U>
   1105     inline void Vector<T, inlineCapacity, Allocator>::prepend(const U& val)
   1106     {
   1107         insert(0, val);
   1108     }
   1109 
   1110     template<typename T, size_t inlineCapacity, typename Allocator> template<typename U, size_t c, typename V>
   1111     inline void Vector<T, inlineCapacity, Allocator>::prepend(const Vector<U, c, V>& val)
   1112     {
   1113         insert(0, val.begin(), val.size());
   1114     }
   1115 
   1116     template<typename T, size_t inlineCapacity, typename Allocator>
   1117     inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position)
   1118     {
   1119         RELEASE_ASSERT(position < size());
   1120         T* spot = begin() + position;
   1121         spot->~T();
   1122         TypeOperations::moveOverlapping(spot + 1, end(), spot);
   1123         clearUnusedSlots(end() - 1, end());
   1124         --m_size;
   1125     }
   1126 
   1127     template<typename T, size_t inlineCapacity, typename Allocator>
   1128     inline void Vector<T, inlineCapacity, Allocator>::remove(size_t position, size_t length)
   1129     {
   1130         ASSERT_WITH_SECURITY_IMPLICATION(position <= size());
   1131         RELEASE_ASSERT(position + length <= size());
   1132         T* beginSpot = begin() + position;
   1133         T* endSpot = beginSpot + length;
   1134         TypeOperations::destruct(beginSpot, endSpot);
   1135         TypeOperations::moveOverlapping(endSpot, end(), beginSpot);
   1136         clearUnusedSlots(end() - length, end());
   1137         m_size -= length;
   1138     }
   1139 
   1140     template<typename T, size_t inlineCapacity, typename Allocator>
   1141     inline void Vector<T, inlineCapacity, Allocator>::reverse()
   1142     {
   1143         for (size_t i = 0; i < m_size / 2; ++i)
   1144             std::swap(at(i), at(m_size - 1 - i));
   1145     }
   1146 
   1147     template<typename T, size_t inlineCapacity, typename Allocator>
   1148     void deleteAllValues(const Vector<T, inlineCapacity, Allocator>& collection)
   1149     {
   1150         typedef typename Vector<T, inlineCapacity, Allocator>::const_iterator iterator;
   1151         iterator end = collection.end();
   1152         for (iterator it = collection.begin(); it != end; ++it)
   1153             delete *it;
   1154     }
   1155 
   1156     template<typename T, size_t inlineCapacity, typename Allocator>
   1157     inline void swap(Vector<T, inlineCapacity, Allocator>& a, Vector<T, inlineCapacity, Allocator>& b)
   1158     {
   1159         a.swap(b);
   1160     }
   1161 
   1162     template<typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
   1163     bool operator==(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
   1164     {
   1165         if (a.size() != b.size())
   1166             return false;
   1167 
   1168         return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size());
   1169     }
   1170 
   1171     template<typename T, size_t inlineCapacityA, size_t inlineCapacityB, typename Allocator>
   1172     inline bool operator!=(const Vector<T, inlineCapacityA, Allocator>& a, const Vector<T, inlineCapacityB, Allocator>& b)
   1173     {
   1174         return !(a == b);
   1175     }
   1176 
   1177     // This is only called if the allocator is a HeapAllocator. It is used when
   1178     // visiting during a tracing GC.
   1179     template<typename T, size_t inlineCapacity, typename Allocator>
   1180     void Vector<T, inlineCapacity, Allocator>::trace(typename Allocator::Visitor* visitor)
   1181     {
   1182         ASSERT(Allocator::isGarbageCollected); // Garbage collector must be enabled.
   1183         const T* bufferBegin = buffer();
   1184         const T* bufferEnd = buffer() + size();
   1185         if (ShouldBeTraced<VectorTraits<T> >::value) {
   1186             for (const T* bufferEntry = bufferBegin; bufferEntry != bufferEnd; bufferEntry++)
   1187                 Allocator::template trace<T, VectorTraits<T> >(visitor, *const_cast<T*>(bufferEntry));
   1188         }
   1189         if (this->hasOutOfLineBuffer())
   1190             Allocator::markNoTracing(visitor, buffer());
   1191     }
   1192 
   1193 #if !ENABLE(OILPAN)
   1194     template<typename T, size_t N>
   1195     struct NeedsTracing<Vector<T, N> > {
   1196         static const bool value = false;
   1197     };
   1198 #endif
   1199 
   1200 } // namespace WTF
   1201 
   1202 using WTF::Vector;
   1203 
   1204 #endif // WTF_Vector_h
   1205