LLVM API Documentation
00001 //===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the SmallPtrSet class. See SmallPtrSet.h for an 00011 // overview of the algorithm. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/ADT/SmallPtrSet.h" 00016 #include "llvm/ADT/DenseMapInfo.h" 00017 #include "llvm/Support/MathExtras.h" 00018 #include <algorithm> 00019 #include <cstdlib> 00020 00021 using namespace llvm; 00022 00023 void SmallPtrSetImplBase::shrink_and_clear() { 00024 assert(!isSmall() && "Can't shrink a small set!"); 00025 free(CurArray); 00026 00027 // Reduce the number of buckets. 00028 CurArraySize = NumElements > 16 ? 1 << (Log2_32_Ceil(NumElements) + 1) : 32; 00029 NumElements = NumTombstones = 0; 00030 00031 // Install the new array. Clear all the buckets to empty. 00032 CurArray = (const void**)malloc(sizeof(void*) * CurArraySize); 00033 assert(CurArray && "Failed to allocate memory?"); 00034 memset(CurArray, -1, CurArraySize*sizeof(void*)); 00035 } 00036 00037 bool SmallPtrSetImplBase::insert_imp(const void * Ptr) { 00038 if (isSmall()) { 00039 // Check to see if it is already in the set. 00040 for (const void **APtr = SmallArray, **E = SmallArray+NumElements; 00041 APtr != E; ++APtr) 00042 if (*APtr == Ptr) 00043 return false; 00044 00045 // Nope, there isn't. If we stay small, just 'pushback' now. 00046 if (NumElements < CurArraySize) { 00047 SmallArray[NumElements++] = Ptr; 00048 return true; 00049 } 00050 // Otherwise, hit the big set case, which will call grow. 00051 } 00052 00053 if (NumElements*4 >= CurArraySize*3) { 00054 // If more than 3/4 of the array is full, grow. 00055 Grow(CurArraySize < 64 ? 128 : CurArraySize*2); 00056 } else if (CurArraySize-(NumElements+NumTombstones) < CurArraySize/8) { 00057 // If fewer of 1/8 of the array is empty (meaning that many are filled with 00058 // tombstones), rehash. 00059 Grow(CurArraySize); 00060 } 00061 00062 // Okay, we know we have space. Find a hash bucket. 00063 const void **Bucket = const_cast<const void**>(FindBucketFor(Ptr)); 00064 if (*Bucket == Ptr) return false; // Already inserted, good. 00065 00066 // Otherwise, insert it! 00067 if (*Bucket == getTombstoneMarker()) 00068 --NumTombstones; 00069 *Bucket = Ptr; 00070 ++NumElements; // Track density. 00071 return true; 00072 } 00073 00074 bool SmallPtrSetImplBase::erase_imp(const void * Ptr) { 00075 if (isSmall()) { 00076 // Check to see if it is in the set. 00077 for (const void **APtr = SmallArray, **E = SmallArray+NumElements; 00078 APtr != E; ++APtr) 00079 if (*APtr == Ptr) { 00080 // If it is in the set, replace this element. 00081 *APtr = E[-1]; 00082 E[-1] = getEmptyMarker(); 00083 --NumElements; 00084 return true; 00085 } 00086 00087 return false; 00088 } 00089 00090 // Okay, we know we have space. Find a hash bucket. 00091 void **Bucket = const_cast<void**>(FindBucketFor(Ptr)); 00092 if (*Bucket != Ptr) return false; // Not in the set? 00093 00094 // Set this as a tombstone. 00095 *Bucket = getTombstoneMarker(); 00096 --NumElements; 00097 ++NumTombstones; 00098 return true; 00099 } 00100 00101 const void * const *SmallPtrSetImplBase::FindBucketFor(const void *Ptr) const { 00102 unsigned Bucket = DenseMapInfo<void *>::getHashValue(Ptr) & (CurArraySize-1); 00103 unsigned ArraySize = CurArraySize; 00104 unsigned ProbeAmt = 1; 00105 const void *const *Array = CurArray; 00106 const void *const *Tombstone = nullptr; 00107 while (1) { 00108 // Found Ptr's bucket? 00109 if (Array[Bucket] == Ptr) 00110 return Array+Bucket; 00111 00112 // If we found an empty bucket, the pointer doesn't exist in the set. 00113 // Return a tombstone if we've seen one so far, or the empty bucket if 00114 // not. 00115 if (Array[Bucket] == getEmptyMarker()) 00116 return Tombstone ? Tombstone : Array+Bucket; 00117 00118 // If this is a tombstone, remember it. If Ptr ends up not in the set, we 00119 // prefer to return it than something that would require more probing. 00120 if (Array[Bucket] == getTombstoneMarker() && !Tombstone) 00121 Tombstone = Array+Bucket; // Remember the first tombstone found. 00122 00123 // It's a hash collision or a tombstone. Reprobe. 00124 Bucket = (Bucket + ProbeAmt++) & (ArraySize-1); 00125 } 00126 } 00127 00128 /// Grow - Allocate a larger backing store for the buckets and move it over. 00129 /// 00130 void SmallPtrSetImplBase::Grow(unsigned NewSize) { 00131 // Allocate at twice as many buckets, but at least 128. 00132 unsigned OldSize = CurArraySize; 00133 00134 const void **OldBuckets = CurArray; 00135 bool WasSmall = isSmall(); 00136 00137 // Install the new array. Clear all the buckets to empty. 00138 CurArray = (const void**)malloc(sizeof(void*) * NewSize); 00139 assert(CurArray && "Failed to allocate memory?"); 00140 CurArraySize = NewSize; 00141 memset(CurArray, -1, NewSize*sizeof(void*)); 00142 00143 // Copy over all the elements. 00144 if (WasSmall) { 00145 // Small sets store their elements in order. 00146 for (const void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements; 00147 BucketPtr != E; ++BucketPtr) { 00148 const void *Elt = *BucketPtr; 00149 *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt); 00150 } 00151 } else { 00152 // Copy over all valid entries. 00153 for (const void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize; 00154 BucketPtr != E; ++BucketPtr) { 00155 // Copy over the element if it is valid. 00156 const void *Elt = *BucketPtr; 00157 if (Elt != getTombstoneMarker() && Elt != getEmptyMarker()) 00158 *const_cast<void**>(FindBucketFor(Elt)) = const_cast<void*>(Elt); 00159 } 00160 00161 free(OldBuckets); 00162 NumTombstones = 0; 00163 } 00164 } 00165 00166 SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, 00167 const SmallPtrSetImplBase& that) { 00168 SmallArray = SmallStorage; 00169 00170 // If we're becoming small, prepare to insert into our stack space 00171 if (that.isSmall()) { 00172 CurArray = SmallArray; 00173 // Otherwise, allocate new heap space (unless we were the same size) 00174 } else { 00175 CurArray = (const void**)malloc(sizeof(void*) * that.CurArraySize); 00176 assert(CurArray && "Failed to allocate memory?"); 00177 } 00178 00179 // Copy over the new array size 00180 CurArraySize = that.CurArraySize; 00181 00182 // Copy over the contents from the other set 00183 memcpy(CurArray, that.CurArray, sizeof(void*)*CurArraySize); 00184 00185 NumElements = that.NumElements; 00186 NumTombstones = that.NumTombstones; 00187 } 00188 00189 SmallPtrSetImplBase::SmallPtrSetImplBase(const void **SmallStorage, 00190 unsigned SmallSize, 00191 SmallPtrSetImplBase &&that) { 00192 SmallArray = SmallStorage; 00193 00194 // Copy over the basic members. 00195 CurArraySize = that.CurArraySize; 00196 NumElements = that.NumElements; 00197 NumTombstones = that.NumTombstones; 00198 00199 // When small, just copy into our small buffer. 00200 if (that.isSmall()) { 00201 CurArray = SmallArray; 00202 memcpy(CurArray, that.CurArray, sizeof(void *) * CurArraySize); 00203 } else { 00204 // Otherwise, we steal the large memory allocation and no copy is needed. 00205 CurArray = that.CurArray; 00206 that.CurArray = that.SmallArray; 00207 } 00208 00209 // Make the "that" object small and empty. 00210 that.CurArraySize = SmallSize; 00211 assert(that.CurArray == that.SmallArray); 00212 that.NumElements = 0; 00213 that.NumTombstones = 0; 00214 } 00215 00216 /// CopyFrom - implement operator= from a smallptrset that has the same pointer 00217 /// type, but may have a different small size. 00218 void SmallPtrSetImplBase::CopyFrom(const SmallPtrSetImplBase &RHS) { 00219 assert(&RHS != this && "Self-copy should be handled by the caller."); 00220 00221 if (isSmall() && RHS.isSmall()) 00222 assert(CurArraySize == RHS.CurArraySize && 00223 "Cannot assign sets with different small sizes"); 00224 00225 // If we're becoming small, prepare to insert into our stack space 00226 if (RHS.isSmall()) { 00227 if (!isSmall()) 00228 free(CurArray); 00229 CurArray = SmallArray; 00230 // Otherwise, allocate new heap space (unless we were the same size) 00231 } else if (CurArraySize != RHS.CurArraySize) { 00232 if (isSmall()) 00233 CurArray = (const void**)malloc(sizeof(void*) * RHS.CurArraySize); 00234 else { 00235 const void **T = (const void**)realloc(CurArray, 00236 sizeof(void*) * RHS.CurArraySize); 00237 if (!T) 00238 free(CurArray); 00239 CurArray = T; 00240 } 00241 assert(CurArray && "Failed to allocate memory?"); 00242 } 00243 00244 // Copy over the new array size 00245 CurArraySize = RHS.CurArraySize; 00246 00247 // Copy over the contents from the other set 00248 memcpy(CurArray, RHS.CurArray, sizeof(void*)*CurArraySize); 00249 00250 NumElements = RHS.NumElements; 00251 NumTombstones = RHS.NumTombstones; 00252 } 00253 00254 void SmallPtrSetImplBase::MoveFrom(unsigned SmallSize, 00255 SmallPtrSetImplBase &&RHS) { 00256 assert(&RHS != this && "Self-move should be handled by the caller."); 00257 00258 if (!isSmall()) 00259 free(CurArray); 00260 00261 if (RHS.isSmall()) { 00262 // Copy a small RHS rather than moving. 00263 CurArray = SmallArray; 00264 memcpy(CurArray, RHS.CurArray, sizeof(void*)*RHS.CurArraySize); 00265 } else { 00266 CurArray = RHS.CurArray; 00267 RHS.CurArray = RHS.SmallArray; 00268 } 00269 00270 // Copy the rest of the trivial members. 00271 CurArraySize = RHS.CurArraySize; 00272 NumElements = RHS.NumElements; 00273 NumTombstones = RHS.NumTombstones; 00274 00275 // Make the RHS small and empty. 00276 RHS.CurArraySize = SmallSize; 00277 assert(RHS.CurArray == RHS.SmallArray); 00278 RHS.NumElements = 0; 00279 RHS.NumTombstones = 0; 00280 } 00281 00282 void SmallPtrSetImplBase::swap(SmallPtrSetImplBase &RHS) { 00283 if (this == &RHS) return; 00284 00285 // We can only avoid copying elements if neither set is small. 00286 if (!this->isSmall() && !RHS.isSmall()) { 00287 std::swap(this->CurArray, RHS.CurArray); 00288 std::swap(this->CurArraySize, RHS.CurArraySize); 00289 std::swap(this->NumElements, RHS.NumElements); 00290 std::swap(this->NumTombstones, RHS.NumTombstones); 00291 return; 00292 } 00293 00294 // FIXME: From here on we assume that both sets have the same small size. 00295 00296 // If only RHS is small, copy the small elements into LHS and move the pointer 00297 // from LHS to RHS. 00298 if (!this->isSmall() && RHS.isSmall()) { 00299 std::copy(RHS.SmallArray, RHS.SmallArray+RHS.CurArraySize, 00300 this->SmallArray); 00301 std::swap(this->NumElements, RHS.NumElements); 00302 std::swap(this->CurArraySize, RHS.CurArraySize); 00303 RHS.CurArray = this->CurArray; 00304 RHS.NumTombstones = this->NumTombstones; 00305 this->CurArray = this->SmallArray; 00306 this->NumTombstones = 0; 00307 return; 00308 } 00309 00310 // If only LHS is small, copy the small elements into RHS and move the pointer 00311 // from RHS to LHS. 00312 if (this->isSmall() && !RHS.isSmall()) { 00313 std::copy(this->SmallArray, this->SmallArray+this->CurArraySize, 00314 RHS.SmallArray); 00315 std::swap(RHS.NumElements, this->NumElements); 00316 std::swap(RHS.CurArraySize, this->CurArraySize); 00317 this->CurArray = RHS.CurArray; 00318 this->NumTombstones = RHS.NumTombstones; 00319 RHS.CurArray = RHS.SmallArray; 00320 RHS.NumTombstones = 0; 00321 return; 00322 } 00323 00324 // Both a small, just swap the small elements. 00325 assert(this->isSmall() && RHS.isSmall()); 00326 assert(this->CurArraySize == RHS.CurArraySize); 00327 std::swap_ranges(this->SmallArray, this->SmallArray+this->CurArraySize, 00328 RHS.SmallArray); 00329 std::swap(this->NumElements, RHS.NumElements); 00330 } 00331 00332 SmallPtrSetImplBase::~SmallPtrSetImplBase() { 00333 if (!isSmall()) 00334 free(CurArray); 00335 }