LCOV - code coverage report
Current view: top level - mfbt - Vector.h (source / functions) Hit Total Coverage
Test: output.info Lines: 425 511 83.2 %
Date: 2017-07-14 16:53:18 Functions: 5646 13413 42.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* A type/length-parametrized vector class. */
       8             : 
       9             : #ifndef mozilla_Vector_h
      10             : #define mozilla_Vector_h
      11             : 
      12             : #include "mozilla/Alignment.h"
      13             : #include "mozilla/AllocPolicy.h"
      14             : #include "mozilla/ArrayUtils.h" // for PointerRangeSize
      15             : #include "mozilla/Assertions.h"
      16             : #include "mozilla/Attributes.h"
      17             : #include "mozilla/MathAlgorithms.h"
      18             : #include "mozilla/MemoryReporting.h"
      19             : #include "mozilla/Move.h"
      20             : #include "mozilla/OperatorNewExtensions.h"
      21             : #include "mozilla/ReentrancyGuard.h"
      22             : #include "mozilla/TemplateLib.h"
      23             : #include "mozilla/TypeTraits.h"
      24             : 
      25             : #include <new> // for placement new
      26             : 
      27             : /* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
      28             : #ifdef _MSC_VER
      29             : #pragma warning(push)
      30             : #pragma warning(disable:4345)
      31             : #endif
      32             : 
      33             : namespace mozilla {
      34             : 
      35             : template<typename T, size_t N, class AllocPolicy>
      36             : class Vector;
      37             : 
      38             : namespace detail {
      39             : 
      40             : /*
      41             :  * Check that the given capacity wastes the minimal amount of space if
      42             :  * allocated on the heap. This means that aCapacity*sizeof(T) is as close to a
      43             :  * power-of-two as possible. growStorageBy() is responsible for ensuring this.
      44             :  */
      45             : template<typename T>
      46      139654 : static bool CapacityHasExcessSpace(size_t aCapacity)
      47             : {
      48      139654 :   size_t size = aCapacity * sizeof(T);
      49      139654 :   return RoundUpPow2(size) - size >= sizeof(T);
      50             : }
      51             : 
      52             : /*
      53             :  * This template class provides a default implementation for vector operations
      54             :  * when the element type is not known to be a POD, as judged by IsPod.
      55             :  */
      56             : template<typename T, size_t N, class AP, bool IsPod>
      57             : struct VectorImpl
      58             : {
      59             :   /*
      60             :    * Constructs an object in the uninitialized memory at *aDst with aArgs.
      61             :    */
      62             :   template<typename... Args>
      63             :   MOZ_NONNULL(1)
      64      633172 :   static inline void new_(T* aDst, Args&&... aArgs)
      65             :   {
      66      633172 :     new(KnownNotNull, aDst) T(Forward<Args>(aArgs)...);
      67      633172 :   }
      68             : 
      69             :   /* Destroys constructed objects in the range [aBegin, aEnd). */
      70      497837 :   static inline void destroy(T* aBegin, T* aEnd)
      71             :   {
      72      497837 :     MOZ_ASSERT(aBegin <= aEnd);
      73      527543 :     for (T* p = aBegin; p < aEnd; ++p) {
      74       29706 :       p->~T();
      75             :     }
      76      497837 :   }
      77             : 
      78             :   /* Constructs objects in the uninitialized range [aBegin, aEnd). */
      79        8871 :   static inline void initialize(T* aBegin, T* aEnd)
      80             :   {
      81        8871 :     MOZ_ASSERT(aBegin <= aEnd);
      82       40577 :     for (T* p = aBegin; p < aEnd; ++p) {
      83       31706 :       new_(p);
      84             :     }
      85        8871 :   }
      86             : 
      87             :   /*
      88             :    * Copy-constructs objects in the uninitialized range
      89             :    * [aDst, aDst+(aSrcEnd-aSrcStart)) from the range [aSrcStart, aSrcEnd).
      90             :    */
      91             :   template<typename U>
      92        7153 :   static inline void copyConstruct(T* aDst,
      93             :                                    const U* aSrcStart, const U* aSrcEnd)
      94             :   {
      95        7153 :     MOZ_ASSERT(aSrcStart <= aSrcEnd);
      96        7309 :     for (const U* p = aSrcStart; p < aSrcEnd; ++p, ++aDst) {
      97         156 :       new_(aDst, *p);
      98             :     }
      99        7153 :   }
     100             : 
     101             :   /*
     102             :    * Move-constructs objects in the uninitialized range
     103             :    * [aDst, aDst+(aSrcEnd-aSrcStart)) from the range [aSrcStart, aSrcEnd).
     104             :    */
     105             :   template<typename U>
     106       89520 :   static inline void moveConstruct(T* aDst, U* aSrcStart, U* aSrcEnd)
     107             :   {
     108       89520 :     MOZ_ASSERT(aSrcStart <= aSrcEnd);
     109      145197 :     for (U* p = aSrcStart; p < aSrcEnd; ++p, ++aDst) {
     110       55677 :       new_(aDst, Move(*p));
     111             :     }
     112       89520 :   }
     113             : 
     114             :   /*
     115             :    * Copy-constructs objects in the uninitialized range [aDst, aDst+aN) from
     116             :    * the same object aU.
     117             :    */
     118             :   template<typename U>
     119        8004 :   static inline void copyConstructN(T* aDst, size_t aN, const U& aU)
     120             :   {
     121       32418 :     for (T* end = aDst + aN; aDst < end; ++aDst) {
     122       24414 :       new_(aDst, aU);
     123             :     }
     124        8004 :   }
     125             : 
     126             :   /*
     127             :    * Grows the given buffer to have capacity aNewCap, preserving the objects
     128             :    * constructed in the range [begin, end) and updating aV. Assumes that (1)
     129             :    * aNewCap has not overflowed, and (2) multiplying aNewCap by sizeof(T) will
     130             :    * not overflow.
     131             :    */
     132             :   static inline MOZ_MUST_USE bool
     133       19253 :   growTo(Vector<T, N, AP>& aV, size_t aNewCap)
     134             :   {
     135       19253 :     MOZ_ASSERT(!aV.usingInlineStorage());
     136       19253 :     MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
     137       19253 :     T* newbuf = aV.template pod_malloc<T>(aNewCap);
     138       19253 :     if (MOZ_UNLIKELY(!newbuf)) {
     139           0 :       return false;
     140             :     }
     141       19253 :     T* dst = newbuf;
     142       19253 :     T* src = aV.beginNoCheck();
     143      393143 :     for (; src < aV.endNoCheck(); ++dst, ++src) {
     144      186945 :       new_(dst, Move(*src));
     145             :     }
     146       19253 :     VectorImpl::destroy(aV.beginNoCheck(), aV.endNoCheck());
     147       19253 :     aV.free_(aV.mBegin);
     148       19253 :     aV.mBegin = newbuf;
     149             :     /* aV.mLength is unchanged. */
     150       19253 :     aV.mTail.mCapacity = aNewCap;
     151       19253 :     return true;
     152             :   }
     153             : };
     154             : 
     155             : /*
     156             :  * This partial template specialization provides a default implementation for
     157             :  * vector operations when the element type is known to be a POD, as judged by
     158             :  * IsPod.
     159             :  */
     160             : template<typename T, size_t N, class AP>
     161             : struct VectorImpl<T, N, AP, true>
     162             : {
     163             :   template<typename... Args>
     164             :   MOZ_NONNULL(1)
     165     8748445 :   static inline void new_(T* aDst, Args&&... aArgs)
     166             :   {
     167             :     // Explicitly construct a local object instead of using a temporary since
     168             :     // T(args...) will be treated like a C-style cast in the unary case and
     169             :     // allow unsafe conversions. Both forms should be equivalent to an
     170             :     // optimizing compiler.
     171     8748445 :     T temp(Forward<Args>(aArgs)...);
     172     8748417 :     *aDst = temp;
     173     8748417 :   }
     174             : 
     175      393339 :   static inline void destroy(T*, T*) {}
     176             : 
     177      709128 :   static inline void initialize(T* aBegin, T* aEnd)
     178             :   {
     179             :     /*
     180             :      * You would think that memset would be a big win (or even break even)
     181             :      * when we know T is a POD. But currently it's not. This is probably
     182             :      * because |append| tends to be given small ranges and memset requires
     183             :      * a function call that doesn't get inlined.
     184             :      *
     185             :      * memset(aBegin, 0, sizeof(T) * (aEnd - aBegin));
     186             :      */
     187      709128 :     MOZ_ASSERT(aBegin <= aEnd);
     188     2153744 :     for (T* p = aBegin; p < aEnd; ++p) {
     189     1444616 :       new_(p);
     190             :     }
     191      709128 :   }
     192             : 
     193             :   template<typename U>
     194     3844740 :   static inline void copyConstruct(T* aDst,
     195             :                                    const U* aSrcStart, const U* aSrcEnd)
     196             :   {
     197             :     /*
     198             :      * See above memset comment. Also, notice that copyConstruct is
     199             :      * currently templated (T != U), so memcpy won't work without
     200             :      * requiring T == U.
     201             :      *
     202             :      * memcpy(aDst, aSrcStart, sizeof(T) * (aSrcEnd - aSrcStart));
     203             :      */
     204     3844740 :     MOZ_ASSERT(aSrcStart <= aSrcEnd);
     205     9849672 :     for (const U* p = aSrcStart; p < aSrcEnd; ++p, ++aDst) {
     206     6004794 :       new_(aDst, *p);
     207             :     }
     208     3844878 :   }
     209             : 
     210             :   template<typename U>
     211       79339 :   static inline void moveConstruct(T* aDst,
     212             :                                    const U* aSrcStart, const U* aSrcEnd)
     213             :   {
     214       79339 :     copyConstruct(aDst, aSrcStart, aSrcEnd);
     215       79339 :   }
     216             : 
     217          51 :   static inline void copyConstructN(T* aDst, size_t aN, const T& aT)
     218             :   {
     219        6028 :     for (T* end = aDst + aN; aDst < end; ++aDst) {
     220        5977 :       new_(aDst, aT);
     221             :     }
     222          51 :   }
     223             : 
     224             :   static inline MOZ_MUST_USE bool
     225       16663 :   growTo(Vector<T, N, AP>& aV, size_t aNewCap)
     226             :   {
     227       16663 :     MOZ_ASSERT(!aV.usingInlineStorage());
     228       16663 :     MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
     229             :     T* newbuf =
     230       16663 :       aV.template pod_realloc<T>(aV.mBegin, aV.mTail.mCapacity, aNewCap);
     231       16663 :     if (MOZ_UNLIKELY(!newbuf)) {
     232           0 :       return false;
     233             :     }
     234       16663 :     aV.mBegin = newbuf;
     235             :     /* aV.mLength is unchanged. */
     236       16663 :     aV.mTail.mCapacity = aNewCap;
     237       16663 :     return true;
     238             :   }
     239             : 
     240             :   static inline void
     241           0 :   podResizeToFit(Vector<T, N, AP>& aV)
     242             :   {
     243           0 :     if (aV.usingInlineStorage() || aV.mLength == aV.mTail.mCapacity) {
     244           0 :       return;
     245             :     }
     246             :     T* newbuf =
     247           0 :       aV.template pod_realloc<T>(aV.mBegin, aV.mTail.mCapacity, aV.mLength);
     248           0 :     if (MOZ_UNLIKELY(!newbuf)) {
     249           0 :       return;
     250             :     }
     251           0 :     aV.mBegin = newbuf;
     252           0 :     aV.mTail.mCapacity = aV.mLength;
     253             :   }
     254             : };
     255             : 
     256             : // A struct for TestVector.cpp to access private internal fields.
     257             : // DO NOT DEFINE IN YOUR OWN CODE.
     258             : struct VectorTesting;
     259             : 
     260             : } // namespace detail
     261             : 
     262             : /*
     263             :  * STL-like container providing a short-lived, dynamic buffer.  Vector calls the
     264             :  * constructors/destructors of all elements stored in its internal buffer, so
     265             :  * non-PODs may be safely used.  Additionally, Vector will store the first N
     266             :  * elements in-place before resorting to dynamic allocation.
     267             :  *
     268             :  * T requirements:
     269             :  *  - default and copy constructible, assignable, destructible
     270             :  *  - operations do not throw
     271             :  * MinInlineCapacity requirements:
     272             :  *  - any value, however, MinInlineCapacity is clamped to min/max values
     273             :  * AllocPolicy:
     274             :  *  - see "Allocation policies" in AllocPolicy.h (defaults to
     275             :  *    mozilla::MallocAllocPolicy)
     276             :  *
     277             :  * Vector is not reentrant: T member functions called during Vector member
     278             :  * functions must not call back into the same object!
     279             :  */
     280             : template<typename T,
     281             :          size_t MinInlineCapacity = 0,
     282             :          class AllocPolicy = MallocAllocPolicy>
     283             : class MOZ_NON_PARAM Vector final : private AllocPolicy
     284             : {
     285             :   /* utilities */
     286             : 
     287             :   static const bool kElemIsPod = IsPod<T>::value;
     288             :   typedef detail::VectorImpl<T, MinInlineCapacity, AllocPolicy, kElemIsPod> Impl;
     289             :   friend struct detail::VectorImpl<T, MinInlineCapacity, AllocPolicy, kElemIsPod>;
     290             : 
     291             :   friend struct detail::VectorTesting;
     292             : 
     293             :   MOZ_MUST_USE bool growStorageBy(size_t aIncr);
     294             :   MOZ_MUST_USE bool convertToHeapStorage(size_t aNewCap);
     295             :   MOZ_MUST_USE bool maybeCheckSimulatedOOM(size_t aRequestedSize);
     296             : 
     297             :   /* magic constants */
     298             : 
     299             :   /**
     300             :    * The maximum space allocated for inline element storage.
     301             :    *
     302             :    * We reduce space by what the AllocPolicy base class and prior Vector member
     303             :    * fields likely consume to attempt to play well with binary size classes.
     304             :    */
     305             :   static constexpr size_t kMaxInlineBytes =
     306             :     1024 - (sizeof(AllocPolicy) + sizeof(T*) + sizeof(size_t) + sizeof(size_t));
     307             : 
     308             :   /**
     309             :    * The number of T elements of inline capacity built into this Vector.  This
     310             :    * is usually |MinInlineCapacity|, but it may be less (or zero!) for large T.
     311             :    *
     312             :    * We use a partially-specialized template (not explicit specialization, which
     313             :    * is only allowed at namespace scope) to compute this value.  The benefit is
     314             :    * that |sizeof(T)| need not be computed, and |T| doesn't have to be fully
     315             :    * defined at the time |Vector<T>| appears, if no inline storage is requested.
     316             :    */
     317             :   template<size_t MinimumInlineCapacity, size_t Dummy>
     318             :   struct ComputeCapacity
     319             :   {
     320             :     static constexpr size_t value =
     321             :       tl::Min<MinimumInlineCapacity, kMaxInlineBytes / sizeof(T)>::value;
     322             :   };
     323             : 
     324             :   template<size_t Dummy>
     325             :   struct ComputeCapacity<0, Dummy>
     326             :   {
     327             :     static constexpr size_t value = 0;
     328             :   };
     329             : 
     330             :   /** The actual inline capacity in number of elements T.  This may be zero! */
     331             :   static constexpr size_t kInlineCapacity =
     332             :     ComputeCapacity<MinInlineCapacity, 0>::value;
     333             : 
     334             :   /* member data */
     335             : 
     336             :   /*
     337             :    * Pointer to the buffer, be it inline or heap-allocated. Only [mBegin,
     338             :    * mBegin + mLength) hold valid constructed T objects. The range [mBegin +
     339             :    * mLength, mBegin + mCapacity) holds uninitialized memory. The range
     340             :    * [mBegin + mLength, mBegin + mReserved) also holds uninitialized memory
     341             :    * previously allocated by a call to reserve().
     342             :    */
     343             :   T* mBegin;
     344             : 
     345             :   /* Number of elements in the vector. */
     346             :   size_t mLength;
     347             : 
     348             :   /*
     349             :    * Memory used to store capacity, reserved element count (debug builds only),
     350             :    * and inline storage.  The simple "answer" is:
     351             :    *
     352             :    *   size_t mCapacity;
     353             :    *   #ifdef DEBUG
     354             :    *   size_t mReserved;
     355             :    *   #endif
     356             :    *   alignas(T) unsigned char mBytes[kInlineCapacity * sizeof(T)];
     357             :    *
     358             :    * but there are complications.  First, C++ forbids zero-sized arrays that
     359             :    * might result.  Second, we don't want zero capacity to affect Vector's size
     360             :    * (even empty classes take up a byte, unless they're base classes).
     361             :    *
     362             :    * Yet again, we eliminate the zero-sized array using partial specialization.
     363             :    * And we eliminate potential size hit by putting capacity/reserved in one
     364             :    * struct, then putting the array (if any) in a derived struct.  If no array
     365             :    * is needed, the derived struct won't consume extra space.
     366             :    */
     367             :   struct CapacityAndReserved
     368             :   {
     369      622150 :     explicit CapacityAndReserved(size_t aCapacity, size_t aReserved)
     370             :       : mCapacity(aCapacity)
     371             : #ifdef DEBUG
     372      622150 :       , mReserved(aReserved)
     373             : #endif
     374      622150 :     {}
     375       98639 :     CapacityAndReserved() = default;
     376             : 
     377             :     /* Max number of elements storable in the vector without resizing. */
     378             :     size_t mCapacity;
     379             : 
     380             : #ifdef DEBUG
     381             :     /* Max elements of reserved or used space in this vector. */
     382             :     size_t mReserved;
     383             : #endif
     384             :   };
     385             : 
     386             : // Silence warnings about this struct possibly being padded dued to the
     387             : // alignas() in it -- there's nothing we can do to avoid it.
     388             : #ifdef _MSC_VER
     389             : #  pragma warning(push)
     390             : #  pragma warning(disable:4324)
     391             : #endif // _MSC_VER
     392             : 
     393             :   template<size_t Capacity, size_t Dummy>
     394             :   struct CRAndStorage : CapacityAndReserved
     395             :   {
     396      431891 :     explicit CRAndStorage(size_t aCapacity, size_t aReserved)
     397      431891 :       : CapacityAndReserved(aCapacity, aReserved)
     398      431890 :     {}
     399       61241 :     CRAndStorage() = default;
     400             : 
     401             :     alignas(T) unsigned char mBytes[Capacity * sizeof(T)];
     402             : 
     403             :     // GCC fails due to -Werror=strict-aliasing if |mBytes| is directly cast to
     404             :     // T*.  Indirecting through this function addresses the problem.
     405     4119988 :     void* data() { return mBytes; }
     406             : 
     407     4119988 :     T* storage() { return static_cast<T*>(data()); }
     408             :   };
     409             : 
     410             :   template<size_t Dummy>
     411             :   struct CRAndStorage<0, Dummy> : CapacityAndReserved
     412             :   {
     413      190261 :     explicit CRAndStorage(size_t aCapacity, size_t aReserved)
     414      190261 :       : CapacityAndReserved(aCapacity, aReserved)
     415      190261 :     {}
     416       37398 :     CRAndStorage() = default;
     417             : 
     418     2494835 :     T* storage() { return nullptr; }
     419             :   };
     420             : 
     421             :   CRAndStorage<kInlineCapacity, 0> mTail;
     422             : 
     423             : #ifdef _MSC_VER
     424             : #  pragma warning(pop)
     425             : #endif // _MSC_VER
     426             : 
     427             : #ifdef DEBUG
     428             :   friend class ReentrancyGuard;
     429             :   bool mEntered;
     430             : #endif
     431             : 
     432             :   /* private accessors */
     433             : 
     434     5893592 :   bool usingInlineStorage() const
     435             :   {
     436     5893592 :     return mBegin == const_cast<Vector*>(this)->inlineStorage();
     437             :   }
     438             : 
     439     6614862 :   T* inlineStorage()
     440             :   {
     441     6614862 :     return mTail.storage();
     442             :   }
     443             : 
     444     1144172 :   T* beginNoCheck() const
     445             :   {
     446     1144172 :     return mBegin;
     447             :   }
     448             : 
     449     8411588 :   T* endNoCheck()
     450             :   {
     451     8411588 :     return mBegin + mLength;
     452             :   }
     453             : 
     454             :   const T* endNoCheck() const
     455             :   {
     456             :     return mBegin + mLength;
     457             :   }
     458             : 
     459             : #ifdef DEBUG
     460             :   /**
     461             :    * The amount of explicitly allocated space in this vector that is immediately
     462             :    * available to be filled by appending additional elements.  This value is
     463             :    * always greater than or equal to |length()| -- the vector's actual elements
     464             :    * are implicitly reserved.  This value is always less than or equal to
     465             :    * |capacity()|.  It may be explicitly increased using the |reserve()| method.
     466             :    */
     467     9978392 :   size_t reserved() const
     468             :   {
     469     9978392 :     MOZ_ASSERT(mLength <= mTail.mReserved);
     470     9978392 :     MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
     471     9978392 :     return mTail.mReserved;
     472             :   }
     473             : #endif
     474             : 
     475             :   /* Append operations guaranteed to succeed due to pre-reserved space. */
     476             :   template<typename U> void internalAppend(U&& aU);
     477             :   template<typename U, size_t O, class BP>
     478             :   void internalAppendAll(const Vector<U, O, BP>& aU);
     479             :   void internalAppendN(const T& aT, size_t aN);
     480             :   template<typename U> void internalAppend(const U* aBegin, size_t aLength);
     481             : 
     482             : public:
     483             :   static const size_t sMaxInlineStorage = MinInlineCapacity;
     484             : 
     485             :   typedef T ElementType;
     486             : 
     487             :   explicit Vector(AllocPolicy = AllocPolicy());
     488             :   Vector(Vector&&); /* Move constructor. */
     489             :   Vector& operator=(Vector&&); /* Move assignment. */
     490             :   ~Vector();
     491             : 
     492             :   /* accessors */
     493             : 
     494          15 :   const AllocPolicy& allocPolicy() const { return *this; }
     495             : 
     496     1678086 :   AllocPolicy& allocPolicy() { return *this; }
     497             : 
     498             :   enum { InlineLength = MinInlineCapacity };
     499             : 
     500     6010037 :   size_t length() const { return mLength; }
     501             : 
     502     1868092 :   bool empty() const { return mLength == 0; }
     503             : 
     504     1841563 :   size_t capacity() const { return mTail.mCapacity; }
     505             : 
     506     6215259 :   T* begin()
     507             :   {
     508     6215259 :     MOZ_ASSERT(!mEntered);
     509     6215259 :     return mBegin;
     510             :   }
     511             : 
     512     2642317 :   const T* begin() const
     513             :   {
     514     2642317 :     MOZ_ASSERT(!mEntered);
     515     2642317 :     return mBegin;
     516             :   }
     517             : 
     518     2415057 :   T* end()
     519             :   {
     520     2415057 :     MOZ_ASSERT(!mEntered);
     521     2415057 :     return mBegin + mLength;
     522             :   }
     523             : 
     524      107121 :   const T* end() const
     525             :   {
     526      107121 :     MOZ_ASSERT(!mEntered);
     527      107121 :     return mBegin + mLength;
     528             :   }
     529             : 
     530     4121945 :   T& operator[](size_t aIndex)
     531             :   {
     532     4121945 :     MOZ_ASSERT(!mEntered);
     533     4121945 :     MOZ_ASSERT(aIndex < mLength);
     534     4121945 :     return begin()[aIndex];
     535             :   }
     536             : 
     537     2529019 :   const T& operator[](size_t aIndex) const
     538             :   {
     539     2529019 :     MOZ_ASSERT(!mEntered);
     540     2529019 :     MOZ_ASSERT(aIndex < mLength);
     541     2529019 :     return begin()[aIndex];
     542             :   }
     543             : 
     544      682558 :   T& back()
     545             :   {
     546      682558 :     MOZ_ASSERT(!mEntered);
     547      682558 :     MOZ_ASSERT(!empty());
     548      682558 :     return *(end() - 1);
     549             :   }
     550             : 
     551        7812 :   const T& back() const
     552             :   {
     553        7812 :     MOZ_ASSERT(!mEntered);
     554        7812 :     MOZ_ASSERT(!empty());
     555        7812 :     return *(end() - 1);
     556             :   }
     557             : 
     558             :   class Range
     559             :   {
     560             :     friend class Vector;
     561             :     T* mCur;
     562             :     T* mEnd;
     563           0 :     Range(T* aCur, T* aEnd)
     564             :       : mCur(aCur)
     565           0 :       , mEnd(aEnd)
     566             :     {
     567           0 :       MOZ_ASSERT(aCur <= aEnd);
     568           0 :     }
     569             : 
     570             :   public:
     571           0 :     bool empty() const { return mCur == mEnd; }
     572             :     size_t remain() const { return PointerRangeSize(mCur, mEnd); }
     573           0 :     T& front() const { MOZ_ASSERT(!empty()); return *mCur; }
     574           0 :     void popFront() { MOZ_ASSERT(!empty()); ++mCur; }
     575             :     T popCopyFront() { MOZ_ASSERT(!empty()); return *mCur++; }
     576             :   };
     577             : 
     578             :   class ConstRange
     579             :   {
     580             :     friend class Vector;
     581             :     const T* mCur;
     582             :     const T* mEnd;
     583           0 :     ConstRange(const T* aCur, const T* aEnd)
     584             :       : mCur(aCur)
     585           0 :       , mEnd(aEnd)
     586             :     {
     587           0 :       MOZ_ASSERT(aCur <= aEnd);
     588           0 :     }
     589             : 
     590             :   public:
     591           0 :     bool empty() const { return mCur == mEnd; }
     592             :     size_t remain() const { return PointerRangeSize(mCur, mEnd); }
     593           0 :     const T& front() const { MOZ_ASSERT(!empty()); return *mCur; }
     594           0 :     void popFront() { MOZ_ASSERT(!empty()); ++mCur; }
     595           0 :     T popCopyFront() { MOZ_ASSERT(!empty()); return *mCur++; }
     596             :   };
     597             : 
     598           0 :   Range all() { return Range(begin(), end()); }
     599           0 :   ConstRange all() const { return ConstRange(begin(), end()); }
     600             : 
     601             :   /* mutators */
     602             : 
     603             :   /**
     604             :    * Reverse the order of the elements in the vector in place.
     605             :    */
     606             :   void reverse();
     607             : 
     608             :   /**
     609             :    * Given that the vector is empty, grow the internal capacity to |aRequest|,
     610             :    * keeping the length 0.
     611             :    */
     612             :   MOZ_MUST_USE bool initCapacity(size_t aRequest);
     613             : 
     614             :   /**
     615             :    * Given that the vector is empty, grow the internal capacity and length to
     616             :    * |aRequest| leaving the elements' memory completely uninitialized (with all
     617             :    * the associated hazards and caveats). This avoids the usual allocation-size
     618             :    * rounding that happens in resize and overhead of initialization for elements
     619             :    * that are about to be overwritten.
     620             :    */
     621             :   MOZ_MUST_USE bool initLengthUninitialized(size_t aRequest);
     622             : 
     623             :   /**
     624             :    * If reserve(aRequest) succeeds and |aRequest >= length()|, then appending
     625             :    * |aRequest - length()| elements, in any sequence of append/appendAll calls,
     626             :    * is guaranteed to succeed.
     627             :    *
     628             :    * A request to reserve an amount less than the current length does not affect
     629             :    * reserved space.
     630             :    */
     631             :   MOZ_MUST_USE bool reserve(size_t aRequest);
     632             : 
     633             :   /**
     634             :    * Destroy elements in the range [end() - aIncr, end()). Does not deallocate
     635             :    * or unreserve storage for those elements.
     636             :    */
     637             :   void shrinkBy(size_t aIncr);
     638             : 
     639             :   /**
     640             :    * Destroy elements in the range [aNewLength, end()). Does not deallocate
     641             :    * or unreserve storage for those elements.
     642             :    */
     643             :   void shrinkTo(size_t aNewLength);
     644             : 
     645             :   /** Grow the vector by aIncr elements. */
     646             :   MOZ_MUST_USE bool growBy(size_t aIncr);
     647             : 
     648             :   /** Call shrinkBy or growBy based on whether newSize > length(). */
     649             :   MOZ_MUST_USE bool resize(size_t aNewLength);
     650             : 
     651             :   /**
     652             :    * Increase the length of the vector, but don't initialize the new elements
     653             :    * -- leave them as uninitialized memory.
     654             :    */
     655             :   MOZ_MUST_USE bool growByUninitialized(size_t aIncr);
     656             :   void infallibleGrowByUninitialized(size_t aIncr);
     657             :   MOZ_MUST_USE bool resizeUninitialized(size_t aNewLength);
     658             : 
     659             :   /** Shorthand for shrinkBy(length()). */
     660             :   void clear();
     661             : 
     662             :   /** Clears and releases any heap-allocated storage. */
     663             :   void clearAndFree();
     664             : 
     665             :   /**
     666             :    * Calls the AllocPolicy's pod_realloc to release excess capacity. Since
     667             :    * realloc is only safe on PODs, this method fails to compile if IsPod<T>
     668             :    * is false.
     669             :    */
     670             :   void podResizeToFit();
     671             : 
     672             :   /**
     673             :    * If true, appending |aNeeded| elements won't reallocate elements storage.
     674             :    * This *doesn't* mean that infallibleAppend may be used!  You still must
     675             :    * reserve the extra space, even if this method indicates that appends won't
     676             :    * need to reallocate elements storage.
     677             :    */
     678             :   bool canAppendWithoutRealloc(size_t aNeeded) const;
     679             : 
     680             :   /** Potentially fallible append operations. */
     681             : 
     682             :   /**
     683             :    * This can take either a T& or a T&&. Given a T&&, it moves |aU| into the
     684             :    * vector, instead of copying it. If it fails, |aU| is left unmoved. ("We are
     685             :    * not amused.")
     686             :    */
     687             :   template<typename U> MOZ_MUST_USE bool append(U&& aU);
     688             : 
     689             :   /**
     690             :    * Construct a T in-place as a new entry at the end of this vector.
     691             :    */
     692             :   template<typename... Args>
     693       20826 :   MOZ_MUST_USE bool emplaceBack(Args&&... aArgs)
     694             :   {
     695       20826 :     if (!growByUninitialized(1))
     696           0 :       return false;
     697       20826 :     Impl::new_(&back(), Forward<Args>(aArgs)...);
     698       20826 :     return true;
     699             :   }
     700             : 
     701             :   template<typename U, size_t O, class BP>
     702             :   MOZ_MUST_USE bool appendAll(const Vector<U, O, BP>& aU);
     703             :   MOZ_MUST_USE bool appendN(const T& aT, size_t aN);
     704             :   template<typename U> MOZ_MUST_USE bool append(const U* aBegin, const U* aEnd);
     705             :   template<typename U> MOZ_MUST_USE bool append(const U* aBegin, size_t aLength);
     706             : 
     707             :   /*
     708             :    * Guaranteed-infallible append operations for use upon vectors whose
     709             :    * memory has been pre-reserved.  Don't use this if you haven't reserved the
     710             :    * memory!
     711             :    */
     712       79115 :   template<typename U> void infallibleAppend(U&& aU)
     713             :   {
     714       79115 :     internalAppend(Forward<U>(aU));
     715       79115 :   }
     716             :   void infallibleAppendN(const T& aT, size_t aN)
     717             :   {
     718             :     internalAppendN(aT, aN);
     719             :   }
     720             :   template<typename U> void infallibleAppend(const U* aBegin, const U* aEnd)
     721             :   {
     722             :     internalAppend(aBegin, PointerRangeSize(aBegin, aEnd));
     723             :   }
     724     3724133 :   template<typename U> void infallibleAppend(const U* aBegin, size_t aLength)
     725             :   {
     726     3724133 :     internalAppend(aBegin, aLength);
     727     3724332 :   }
     728             :   template<typename... Args>
     729        9832 :   void infallibleEmplaceBack(Args&&... aArgs)
     730             :   {
     731        9832 :     infallibleGrowByUninitialized(1);
     732        9832 :     Impl::new_(&back(), Forward<Args>(aArgs)...);
     733        9832 :   }
     734             : 
     735             :   void popBack();
     736             : 
     737             :   T popCopy();
     738             : 
     739             :   /**
     740             :    * If elements are stored in-place, return nullptr and leave this vector
     741             :    * unmodified.
     742             :    *
     743             :    * Otherwise return this vector's elements buffer, and clear this vector as if
     744             :    * by clearAndFree(). The caller now owns the buffer and is responsible for
     745             :    * deallocating it consistent with this vector's AllocPolicy.
     746             :    *
     747             :    * N.B. Although a T*, only the range [0, length()) is constructed.
     748             :    */
     749             :   MOZ_MUST_USE T* extractRawBuffer();
     750             : 
     751             :   /**
     752             :    * If elements are stored in-place, allocate a new buffer, move this vector's
     753             :    * elements into it, and return that buffer.
     754             :    *
     755             :    * Otherwise return this vector's elements buffer. The caller now owns the
     756             :    * buffer and is responsible for deallocating it consistent with this vector's
     757             :    * AllocPolicy.
     758             :    *
     759             :    * This vector is cleared, as if by clearAndFree(), when this method
     760             :    * succeeds. This method fails and returns nullptr only if new elements buffer
     761             :    * allocation fails.
     762             :    *
     763             :    * N.B. Only the range [0, length()) of the returned buffer is constructed.
     764             :    * If any of these elements are uninitialized (as growByUninitialized
     765             :    * enables), behavior is undefined.
     766             :    */
     767             :   MOZ_MUST_USE T* extractOrCopyRawBuffer();
     768             : 
     769             :   /**
     770             :    * Transfer ownership of an array of objects into the vector.  The caller
     771             :    * must have allocated the array in accordance with this vector's
     772             :    * AllocPolicy.
     773             :    *
     774             :    * N.B. This call assumes that there are no uninitialized elements in the
     775             :    *      passed array.
     776             :    */
     777             :   void replaceRawBuffer(T* aP, size_t aLength);
     778             : 
     779             :   /**
     780             :    * Places |aVal| at position |aP|, shifting existing elements from |aP| onward
     781             :    * one position higher.  On success, |aP| should not be reused because it'll
     782             :    * be a dangling pointer if reallocation of the vector storage occurred; the
     783             :    * return value should be used instead.  On failure, nullptr is returned.
     784             :    *
     785             :    * Example usage:
     786             :    *
     787             :    *   if (!(p = vec.insert(p, val))) {
     788             :    *     <handle failure>
     789             :    *   }
     790             :    *   <keep working with p>
     791             :    *
     792             :    * This is inherently a linear-time operation.  Be careful!
     793             :    */
     794             :   template<typename U>
     795             :   MOZ_MUST_USE T* insert(T* aP, U&& aVal);
     796             : 
     797             :   /**
     798             :    * Removes the element |aT|, which must fall in the bounds [begin, end),
     799             :    * shifting existing elements from |aT + 1| onward one position lower.
     800             :    */
     801             :   void erase(T* aT);
     802             : 
     803             :   /**
     804             :    * Removes the elements [|aBegin|, |aEnd|), which must fall in the bounds
     805             :    * [begin, end), shifting existing elements from |aEnd + 1| onward to aBegin's
     806             :    * old position.
     807             :    */
     808             :   void erase(T* aBegin, T* aEnd);
     809             : 
     810             :   /**
     811             :    * Measure the size of the vector's heap-allocated storage.
     812             :    */
     813             :   size_t sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
     814             : 
     815             :   /**
     816             :    * Like sizeOfExcludingThis, but also measures the size of the vector
     817             :    * object (which must be heap-allocated) itself.
     818             :    */
     819             :   size_t sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
     820             : 
     821             :   void swap(Vector& aOther);
     822             : 
     823             : private:
     824             :   Vector(const Vector&) = delete;
     825             :   void operator=(const Vector&) = delete;
     826             : };
     827             : 
     828             : /* This does the re-entrancy check plus several other sanity checks. */
     829             : #define MOZ_REENTRANCY_GUARD_ET_AL \
     830             :   ReentrancyGuard g(*this); \
     831             :   MOZ_ASSERT_IF(usingInlineStorage(), mTail.mCapacity == kInlineCapacity); \
     832             :   MOZ_ASSERT(reserved() <= mTail.mCapacity); \
     833             :   MOZ_ASSERT(mLength <= reserved()); \
     834             :   MOZ_ASSERT(mLength <= mTail.mCapacity)
     835             : 
     836             : /* Vector Implementation */
     837             : 
     838             : template<typename T, size_t N, class AP>
     839             : MOZ_ALWAYS_INLINE
     840      622151 : Vector<T, N, AP>::Vector(AP aAP)
     841             :   : AP(aAP)
     842             :   , mLength(0)
     843             :   , mTail(kInlineCapacity, 0)
     844             : #ifdef DEBUG
     845      622151 :   , mEntered(false)
     846             : #endif
     847             : {
     848      622149 :   mBegin = inlineStorage();
     849      622150 : }
     850             : 
     851             : /* Move constructor. */
     852             : template<typename T, size_t N, class AllocPolicy>
     853             : MOZ_ALWAYS_INLINE
     854       98639 : Vector<T, N, AllocPolicy>::Vector(Vector&& aRhs)
     855       98639 :   : AllocPolicy(Move(aRhs))
     856             : #ifdef DEBUG
     857       98639 :   , mEntered(false)
     858             : #endif
     859             : {
     860       98639 :   mLength = aRhs.mLength;
     861       98639 :   mTail.mCapacity = aRhs.mTail.mCapacity;
     862             : #ifdef DEBUG
     863       98639 :   mTail.mReserved = aRhs.mTail.mReserved;
     864             : #endif
     865             : 
     866       98639 :   if (aRhs.usingInlineStorage()) {
     867             :     /* We can't move the buffer over in this case, so copy elements. */
     868       96887 :     mBegin = inlineStorage();
     869       96887 :     Impl::moveConstruct(mBegin, aRhs.beginNoCheck(), aRhs.endNoCheck());
     870             :     /*
     871             :      * Leave aRhs's mLength, mBegin, mCapacity, and mReserved as they are.
     872             :      * The elements in its in-line storage still need to be destroyed.
     873             :      */
     874             :   } else {
     875             :     /*
     876             :      * Take src's buffer, and turn src into an empty vector using
     877             :      * in-line storage.
     878             :      */
     879        1752 :     mBegin = aRhs.mBegin;
     880        1752 :     aRhs.mBegin = aRhs.inlineStorage();
     881        1752 :     aRhs.mTail.mCapacity = kInlineCapacity;
     882        1752 :     aRhs.mLength = 0;
     883             : #ifdef DEBUG
     884        1752 :     aRhs.mTail.mReserved = 0;
     885             : #endif
     886             :   }
     887       98639 : }
     888             : 
     889             : /* Move assignment. */
     890             : template<typename T, size_t N, class AP>
     891             : MOZ_ALWAYS_INLINE Vector<T, N, AP>&
     892         730 : Vector<T, N, AP>::operator=(Vector&& aRhs)
     893             : {
     894         730 :   MOZ_ASSERT(this != &aRhs, "self-move assignment is prohibited");
     895         730 :   this->~Vector();
     896         730 :   new(KnownNotNull, this) Vector(Move(aRhs));
     897         730 :   return *this;
     898             : }
     899             : 
     900             : template<typename T, size_t N, class AP>
     901             : MOZ_ALWAYS_INLINE
     902      698595 : Vector<T, N, AP>::~Vector()
     903             : {
     904     1397188 :   MOZ_REENTRANCY_GUARD_ET_AL;
     905      698594 :   Impl::destroy(beginNoCheck(), endNoCheck());
     906      698594 :   if (!usingInlineStorage()) {
     907       66539 :     this->free_(beginNoCheck());
     908             :   }
     909      698593 : }
     910             : 
     911             : template<typename T, size_t N, class AP>
     912             : MOZ_ALWAYS_INLINE void
     913           0 : Vector<T, N, AP>::reverse() {
     914           0 :   MOZ_REENTRANCY_GUARD_ET_AL;
     915           0 :   T* elems = mBegin;
     916           0 :   size_t len = mLength;
     917           0 :   size_t mid = len / 2;
     918           0 :   for (size_t i = 0; i < mid; i++) {
     919           0 :     Swap(elems[i], elems[len - i - 1]);
     920             :   }
     921           0 : }
     922             : 
     923             : /*
     924             :  * This function will create a new heap buffer with capacity aNewCap,
     925             :  * move all elements in the inline buffer to this new buffer,
     926             :  * and fail on OOM.
     927             :  */
     928             : template<typename T, size_t N, class AP>
     929             : inline bool
     930       71473 : Vector<T, N, AP>::convertToHeapStorage(size_t aNewCap)
     931             : {
     932       71473 :   MOZ_ASSERT(usingInlineStorage());
     933             : 
     934             :   /* Allocate buffer. */
     935       71473 :   MOZ_ASSERT(!detail::CapacityHasExcessSpace<T>(aNewCap));
     936       71473 :   T* newBuf = this->template pod_malloc<T>(aNewCap);
     937       71473 :   if (MOZ_UNLIKELY(!newBuf)) {
     938           0 :     return false;
     939             :   }
     940             : 
     941             :   /* Copy inline elements into heap buffer. */
     942       71473 :   Impl::moveConstruct(newBuf, beginNoCheck(), endNoCheck());
     943       71473 :   Impl::destroy(beginNoCheck(), endNoCheck());
     944             : 
     945             :   /* Switch in heap buffer. */
     946       71473 :   mBegin = newBuf;
     947             :   /* mLength is unchanged. */
     948       71473 :   mTail.mCapacity = aNewCap;
     949       71473 :   return true;
     950             : }
     951             : 
     952             : template<typename T, size_t N, class AP>
     953             : MOZ_NEVER_INLINE bool
     954      107389 : Vector<T, N, AP>::growStorageBy(size_t aIncr)
     955             : {
     956      107389 :   MOZ_ASSERT(mLength + aIncr > mTail.mCapacity);
     957             : 
     958             :   /*
     959             :    * When choosing a new capacity, its size should is as close to 2**N bytes
     960             :    * as possible.  2**N-sized requests are best because they are unlikely to
     961             :    * be rounded up by the allocator.  Asking for a 2**N number of elements
     962             :    * isn't as good, because if sizeof(T) is not a power-of-two that would
     963             :    * result in a non-2**N request size.
     964             :    */
     965             : 
     966             :   size_t newCap;
     967             : 
     968      107389 :   if (aIncr == 1) {
     969       76874 :     if (usingInlineStorage()) {
     970             :       /* This case occurs in ~70--80% of the calls to this function. */
     971             :       size_t newSize =
     972       44602 :         tl::RoundUpPow2<(kInlineCapacity + 1) * sizeof(T)>::value;
     973       44602 :       newCap = newSize / sizeof(T);
     974       44602 :       goto convert;
     975             :     }
     976             : 
     977       32272 :     if (mLength == 0) {
     978             :       /* This case occurs in ~0--10% of the calls to this function. */
     979           8 :       newCap = 1;
     980           8 :       goto grow;
     981             :     }
     982             : 
     983             :     /* This case occurs in ~15--20% of the calls to this function. */
     984             : 
     985             :     /*
     986             :      * Will mLength * 4 *sizeof(T) overflow?  This condition limits a vector
     987             :      * to 1GB of memory on a 32-bit system, which is a reasonable limit.  It
     988             :      * also ensures that
     989             :      *
     990             :      *   static_cast<char*>(end()) - static_cast<char*>(begin())
     991             :      *
     992             :      * doesn't overflow ptrdiff_t (see bug 510319).
     993             :      */
     994       32264 :     if (MOZ_UNLIKELY(mLength & tl::MulOverflowMask<4 * sizeof(T)>::value)) {
     995           0 :       this->reportAllocOverflow();
     996           0 :       return false;
     997             :     }
     998             : 
     999             :     /*
    1000             :      * If we reach here, the existing capacity will have a size that is already
    1001             :      * as close to 2^N as sizeof(T) will allow.  Just double the capacity, and
    1002             :      * then there might be space for one more element.
    1003             :      */
    1004       32264 :     newCap = mLength * 2;
    1005       32264 :     if (detail::CapacityHasExcessSpace<T>(newCap)) {
    1006        2097 :       newCap += 1;
    1007             :     }
    1008             :   } else {
    1009             :     /* This case occurs in ~2% of the calls to this function. */
    1010       30515 :     size_t newMinCap = mLength + aIncr;
    1011             : 
    1012             :     /* Did mLength + aIncr overflow?  Will newCap * sizeof(T) overflow? */
    1013       30515 :     if (MOZ_UNLIKELY(newMinCap < mLength ||
    1014             :                      newMinCap & tl::MulOverflowMask<2 * sizeof(T)>::value))
    1015             :     {
    1016           0 :       this->reportAllocOverflow();
    1017           0 :       return false;
    1018             :     }
    1019             : 
    1020       30515 :     size_t newMinSize = newMinCap * sizeof(T);
    1021       30515 :     size_t newSize = RoundUpPow2(newMinSize);
    1022       30515 :     newCap = newSize / sizeof(T);
    1023             :   }
    1024             : 
    1025       62779 :   if (usingInlineStorage()) {
    1026             : convert:
    1027       71473 :     return convertToHeapStorage(newCap);
    1028             :   }
    1029             : 
    1030             : grow:
    1031       35916 :   return Impl::growTo(*this, newCap);
    1032             : }
    1033             : 
    1034             : template<typename T, size_t N, class AP>
    1035             : inline bool
    1036          15 : Vector<T, N, AP>::initCapacity(size_t aRequest)
    1037             : {
    1038          15 :   MOZ_ASSERT(empty());
    1039          15 :   MOZ_ASSERT(usingInlineStorage());
    1040          15 :   if (aRequest == 0) {
    1041           0 :     return true;
    1042             :   }
    1043          15 :   T* newbuf = this->template pod_malloc<T>(aRequest);
    1044          15 :   if (MOZ_UNLIKELY(!newbuf)) {
    1045           0 :     return false;
    1046             :   }
    1047          15 :   mBegin = newbuf;
    1048          15 :   mTail.mCapacity = aRequest;
    1049             : #ifdef DEBUG
    1050          15 :   mTail.mReserved = aRequest;
    1051             : #endif
    1052          15 :   return true;
    1053             : }
    1054             : 
    1055             : template<typename T, size_t N, class AP>
    1056             : inline bool
    1057           0 : Vector<T, N, AP>::initLengthUninitialized(size_t aRequest)
    1058             : {
    1059           0 :   if (!initCapacity(aRequest)) {
    1060           0 :     return false;
    1061             :   }
    1062           0 :   infallibleGrowByUninitialized(aRequest);
    1063           0 :   return true;
    1064             : }
    1065             : 
    1066             : template<typename T, size_t N, class AP>
    1067             : inline bool
    1068     3608565 : Vector<T, N, AP>::maybeCheckSimulatedOOM(size_t aRequestedSize)
    1069             : {
    1070     3608565 :   if (aRequestedSize <= N) {
    1071      983105 :     return true;
    1072             :   }
    1073             : 
    1074             : #ifdef DEBUG
    1075     2625460 :   if (aRequestedSize <= mTail.mReserved) {
    1076      947374 :     return true;
    1077             :   }
    1078             : #endif
    1079             : 
    1080     1678086 :   return allocPolicy().checkSimulatedOOM();
    1081             : }
    1082             : 
    1083             : template<typename T, size_t N, class AP>
    1084             : inline bool
    1085     1144253 : Vector<T, N, AP>::reserve(size_t aRequest)
    1086             : {
    1087     2288522 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1088     1144277 :   if (aRequest > mTail.mCapacity) {
    1089       21104 :     if (MOZ_UNLIKELY(!growStorageBy(aRequest - mLength))) {
    1090           0 :       return false;
    1091             :     }
    1092     1123173 :   } else if (!maybeCheckSimulatedOOM(aRequest)) {
    1093           0 :     return false;
    1094             :   }
    1095             : #ifdef DEBUG
    1096     1144269 :   if (aRequest > mTail.mReserved) {
    1097     1143741 :     mTail.mReserved = aRequest;
    1098             :   }
    1099     1144269 :   MOZ_ASSERT(mLength <= mTail.mReserved);
    1100     1144269 :   MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
    1101             : #endif
    1102     1144269 :   return true;
    1103             : }
    1104             : 
    1105             : template<typename T, size_t N, class AP>
    1106             : inline void
    1107        1689 : Vector<T, N, AP>::shrinkBy(size_t aIncr)
    1108             : {
    1109        3378 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1110        1689 :   MOZ_ASSERT(aIncr <= mLength);
    1111        1689 :   Impl::destroy(endNoCheck() - aIncr, endNoCheck());
    1112        1689 :   mLength -= aIncr;
    1113        1689 : }
    1114             : 
    1115             : template<typename T, size_t N, class AP>
    1116             : MOZ_ALWAYS_INLINE void
    1117           4 : Vector<T, N, AP>::shrinkTo(size_t aNewLength)
    1118             : {
    1119           4 :   MOZ_ASSERT(aNewLength <= mLength);
    1120           4 :   shrinkBy(mLength - aNewLength);
    1121           4 : }
    1122             : 
    1123             : template<typename T, size_t N, class AP>
    1124             : MOZ_ALWAYS_INLINE bool
    1125      717999 : Vector<T, N, AP>::growBy(size_t aIncr)
    1126             : {
    1127     1435998 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1128      717999 :   if (aIncr > mTail.mCapacity - mLength) {
    1129        3404 :     if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
    1130           0 :       return false;
    1131             :     }
    1132      714595 :   } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
    1133           0 :     return false;
    1134             :   }
    1135      717999 :   MOZ_ASSERT(mLength + aIncr <= mTail.mCapacity);
    1136      717999 :   T* newend = endNoCheck() + aIncr;
    1137      717999 :   Impl::initialize(endNoCheck(), newend);
    1138      717999 :   mLength += aIncr;
    1139             : #ifdef DEBUG
    1140      717999 :   if (mLength > mTail.mReserved) {
    1141       97685 :     mTail.mReserved = mLength;
    1142             :   }
    1143             : #endif
    1144      717999 :   return true;
    1145             : }
    1146             : 
    1147             : template<typename T, size_t N, class AP>
    1148             : MOZ_ALWAYS_INLINE bool
    1149      278509 : Vector<T, N, AP>::growByUninitialized(size_t aIncr)
    1150             : {
    1151      557018 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1152      278509 :   if (aIncr > mTail.mCapacity - mLength) {
    1153        2855 :     if (MOZ_UNLIKELY(!growStorageBy(aIncr))) {
    1154           0 :       return false;
    1155             :     }
    1156      275654 :   } else if (!maybeCheckSimulatedOOM(mLength + aIncr)) {
    1157           0 :     return false;
    1158             :   }
    1159             : #ifdef DEBUG
    1160      278509 :   if (mLength + aIncr > mTail.mReserved) {
    1161      276784 :     mTail.mReserved = mLength + aIncr;
    1162             :   }
    1163             : #endif
    1164      278509 :   infallibleGrowByUninitialized(aIncr);
    1165      278509 :   return true;
    1166             : }
    1167             : 
    1168             : template<typename T, size_t N, class AP>
    1169             : MOZ_ALWAYS_INLINE void
    1170      288341 : Vector<T, N, AP>::infallibleGrowByUninitialized(size_t aIncr)
    1171             : {
    1172      288341 :   MOZ_ASSERT(mLength + aIncr <= reserved());
    1173      288341 :   mLength += aIncr;
    1174      288341 : }
    1175             : 
    1176             : template<typename T, size_t N, class AP>
    1177             : inline bool
    1178       24788 : Vector<T, N, AP>::resize(size_t aNewLength)
    1179             : {
    1180       24788 :   size_t curLength = mLength;
    1181       24788 :   if (aNewLength > curLength) {
    1182       24521 :     return growBy(aNewLength - curLength);
    1183             :   }
    1184         267 :   shrinkBy(curLength - aNewLength);
    1185         267 :   return true;
    1186             : }
    1187             : 
    1188             : template<typename T, size_t N, class AP>
    1189             : MOZ_ALWAYS_INLINE bool
    1190          89 : Vector<T, N, AP>::resizeUninitialized(size_t aNewLength)
    1191             : {
    1192          89 :   size_t curLength = mLength;
    1193          89 :   if (aNewLength > curLength) {
    1194          28 :     return growByUninitialized(aNewLength - curLength);
    1195             :   }
    1196          61 :   shrinkBy(curLength - aNewLength);
    1197          61 :   return true;
    1198             : }
    1199             : 
    1200             : template<typename T, size_t N, class AP>
    1201             : inline void
    1202       98415 : Vector<T, N, AP>::clear()
    1203             : {
    1204      196830 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1205       98415 :   Impl::destroy(beginNoCheck(), endNoCheck());
    1206       98415 :   mLength = 0;
    1207       98415 : }
    1208             : 
    1209             : template<typename T, size_t N, class AP>
    1210             : inline void
    1211        2442 : Vector<T, N, AP>::clearAndFree()
    1212             : {
    1213        2442 :   clear();
    1214             : 
    1215        2442 :   if (usingInlineStorage()) {
    1216        2421 :     return;
    1217             :   }
    1218          21 :   this->free_(beginNoCheck());
    1219          21 :   mBegin = inlineStorage();
    1220          21 :   mTail.mCapacity = kInlineCapacity;
    1221             : #ifdef DEBUG
    1222          21 :   mTail.mReserved = 0;
    1223             : #endif
    1224             : }
    1225             : 
    1226             : template<typename T, size_t N, class AP>
    1227             : inline void
    1228           0 : Vector<T, N, AP>::podResizeToFit()
    1229             : {
    1230             :   // This function is only defined if IsPod is true and will fail to compile
    1231             :   // otherwise.
    1232           0 :   Impl::podResizeToFit(*this);
    1233           0 : }
    1234             : 
    1235             : template<typename T, size_t N, class AP>
    1236             : inline bool
    1237           0 : Vector<T, N, AP>::canAppendWithoutRealloc(size_t aNeeded) const
    1238             : {
    1239           0 :   return mLength + aNeeded <= mTail.mCapacity;
    1240             : }
    1241             : 
    1242             : template<typename T, size_t N, class AP>
    1243             : template<typename U, size_t O, class BP>
    1244             : MOZ_ALWAYS_INLINE void
    1245             : Vector<T, N, AP>::internalAppendAll(const Vector<U, O, BP>& aOther)
    1246             : {
    1247             :   internalAppend(aOther.begin(), aOther.length());
    1248             : }
    1249             : 
    1250             : template<typename T, size_t N, class AP>
    1251             : template<typename U>
    1252             : MOZ_ALWAYS_INLINE void
    1253     1596524 : Vector<T, N, AP>::internalAppend(U&& aU)
    1254             : {
    1255     1596524 :   MOZ_ASSERT(mLength + 1 <= mTail.mReserved);
    1256     1596524 :   MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
    1257     1596524 :   Impl::new_(endNoCheck(), Forward<U>(aU));
    1258     1596461 :   ++mLength;
    1259     1596461 : }
    1260             : 
    1261             : template<typename T, size_t N, class AP>
    1262             : MOZ_ALWAYS_INLINE bool
    1263        8055 : Vector<T, N, AP>::appendN(const T& aT, size_t aNeeded)
    1264             : {
    1265       16110 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1266        8055 :   if (mLength + aNeeded > mTail.mCapacity) {
    1267        6330 :     if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
    1268           0 :       return false;
    1269             :     }
    1270        1725 :   } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
    1271           0 :     return false;
    1272             :   }
    1273             : #ifdef DEBUG
    1274        8055 :   if (mLength + aNeeded > mTail.mReserved) {
    1275        6797 :     mTail.mReserved = mLength + aNeeded;
    1276             :   }
    1277             : #endif
    1278        8055 :   internalAppendN(aT, aNeeded);
    1279        8055 :   return true;
    1280             : }
    1281             : 
    1282             : template<typename T, size_t N, class AP>
    1283             : MOZ_ALWAYS_INLINE void
    1284        8055 : Vector<T, N, AP>::internalAppendN(const T& aT, size_t aNeeded)
    1285             : {
    1286        8055 :   MOZ_ASSERT(mLength + aNeeded <= mTail.mReserved);
    1287        8055 :   MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
    1288        8055 :   Impl::copyConstructN(endNoCheck(), aNeeded, aT);
    1289        8055 :   mLength += aNeeded;
    1290        8055 : }
    1291             : 
    1292             : template<typename T, size_t N, class AP>
    1293             : template<typename U>
    1294             : inline T*
    1295       55075 : Vector<T, N, AP>::insert(T* aP, U&& aVal)
    1296             : {
    1297       55075 :   MOZ_ASSERT(begin() <= aP);
    1298       55075 :   MOZ_ASSERT(aP <= end());
    1299       55075 :   size_t pos = aP - begin();
    1300       55075 :   MOZ_ASSERT(pos <= mLength);
    1301       55075 :   size_t oldLength = mLength;
    1302       55075 :   if (pos == oldLength) {
    1303           9 :     if (!append(Forward<U>(aVal))) {
    1304           0 :       return nullptr;
    1305             :     }
    1306             :   } else {
    1307       55066 :     T oldBack = Move(back());
    1308       55066 :     if (!append(Move(oldBack))) {
    1309           0 :       return nullptr;
    1310             :     }
    1311      433198 :     for (size_t i = oldLength - 1; i > pos; --i) {
    1312      378132 :       (*this)[i] = Move((*this)[i - 1]);
    1313             :     }
    1314       55066 :     (*this)[pos] = Forward<U>(aVal);
    1315             :   }
    1316       55075 :   return begin() + pos;
    1317             : }
    1318             : 
    1319             : template<typename T, size_t N, class AP>
    1320             : inline void
    1321         284 : Vector<T, N, AP>::erase(T* aIt)
    1322             : {
    1323         284 :   MOZ_ASSERT(begin() <= aIt);
    1324         284 :   MOZ_ASSERT(aIt < end());
    1325         804 :   while (aIt + 1 < end()) {
    1326         260 :     *aIt = Move(*(aIt + 1));
    1327         260 :     ++aIt;
    1328             :   }
    1329         284 :   popBack();
    1330         284 : }
    1331             : 
    1332             : template<typename T, size_t N, class AP>
    1333             : inline void
    1334          40 : Vector<T, N, AP>::erase(T* aBegin, T* aEnd)
    1335             : {
    1336          40 :   MOZ_ASSERT(begin() <= aBegin);
    1337          40 :   MOZ_ASSERT(aBegin <= aEnd);
    1338          40 :   MOZ_ASSERT(aEnd <= end());
    1339         120 :   while (aEnd < end()) {
    1340          40 :     *aBegin++ = Move(*aEnd++);
    1341             :   }
    1342          40 :   shrinkBy(aEnd - aBegin);
    1343          40 : }
    1344             : 
    1345             : template<typename T, size_t N, class AP>
    1346             : template<typename U>
    1347             : MOZ_ALWAYS_INLINE bool
    1348       48358 : Vector<T, N, AP>::append(const U* aInsBegin, const U* aInsEnd)
    1349             : {
    1350       96716 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1351       48358 :   size_t aNeeded = PointerRangeSize(aInsBegin, aInsEnd);
    1352       48358 :   if (mLength + aNeeded > mTail.mCapacity) {
    1353         294 :     if (MOZ_UNLIKELY(!growStorageBy(aNeeded))) {
    1354           0 :       return false;
    1355             :     }
    1356       48064 :   } else if (!maybeCheckSimulatedOOM(mLength + aNeeded)) {
    1357           0 :       return false;
    1358             :   }
    1359             : #ifdef DEBUG
    1360       48358 :   if (mLength + aNeeded > mTail.mReserved) {
    1361       36160 :     mTail.mReserved = mLength + aNeeded;
    1362             :   }
    1363             : #endif
    1364       48358 :   internalAppend(aInsBegin, aNeeded);
    1365       48358 :   return true;
    1366             : }
    1367             : 
    1368             : template<typename T, size_t N, class AP>
    1369             : template<typename U>
    1370             : MOZ_ALWAYS_INLINE void
    1371     3772858 : Vector<T, N, AP>::internalAppend(const U* aInsBegin, size_t aInsLength)
    1372             : {
    1373     3772858 :   MOZ_ASSERT(mLength + aInsLength <= mTail.mReserved);
    1374     3772858 :   MOZ_ASSERT(mTail.mReserved <= mTail.mCapacity);
    1375     3772858 :   Impl::copyConstruct(endNoCheck(), aInsBegin, aInsBegin + aInsLength);
    1376     3772705 :   mLength += aInsLength;
    1377     3772705 : }
    1378             : 
    1379             : template<typename T, size_t N, class AP>
    1380             : template<typename U>
    1381             : MOZ_ALWAYS_INLINE bool
    1382     1517413 : Vector<T, N, AP>::append(U&& aU)
    1383             : {
    1384     3034761 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1385     1517415 :   if (mLength == mTail.mCapacity) {
    1386       73382 :     if (MOZ_UNLIKELY(!growStorageBy(1))) {
    1387           0 :       return false;
    1388             :     }
    1389     1444033 :   } else if (!maybeCheckSimulatedOOM(mLength + 1)) {
    1390           0 :       return false;
    1391             :   }
    1392             : #ifdef DEBUG
    1393     1517417 :   if (mLength + 1 > mTail.mReserved) {
    1394      866682 :     mTail.mReserved = mLength + 1;
    1395             :   }
    1396             : #endif
    1397     1517417 :   internalAppend(Forward<U>(aU));
    1398     1517348 :   return true;
    1399             : }
    1400             : 
    1401             : template<typename T, size_t N, class AP>
    1402             : template<typename U, size_t O, class BP>
    1403             : MOZ_ALWAYS_INLINE bool
    1404        8602 : Vector<T, N, AP>::appendAll(const Vector<U, O, BP>& aOther)
    1405             : {
    1406        8602 :   return append(aOther.begin(), aOther.length());
    1407             : }
    1408             : 
    1409             : template<typename T, size_t N, class AP>
    1410             : template<class U>
    1411             : MOZ_ALWAYS_INLINE bool
    1412       29460 : Vector<T, N, AP>::append(const U* aInsBegin, size_t aInsLength)
    1413             : {
    1414       29460 :   return append(aInsBegin, aInsBegin + aInsLength);
    1415             : }
    1416             : 
    1417             : template<typename T, size_t N, class AP>
    1418             : MOZ_ALWAYS_INLINE void
    1419      328296 : Vector<T, N, AP>::popBack()
    1420             : {
    1421      656590 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1422      328294 :   MOZ_ASSERT(!empty());
    1423      328294 :   --mLength;
    1424      328294 :   endNoCheck()->~T();
    1425      328294 : }
    1426             : 
    1427             : template<typename T, size_t N, class AP>
    1428             : MOZ_ALWAYS_INLINE T
    1429       72091 : Vector<T, N, AP>::popCopy()
    1430             : {
    1431       72091 :   T ret = back();
    1432       72091 :   popBack();
    1433       72091 :   return ret;
    1434             : }
    1435             : 
    1436             : template<typename T, size_t N, class AP>
    1437             : inline T*
    1438         551 : Vector<T, N, AP>::extractRawBuffer()
    1439             : {
    1440        1102 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1441             : 
    1442         551 :   if (usingInlineStorage()) {
    1443         494 :     return nullptr;
    1444             :   }
    1445             : 
    1446          57 :   T* ret = mBegin;
    1447          57 :   mBegin = inlineStorage();
    1448          57 :   mLength = 0;
    1449          57 :   mTail.mCapacity = kInlineCapacity;
    1450             : #ifdef DEBUG
    1451          57 :   mTail.mReserved = 0;
    1452             : #endif
    1453          57 :   return ret;
    1454             : }
    1455             : 
    1456             : template<typename T, size_t N, class AP>
    1457             : inline T*
    1458         551 : Vector<T, N, AP>::extractOrCopyRawBuffer()
    1459             : {
    1460         551 :   if (T* ret = extractRawBuffer()) {
    1461          57 :     return ret;
    1462             :   }
    1463             : 
    1464         988 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1465             : 
    1466         494 :   T* copy = this->template pod_malloc<T>(mLength);
    1467         494 :   if (!copy) {
    1468           0 :     return nullptr;
    1469             :   }
    1470             : 
    1471         494 :   Impl::moveConstruct(copy, beginNoCheck(), endNoCheck());
    1472         494 :   Impl::destroy(beginNoCheck(), endNoCheck());
    1473         494 :   mBegin = inlineStorage();
    1474         494 :   mLength = 0;
    1475         494 :   mTail.mCapacity = kInlineCapacity;
    1476             : #ifdef DEBUG
    1477         494 :   mTail.mReserved = 0;
    1478             : #endif
    1479         494 :   return copy;
    1480             : }
    1481             : 
    1482             : template<typename T, size_t N, class AP>
    1483             : inline void
    1484        1167 : Vector<T, N, AP>::replaceRawBuffer(T* aP, size_t aLength)
    1485             : {
    1486        2334 :   MOZ_REENTRANCY_GUARD_ET_AL;
    1487             : 
    1488             :   /* Destroy what we have. */
    1489        1167 :   Impl::destroy(beginNoCheck(), endNoCheck());
    1490        1167 :   if (!usingInlineStorage()) {
    1491           0 :     this->free_(beginNoCheck());
    1492             :   }
    1493             : 
    1494             :   /* Take in the new buffer. */
    1495        1167 :   if (aLength <= kInlineCapacity) {
    1496             :     /*
    1497             :      * We convert to inline storage if possible, even though aP might
    1498             :      * otherwise be acceptable.  Maybe this behaviour should be
    1499             :      * specifiable with an argument to this function.
    1500             :      */
    1501           4 :     mBegin = inlineStorage();
    1502           4 :     mLength = aLength;
    1503           4 :     mTail.mCapacity = kInlineCapacity;
    1504           4 :     Impl::moveConstruct(mBegin, aP, aP + aLength);
    1505           4 :     Impl::destroy(aP, aP + aLength);
    1506           4 :     this->free_(aP);
    1507             :   } else {
    1508        1163 :     mBegin = aP;
    1509        1163 :     mLength = aLength;
    1510        1163 :     mTail.mCapacity = aLength;
    1511             :   }
    1512             : #ifdef DEBUG
    1513        1167 :   mTail.mReserved = aLength;
    1514             : #endif
    1515        1167 : }
    1516             : 
    1517             : template<typename T, size_t N, class AP>
    1518             : inline size_t
    1519           0 : Vector<T, N, AP>::sizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
    1520             : {
    1521           0 :   return usingInlineStorage() ? 0 : aMallocSizeOf(beginNoCheck());
    1522             : }
    1523             : 
    1524             : template<typename T, size_t N, class AP>
    1525             : inline size_t
    1526           0 : Vector<T, N, AP>::sizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
    1527             : {
    1528           0 :   return aMallocSizeOf(this) + sizeOfExcludingThis(aMallocSizeOf);
    1529             : }
    1530             : 
    1531             : template<typename T, size_t N, class AP>
    1532             : inline void
    1533           0 : Vector<T, N, AP>::swap(Vector& aOther)
    1534             : {
    1535             :   static_assert(N == 0,
    1536             :                 "still need to implement this for N != 0");
    1537             : 
    1538             :   // This only works when inline storage is always empty.
    1539           0 :   if (!usingInlineStorage() && aOther.usingInlineStorage()) {
    1540           0 :     aOther.mBegin = mBegin;
    1541           0 :     mBegin = inlineStorage();
    1542           0 :   } else if (usingInlineStorage() && !aOther.usingInlineStorage()) {
    1543           0 :     mBegin = aOther.mBegin;
    1544           0 :     aOther.mBegin = aOther.inlineStorage();
    1545           0 :   } else if (!usingInlineStorage() && !aOther.usingInlineStorage()) {
    1546           0 :     Swap(mBegin, aOther.mBegin);
    1547             :   } else {
    1548             :     // This case is a no-op, since we'd set both to use their inline storage.
    1549             :   }
    1550             : 
    1551           0 :   Swap(mLength, aOther.mLength);
    1552           0 :   Swap(mTail.mCapacity, aOther.mTail.mCapacity);
    1553             : #ifdef DEBUG
    1554           0 :   Swap(mTail.mReserved, aOther.mTail.mReserved);
    1555             : #endif
    1556           0 : }
    1557             : 
    1558             : } // namespace mozilla
    1559             : 
    1560             : #ifdef _MSC_VER
    1561             : #pragma warning(pop)
    1562             : #endif
    1563             : 
    1564             : #endif /* mozilla_Vector_h */

Generated by: LCOV version 1.13