1 //===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the BumpPtrAllocator interface.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Support/Allocator.h"
15 #include "llvm/Support/DataTypes.h"
16 #include "llvm/Support/Recycler.h"
17 #include "llvm/Support/raw_ostream.h"
22 BumpPtrAllocator::BumpPtrAllocator(size_t size
, size_t threshold
,
23 SlabAllocator
&allocator
)
24 : SlabSize(size
), SizeThreshold(threshold
), Allocator(allocator
),
25 CurSlab(0), BytesAllocated(0) {
29 BumpPtrAllocator::~BumpPtrAllocator() {
30 DeallocateSlabs(CurSlab
);
33 /// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should
34 /// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and
35 /// AlignPtr(8, 4) == 8.
36 char *BumpPtrAllocator::AlignPtr(char *Ptr
, size_t Alignment
) {
37 assert(Alignment
&& (Alignment
& (Alignment
- 1)) == 0 &&
38 "Alignment is not a power of two!");
41 return (char*)(((uintptr_t)Ptr
+ Alignment
- 1) &
42 ~(uintptr_t)(Alignment
- 1));
45 /// StartNewSlab - Allocate a new slab and move the bump pointers over into
46 /// the new slab. Modifies CurPtr and End.
47 void BumpPtrAllocator::StartNewSlab() {
48 MemSlab
*NewSlab
= Allocator
.Allocate(SlabSize
);
49 NewSlab
->NextPtr
= CurSlab
;
51 CurPtr
= (char*)(CurSlab
+ 1);
52 End
= ((char*)CurSlab
) + CurSlab
->Size
;
55 /// DeallocateSlabs - Deallocate all memory slabs after and including this
57 void BumpPtrAllocator::DeallocateSlabs(MemSlab
*Slab
) {
59 MemSlab
*NextSlab
= Slab
->NextPtr
;
61 // Poison the memory so stale pointers crash sooner. Note we must
62 // preserve the Size and NextPtr fields at the beginning.
63 memset(Slab
+ 1, 0xCD, Slab
->Size
- sizeof(MemSlab
));
65 Allocator
.Deallocate(Slab
);
70 /// Reset - Deallocate all but the current slab and reset the current pointer
71 /// to the beginning of it, freeing all memory allocated so far.
72 void BumpPtrAllocator::Reset() {
73 DeallocateSlabs(CurSlab
->NextPtr
);
75 CurPtr
= (char*)(CurSlab
+ 1);
76 End
= ((char*)CurSlab
) + CurSlab
->Size
;
79 /// Allocate - Allocate space at the specified alignment.
81 void *BumpPtrAllocator::Allocate(size_t Size
, size_t Alignment
) {
82 // Keep track of how many bytes we've allocated.
83 BytesAllocated
+= Size
;
85 // 0-byte alignment means 1-byte alignment.
86 if (Alignment
== 0) Alignment
= 1;
88 // Allocate the aligned space, going forwards from CurPtr.
89 char *Ptr
= AlignPtr(CurPtr
, Alignment
);
91 // Check if we can hold it.
92 if (Ptr
+ Size
<= End
) {
97 // If Size is really big, allocate a separate slab for it.
98 size_t PaddedSize
= Size
+ sizeof(MemSlab
) + Alignment
- 1;
99 if (PaddedSize
> SizeThreshold
) {
100 MemSlab
*NewSlab
= Allocator
.Allocate(PaddedSize
);
102 // Put the new slab after the current slab, since we are not allocating
104 NewSlab
->NextPtr
= CurSlab
->NextPtr
;
105 CurSlab
->NextPtr
= NewSlab
;
107 Ptr
= AlignPtr((char*)(NewSlab
+ 1), Alignment
);
108 assert((uintptr_t)Ptr
+ Size
<= (uintptr_t)NewSlab
+ NewSlab
->Size
);
112 // Otherwise, start a new slab and try again.
114 Ptr
= AlignPtr(CurPtr
, Alignment
);
116 assert(CurPtr
<= End
&& "Unable to allocate memory!");
120 unsigned BumpPtrAllocator::GetNumSlabs() const {
121 unsigned NumSlabs
= 0;
122 for (MemSlab
*Slab
= CurSlab
; Slab
!= 0; Slab
= Slab
->NextPtr
) {
128 void BumpPtrAllocator::PrintStats() const {
129 unsigned NumSlabs
= 0;
130 size_t TotalMemory
= 0;
131 for (MemSlab
*Slab
= CurSlab
; Slab
!= 0; Slab
= Slab
->NextPtr
) {
132 TotalMemory
+= Slab
->Size
;
136 errs() << "\nNumber of memory regions: " << NumSlabs
<< '\n'
137 << "Bytes used: " << BytesAllocated
<< '\n'
138 << "Bytes allocated: " << TotalMemory
<< '\n'
139 << "Bytes wasted: " << (TotalMemory
- BytesAllocated
)
140 << " (includes alignment, etc)\n";
143 MallocSlabAllocator
BumpPtrAllocator::DefaultSlabAllocator
=
144 MallocSlabAllocator();
146 SlabAllocator::~SlabAllocator() { }
148 MallocSlabAllocator::~MallocSlabAllocator() { }
150 MemSlab
*MallocSlabAllocator::Allocate(size_t Size
) {
151 MemSlab
*Slab
= (MemSlab
*)Allocator
.Allocate(Size
, 0);
157 void MallocSlabAllocator::Deallocate(MemSlab
*Slab
) {
158 Allocator
.Deallocate(Slab
);
161 void PrintRecyclerStats(size_t Size
,
163 size_t FreeListSize
) {
164 errs() << "Recycler element size: " << Size
<< '\n'
165 << "Recycler element alignment: " << Align
<< '\n'
166 << "Number of elements free for recycling: " << FreeListSize
<< '\n';