[llvm-commits] [llvm] r91426 - /llvm/trunk/include/llvm/ADT/SmallVector.h

Chris Lattner sabre at nondot.org
Tue Dec 15 00:29:22 PST 2009


Author: lattner
Date: Tue Dec 15 02:29:22 2009
New Revision: 91426

URL: http://llvm.org/viewvc/llvm-project?rev=91426&view=rev
Log:
hoist the begin/end/capacity members and a few trivial methods
up into the non-templated SmallVectorBase class.


Modified:
    llvm/trunk/include/llvm/ADT/SmallVector.h

Modified: llvm/trunk/include/llvm/ADT/SmallVector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91426&r1=91425&r2=91426&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ADT/SmallVector.h (original)
+++ llvm/trunk/include/llvm/ADT/SmallVector.h Tue Dec 15 02:29:22 2009
@@ -49,24 +49,14 @@
 /// SmallVectorBase - This is all the non-templated stuff common to all
 /// SmallVectors.
 class SmallVectorBase {
-  
-};
-  
-  
-/// SmallVectorImpl - This class consists of common code factored out of the
-/// SmallVector class to reduce code duplication based on the SmallVector 'N'
-/// template parameter.
-template <typename T>
-class SmallVectorImpl {
 protected:
-  T *Begin, *End, *Capacity;
+  void *BeginX, *EndX, *CapacityX;
 
   // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
   // don't want it to be automatically run, so we need to represent the space as
   // something else.  An array of char would work great, but might not be
   // aligned sufficiently.  Instead, we either use GCC extensions, or some
   // number of union instances for the space, which guarantee maximal alignment.
-protected:
 #ifdef __GNUC__
   typedef char U;
   U FirstEl __attribute__((aligned));
@@ -79,46 +69,65 @@
   } FirstEl;
 #endif
   // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
