Remove assertions from the SmallVector class. They slow down clients of
[oota-llvm.git] / include / llvm / ADT / SmallVector.h
1 //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the SmallVector class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ADT_SMALLVECTOR_H
15 #define LLVM_ADT_SMALLVECTOR_H
16
17 #include <algorithm>
18 #include <iterator>
19 #include <memory>
20
21 namespace llvm {
22
23 /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized
24 /// for the case when the array is small.  It contains some number of elements
25 /// in-place, which allows it to avoid heap allocation when the actual number of
26 /// elements is below that threshold.  This allows normal "small" cases to be
27 /// fast without losing generality for large inputs.
28 ///
29 /// Note that this does not attempt to be exception safe.
30 ///
31 template <typename T, unsigned N>
32 class SmallVector {
33   // Allocate raw space for N elements of type T.  If T has a ctor or dtor, we
34   // don't want it to be automatically run, so we need to represent the space as
35   // something else.  An array of char would work great, but might not be
36   // aligned sufficiently.  Instead, we either use GCC extensions, or some
37   // number of union instances for the space, which guarantee maximal alignment.
38   union U {
39     double D;
40     long double LD;
41     long long L;
42     void *P;
43   };
44   
45   /// InlineElts - These are the 'N' elements that are stored inline in the body
46   /// of the vector
47   U InlineElts[(sizeof(T)*N+sizeof(U)-1)/sizeof(U)];
48   T *Begin, *End, *Capacity;
49 public:
50   // Default ctor - Initialize to empty.
51   SmallVector() : Begin((T*)InlineElts), End(Begin), Capacity(Begin+N) {
52   }
53   
54   SmallVector(const SmallVector &RHS) {
55     unsigned RHSSize = RHS.size();
56     Begin = (T*)InlineElts;
57
58     // Doesn't fit in the small case?  Allocate space.
59     if (RHSSize > N) {
60       End = Capacity = Begin;
61       grow(RHSSize);
62     }
63     End = Begin+RHSSize;
64     Capacity = Begin+N;
65     std::uninitialized_copy(RHS.begin(), RHS.end(), Begin);
66   }
67   ~SmallVector() {
68     // Destroy the constructed elements in the vector.
69     for (iterator I = Begin, E = End; I != E; ++I)
70       I->~T();
71
72     // If this wasn't grown from the inline copy, deallocate the old space.
73     if ((void*)Begin != (void*)InlineElts)
74       delete[] (char*)Begin;
75   }
76   
77   typedef size_t size_type;
78   typedef T* iterator;
79   typedef const T* const_iterator;
80   typedef T& reference;
81   typedef const T& const_reference;
82
83   bool empty() const { return Begin == End; }
84   size_type size() const { return End-Begin; }
85   
86   iterator begin() { return Begin; }
87   const_iterator begin() const { return Begin; }
88
89   iterator end() { return End; }
90   const_iterator end() const { return End; }
91   
92   reference operator[](unsigned idx) {
93     return Begin[idx];
94   }
95   const_reference operator[](unsigned idx) const {
96     return Begin[idx];
97   }
98   
99   reference back() {
100     return end()[-1];
101   }
102   const_reference back() const {
103     return end()[-1];
104   }
105   
106   void push_back(const_reference Elt) {
107     if (End < Capacity) {
108   Retry:
109       new (End) T(Elt);
110       ++End;
111       return;
112     }
113     grow();
114     goto Retry;
115   }
116   
117   void pop_back() {
118     --End;
119     End->~T();
120   }
121   
122   void clear() {
123     while (End != Begin) {
124       End->~T();
125       --End;
126     }
127   }
128   
129   /// append - Add the specified range to the end of the SmallVector.
130   ///
131   template<typename in_iter>
132   void append(in_iter in_start, in_iter in_end) {
133     unsigned NumInputs = std::distance(in_start, in_end);
134     // Grow allocated space if needed.
135     if (End+NumInputs > Capacity)
136       grow(size()+NumInputs);
137
138     // Copy the new elements over.
139     std::uninitialized_copy(in_start, in_end, End);
140     End += NumInputs;
141   }
142   
143   const SmallVector &operator=(const SmallVector &RHS) {
144     // Avoid self-assignment.
145     if (this == &RHS) return *this;
146     
147     // If we already have sufficient space, assign the common elements, then
148     // destroy any excess.
149     unsigned RHSSize = RHS.size();
150     unsigned CurSize = size();
151     if (CurSize >= RHSSize) {
152       // Assign common elements.
153       std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin);
154       
155       // Destroy excess elements.
156       for (unsigned i = RHSSize; i != CurSize; ++i)
157         Begin[i].~T();
158       
159       // Trim.
160       End = Begin + RHSSize;
161       return *this;
162     }
163     
164     // If we have to grow to have enough elements, destroy the current elements.
165     // This allows us to avoid copying them during the grow.
166     if (Capacity-Begin < RHSSize) {
167       // Destroy current elements.
168       for (iterator I = Begin, E = End; I != E; ++I)
169         I->~T();
170       End = Begin;
171       CurSize = 0;
172       grow(RHSSize);
173     } else if (CurSize) {
174       // Otherwise, use assignment for the already-constructed elements.
175       std::copy(RHS.Begin, RHS.Begin+CurSize, Begin);
176     }
177     
178     // Copy construct the new elements in place.
179     std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
180     
181     // Set end.
182     End = Begin+RHSSize;
183   }
184   
185 private:
186   /// isSmall - Return true if this is a smallvector which has not had dynamic
187   /// memory allocated for it.
188   bool isSmall() const {
189     return (void*)Begin == (void*)InlineElts;
190   }
191
192   /// grow - double the size of the allocated memory, guaranteeing space for at
193   /// least one more element or MinSize if specified.
194   void grow(unsigned MinSize = 0) {
195     unsigned CurCapacity = Capacity-Begin;
196     unsigned CurSize = size();
197     unsigned NewCapacity = 2*CurCapacity;
198     if (NewCapacity < MinSize)
199       NewCapacity = MinSize;
200     T *NewElts = reinterpret_cast<T*>(new char[NewCapacity*sizeof(T)]);
201
202     // Copy the elements over.
203     std::uninitialized_copy(Begin, End, NewElts);
204     
205     // Destroy the original elements.
206     for (iterator I = Begin, E = End; I != E; ++I)
207       I->~T();
208     
209     // If this wasn't grown from the inline copy, deallocate the old space.
210     if (!isSmall())
211       delete[] (char*)Begin;
212     
213     Begin = NewElts;
214     End = NewElts+CurSize;
215     Capacity = Begin+NewCapacity;
216   }
217 };
218
219 } // End llvm namespace
220
221 #endif