File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef LLVM_ADT_PAGEDVECTOR_H
0013 #define LLVM_ADT_PAGEDVECTOR_H
0014
0015 #include "llvm/ADT/PointerIntPair.h"
0016 #include "llvm/ADT/SmallVector.h"
0017 #include "llvm/ADT/iterator_range.h"
0018 #include "llvm/Support/Allocator.h"
0019 #include <cassert>
0020 #include <vector>
0021
0022 namespace llvm {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 template <typename T, size_t PageSize = 1024 / sizeof(T)> class PagedVector {
0043 static_assert(PageSize > 1, "PageSize must be greater than 0. Most likely "
0044 "you want it to be greater than 16.");
0045
0046 size_t Size = 0;
0047
0048
0049
0050 mutable SmallVector<T *, 0> PageToDataPtrs;
0051
0052
0053
0054 PointerIntPair<BumpPtrAllocator *, 1, bool> Allocator;
0055
0056 public:
0057 using value_type = T;
0058
0059
0060
0061 PagedVector() : Allocator(new BumpPtrAllocator, true) {}
0062 explicit PagedVector(BumpPtrAllocator *A) : Allocator(A, false) {
0063 assert(A && "Allocator cannot be nullptr");
0064 }
0065
0066 ~PagedVector() {
0067 clear();
0068
0069 if (Allocator.getInt())
0070 delete Allocator.getPointer();
0071 }
0072
0073
0074 PagedVector(const PagedVector &) = delete;
0075 PagedVector(PagedVector &&) = delete;
0076 PagedVector &operator=(const PagedVector &) = delete;
0077 PagedVector &operator=(PagedVector &&) = delete;
0078
0079
0080
0081
0082 T &operator[](size_t Index) const {
0083 assert(Index < Size);
0084 assert(Index / PageSize < PageToDataPtrs.size());
0085 T *&PagePtr = PageToDataPtrs[Index / PageSize];
0086
0087 if (LLVM_UNLIKELY(!PagePtr)) {
0088 PagePtr = Allocator.getPointer()->template Allocate<T>(PageSize);
0089
0090
0091 std::uninitialized_value_construct_n(PagePtr, PageSize);
0092 }
0093
0094 return PagePtr[Index % PageSize];
0095 }
0096
0097
0098
0099 [[nodiscard]] size_t capacity() const {
0100 return PageToDataPtrs.size() * PageSize;
0101 }
0102
0103
0104 [[nodiscard]] size_t size() const { return Size; }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116 void resize(size_t NewSize) {
0117 if (NewSize == 0) {
0118 clear();
0119 return;
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 size_t NewLastPage = (NewSize - 1) / PageSize;
0131 if (NewSize < Size) {
0132 for (size_t I = NewLastPage + 1, N = PageToDataPtrs.size(); I < N; ++I) {
0133 T *Page = PageToDataPtrs[I];
0134 if (!Page)
0135 continue;
0136
0137 std::destroy_n(Page, PageSize);
0138 Allocator.getPointer()->Deallocate(Page);
0139 }
0140 }
0141
0142 Size = NewSize;
0143 PageToDataPtrs.resize(NewLastPage + 1);
0144 }
0145
0146 [[nodiscard]] bool empty() const { return Size == 0; }
0147
0148
0149
0150 void clear() {
0151 Size = 0;
0152 for (T *Page : PageToDataPtrs) {
0153 if (Page == nullptr)
0154 continue;
0155 std::destroy_n(Page, PageSize);
0156
0157 if (!Allocator.getInt())
0158 Allocator.getPointer()->Deallocate(Page);
0159 }
0160
0161 if (Allocator.getInt())
0162 Allocator.getPointer()->Reset();
0163 PageToDataPtrs.clear();
0164 }
0165
0166
0167
0168 class MaterializedIterator {
0169 const PagedVector *PV;
0170 size_t ElementIdx;
0171
0172 public:
0173 using iterator_category = std::forward_iterator_tag;
0174 using value_type = T;
0175 using difference_type = std::ptrdiff_t;
0176 using pointer = T *;
0177 using reference = T &;
0178
0179 MaterializedIterator(PagedVector const *PV, size_t ElementIdx)
0180 : PV(PV), ElementIdx(ElementIdx) {}
0181
0182
0183
0184
0185
0186 MaterializedIterator &operator++() {
0187 ++ElementIdx;
0188 if (ElementIdx % PageSize == 0) {
0189 while (ElementIdx < PV->Size &&
0190 !PV->PageToDataPtrs[ElementIdx / PageSize])
0191 ElementIdx += PageSize;
0192 if (ElementIdx > PV->Size)
0193 ElementIdx = PV->Size;
0194 }
0195
0196 return *this;
0197 }
0198
0199 MaterializedIterator operator++(int) {
0200 MaterializedIterator Copy = *this;
0201 ++*this;
0202 return Copy;
0203 }
0204
0205 T const &operator*() const {
0206 assert(ElementIdx < PV->Size);
0207 assert(PV->PageToDataPtrs[ElementIdx / PageSize]);
0208 T *PagePtr = PV->PageToDataPtrs[ElementIdx / PageSize];
0209 return PagePtr[ElementIdx % PageSize];
0210 }
0211
0212
0213 friend bool operator==(const MaterializedIterator &LHS,
0214 const MaterializedIterator &RHS) {
0215 return LHS.equals(RHS);
0216 }
0217
0218 [[nodiscard]] size_t getIndex() const { return ElementIdx; }
0219
0220 friend bool operator!=(const MaterializedIterator &LHS,
0221 const MaterializedIterator &RHS) {
0222 return !(LHS == RHS);
0223 }
0224
0225 private:
0226 void verify() const {
0227 assert(
0228 ElementIdx == PV->Size ||
0229 (ElementIdx < PV->Size && PV->PageToDataPtrs[ElementIdx / PageSize]));
0230 }
0231
0232 bool equals(const MaterializedIterator &Other) const {
0233 assert(PV == Other.PV);
0234 verify();
0235 Other.verify();
0236 return ElementIdx == Other.ElementIdx;
0237 }
0238 };
0239
0240
0241
0242
0243
0244
0245 MaterializedIterator materialized_begin() const {
0246
0247 for (size_t ElementIdx = 0; ElementIdx < Size; ElementIdx += PageSize)
0248 if (PageToDataPtrs[ElementIdx / PageSize])
0249 return MaterializedIterator(this, ElementIdx);
0250
0251 return MaterializedIterator(this, Size);
0252 }
0253
0254 MaterializedIterator materialized_end() const {
0255 return MaterializedIterator(this, Size);
0256 }
0257
0258 [[nodiscard]] llvm::iterator_range<MaterializedIterator>
0259 materialized() const {
0260 return {materialized_begin(), materialized_end()};
0261 }
0262 };
0263 }
0264 #endif