1 //===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the SmallPtrSet class. See SmallPtrSet.h for an
11 // overview of the algorithm.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/Support/MathExtras.h"
21 void SmallPtrSetImpl::shrink_and_clear() {
22 assert(!isSmall() && "Can't shrink a small set!");
25 // Reduce the number of buckets.
26 CurArraySize
= NumElements
> 16 ? 1 << (Log2_32_Ceil(NumElements
) + 1) : 32;
27 NumElements
= NumTombstones
= 0;
29 // Install the new array. Clear all the buckets to empty.
30 CurArray
= (const void**)malloc(sizeof(void*) * (CurArraySize
+1));
31 assert(CurArray
&& "Failed to allocate memory?");
32 memset(CurArray
, -1, CurArraySize
*sizeof(void*));
34 // The end pointer, always valid, is set to a valid element to help the
36 CurArray
[CurArraySize
] = 0;
39 bool SmallPtrSetImpl::insert_imp(const void * Ptr
) {
41 // Check to see if it is already in the set.
42 for (const void **APtr
= SmallArray
, **E
= SmallArray
+NumElements
;
47 // Nope, there isn't. If we stay small, just 'pushback' now.
48 if (NumElements
< CurArraySize
-1) {
49 SmallArray
[NumElements
++] = Ptr
;
52 // Otherwise, hit the big set case, which will call grow.
55 if (NumElements
*4 >= CurArraySize
*3) {
56 // If more than 3/4 of the array is full, grow.
57 Grow(CurArraySize
< 64 ? 128 : CurArraySize
*2);
58 } else if (CurArraySize
-(NumElements
+NumTombstones
) < CurArraySize
/8) {
59 // If fewer of 1/8 of the array is empty (meaning that many are filled with
60 // tombstones), rehash.
64 // Okay, we know we have space. Find a hash bucket.
65 const void **Bucket
= const_cast<const void**>(FindBucketFor(Ptr
));
66 if (*Bucket
== Ptr
) return false; // Already inserted, good.
68 // Otherwise, insert it!
69 if (*Bucket
== getTombstoneMarker())
72 ++NumElements
; // Track density.
76 bool SmallPtrSetImpl::erase_imp(const void * Ptr
) {
78 // Check to see if it is in the set.
79 for (const void **APtr
= SmallArray
, **E
= SmallArray
+NumElements
;
82 // If it is in the set, replace this element.
84 E
[-1] = getEmptyMarker();
92 // Okay, we know we have space. Find a hash bucket.
93 void **Bucket
= const_cast<void**>(FindBucketFor(Ptr
));
94 if (*Bucket
!= Ptr
) return false; // Not in the set?
96 // Set this as a tombstone.
97 *Bucket
= getTombstoneMarker();
103 const void * const *SmallPtrSetImpl::FindBucketFor(const void *Ptr
) const {
104 unsigned Bucket
= Hash(Ptr
);
105 unsigned ArraySize
= CurArraySize
;
106 unsigned ProbeAmt
= 1;
107 const void *const *Array
= CurArray
;
108 const void *const *Tombstone
= 0;
110 // Found Ptr's bucket?
111 if (Array
[Bucket
] == Ptr
)
114 // If we found an empty bucket, the pointer doesn't exist in the set.
115 // Return a tombstone if we've seen one so far, or the empty bucket if
117 if (Array
[Bucket
] == getEmptyMarker())
118 return Tombstone
? Tombstone
: Array
+Bucket
;
120 // If this is a tombstone, remember it. If Ptr ends up not in the set, we
121 // prefer to return it than something that would require more probing.
122 if (Array
[Bucket
] == getTombstoneMarker() && !Tombstone
)
123 Tombstone
= Array
+Bucket
; // Remember the first tombstone found.
125 // It's a hash collision or a tombstone. Reprobe.
126 Bucket
= (Bucket
+ ProbeAmt
++) & (ArraySize
-1);
130 /// Grow - Allocate a larger backing store for the buckets and move it over.
132 void SmallPtrSetImpl::Grow(unsigned NewSize
) {
133 // Allocate at twice as many buckets, but at least 128.
134 unsigned OldSize
= CurArraySize
;
136 const void **OldBuckets
= CurArray
;
137 bool WasSmall
= isSmall();
139 // Install the new array. Clear all the buckets to empty.
140 CurArray
= (const void**)malloc(sizeof(void*) * (NewSize
+1));
141 assert(CurArray
&& "Failed to allocate memory?");
142 CurArraySize
= NewSize
;
143 memset(CurArray
, -1, NewSize
*sizeof(void*));
145 // The end pointer, always valid, is set to a valid element to help the
147 CurArray
[NewSize
] = 0;
149 // Copy over all the elements.
151 // Small sets store their elements in order.
152 for (const void **BucketPtr
= OldBuckets
, **E
= OldBuckets
+NumElements
;
153 BucketPtr
!= E
; ++BucketPtr
) {
154 const void *Elt
= *BucketPtr
;
155 *const_cast<void**>(FindBucketFor(Elt
)) = const_cast<void*>(Elt
);
158 // Copy over all valid entries.
159 for (const void **BucketPtr
= OldBuckets
, **E
= OldBuckets
+OldSize
;
160 BucketPtr
!= E
; ++BucketPtr
) {
161 // Copy over the element if it is valid.
162 const void *Elt
= *BucketPtr
;
163 if (Elt
!= getTombstoneMarker() && Elt
!= getEmptyMarker())
164 *const_cast<void**>(FindBucketFor(Elt
)) = const_cast<void*>(Elt
);
172 SmallPtrSetImpl::SmallPtrSetImpl(const void **SmallStorage
,
173 const SmallPtrSetImpl
& that
) {
174 SmallArray
= SmallStorage
;
176 // If we're becoming small, prepare to insert into our stack space
177 if (that
.isSmall()) {
178 CurArray
= SmallArray
;
179 // Otherwise, allocate new heap space (unless we were the same size)
181 CurArray
= (const void**)malloc(sizeof(void*) * (that
.CurArraySize
+1));
182 assert(CurArray
&& "Failed to allocate memory?");
185 // Copy over the new array size
186 CurArraySize
= that
.CurArraySize
;
188 // Copy over the contents from the other set
189 memcpy(CurArray
, that
.CurArray
, sizeof(void*)*(CurArraySize
+1));
191 NumElements
= that
.NumElements
;
192 NumTombstones
= that
.NumTombstones
;
195 /// CopyFrom - implement operator= from a smallptrset that has the same pointer
196 /// type, but may have a different small size.
197 void SmallPtrSetImpl::CopyFrom(const SmallPtrSetImpl
&RHS
) {
198 if (isSmall() && RHS
.isSmall())
199 assert(CurArraySize
== RHS
.CurArraySize
&&
200 "Cannot assign sets with different small sizes");
202 // If we're becoming small, prepare to insert into our stack space
206 CurArray
= SmallArray
;
207 // Otherwise, allocate new heap space (unless we were the same size)
208 } else if (CurArraySize
!= RHS
.CurArraySize
) {
210 CurArray
= (const void**)malloc(sizeof(void*) * (RHS
.CurArraySize
+1));
212 CurArray
= (const void**)realloc(CurArray
, sizeof(void*)*(RHS
.CurArraySize
+1));
213 assert(CurArray
&& "Failed to allocate memory?");
216 // Copy over the new array size
217 CurArraySize
= RHS
.CurArraySize
;
219 // Copy over the contents from the other set
220 memcpy(CurArray
, RHS
.CurArray
, sizeof(void*)*(CurArraySize
+1));
222 NumElements
= RHS
.NumElements
;
223 NumTombstones
= RHS
.NumTombstones
;
226 SmallPtrSetImpl::~SmallPtrSetImpl() {