blob: f5a207844b859c86df1b67a83aa9bd144a1475a0 [file] [log] [blame]
Chris Lattner9f617d62006-10-29 22:08:03 +00001//===--- Allocator.cpp - Simple memory allocation abstraction -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner9f617d62006-10-29 22:08:03 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the BumpPtrAllocator interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Support/Allocator.h"
Dan Gohmane14d81d2008-07-07 22:58:06 +000015#include "llvm/Support/Recycler.h"
John Criswell72a780f2006-11-08 15:04:35 +000016#include "llvm/Support/DataTypes.h"
Bill Wendlingfe6b1462006-11-26 10:52:51 +000017#include "llvm/Support/Streams.h"
Chris Lattner9f617d62006-10-29 22:08:03 +000018
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000019namespace llvm {
Chris Lattner9f617d62006-10-29 22:08:03 +000020
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000021BumpPtrAllocator::BumpPtrAllocator(size_t size, size_t threshold,
22 SlabAllocator &allocator)
23 : SlabSize(size), SizeThreshold(threshold), Allocator(allocator),
24 CurSlab(0), BytesAllocated(0) {
25 StartNewSlab();
Chris Lattner9f617d62006-10-29 22:08:03 +000026}
27
28BumpPtrAllocator::~BumpPtrAllocator() {
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000029 DeallocateSlabs(CurSlab);
Chris Lattner9f617d62006-10-29 22:08:03 +000030}
31
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000032/// AlignPtr - Align Ptr to Alignment bytes, rounding up. Alignment should
33/// be a power of two. This method rounds up, so AlignPtr(7, 4) == 8 and
34/// AlignPtr(8, 4) == 8.
35char *BumpPtrAllocator::AlignPtr(char *Ptr, size_t Alignment) {
36 assert(Alignment && (Alignment & (Alignment - 1)) == 0 &&
37 "Alignment is not a power of two!");
38
39 // Do the alignment.
40 return (char*)(((uintptr_t)Ptr + Alignment - 1) &
41 ~(uintptr_t)(Alignment - 1));
42}
43
44/// StartNewSlab - Allocate a new slab and move the bump pointers over into
45/// the new slab. Modifies CurPtr and End.
46void BumpPtrAllocator::StartNewSlab() {
47 MemSlab *NewSlab = Allocator.Allocate(SlabSize);
48 NewSlab->NextPtr = CurSlab;
49 CurSlab = NewSlab;
50 CurPtr = (char*)(CurSlab + 1);
51 End = CurPtr + CurSlab->Size;
52}
53
54/// DeallocateSlabs - Deallocate all memory slabs after and including this
55/// one.
56void BumpPtrAllocator::DeallocateSlabs(MemSlab *Slab) {
57 while (Slab) {
58 MemSlab *NextSlab = Slab->NextPtr;
59#ifndef NDEBUG
60 // Poison the memory so stale pointers crash sooner. Note we must
61 // preserve the Size and NextPtr fields at the beginning.
62 memset(Slab + 1, 0xCD, Slab->Size - sizeof(MemSlab));
63#endif
64 Allocator.Deallocate(Slab);
65 Slab = NextSlab;
66 }
67}
68
69/// Reset - Deallocate all but the current slab and reset the current pointer
70/// to the beginning of it, freeing all memory allocated so far.
Evan Cheng188b5222007-09-05 21:41:34 +000071void BumpPtrAllocator::Reset() {
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000072 DeallocateSlabs(CurSlab->NextPtr);
73 CurSlab->NextPtr = 0;
74 CurPtr = (char*)(CurSlab + 1);
75 End = CurPtr + CurSlab->Size;
Evan Cheng188b5222007-09-05 21:41:34 +000076}
77
Reid Kleckner95eb3ad2009-07-23 00:30:41 +000078/// Allocate - Allocate space at the specified alignment.
79///
80void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) {
81 // Keep track of how many bytes we've allocated.
82 BytesAllocated += Size;
83
84 // 0-byte alignment means 1-byte alignment.
85 if (Alignment == 0) Alignment = 1;
86
87 // Allocate the aligned space, going forwards from CurPtr.
88 char *Ptr = AlignPtr(CurPtr, Alignment);
89
90 // Check if we can hold it.
91 if (Ptr + Size < End) {
92 CurPtr = Ptr + Size;
93 return Ptr;
94 }
95
96 // If Size is really big, allocate a separate slab for it.
97 if (Size > SizeThreshold) {
98 size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1;
99 MemSlab *NewSlab = Allocator.Allocate(PaddedSize);
100
101 // Put the new slab after the current slab, since we are not allocating
102 // into it.
103 NewSlab->NextPtr = CurSlab->NextPtr;
104 CurSlab->NextPtr = NewSlab;
105
106 Ptr = AlignPtr((char*)(NewSlab + 1), Alignment);
107 assert((uintptr_t)Ptr + Size < (uintptr_t)NewSlab + NewSlab->Size);
108 return Ptr;
109 }
110
111 // Otherwise, start a new slab and try again.
112 StartNewSlab();
113 Ptr = AlignPtr(CurPtr, Alignment);
114 CurPtr = Ptr + Size;
115 assert(CurPtr < End && "Unable to allocate memory!");
Chris Lattnerd675b832007-02-23 22:31:24 +0000116 return Ptr;
Chris Lattner9f617d62006-10-29 22:08:03 +0000117}
118
Reid Kleckner95eb3ad2009-07-23 00:30:41 +0000119unsigned BumpPtrAllocator::GetNumSlabs() const {
120 unsigned NumSlabs = 0;
121 for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
122 ++NumSlabs;
123 }
124 return NumSlabs;
Chris Lattner9f617d62006-10-29 22:08:03 +0000125}
Dan Gohmane14d81d2008-07-07 22:58:06 +0000126
Reid Kleckner95eb3ad2009-07-23 00:30:41 +0000127void BumpPtrAllocator::PrintStats() const {
128 unsigned NumSlabs = 0;
129 size_t TotalMemory = 0;
130 for (MemSlab *Slab = CurSlab; Slab != 0; Slab = Slab->NextPtr) {
131 TotalMemory += Slab->Size;
132 ++NumSlabs;
133 }
134
135 cerr << "\nNumber of memory regions: " << NumSlabs << '\n'
136 << "Bytes used: " << BytesAllocated << '\n'
137 << "Bytes allocated: " << TotalMemory << '\n'
138 << "Bytes wasted: " << (TotalMemory - BytesAllocated)
139 << " (includes alignment, etc)\n";
140}
141
142MallocSlabAllocator BumpPtrAllocator::DefaultSlabAllocator =
143 MallocSlabAllocator();
144
145SlabAllocator::~SlabAllocator() { }
146
147MallocSlabAllocator::~MallocSlabAllocator() { }
148
149MemSlab *MallocSlabAllocator::Allocate(size_t Size) {
150 MemSlab *Slab = (MemSlab*)Allocator.Allocate(Size, 0);
151 Slab->Size = Size;
152 Slab->NextPtr = 0;
153 return Slab;
154}
155
156void MallocSlabAllocator::Deallocate(MemSlab *Slab) {
157 Allocator.Deallocate(Slab);
158}
159
160void PrintRecyclerStats(size_t Size,
161 size_t Align,
162 size_t FreeListSize) {
163 cerr << "Recycler element size: " << Size << '\n'
164 << "Recycler element alignment: " << Align << '\n'
165 << "Number of elements free for recycling: " << FreeListSize << '\n';
166}
167
Dan Gohmane14d81d2008-07-07 22:58:06 +0000168}