File indexing completed on 2026-05-10 08:44:33
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_RECYCLER_H
0015 #define LLVM_SUPPORT_RECYCLER_H
0016
0017 #include "llvm/ADT/ilist.h"
0018 #include "llvm/Support/Allocator.h"
0019 #include "llvm/Support/ErrorHandling.h"
0020 #include <cassert>
0021
0022 namespace llvm {
0023
0024
0025
0026
0027 void PrintRecyclerStats(size_t Size, size_t Align, size_t FreeListSize);
0028
0029
0030
0031
0032
0033 template <class T, size_t Size = sizeof(T), size_t Align = alignof(T)>
0034 class Recycler {
0035 struct FreeNode {
0036 FreeNode *Next;
0037 };
0038
0039
0040 FreeNode *FreeList = nullptr;
0041
0042 FreeNode *pop_val() {
0043 auto *Val = FreeList;
0044 __asan_unpoison_memory_region(Val, Size);
0045 FreeList = FreeList->Next;
0046 __msan_allocated_memory(Val, Size);
0047 return Val;
0048 }
0049
0050 void push(FreeNode *N) {
0051 N->Next = FreeList;
0052 FreeList = N;
0053 __asan_poison_memory_region(N, Size);
0054 }
0055
0056 public:
0057 ~Recycler() {
0058
0059
0060
0061 assert(!FreeList && "Non-empty recycler deleted!");
0062 }
0063 Recycler(const Recycler &) = delete;
0064 Recycler(Recycler &&Other)
0065 : FreeList(std::exchange(Other.FreeList, nullptr)) {}
0066 Recycler() = default;
0067
0068
0069
0070
0071 template<class AllocatorType>
0072 void clear(AllocatorType &Allocator) {
0073 while (FreeList) {
0074 T *t = reinterpret_cast<T *>(pop_val());
0075 Allocator.Deallocate(t, Size, Align);
0076 }
0077 }
0078
0079
0080
0081
0082
0083
0084 void clear(BumpPtrAllocator &) { FreeList = nullptr; }
0085
0086 template<class SubClass, class AllocatorType>
0087 SubClass *Allocate(AllocatorType &Allocator) {
0088 static_assert(alignof(SubClass) <= Align,
0089 "Recycler allocation alignment is less than object align!");
0090 static_assert(sizeof(SubClass) <= Size,
0091 "Recycler allocation size is less than object size!");
0092 static_assert(Size >= sizeof(FreeNode) &&
0093 "Recycler allocation size must be at least sizeof(FreeNode)");
0094 return FreeList ? reinterpret_cast<SubClass *>(pop_val())
0095 : static_cast<SubClass *>(Allocator.Allocate(Size, Align));
0096 }
0097
0098 template<class AllocatorType>
0099 T *Allocate(AllocatorType &Allocator) {
0100 return Allocate<T>(Allocator);
0101 }
0102
0103 template<class SubClass, class AllocatorType>
0104 void Deallocate(AllocatorType & , SubClass* Element) {
0105 push(reinterpret_cast<FreeNode *>(Element));
0106 }
0107
0108 void PrintStats();
0109 };
0110
0111 template <class T, size_t Size, size_t Align>
0112 void Recycler<T, Size, Align>::PrintStats() {
0113 size_t S = 0;
0114 for (auto *I = FreeList; I; I = I->Next)
0115 ++S;
0116 PrintRecyclerStats(Size, Align, S);
0117 }
0118
0119 }
0120
0121 #endif