File indexing completed on 2026-05-10 08:44:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_ARRAYRECYCLER_H
0015 #define LLVM_SUPPORT_ARRAYRECYCLER_H
0016
0017 #include "llvm/ADT/SmallVector.h"
0018 #include "llvm/Support/Allocator.h"
0019 #include "llvm/Support/MathExtras.h"
0020
0021 namespace llvm {
0022
0023
0024
0025
0026
0027
0028 template <class T, size_t Align = alignof(T)> class ArrayRecycler {
0029
0030
0031 struct FreeList {
0032 FreeList *Next;
0033 };
0034
0035 static_assert(Align >= alignof(FreeList), "Object underaligned");
0036 static_assert(sizeof(T) >= sizeof(FreeList), "Objects are too small");
0037
0038
0039 SmallVector<FreeList*, 8> Bucket;
0040
0041
0042
0043 T *pop(unsigned Idx) {
0044 if (Idx >= Bucket.size())
0045 return nullptr;
0046 FreeList *Entry = Bucket[Idx];
0047 if (!Entry)
0048 return nullptr;
0049 __asan_unpoison_memory_region(Entry, Capacity::get(Idx).getSize());
0050 Bucket[Idx] = Entry->Next;
0051 __msan_allocated_memory(Entry, Capacity::get(Idx).getSize());
0052 return reinterpret_cast<T*>(Entry);
0053 }
0054
0055
0056 void push(unsigned Idx, T *Ptr) {
0057 assert(Ptr && "Cannot recycle NULL pointer");
0058 FreeList *Entry = reinterpret_cast<FreeList*>(Ptr);
0059 if (Idx >= Bucket.size())
0060 Bucket.resize(size_t(Idx) + 1);
0061 Entry->Next = Bucket[Idx];
0062 Bucket[Idx] = Entry;
0063 __asan_poison_memory_region(Ptr, Capacity::get(Idx).getSize());
0064 }
0065
0066 public:
0067
0068
0069
0070
0071 class Capacity {
0072 uint8_t Index;
0073 explicit Capacity(uint8_t idx) : Index(idx) {}
0074
0075 public:
0076 Capacity() : Index(0) {}
0077
0078
0079 static Capacity get(size_t N) {
0080 return Capacity(N ? Log2_64_Ceil(N) : 0);
0081 }
0082
0083
0084 size_t getSize() const { return size_t(1u) << Index; }
0085
0086
0087 unsigned getBucket() const { return Index; }
0088
0089
0090
0091
0092 Capacity getNext() const { return Capacity(Index + 1); }
0093 };
0094
0095 ~ArrayRecycler() {
0096
0097
0098 assert(Bucket.empty() && "Non-empty ArrayRecycler deleted!");
0099 }
0100
0101
0102
0103 template<class AllocatorType>
0104 void clear(AllocatorType &Allocator) {
0105 for (; !Bucket.empty(); Bucket.pop_back())
0106 while (T *Ptr = pop(Bucket.size() - 1))
0107 Allocator.Deallocate(Ptr);
0108 }
0109
0110
0111
0112
0113
0114
0115 void clear(BumpPtrAllocator&) {
0116 Bucket.clear();
0117 }
0118
0119
0120
0121
0122
0123
0124 template<class AllocatorType>
0125 T *allocate(Capacity Cap, AllocatorType &Allocator) {
0126
0127 if (T *Ptr = pop(Cap.getBucket()))
0128 return Ptr;
0129
0130 return static_cast<T*>(Allocator.Allocate(sizeof(T)*Cap.getSize(), Align));
0131 }
0132
0133
0134
0135
0136
0137 void deallocate(Capacity Cap, T *Ptr) {
0138 push(Cap.getBucket(), Ptr);
0139 }
0140 };
0141
0142 }
0143
0144 #endif