17#ifndef LLVM_SUPPORT_ALLOCATOR_H
18#define LLVM_SUPPORT_ALLOCATOR_H
21#include "llvm/Config/abi-breaking.h"
67 size_t SizeThreshold = SlabSize,
size_t GrowthDelay = 128,
71 AllocatorT, SlabSize, SizeThreshold, GrowthDelay, MinAlign>>,
76 static_assert(SizeThreshold <= SlabSize,
77 "The SizeThreshold must be at most the SlabSize to ensure "
78 "that objects larger than a slab go into their own memory "
80 static_assert(GrowthDelay > 0,
81 "GrowthDelay must be at least 1 which already increases the"
82 "slab size after each allocated slab.");
84 "MinAlign must be a power of two");
85 static_assert(
MinAlign <=
alignof(std::max_align_t),
86 "MinAlign must not exceed the alignment of fresh slabs");
98 EndSentinel(Old.EndSentinel), Slabs(
std::
move(Old.Slabs)),
99 CustomSizedSlabs(
std::
move(Old.CustomSizedSlabs)) {
100#if LLVM_ENABLE_ABI_BREAKING_CHECKS
101 RedZoneSize = Old.RedZoneSize;
103 Old.CurPtr =
nullptr;
106 Old.CustomSizedSlabs.clear();
110 DeallocateSlabs(Slabs.begin(), Slabs.end());
111 DeallocateCustomSizedSlabs();
115 DeallocateSlabs(Slabs.begin(), Slabs.end());
116 DeallocateCustomSizedSlabs();
119 EndSentinel =
RHS.EndSentinel;
120#if LLVM_ENABLE_ABI_BREAKING_CHECKS
121 RedZoneSize =
RHS.RedZoneSize;
123 Slabs = std::move(
RHS.Slabs);
124 CustomSizedSlabs = std::move(
RHS.CustomSizedSlabs);
125 AllocTy::operator=(std::move(
RHS.getAllocator()));
127 RHS.CurPtr =
nullptr;
130 RHS.CustomSizedSlabs.clear();
138 DeallocateCustomSizedSlabs();
139 CustomSizedSlabs.clear();
145 CurPtr = (
char *)Slabs.front();
146 EndSentinel =
uintptr_t(CurPtr) + SlabSize + 1;
149 DeallocateSlabs(std::next(Slabs.begin()), Slabs.end());
150 Slabs.erase(std::next(Slabs.begin()), Slabs.end());
161 size_t SizeToAllocate =
Size;
162#if LLVM_ADDRESS_SANITIZER_BUILD && LLVM_ENABLE_ABI_BREAKING_CHECKS
165 SizeToAllocate += RedZoneSize;
172 AlignedPtr =
alignAddr(CurPtr, Alignment);
173 uintptr_t AllocEndPtr = AlignedPtr + SizeToAllocate;
175 "Alignment + Size must not overflow");
180 CurPtr =
reinterpret_cast<char *
>(AllocEndPtr);
187 return reinterpret_cast<char *
>(AlignedPtr);
196 size_t PaddedSize = SizeToAllocate + Alignment.value() - 1;
197 if (PaddedSize > SizeThreshold) {
203 CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize));
207 char *AlignedPtr = (
char*)AlignedAddr;
216 assert(AlignedAddr + SizeToAllocate < EndSentinel &&
217 "Unable to allocate memory!");
218 char *AlignedPtr = (
char*)AlignedAddr;
219 CurPtr = AlignedPtr + SizeToAllocate;
227 assert(Alignment > 0 &&
"0-byte alignment is not allowed. Use 1 instead.");
244 size_t GetNumSlabs()
const {
return Slabs.size() + CustomSizedSlabs.size(); }
252 const char *
P =
static_cast<const char *
>(Ptr);
253 int64_t InSlabIdx = 0;
254 for (
size_t Idx = 0,
E = Slabs.size(); Idx <
E; Idx++) {
255 const char *S =
static_cast<const char *
>(Slabs[Idx]);
256 if (
P >= S &&
P < S + computeSlabSize(Idx))
257 return InSlabIdx +
static_cast<int64_t
>(
P - S);
258 InSlabIdx +=
static_cast<int64_t
>(computeSlabSize(Idx));
262 int64_t InCustomSizedSlabIdx = -1;
263 for (
const auto &Slab : CustomSizedSlabs) {
264 const char *S =
static_cast<const char *
>(Slab.first);
265 size_t Size = Slab.second;
266 if (
P >= S &&
P < S +
Size)
267 return InCustomSizedSlabIdx -
static_cast<int64_t
>(
P - S);
268 InCustomSizedSlabIdx -=
static_cast<int64_t
>(
Size);
279 assert(Out &&
"Wrong allocator used");
293 template <
typename T>
296 assert(Out %
alignof(
T) == 0 &&
"Wrong alignment information");
297 return Out /
alignof(
T);
301 size_t TotalMemory = 0;
302 for (
auto I = Slabs.begin(),
E = Slabs.end();
I !=
E; ++
I)
303 TotalMemory += computeSlabSize(std::distance(Slabs.begin(),
I));
304 for (
const auto &PtrAndSize : CustomSizedSlabs)
305 TotalMemory += PtrAndSize.second;
310#if LLVM_ENABLE_ABI_BREAKING_CHECKS
311 RedZoneSize = NewSize;
323 char *CurPtr =
nullptr;
335#if LLVM_ENABLE_ABI_BREAKING_CHECKS
338 size_t RedZoneSize = 1;
341 static size_t computeSlabSize(
unsigned SlabIdx) {
347 ((
size_t)1 << std::min<size_t>(30, SlabIdx / GrowthDelay));
352 void StartNewSlab() {
353 size_t AllocatedSlabSize = computeSlabSize(Slabs.
size());
356 alignof(std::max_align_t));
362 CurPtr = (
char *)(NewSlab);
363 EndSentinel =
uintptr_t(NewSlab) + AllocatedSlabSize + 1;
369 for (;
I !=
E; ++
I) {
370 size_t AllocatedSlabSize =
371 computeSlabSize(std::distance(Slabs.begin(),
I));
373 alignof(std::max_align_t));
378 void DeallocateCustomSizedSlabs() {
379 for (
auto &PtrAndSize : CustomSizedSlabs) {
380 void *Ptr = PtrAndSize.first;
381 size_t Size = PtrAndSize.second;
403 using BumpPtrAllocatorTy =
405 BumpPtrAllocatorTy Allocator;
411 Allocator.setRedZoneSize(0);
414 : Allocator(
std::
move(Old.Allocator)) {}
419 Allocator = std::move(
RHS.Allocator);
427 auto DestroyElements = [](
char *Begin,
char *
End) {
429 for (
char *Ptr = Begin; Ptr +
sizeof(
T) <=
End; Ptr +=
sizeof(
T))
430 reinterpret_cast<T *
>(Ptr)->~T();
433 for (
auto I = Allocator.Slabs.begin(),
E = Allocator.Slabs.end();
I !=
E;
435 size_t AllocatedSlabSize = BumpPtrAllocatorTy::computeSlabSize(
436 std::distance(Allocator.Slabs.begin(),
I));
438 char *
End = *
I == Allocator.Slabs.back() ? Allocator.CurPtr
439 : (
char *)*
I + AllocatedSlabSize;
441 DestroyElements(Begin,
End);
444 for (
auto &PtrAndSize : Allocator.CustomSizedSlabs) {
445 void *Ptr = PtrAndSize.first;
446 size_t Size = PtrAndSize.second;
459 if constexpr (
alignof(
T) <=
alignof(std::max_align_t))
460 return static_cast<T *
>(Allocator.Allocate(num *
sizeof(
T),
Align()));
461 return Allocator.Allocate<
T>(num);
468 return Allocator.identifyObject(Ptr);
474template <
typename AllocatorT,
size_t SlabSize,
size_t SizeThreshold,
475 size_t GrowthDelay,
size_t MinAlign>
483 auto S =
Size | __STDCPP_DEFAULT_NEW_ALIGNMENT__;
487template <
typename AllocatorT,
size_t SlabSize,
size_t SizeThreshold,
488 size_t GrowthDelay,
size_t MinAlign>
490operator new(
size_t Size, std::align_val_t Alignment,
496template <
typename AllocatorT,
size_t SlabSize,
size_t SizeThreshold,
497 size_t GrowthDelay,
size_t MinAlign>
500 GrowthDelay, MinAlign> &) {}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines MallocAllocator.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define __asan_poison_memory_region(p, size)
#define __asan_unpoison_memory_region(p, size)
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
#define LLVM_ATTRIBUTE_RETURNS_NONNULL
#define __msan_allocated_memory(p, size)
#define LLVM_LIKELY(EXPR)
This file defines the SmallVector class.
CRTP base class providing obvious overloads for the core Allocate() methods of LLVM-style allocators.
Allocate memory in an ever growing pool, as if by bump-pointer.
int64_t identifyKnownObject(const void *Ptr)
A wrapper around identifyObject that additionally asserts that the object is indeed within the alloca...
BumpPtrAllocatorImpl(T &&Allocator)
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_NOINLINE void * AllocateSlow(size_t Size, size_t SizeToAllocate, Align Alignment)
BumpPtrAllocatorImpl & operator=(BumpPtrAllocatorImpl &&RHS)
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
void Deallocate(const void *Ptr, size_t Size, size_t)
BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old)
size_t GetNumSlabs() const
void Reset()
Deallocate all but the current slab and reset the current pointer to the beginning of it,...
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, size_t Alignment)
void setRedZoneSize(size_t NewSize)
friend class SpecificBumpPtrAllocator
int64_t identifyKnownAlignedObject(const void *Ptr)
A wrapper around identifyKnownObject.
size_t getTotalMemory() const
BumpPtrAllocatorImpl()=default
std::optional< int64_t > identifyObject(const void *Ptr)
void Deallocate(const void *Ptr, size_t Size, size_t Alignment)
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, size_t Alignment)
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
~SpecificBumpPtrAllocator()
std::optional< int64_t > identifyObject(const void *Ptr)
SpecificBumpPtrAllocator(SpecificBumpPtrAllocator &&Old)
T * Allocate(size_t num=1)
Allocate space for an array of objects without constructing them.
void DestroyAll()
Call the destructor of each allocated object and deallocate all but the current slab and reset the cu...
SpecificBumpPtrAllocator()
SpecificBumpPtrAllocator & operator=(SpecificBumpPtrAllocator &&RHS)
MallocAllocator & getAllocator()
A self-contained host- and target-independent arbitrary-precision floating-point software implementat...
LLVM_ABI void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t TotalMemory)
This is an optimization pass for GlobalISel generic memory operations.
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
constexpr T alignToPowerOf2(U Value, V Align)
Will overflow only if result is not representable in T.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
@ End
Run the machine verifier once, at the end of the pipeline.
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static constexpr Align Of()
Allow constructions of constexpr Align from types.