blob: 0e6d3345905b1d1c2c543a81a3f913cc7d238778 [file] [log] [blame]
Chris Lattnerc95dc982007-01-27 07:10:46 +00001//===- llvm/ADT/SmallPtrSet.cpp - 'Normally small' pointer set ------------===//
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 implements the SmallPtrSet class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/SmallPtrSet.h"
15using namespace llvm;
16
17bool SmallPtrSetImpl::insert(void *Ptr) {
18 if (isSmall()) {
19 // Check to see if it is already in the set.
20 for (void **APtr = SmallArray, **E = SmallArray+NumElements;
21 APtr != E; ++APtr)
22 if (*APtr == Ptr)
23 return false;
24
25 // Nope, there isn't. If we stay small, just 'pushback' now.
26 if (NumElements < CurArraySize-1) {
27 SmallArray[NumElements++] = Ptr;
28 return true;
29 }
30 // Otherwise, hit the big set case, which will call grow.
31 }
32
33 // If more than 3/4 of the array is full, grow.
34 if (NumElements*4 >= CurArraySize*3)
35 Grow();
36
37 // Okay, we know we have space. Find a hash bucket.
38 void **Bucket = const_cast<void**>(FindBucketFor(Ptr));
39 if (*Bucket == Ptr) return false; // Already inserted, good.
40
41 // Otherwise, insert it!
42 *Bucket = Ptr;
43 ++NumElements; // Track density.
44 return true;
45}
46
47void * const *SmallPtrSetImpl::FindBucketFor(void *Ptr) const {
48 unsigned Bucket = Hash(Ptr);
49 unsigned ArraySize = CurArraySize;
50 unsigned ProbeAmt = 1;
51 void *const *Array = CurArray;
52 void *const *Tombstone = 0;
53 while (1) {
54 // Found Ptr's bucket?
55 if (Array[Bucket] == Ptr)
56 return Array+Bucket;
57
58 // If we found an empty bucket, the pointer doesn't exist in the set.
59 // Return a tombstone if we've seen one so far, or the empty bucket if
60 // not.
61 if (Array[Bucket] == getEmptyMarker())
62 return Tombstone ? Tombstone : Array+Bucket;
63
64 // If this is a tombstone, remember it. If Ptr ends up not in the set, we
65 // prefer to return it than something that would require more probing.
66 if (Array[Bucket] == getTombstoneMarker() && !Tombstone)
67 Tombstone = Array+Bucket; // Remember the first tombstone found.
68
69 // It's a hash collision or a tombstone. Reprobe.
70 Bucket = (Bucket + ProbeAmt++) & (ArraySize-1);
71 }
72}
73
74/// Grow - Allocate a larger backing store for the buckets and move it over.
75///
76void SmallPtrSetImpl::Grow() {
77 // Allocate at twice as many buckets, but at least 128.
78 unsigned OldSize = CurArraySize;
79 unsigned NewSize = OldSize < 64 ? 128 : OldSize*2;
80
81 void **OldBuckets = CurArray;
82 bool WasSmall = isSmall();
83
84 // Install the new array. Clear all the buckets to empty.
85 CurArray = new void*[NewSize+1];
86 CurArraySize = NewSize;
87 memset(CurArray, -1, NewSize*sizeof(void*));
88
89 // The end pointer, always valid, is set to a valid element to help the
90 // iterator.
91 CurArray[NewSize] = 0;
92
93 // Copy over all the elements.
94 if (WasSmall) {
95 // Small sets store their elements in order.
96 for (void **BucketPtr = OldBuckets, **E = OldBuckets+NumElements;
97 BucketPtr != E; ++BucketPtr) {
98 void *Elt = *BucketPtr;
99 *const_cast<void**>(FindBucketFor(Elt)) = Elt;
100 }
101 } else {
102 // Copy over all valid entries.
103 for (void **BucketPtr = OldBuckets, **E = OldBuckets+OldSize;
104 BucketPtr != E; ++BucketPtr) {
105 // Copy over the element if it is valid.
106 void *Elt = *BucketPtr;
107 if (Elt != getTombstoneMarker() && Elt != getEmptyMarker())
108 *const_cast<void**>(FindBucketFor(Elt)) = Elt;
109 }
110
111 delete [] OldBuckets;
112 }
113}