Bug 808679 - Add asserts for Vector::Range and Vector srcbeg <= srcend. r=Waldo
authorChris Peterson <cpeterson@mozilla.com>
Tue, 11 Feb 2014 22:42:39 -0800
changeset 188327 61834b158c735d050c6dd1f925ff5a70d0974d5f
parent 188326 543382e6f36778c888515df397fc0566e7072f47
child 188328 56f74fcba1d667d98bcdb4d1e6cdf472bcee8d98
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs808679
milestone30.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 808679 - Add asserts for Vector::Range and Vector srcbeg <= srcend. r=Waldo
mfbt/Vector.h
--- a/mfbt/Vector.h
+++ b/mfbt/Vector.h
@@ -54,42 +54,46 @@ static bool CapacityHasExcessSpace(size_
  * This template class provides a default implementation for vector operations
  * when the element type is not known to be a POD, as judged by IsPod.
  */
 template<typename T, size_t N, class AP, class ThisVector, bool IsPod>
 struct VectorImpl
 {
     /* Destroys constructed objects in the range [begin, end). */
     static inline void destroy(T* begin, T* end) {
+      MOZ_ASSERT(begin <= end);
       for (T* p = begin; p < end; ++p)
         p->~T();
     }
 
     /* Constructs objects in the uninitialized range [begin, end). */
     static inline void initialize(T* begin, T* end) {
+      MOZ_ASSERT(begin <= end);
       for (T* p = begin; p < end; ++p)
         new(p) T();
     }
 
     /*
      * Copy-constructs objects in the uninitialized range
      * [dst, dst+(srcend-srcbeg)) from the range [srcbeg, srcend).
      */
     template<typename U>
     static inline void copyConstruct(T* dst, const U* srcbeg, const U* srcend) {
+      MOZ_ASSERT(srcbeg <= srcend);
       for (const U* p = srcbeg; p < srcend; ++p, ++dst)
         new(dst) T(*p);
     }
 
     /*
      * Move-constructs objects in the uninitialized range
      * [dst, dst+(srcend-srcbeg)) from the range [srcbeg, srcend).
      */
     template<typename U>
     static inline void moveConstruct(T* dst, U* srcbeg, U* srcend) {
+      MOZ_ASSERT(srcbeg <= srcend);
       for (U* p = srcbeg; p < srcend; ++p, ++dst)
         new(dst) T(Move(*p));
     }
 
     /*
      * Copy-constructs objects in the uninitialized range [dst, dst+n) from the
      * same object u.
      */
@@ -139,29 +143,31 @@ struct VectorImpl<T, N, AP, ThisVector, 
       /*
        * You would think that memset would be a big win (or even break even)
        * when we know T is a POD. But currently it's not. This is probably
        * because |append| tends to be given small ranges and memset requires
        * a function call that doesn't get inlined.
        *
        * memset(begin, 0, sizeof(T) * (end-begin));
        */
+      MOZ_ASSERT(begin <= end);
       for (T* p = begin; p < end; ++p)
         new(p) T();
     }
 
     template<typename U>
     static inline void copyConstruct(T* dst, const U* srcbeg, const U* srcend) {
       /*
        * See above memset comment. Also, notice that copyConstruct is
        * currently templated (T != U), so memcpy won't work without
        * requiring T == U.
        *
        * memcpy(dst, srcbeg, sizeof(T) * (srcend - srcbeg));
        */
+      MOZ_ASSERT(srcbeg <= srcend);
       for (const U* p = srcbeg; p < srcend; ++p, ++dst)
         *dst = *p;
     }
 
     template<typename U>
     static inline void moveConstruct(T* dst, const U* srcbeg, const U* srcend) {
       copyConstruct(dst, srcbeg, srcend);
     }
@@ -386,23 +392,25 @@ class VectorBase : private AllocPolicy
       return *(end() - 1);
     }
 
     class Range
     {
         friend class VectorBase;
         T* cur_;
         T* end_;
-        Range(T* cur, T* end) : cur_(cur), end_(end) {}
+        Range(T* cur, T* end) : cur_(cur), end_(end) {
+          MOZ_ASSERT(cur <= end);
+        }
 
       public:
         Range() {}
         bool empty() const { return cur_ == end_; }
-        size_t remain() const { return end_ - cur_; }
-        T& front() const { return *cur_; }
+        size_t remain() const { return PointerRangeSize(cur_, end_); }
+        T& front() const { MOZ_ASSERT(!empty()); return *cur_; }
         void popFront() { MOZ_ASSERT(!empty()); ++cur_; }
         T popCopyFront() { MOZ_ASSERT(!empty()); return *cur_++; }
     };
 
     Range all() {
       return Range(begin(), end());
     }