+  
+protected:
+  SmallVectorBase(size_t Size)
+    : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {}
+  
+  /// isSmall - Return true if this is a smallvector which has not had dynamic
+  /// memory allocated for it.
+  bool isSmall() const {
+    return BeginX == static_cast<const void*>(&FirstEl);
+  }
+  
+  
+public:
+  bool empty() const { return BeginX == EndX; }
+};
+  
+/// SmallVectorImpl - This class consists of common code factored out of the
+/// SmallVector class to reduce code duplication based on the SmallVector 'N'
+/// template parameter.
+template <typename T>
+class SmallVectorImpl : public SmallVectorBase {
+  void setEnd(T *P) { EndX = P; }
 public:
   // Default ctor - Initialize to empty.
-  explicit SmallVectorImpl(unsigned N)
-    : Begin(reinterpret_cast<T*>(&FirstEl)),
-      End(reinterpret_cast<T*>(&FirstEl)),
-      Capacity(reinterpret_cast<T*>(&FirstEl)+N) {
+  explicit SmallVectorImpl(unsigned N) : SmallVectorBase(N*sizeof(T)) {
   }
 
   ~SmallVectorImpl() {
     // Destroy the constructed elements in the vector.
-    destroy_range(Begin, End);
+    destroy_range(begin(), end());
 
     // If this wasn't grown from the inline copy, deallocate the old space.
     if (!isSmall())
-      operator delete(Begin);
+      operator delete(begin());
   }
 
   typedef size_t size_type;
   typedef ptrdiff_t difference_type;
   typedef T value_type;
-  typedef T* iterator;
-  typedef const T* const_iterator;
-
-  typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
-  typedef std::reverse_iterator<iterator>  reverse_iterator;
+  typedef T *iterator;
+  typedef const T *const_iterator;
 
-  typedef T& reference;
-  typedef const T& const_reference;
-  typedef T* pointer;
-  typedef const T* const_pointer;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<iterator> reverse_iterator;
 
-  bool empty() const { return Begin == End; }
-  size_type size() const { return End-Begin; }
-  size_type max_size() const { return size_type(-1) / sizeof(T); }
+  typedef T &reference;
+  typedef const T &const_reference;
+  typedef T *pointer;
+  typedef const T *const_pointer;
 
   // forward iterator creation methods.
-  iterator begin() { return Begin; }
-  const_iterator begin() const { return Begin; }
-  iterator end() { return End; }
-  const_iterator end() const { return End; }
+  iterator begin() { return (iterator)BeginX; }
+  const_iterator begin() const { return (const_iterator)BeginX; }
+  iterator end() { return (iterator)EndX; }
+  const_iterator end() const { return (const_iterator)EndX; }
+private:
+  iterator capacity_ptr() { return (iterator)CapacityX; }
+  const_iterator capacity_ptr() const { return (const_iterator)CapacityX; }
+public:
 
   // reverse iterator creation methods.
   reverse_iterator rbegin()            { return reverse_iterator(end()); }
@@ -126,14 +135,25 @@
   reverse_iterator rend()              { return reverse_iterator(begin()); }
   const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
 
-
+  size_type size() const { return end()-begin(); }
+  size_type max_size() const { return size_type(-1) / sizeof(T); }
+  
+  /// capacity - Return the total number of elements in the currently allocated
+  /// buffer.
+  size_t capacity() const { return capacity_ptr() - begin(); }
+  
+  /// data - Return a pointer to the vector's buffer, even if empty().
+  pointer data() { return pointer(begin()); }
+  /// data - Return a pointer to the vector's buffer, even if empty().
+  const_pointer data() const { return const_pointer(begin()); }
+  
   reference operator[](unsigned idx) {
-    assert(Begin + idx < End);
-    return Begin[idx];
+    assert(begin() + idx < end());
+    return begin()[idx];
   }
   const_reference operator[](unsigned idx) const {
-    assert(Begin + idx < End);
-    return Begin[idx];
+    assert(begin() + idx < end());
+    return begin()[idx];
   }
 
   reference front() {
@@ -151,10 +171,10 @@
   }
 
   void push_back(const_reference Elt) {
-    if (End < Capacity) {
+    if (EndX < CapacityX) {
   Retry:
-      new (End) T(Elt);
-      ++End;
+      new (end()) T(Elt);
+      setEnd(end()+1);
       return;
     }
     grow();
@@ -162,8 +182,8 @@
   }
 
   void pop_back() {
-    --End;
-    End->~T();
+    setEnd(end()-1);
+    end()->~T();
   }
 
   T pop_back_val() {
@@ -173,36 +193,36 @@
   }
 
   void clear() {
-    destroy_range(Begin, End);
-    End = Begin;
+    destroy_range(begin(), end());
+    EndX = BeginX;
   }
 
   void resize(unsigned N) {
     if (N < size()) {
-      destroy_range(Begin+N, End);
-      End = Begin+N;
+      destroy_range(begin()+N, end());
+      setEnd(begin()+N);
     } else if (N > size()) {
-      if (unsigned(Capacity-Begin) < N)
+      if (capacity() < N)
         grow(N);
-      construct_range(End, Begin+N, T());
-      End = Begin+N;
+      construct_range(end(), begin()+N, T());
+      setEnd(begin()+N);
     }
   }
 
   void resize(unsigned N, const T &NV) {
     if (N < size()) {
-      destroy_range(Begin+N, End);
-      End = Begin+N;
+      destroy_range(begin()+N, end());
+      setEnd(begin()+N);
     } else if (N > size()) {
-      if (unsigned(Capacity-Begin) < N)
+      if (capacity() < N)
         grow(N);
-      construct_range(End, Begin+N, NV);
-      End = Begin+N;
+      construct_range(end(), begin()+N, NV);
+      setEnd(begin()+N);
     }
   }
 
   void reserve(unsigned N) {
-    if (unsigned(Capacity-Begin) < N)
+    if (capacity() < N)
       grow(N);
   }
 
@@ -214,38 +234,38 @@
   void append(in_iter in_start, in_iter in_end) {
     size_type NumInputs = std::distance(in_start, in_end);
     // Grow allocated space if needed.
-    if (NumInputs > size_type(Capacity-End))
+    if (NumInputs > size_type(capacity_ptr()-end()))
       grow(size()+NumInputs);
 
     // Copy the new elements over.
-    std::uninitialized_copy(in_start, in_end, End);
-    End += NumInputs;
+    std::uninitialized_copy(in_start, in_end, end());
+    setEnd(end() + NumInputs);
   }
 
   /// append - Add the specified range to the end of the SmallVector.
   ///
   void append(size_type NumInputs, const T &Elt) {
     // Grow allocated space if needed.
-    if (NumInputs > size_type(Capacity-End))
+    if (NumInputs > size_type(capacity_ptr()-end()))
       grow(size()+NumInputs);
 
     // Copy the new elements over.
-    std::uninitialized_fill_n(End, NumInputs, Elt);
-    End += NumInputs;
+    std::uninitialized_fill_n(end(), NumInputs, Elt);
+    setEnd(end() + NumInputs);
   }
 
   void assign(unsigned NumElts, const T &Elt) {
     clear();
-    if (unsigned(Capacity-Begin) < NumElts)
+    if (capacity() < NumElts)
       grow(NumElts);
-    End = Begin+NumElts;
-    construct_range(Begin, End, Elt);
+    setEnd(begin()+NumElts);
+    construct_range(begin(), end(), Elt);
   }
 
   iterator erase(iterator I) {
     iterator N = I;
     // Shift all elts down one.
-    std::copy(I+1, End, I);
+    std::copy(I+1, end(), I);
     // Drop the last elt.
     pop_back();
     return(N);
@@ -254,36 +274,36 @@
   iterator erase(iterator S, iterator E) {
     iterator N = S;
     // Shift all elts down.
-    iterator I = std::copy(E, End, S);
+    iterator I = std::copy(E, end(), S);
     // Drop the last elts.
-    destroy_range(I, End);
-    End = I;
+    destroy_range(I, end());
+    setEnd(I);
     return(N);
   }
 
   iterator insert(iterator I, const T &Elt) {
-    if (I == End) {  // Important special case for empty vector.
+    if (I == end()) {  // Important special case for empty vector.
       push_back(Elt);
       return end()-1;
     }
 
-    if (End < Capacity) {
+    if (EndX < CapacityX) {
   Retry:
-      new (End) T(back());
-      ++End;
+      new (end()) T(back());
+      setEnd(end()+1);
       // Push everything else over.
-      std::copy_backward(I, End-1, End);
+      std::copy_backward(I, end()-1, end());
       *I = Elt;
       return I;
     }
-    size_t EltNo = I-Begin;
+    size_t EltNo = I-begin();
     grow();
-    I = Begin+EltNo;
+    I = begin()+EltNo;
     goto Retry;
   }
 
   iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
-    if (I == End) {  // Important special case for empty vector.
+    if (I == end()) {  // Important special case for empty vector.
       append(NumToInsert, Elt);
       return end()-1;
     }
@@ -302,8 +322,8 @@
     // insertion.  Since we already reserved space, we know that this won't
     // reallocate the vector.
     if (size_t(end()-I) >= NumToInsert) {
-      T *OldEnd = End;
-      append(End-NumToInsert, End);
+      T *OldEnd = end();
+      append(end()-NumToInsert, end());
 
       // Copy the existing elements that get replaced.
       std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
@@ -316,10 +336,10 @@
     // not inserting at the end.
 
     // Copy over the elements that we're about to overwrite.
-    T *OldEnd = End;
-    End += NumToInsert;
+    T *OldEnd = end();
+    setEnd(end() + NumToInsert);
     size_t NumOverwritten = OldEnd-I;
-    std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
+    std::uninitialized_copy(I, OldEnd, end()-NumOverwritten);
 
     // Replace the overwritten part.
     std::fill_n(I, NumOverwritten, Elt);
@@ -331,7 +351,7 @@
 
   template<typename ItTy>
   iterator insert(iterator I, ItTy From, ItTy To) {
-    if (I == End) {  // Important special case for empty vector.
+    if (I == end()) {  // Important special case for empty vector.
       append(From, To);
       return end()-1;
     }
@@ -351,8 +371,8 @@
     // insertion.  Since we already reserved space, we know that this won't
     // reallocate the vector.
     if (size_t(end()-I) >= NumToInsert) {
-      T *OldEnd = End;
-      append(End-NumToInsert, End);
+      T *OldEnd = end();
+      append(end()-NumToInsert, end());
 
       // Copy the existing elements that get replaced.
       std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
@@ -365,10 +385,10 @@
     // not inserting at the end.
 
     // Copy over the elements that we're about to overwrite.
-    T *OldEnd = End;
-    End += NumToInsert;
+    T *OldEnd = end();
+    setEnd(end() + NumToInsert);
     size_t NumOverwritten = OldEnd-I;
-    std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
+    std::uninitialized_copy(I, OldEnd, end()-NumOverwritten);
 
     // Replace the overwritten part.
     std::copy(From, From+NumOverwritten, I);
@@ -378,21 +398,11 @@
     return I;
   }
 
-  /// data - Return a pointer to the vector's buffer, even if empty().
-  pointer data() {
-    return pointer(Begin);
-  }
-
-  /// data - Return a pointer to the vector's buffer, even if empty().
-  const_pointer data() const {
-    return const_pointer(Begin);
-  }
-
   const SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
 
   bool operator==(const SmallVectorImpl &RHS) const {
     if (size() != RHS.size()) return false;
-    for (T *This = Begin, *That = RHS.Begin, *E = Begin+size();
+    for (const T *This = begin(), *That = RHS.begin(), *E = end();
          This != E; ++This, ++That)
       if (*This != *That)
         return false;
@@ -405,10 +415,6 @@
                                         RHS.begin(), RHS.end());
   }
 
-  /// capacity - Return the total number of elements in the currently allocated
-  /// buffer.
-  size_t capacity() const { return Capacity - Begin; }
-
   /// set_size - Set the array size to \arg N, which the current array must have
   /// enough capacity for.
   ///
@@ -420,17 +426,10 @@
   /// which will only be overwritten.
   void set_size(unsigned N) {
     assert(N <= capacity());
-    End = Begin + N;
+    setEnd(begin() + N);
   }
 
 private:
-  /// isSmall - Return true if this is a smallvector which has not had dynamic
-  /// memory allocated for it.
-  bool isSmall() const {
-    return static_cast<const void*>(Begin) ==
-           static_cast<const void*>(&FirstEl);
-  }
-
   /// grow - double the size of the allocated memory, guaranteeing space for at
   /// least one more element or MinSize if specified.
   void grow(size_type MinSize = 0);
@@ -441,6 +440,7 @@
   }
 
   void destroy_range(T *S, T *E) {
+    // TODO: POD
     while (S != E) {
       --E;
       E->~T();
@@ -451,7 +451,7 @@
 // Define this out-of-line to dissuade the C++ compiler from inlining it.
 template <typename T>
 void SmallVectorImpl<T>::grow(size_t MinSize) {
-  size_t CurCapacity = Capacity-Begin;
+  size_t CurCapacity = capacity();
   size_t CurSize = size();
   size_t NewCapacity = 2*CurCapacity;
   if (NewCapacity < MinSize)
@@ -460,21 +460,21 @@
 
   // Copy the elements over.
   if (is_class<T>::value)
-    std::uninitialized_copy(Begin, End, NewElts);
+    std::uninitialized_copy(begin(), end(), NewElts);
   else
     // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
-    memcpy(NewElts, Begin, CurSize * sizeof(T));
+    memcpy(NewElts, begin(), CurSize * sizeof(T));
 
   // Destroy the original elements.
-  destroy_range(Begin, End);
+  destroy_range(begin(), end());
 
   // If this wasn't grown from the inline copy, deallocate the old space.
   if (!isSmall())
-    operator delete(Begin);
+    operator delete(begin());
 
-  Begin = NewElts;
-  End = NewElts+CurSize;
-  Capacity = Begin+NewCapacity;
+  setEnd(NewElts+CurSize);
+  BeginX = NewElts;
+  CapacityX = begin()+NewCapacity;
 }
 
 template <typename T>
@@ -483,35 +483,35 @@
 
   // We can only avoid copying elements if neither vector is small.
   if (!isSmall() && !RHS.isSmall()) {
-    std::swap(Begin, RHS.Begin);
-    std::swap(End, RHS.End);
-    std::swap(Capacity, RHS.Capacity);
+    std::swap(BeginX, RHS.BeginX);
+    std::swap(EndX, RHS.EndX);
+    std::swap(CapacityX, RHS.CapacityX);
     return;
   }
-  if (RHS.size() > size_type(Capacity-Begin))
+  if (RHS.size() > capacity())
     grow(RHS.size());
-  if (size() > size_type(RHS.Capacity-RHS.begin()))
+  if (size() > RHS.capacity())
     RHS.grow(size());
 
   // Swap the shared elements.
   size_t NumShared = size();
   if (NumShared > RHS.size()) NumShared = RHS.size();
   for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
-    std::swap(Begin[i], RHS[i]);
+    std::swap((*this)[i], RHS[i]);
 
   // Copy over the extra elts.
   if (size() > RHS.size()) {
     size_t EltDiff = size() - RHS.size();
-    std::uninitialized_copy(Begin+NumShared, End, RHS.End);
-    RHS.End += EltDiff;
-    destroy_range(Begin+NumShared, End);
-    End = Begin+NumShared;
+    std::uninitialized_copy(begin()+NumShared, end(), RHS.end());
+    RHS.setEnd(RHS.end()+EltDiff);
+    destroy_range(begin()+NumShared, end());
+    setEnd(begin()+NumShared);
   } else if (RHS.size() > size()) {
     size_t EltDiff = RHS.size() - size();
-    std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End);
-    End += EltDiff;
-    destroy_range(RHS.Begin+NumShared, RHS.End);
-    RHS.End = RHS.Begin+NumShared;
+    std::uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end());
+    setEnd(end() + EltDiff);
+    destroy_range(RHS.begin()+NumShared, RHS.end());
+    RHS.setEnd(RHS.begin()+NumShared);
   }
 }
 
@@ -523,42 +523,42 @@
 
   // If we already have sufficient space, assign the common elements, then
   // destroy any excess.
-  unsigned RHSSize = unsigned(RHS.size());
-  unsigned CurSize = unsigned(size());
+  size_t RHSSize = RHS.size();
+  size_t CurSize = size();
   if (CurSize >= RHSSize) {
     // Assign common elements.
     iterator NewEnd;
     if (RHSSize)
-      NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin);
+      NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, begin());
     else
-      NewEnd = Begin;
+      NewEnd = begin();
 
     // Destroy excess elements.
-    destroy_range(NewEnd, End);
+    destroy_range(NewEnd, end());
 
     // Trim.
-    End = NewEnd;
+    setEnd(NewEnd);
     return *this;
   }
 
   // If we have to grow to have enough elements, destroy the current elements.
   // This allows us to avoid copying them during the grow.
-  if (unsigned(Capacity-Begin) < RHSSize) {
+  if (capacity() < RHSSize) {
     // Destroy current elements.
-    destroy_range(Begin, End);
-    End = Begin;
+    destroy_range(begin(), end());
+    setEnd(begin());
     CurSize = 0;
     grow(RHSSize);
   } else if (CurSize) {
     // Otherwise, use assignment for the already-constructed elements.
-    std::copy(RHS.Begin, RHS.Begin+CurSize, Begin);
+    std::copy(RHS.begin(), RHS.begin()+CurSize, begin());
   }
 
   // Copy construct the new elements in place.
-  std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
+  std::uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize);
 
   // Set end.
-  End = Begin+RHSSize;
+  setEnd(begin()+RHSSize);
   return *this;
 }
 





More information about the llvm-commits mailing list