xref: /aosp_15_r20/external/llvm/lib/Support/SmallPtrSet.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the SmallPtrSet class.  See SmallPtrSet.h for an
11*9880d681SAndroid Build Coastguard Worker // overview of the algorithm.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMapInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
18*9880d681SAndroid Build Coastguard Worker #include <algorithm>
19*9880d681SAndroid Build Coastguard Worker #include <cstdlib>
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker using namespace llvm;
22*9880d681SAndroid Build Coastguard Worker 
shrink_and_clear()23*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::shrink_and_clear() {
24*9880d681SAndroid Build Coastguard Worker   assert(!isSmall() && "Can't shrink a small set!");
25*9880d681SAndroid Build Coastguard Worker   free(CurArray);
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker   // Reduce the number of buckets.
28*9880d681SAndroid Build Coastguard Worker   unsigned Size = size();
29*9880d681SAndroid Build Coastguard Worker   CurArraySize = Size > 16 ? 1 << (Log2_32_Ceil(Size) + 1) : 32;
30*9880d681SAndroid Build Coastguard Worker   NumNonEmpty = NumTombstones = 0;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker   // Install the new array.  Clear all the buckets to empty.
33*9880d681SAndroid Build Coastguard Worker   CurArray = (const void**)malloc(sizeof(void*) * CurArraySize);
34*9880d681SAndroid Build Coastguard Worker   assert(CurArray && "Failed to allocate memory?");
35*9880d681SAndroid Build Coastguard Worker   memset(CurArray, -1, CurArraySize*sizeof(void*));
36*9880d681SAndroid Build Coastguard Worker }
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker std::pair<const void *const *, bool>
insert_imp_big(const void * Ptr)39*9880d681SAndroid Build Coastguard Worker SmallPtrSetImplBase::insert_imp_big(const void *Ptr) {
40*9880d681SAndroid Build Coastguard Worker   if (LLVM_UNLIKELY(size() * 4 >= CurArraySize * 3)) {
41*9880d681SAndroid Build Coastguard Worker     // If more than 3/4 of the array is full, grow.
42*9880d681SAndroid Build Coastguard Worker     Grow(CurArraySize < 64 ? 128 : CurArraySize * 2);
43*9880d681SAndroid Build Coastguard Worker   } else if (LLVM_UNLIKELY(CurArraySize - NumNonEmpty < CurArraySize / 8)) {
44*9880d681SAndroid Build Coastguard Worker     // If fewer of 1/8 of the array is empty (meaning that many are filled with
45*9880d681SAndroid Build Coastguard Worker     // tombstones), rehash.
46*9880d681SAndroid Build Coastguard Worker     Grow(CurArraySize);
47*9880d681SAndroid Build Coastguard Worker   }
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker   // Okay, we know we have space.  Find a hash bucket.
50*9880d681SAndroid Build Coastguard Worker   const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr));
51*9880d681SAndroid Build Coastguard Worker   if (*Bucket == Ptr)
52*9880d681SAndroid Build Coastguard Worker     return std::make_pair(Bucket, false); // Already inserted, good.
53*9880d681SAndroid Build Coastguard Worker 
54*9880d681SAndroid Build Coastguard Worker   // Otherwise, insert it!
55*9880d681SAndroid Build Coastguard Worker   if (*Bucket == getTombstoneMarker())
56*9880d681SAndroid Build Coastguard Worker     --NumTombstones;
57*9880d681SAndroid Build Coastguard Worker   else
58*9880d681SAndroid Build Coastguard Worker     ++NumNonEmpty; // Track density.
59*9880d681SAndroid Build Coastguard Worker   *Bucket = Ptr;
60*9880d681SAndroid Build Coastguard Worker   return std::make_pair(Bucket, true);
61*9880d681SAndroid Build Coastguard Worker }
62*9880d681SAndroid Build Coastguard Worker 
erase_imp(const void * Ptr)63*9880d681SAndroid Build Coastguard Worker bool SmallPtrSetImplBase::erase_imp(const void * Ptr) {
64*9880d681SAndroid Build Coastguard Worker   if (isSmall()) {
65*9880d681SAndroid Build Coastguard Worker     // Check to see if it is in the set.
66*9880d681SAndroid Build Coastguard Worker     for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty; APtr != E;
67*9880d681SAndroid Build Coastguard Worker          ++APtr)
68*9880d681SAndroid Build Coastguard Worker       if (*APtr == Ptr) {
69*9880d681SAndroid Build Coastguard Worker         // If it is in the set, replace this element.
70*9880d681SAndroid Build Coastguard Worker         *APtr = getTombstoneMarker();
71*9880d681SAndroid Build Coastguard Worker         ++NumTombstones;
72*9880d681SAndroid Build Coastguard Worker         return true;
73*9880d681SAndroid Build Coastguard Worker       }
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker     return false;
76*9880d681SAndroid Build Coastguard Worker   }
77*9880d681SAndroid Build Coastguard Worker 
78*9880d681SAndroid Build Coastguard Worker   // Okay, we know we have space.  Find a hash bucket.
79*9880d681SAndroid Build Coastguard Worker   void **Bucket = const_cast<void**>(FindBucketFor(Ptr));
80*9880d681SAndroid Build Coastguard Worker   if (*Bucket != Ptr) return false;  // Not in the set?
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker   // Set this as a tombstone.
83*9880d681SAndroid Build Coastguard Worker   *Bucket = getTombstoneMarker();
84*9880d681SAndroid Build Coastguard Worker   ++NumTombstones;
85*9880d681SAndroid Build Coastguard Worker   return true;
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker 
FindBucketFor(const void * Ptr) const88*9880d681SAndroid Build Coastguard Worker const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const {
89*9880d681SAndroid Build Coastguard Worker   unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1);
90*9880d681SAndroid Build Coastguard Worker   unsigned ArraySize = CurArraySize;
91*9880d681SAndroid Build Coastguard Worker   unsigned ProbeAmt = 1;
92*9880d681SAndroid Build Coastguard Worker   const void *const *Array = CurArray;
93*9880d681SAndroid Build Coastguard Worker   const void *const *Tombstone = nullptr;
94*9880d681SAndroid Build Coastguard Worker   while (1) {
95*9880d681SAndroid Build Coastguard Worker     // If we found an empty bucket, the pointer doesn't exist in the set.
96*9880d681SAndroid Build Coastguard Worker     // Return a tombstone if we've seen one so far, or the empty bucket if
97*9880d681SAndroid Build Coastguard Worker     // not.
98*9880d681SAndroid Build Coastguard Worker     if (LLVM_LIKELY(Array[Bucket] == getEmptyMarker()))
99*9880d681SAndroid Build Coastguard Worker       return Tombstone ? Tombstone : Array+Bucket;
100*9880d681SAndroid Build Coastguard Worker 
101*9880d681SAndroid Build Coastguard Worker     // Found Ptr's bucket?
102*9880d681SAndroid Build Coastguard Worker     if (LLVM_LIKELY(Array[Bucket] == Ptr))
103*9880d681SAndroid Build Coastguard Worker       return Array+Bucket;
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker     // If this is a tombstone, remember it.  If Ptr ends up not in the set, we
106*9880d681SAndroid Build Coastguard Worker     // prefer to return it than something that would require more probing.
107*9880d681SAndroid Build Coastguard Worker     if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
108*9880d681SAndroid Build Coastguard Worker       Tombstone = Array+Bucket;  // Remember the first tombstone found.
109*9880d681SAndroid Build Coastguard Worker 
110*9880d681SAndroid Build Coastguard Worker     // It's a hash collision or a tombstone. Reprobe.
111*9880d681SAndroid Build Coastguard Worker     Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
112*9880d681SAndroid Build Coastguard Worker   }
113*9880d681SAndroid Build Coastguard Worker }
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker /// Grow - Allocate a larger backing store for the buckets and move it over.
116*9880d681SAndroid Build Coastguard Worker ///
Grow(unsigned NewSize)117*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::Grow(unsigned NewSize) {
118*9880d681SAndroid Build Coastguard Worker   const void **OldBuckets = CurArray;
119*9880d681SAndroid Build Coastguard Worker   const void **OldEnd = EndPointer();
120*9880d681SAndroid Build Coastguard Worker   bool WasSmall = isSmall();
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   // Install the new array.  Clear all the buckets to empty.
123*9880d681SAndroid Build Coastguard Worker   CurArray = (const void**)malloc(sizeof(void*) * NewSize);
124*9880d681SAndroid Build Coastguard Worker   assert(CurArray && "Failed to allocate memory?");
125*9880d681SAndroid Build Coastguard Worker   CurArraySize = NewSize;
126*9880d681SAndroid Build Coastguard Worker   memset(CurArray, -1, NewSize*sizeof(void*));
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   // Copy over all valid entries.
129*9880d681SAndroid Build Coastguard Worker   for (const void **BucketPtr = OldBuckets; BucketPtr != OldEnd; ++BucketPtr) {
130*9880d681SAndroid Build Coastguard Worker     // Copy over the element if it is valid.
131*9880d681SAndroid Build Coastguard Worker     const void *Elt = *BucketPtr;
132*9880d681SAndroid Build Coastguard Worker     if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
133*9880d681SAndroid Build Coastguard Worker       *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt);
134*9880d681SAndroid Build Coastguard Worker   }
135*9880d681SAndroid Build Coastguard Worker 
136*9880d681SAndroid Build Coastguard Worker   if (!WasSmall)
137*9880d681SAndroid Build Coastguard Worker     free(OldBuckets);
138*9880d681SAndroid Build Coastguard Worker   NumNonEmpty -= NumTombstones;
139*9880d681SAndroid Build Coastguard Worker   NumTombstones = 0;
140*9880d681SAndroid Build Coastguard Worker }
141*9880d681SAndroid Build Coastguard Worker 
SmallPtrSetImplBase(const void ** SmallStorage,const SmallPtrSetImplBase & that)142*9880d681SAndroid Build Coastguard Worker SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
143*9880d681SAndroid Build Coastguard Worker                                          const SmallPtrSetImplBase &that) {
144*9880d681SAndroid Build Coastguard Worker   SmallArray = SmallStorage;
145*9880d681SAndroid Build Coastguard Worker 
146*9880d681SAndroid Build Coastguard Worker   // If we're becoming small, prepare to insert into our stack space
147*9880d681SAndroid Build Coastguard Worker   if (that.isSmall()) {
148*9880d681SAndroid Build Coastguard Worker     CurArray = SmallArray;
149*9880d681SAndroid Build Coastguard Worker   // Otherwise, allocate new heap space (unless we were the same size)
150*9880d681SAndroid Build Coastguard Worker   } else {
151*9880d681SAndroid Build Coastguard Worker     CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize);
152*9880d681SAndroid Build Coastguard Worker     assert(CurArray && "Failed to allocate memory?");
153*9880d681SAndroid Build Coastguard Worker   }
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker   // Copy over the that array.
156*9880d681SAndroid Build Coastguard Worker   CopyHelper(that);
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker 
SmallPtrSetImplBase(const void ** SmallStorage,unsigned SmallSize,SmallPtrSetImplBase && that)159*9880d681SAndroid Build Coastguard Worker SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage,
160*9880d681SAndroid Build Coastguard Worker                                          unsigned SmallSize,
161*9880d681SAndroid Build Coastguard Worker                                          SmallPtrSetImplBase &&that) {
162*9880d681SAndroid Build Coastguard Worker   SmallArray = SmallStorage;
163*9880d681SAndroid Build Coastguard Worker   MoveHelper(SmallSize, std::move(that));
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker 
CopyFrom(const SmallPtrSetImplBase & RHS)166*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) {
167*9880d681SAndroid Build Coastguard Worker   assert(&RHS != this && "Self-copy should be handled by the caller.");
168*9880d681SAndroid Build Coastguard Worker 
169*9880d681SAndroid Build Coastguard Worker   if (isSmall() && RHS.isSmall())
170*9880d681SAndroid Build Coastguard Worker     assert(CurArraySize == RHS.CurArraySize &&
171*9880d681SAndroid Build Coastguard Worker            "Cannot assign sets with different small sizes");
172*9880d681SAndroid Build Coastguard Worker 
173*9880d681SAndroid Build Coastguard Worker   // If we're becoming small, prepare to insert into our stack space
174*9880d681SAndroid Build Coastguard Worker   if (RHS.isSmall()) {
175*9880d681SAndroid Build Coastguard Worker     if (!isSmall())
176*9880d681SAndroid Build Coastguard Worker       free(CurArray);
177*9880d681SAndroid Build Coastguard Worker     CurArray = SmallArray;
178*9880d681SAndroid Build Coastguard Worker   // Otherwise, allocate new heap space (unless we were the same size)
179*9880d681SAndroid Build Coastguard Worker   } else if (CurArraySize != RHS.CurArraySize) {
180*9880d681SAndroid Build Coastguard Worker     if (isSmall())
181*9880d681SAndroid Build Coastguard Worker       CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize);
182*9880d681SAndroid Build Coastguard Worker     else {
183*9880d681SAndroid Build Coastguard Worker       const void **T = (const void**)realloc(CurArray,
184*9880d681SAndroid Build Coastguard Worker                                              sizeof(void*) * RHS.CurArraySize);
185*9880d681SAndroid Build Coastguard Worker       if (!T)
186*9880d681SAndroid Build Coastguard Worker         free(CurArray);
187*9880d681SAndroid Build Coastguard Worker       CurArray = T;
188*9880d681SAndroid Build Coastguard Worker     }
189*9880d681SAndroid Build Coastguard Worker     assert(CurArray && "Failed to allocate memory?");
190*9880d681SAndroid Build Coastguard Worker   }
191*9880d681SAndroid Build Coastguard Worker 
192*9880d681SAndroid Build Coastguard Worker   CopyHelper(RHS);
193*9880d681SAndroid Build Coastguard Worker }
194*9880d681SAndroid Build Coastguard Worker 
CopyHelper(const SmallPtrSetImplBase & RHS)195*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::CopyHelper(const SmallPtrSetImplBase &RHS) {
196*9880d681SAndroid Build Coastguard Worker   // Copy over the new array size
197*9880d681SAndroid Build Coastguard Worker   CurArraySize = RHS.CurArraySize;
198*9880d681SAndroid Build Coastguard Worker 
199*9880d681SAndroid Build Coastguard Worker   // Copy over the contents from the other set
200*9880d681SAndroid Build Coastguard Worker   std::copy(RHS.CurArray, RHS.EndPointer(), CurArray);
201*9880d681SAndroid Build Coastguard Worker 
202*9880d681SAndroid Build Coastguard Worker   NumNonEmpty = RHS.NumNonEmpty;
203*9880d681SAndroid Build Coastguard Worker   NumTombstones = RHS.NumTombstones;
204*9880d681SAndroid Build Coastguard Worker }
205*9880d681SAndroid Build Coastguard Worker 
MoveFrom(unsigned SmallSize,SmallPtrSetImplBase && RHS)206*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize,
207*9880d681SAndroid Build Coastguard Worker                                    SmallPtrSetImplBase &&RHS) {
208*9880d681SAndroid Build Coastguard Worker   if (!isSmall())
209*9880d681SAndroid Build Coastguard Worker     free(CurArray);
210*9880d681SAndroid Build Coastguard Worker   MoveHelper(SmallSize, std::move(RHS));
211*9880d681SAndroid Build Coastguard Worker }
212*9880d681SAndroid Build Coastguard Worker 
MoveHelper(unsigned SmallSize,SmallPtrSetImplBase && RHS)213*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::MoveHelper(unsigned SmallSize,
214*9880d681SAndroid Build Coastguard Worker                                      SmallPtrSetImplBase &&RHS) {
215*9880d681SAndroid Build Coastguard Worker   assert(&RHS != this && "Self-move should be handled by the caller.");
216*9880d681SAndroid Build Coastguard Worker 
217*9880d681SAndroid Build Coastguard Worker   if (RHS.isSmall()) {
218*9880d681SAndroid Build Coastguard Worker     // Copy a small RHS rather than moving.
219*9880d681SAndroid Build Coastguard Worker     CurArray = SmallArray;
220*9880d681SAndroid Build Coastguard Worker     std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, CurArray);
221*9880d681SAndroid Build Coastguard Worker   } else {
222*9880d681SAndroid Build Coastguard Worker     CurArray = RHS.CurArray;
223*9880d681SAndroid Build Coastguard Worker     RHS.CurArray = RHS.SmallArray;
224*9880d681SAndroid Build Coastguard Worker   }
225*9880d681SAndroid Build Coastguard Worker 
226*9880d681SAndroid Build Coastguard Worker   // Copy the rest of the trivial members.
227*9880d681SAndroid Build Coastguard Worker   CurArraySize = RHS.CurArraySize;
228*9880d681SAndroid Build Coastguard Worker   NumNonEmpty = RHS.NumNonEmpty;
229*9880d681SAndroid Build Coastguard Worker   NumTombstones = RHS.NumTombstones;
230*9880d681SAndroid Build Coastguard Worker 
231*9880d681SAndroid Build Coastguard Worker   // Make the RHS small and empty.
232*9880d681SAndroid Build Coastguard Worker   RHS.CurArraySize = SmallSize;
233*9880d681SAndroid Build Coastguard Worker   assert(RHS.CurArray == RHS.SmallArray);
234*9880d681SAndroid Build Coastguard Worker   RHS.NumNonEmpty = 0;
235*9880d681SAndroid Build Coastguard Worker   RHS.NumTombstones = 0;
236*9880d681SAndroid Build Coastguard Worker }
237*9880d681SAndroid Build Coastguard Worker 
swap(SmallPtrSetImplBase & RHS)238*9880d681SAndroid Build Coastguard Worker void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) {
239*9880d681SAndroid Build Coastguard Worker   if (this == &RHS) return;
240*9880d681SAndroid Build Coastguard Worker 
241*9880d681SAndroid Build Coastguard Worker   // We can only avoid copying elements if neither set is small.
242*9880d681SAndroid Build Coastguard Worker   if (!this->isSmall() && !RHS.isSmall()) {
243*9880d681SAndroid Build Coastguard Worker     std::swap(this->CurArray, RHS.CurArray);
244*9880d681SAndroid Build Coastguard Worker     std::swap(this->CurArraySize, RHS.CurArraySize);
245*9880d681SAndroid Build Coastguard Worker     std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
246*9880d681SAndroid Build Coastguard Worker     std::swap(this->NumTombstones, RHS.NumTombstones);
247*9880d681SAndroid Build Coastguard Worker     return;
248*9880d681SAndroid Build Coastguard Worker   }
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker   // FIXME: From here on we assume that both sets have the same small size.
251*9880d681SAndroid Build Coastguard Worker 
252*9880d681SAndroid Build Coastguard Worker   // If only RHS is small, copy the small elements into LHS and move the pointer
253*9880d681SAndroid Build Coastguard Worker   // from LHS to RHS.
254*9880d681SAndroid Build Coastguard Worker   if (!this->isSmall() && RHS.isSmall()) {
255*9880d681SAndroid Build Coastguard Worker     assert(RHS.CurArray == RHS.SmallArray);
256*9880d681SAndroid Build Coastguard Worker     std::copy(RHS.CurArray, RHS.CurArray + RHS.NumNonEmpty, this->SmallArray);
257*9880d681SAndroid Build Coastguard Worker     std::swap(RHS.CurArraySize, this->CurArraySize);
258*9880d681SAndroid Build Coastguard Worker     std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
259*9880d681SAndroid Build Coastguard Worker     std::swap(this->NumTombstones, RHS.NumTombstones);
260*9880d681SAndroid Build Coastguard Worker     RHS.CurArray = this->CurArray;
261*9880d681SAndroid Build Coastguard Worker     this->CurArray = this->SmallArray;
262*9880d681SAndroid Build Coastguard Worker     return;
263*9880d681SAndroid Build Coastguard Worker   }
264*9880d681SAndroid Build Coastguard Worker 
265*9880d681SAndroid Build Coastguard Worker   // If only LHS is small, copy the small elements into RHS and move the pointer
266*9880d681SAndroid Build Coastguard Worker   // from RHS to LHS.
267*9880d681SAndroid Build Coastguard Worker   if (this->isSmall() && !RHS.isSmall()) {
268*9880d681SAndroid Build Coastguard Worker     assert(this->CurArray == this->SmallArray);
269*9880d681SAndroid Build Coastguard Worker     std::copy(this->CurArray, this->CurArray + this->NumNonEmpty,
270*9880d681SAndroid Build Coastguard Worker               RHS.SmallArray);
271*9880d681SAndroid Build Coastguard Worker     std::swap(RHS.CurArraySize, this->CurArraySize);
272*9880d681SAndroid Build Coastguard Worker     std::swap(RHS.NumNonEmpty, this->NumNonEmpty);
273*9880d681SAndroid Build Coastguard Worker     std::swap(RHS.NumTombstones, this->NumTombstones);
274*9880d681SAndroid Build Coastguard Worker     this->CurArray = RHS.CurArray;
275*9880d681SAndroid Build Coastguard Worker     RHS.CurArray = RHS.SmallArray;
276*9880d681SAndroid Build Coastguard Worker     return;
277*9880d681SAndroid Build Coastguard Worker   }
278*9880d681SAndroid Build Coastguard Worker 
279*9880d681SAndroid Build Coastguard Worker   // Both a small, just swap the small elements.
280*9880d681SAndroid Build Coastguard Worker   assert(this->isSmall() && RHS.isSmall());
281*9880d681SAndroid Build Coastguard Worker   unsigned MinNonEmpty = std::min(this->NumNonEmpty, RHS.NumNonEmpty);
282*9880d681SAndroid Build Coastguard Worker   std::swap_ranges(this->SmallArray, this->SmallArray + MinNonEmpty,
283*9880d681SAndroid Build Coastguard Worker                    RHS.SmallArray);
284*9880d681SAndroid Build Coastguard Worker   if (this->NumNonEmpty > MinNonEmpty) {
285*9880d681SAndroid Build Coastguard Worker     std::copy(this->SmallArray + MinNonEmpty,
286*9880d681SAndroid Build Coastguard Worker               this->SmallArray + this->NumNonEmpty,
287*9880d681SAndroid Build Coastguard Worker               RHS.SmallArray + MinNonEmpty);
288*9880d681SAndroid Build Coastguard Worker   } else {
289*9880d681SAndroid Build Coastguard Worker     std::copy(RHS.SmallArray + MinNonEmpty, RHS.SmallArray + RHS.NumNonEmpty,
290*9880d681SAndroid Build Coastguard Worker               this->SmallArray + MinNonEmpty);
291*9880d681SAndroid Build Coastguard Worker   }
292*9880d681SAndroid Build Coastguard Worker   assert(this->CurArraySize == RHS.CurArraySize);
293*9880d681SAndroid Build Coastguard Worker   std::swap(this->NumNonEmpty, RHS.NumNonEmpty);
294*9880d681SAndroid Build Coastguard Worker   std::swap(this->NumTombstones, RHS.NumTombstones);
295*9880d681SAndroid Build Coastguard Worker }
296