llvm.org GIT mirror llvm / 17f9c2e
[Allocator] Make the underlying allocator a template instead of an abstract interface. The only user of this functionality is the JIT memory manager and it is quite happy to have a custom type here. This removes a virtual function call and a lot of unnecessary abstraction from the common case where this is just a *very* thin vaneer around a call to malloc. Hopefully still no functionality changed here. =] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206149 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 6 years ago
4 changed file(s) with 44 addition(s) and 73 deletion(s). Raw diff Collapse all Expand all
5353 void PrintStats() const {}
5454 };
5555
56 /// SlabAllocator - This class can be used to parameterize the underlying
57 /// allocation strategy for the bump allocator. In particular, this is used
58 /// by the JIT to allocate contiguous swathes of executable memory. The
59 /// interface uses MemSlab's instead of void *'s so that the allocator
60 /// doesn't have to remember the size of the pointer it allocated.
61 class SlabAllocator {
62 public:
63 virtual ~SlabAllocator();
64 virtual void *Allocate(size_t Size) = 0;
65 virtual void Deallocate(void *Slab, size_t Size) = 0;
66 };
67
6856 /// MallocSlabAllocator - The default slab allocator for the bump allocator
6957 /// is an adapter class for MallocAllocator that just forwards the method
7058 /// calls and translates the arguments.
71 class MallocSlabAllocator : public SlabAllocator {
59 class MallocSlabAllocator {
7260 /// Allocator - The underlying allocator that we forward to.
7361 ///
7462 MallocAllocator Allocator;
7563
7664 public:
77 MallocSlabAllocator() : Allocator() {}
78 virtual ~MallocSlabAllocator();
79 void *Allocate(size_t Size) override;
80 void Deallocate(void *Slab, size_t Size) override;
65 void *Allocate(size_t Size) { return Allocator.Allocate(Size, 0); }
66 void Deallocate(void *Slab, size_t Size) { Allocator.Deallocate(Slab); }
8167 };
8268
8369 /// \brief Allocate memory in an ever growing pool, as if by bump-pointer.
9076 ///
9177 /// Note that this also has a threshold for forcing allocations above a certain
9278 /// size into their own slab.
93 template
79 ///
80 /// The BumpPtrAllocatorImpl template defaults to using a MallocSlabAllocator
81 /// object, which wraps malloc, to allocate memory, but it can be changed to
82 /// use a custom allocator.
83 template
84 size_t SizeThreshold = SlabSize>
9485 class BumpPtrAllocatorImpl {
9586 BumpPtrAllocatorImpl(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION;
9687 void operator=(const BumpPtrAllocatorImpl &) LLVM_DELETED_FUNCTION;
10293 "allocation.");
10394
10495 BumpPtrAllocatorImpl()
96 : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator() {}
97 template
98 BumpPtrAllocatorImpl(T &&Allocator)
10599 : CurPtr(nullptr), End(nullptr), BytesAllocated(0),
106 Allocator(DefaultSlabAllocator) {}
107 BumpPtrAllocatorImpl(SlabAllocator &Allocator)
108 : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator(Allocator) {
109 }
100 Allocator(std::forward(Allocator)) {}
110101 ~BumpPtrAllocatorImpl() {
111102 DeallocateSlabs(Slabs.begin(), Slabs.end());
112103 DeallocateCustomSizedSlabs();
236227 /// Used so that we can compute how much space was wasted.
237228 size_t BytesAllocated;
238229
239 /// \brief The default allocator used if one is not provided.
240 MallocSlabAllocator DefaultSlabAllocator;
241
242 /// \brief The underlying allocator we use to get slabs of memory.
243 ///
244 /// This defaults to MallocSlabAllocator, which wraps malloc, but it could be
245 /// changed to use a custom allocator.
246 SlabAllocator &Allocator;
230 /// \brief The allocator instance we use to get slabs of memory.
231 AllocatorT Allocator;
247232
248233 static size_t computeSlabSize(unsigned SlabIdx) {
249234 // Scale the actual allocated slab size based on the number of slabs
312297
313298 public:
314299 SpecificBumpPtrAllocator() : Allocator() {}
315 SpecificBumpPtrAllocator(SlabAllocator &allocator) : Allocator(allocator) {}
316300
317301 ~SpecificBumpPtrAllocator() { DestroyAll(); }
318302
354338
355339 } // end namespace llvm
356340
357 template
358 void *
359 operator new(size_t Size,
360 llvm::BumpPtrAllocatorImpl &Allocator) {
341 template
342 void *operator new(size_t Size,
343 llvm::BumpPtrAllocatorImpl
344 SizeThreshold> &Allocator) {
361345 struct S {
362346 char c;
363347 union {
371355 Size, std::min((size_t)llvm::NextPowerOf2(Size), offsetof(S, x)));
372356 }
373357
374 template
375 void operator delete(void *,
376 llvm::BumpPtrAllocatorImpl &) {}
358 template
359 void operator delete(
360 void *, llvm::BumpPtrAllocatorImpl &) {
361 }
377362
378363 #endif // LLVM_SUPPORT_ALLOCATOR_H
268268
269269 class DefaultJITMemoryManager;
270270
271 class JITSlabAllocator : public SlabAllocator {
271 class JITSlabAllocator {
272272 DefaultJITMemoryManager &JMM;
273273 public:
274274 JITSlabAllocator(DefaultJITMemoryManager &jmm) : JMM(jmm) { }
275 virtual ~JITSlabAllocator() { }
276 void *Allocate(size_t Size) override;
277 void Deallocate(void *Slab, size_t Size) override;
275 void *Allocate(size_t Size);
276 void Deallocate(void *Slab, size_t Size);
278277 };
279278
280279 /// DefaultJITMemoryManager - Manage memory for the JIT code generation.
312311 // Memory slabs allocated by the JIT. We refer to them as slabs so we don't
313312 // confuse them with the blocks of memory described above.
314313 std::vector CodeSlabs;
315 JITSlabAllocator BumpSlabAllocator;
316 BumpPtrAllocatorImpl StubAllocator;
317 BumpPtrAllocatorImpl<DefaultSlabSize, DefaultSizeThreshold> DataAllocator;
314 BumpPtrAllocatorImpl<JITSlabAllocator, DefaultSlabSize,
315 DefaultSizeThreshold> StubAllocator;
316 BumpPtrAllocatorImpl
317 DefaultSizeThreshold> DataAllocator;
318318
319319 // Circular list of free blocks.
320320 FreeRangeHeader *FreeMemoryList;
578578 }
579579
580580 DefaultJITMemoryManager::DefaultJITMemoryManager()
581 :
581 :
582582 #ifdef NDEBUG
583 PoisonMemory(false),
583 PoisonMemory(false),
584584 #else
585 PoisonMemory(true),
585 PoisonMemory(true),
586586 #endif
587 LastSlab(0, 0),
588 BumpSlabAllocator(*this),
589 StubAllocator(BumpSlabAllocator),
590 DataAllocator(BumpSlabAllocator) {
587 LastSlab(0, 0), StubAllocator(*this), DataAllocator(*this) {
591588
592589 // Allocate space for code.
593590 sys::MemoryBlock MemBlock = allocateNewSlab(DefaultCodeSlabSize);
2020
2121 namespace llvm {
2222
23 SlabAllocator::~SlabAllocator() { }
24
25 MallocSlabAllocator::~MallocSlabAllocator() { }
26
27 void *MallocSlabAllocator::Allocate(size_t Size) {
28 return Allocator.Allocate(Size, 0);
29 }
30
31 void MallocSlabAllocator::Deallocate(void *Slab, size_t Size) {
32 Allocator.Deallocate(Slab);
33 }
34
3523 void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated,
3624 size_t TotalMemory) {
3725 errs() << "\nNumber of memory regions: " << NumSlabs << '\n'
101101
102102 // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no
103103 // easy portable way to do this, so this is kind of a hack.
104 class MockSlabAllocator : public SlabAllocator {
105 size_t LastSlabSize;
104 class MockSlabAllocator {
105 static size_t LastSlabSize;
106106
107107 public:
108 virtual ~MockSlabAllocator() { }
108 ~MockSlabAllocator() { }
109109
110 virtual void *Allocate(size_t Size) {
110 void *Allocate(size_t Size) {
111111 // Allocate space for the alignment, the slab, and a void* that goes right
112112 // before the slab.
113113 size_t Alignment = 4096;
123123 return Slab;
124124 }
125125
126 virtual void Deallocate(void *Slab, size_t Size) {
126 void Deallocate(void *Slab, size_t Size) {
127127 free(((void**)Slab)[-1]);
128128 }
129129
130 size_t GetLastSlabSize() { return LastSlabSize; }
130 static size_t GetLastSlabSize() { return LastSlabSize; }
131131 };
132
133 size_t MockSlabAllocator::LastSlabSize = 0;
132134
133135 // Allocate a large-ish block with a really large alignment so that the
134136 // allocator will think that it has space, but after it does the alignment it
135137 // will not.
136138 TEST(AllocatorTest, TestBigAlignment) {
137 MockSlabAllocator SlabAlloc;
138 BumpPtrAllocator Alloc(SlabAlloc);
139 BumpPtrAllocatorImpl Alloc;
139140
140141 // First allocate a tiny bit to ensure we have to re-align things.
141142 (void)Alloc.Allocate(1, 0);
145146
146147 // We test that the last slab size is not the default 4096 byte slab, but
147148 // rather a custom sized slab that is larger.
148 EXPECT_GT(SlabAlloc.GetLastSlabSize(), 4096u);
149 EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
149150 }
150151
151152 } // anonymous namespace