diff options
-rw-r--r-- | lib/Support/Allocator.cpp | 4 | ||||
-rw-r--r-- | unittests/Support/AllocatorTest.cpp | 48 |
2 files changed, 50 insertions, 2 deletions
diff --git a/lib/Support/Allocator.cpp b/lib/Support/Allocator.cpp index 230c421..36da443 100644 --- a/lib/Support/Allocator.cpp +++ b/lib/Support/Allocator.cpp @@ -95,8 +95,8 @@ void *BumpPtrAllocator::Allocate(size_t Size, size_t Alignment) { } // If Size is really big, allocate a separate slab for it. - if (Size > SizeThreshold) { - size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1; + size_t PaddedSize = Size + sizeof(MemSlab) + Alignment - 1; + if (PaddedSize > SizeThreshold) { MemSlab *NewSlab = Allocator.Allocate(PaddedSize); // Put the new slab after the current slab, since we are not allocating diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index cc3296a..463760d 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -10,6 +10,7 @@ #include "llvm/Support/Allocator.h" #include "gtest/gtest.h" +#include <cstdlib> using namespace llvm; @@ -92,4 +93,51 @@ TEST(AllocatorTest, TestOverflow) { EXPECT_EQ(2U, Alloc.GetNumSlabs()); } +// Mock slab allocator that returns slabs aligned on 4096 bytes. There is no +// easy portable way to do this, so this is kind of a hack. +class MockSlabAllocator : public SlabAllocator { + MemSlab *LastSlab; + +public: + virtual ~MockSlabAllocator() { } + + virtual MemSlab *Allocate(size_t Size) { + // Allocate space for the alignment, the slab, and a void* that goes right + // before the slab. + size_t Alignment = 4096; + void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); + + // Make the slab. + MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase + Alignment - 1) & + ~(uintptr_t)(Alignment - 1)); + Slab->Size = Size; + Slab->NextPtr = 0; + + // Hold a pointer to the base so we can free the whole malloced block. + ((void**)Slab)[-1] = MemBase; + + LastSlab = Slab; + return Slab; + } + + virtual void Deallocate(MemSlab *Slab) { + free(((void**)Slab)[-1]); + } + + MemSlab *GetLastSlab() { + return LastSlab; + } +}; + +// Allocate a large-ish block with a really large alignment so that the +// allocator will think that it has space, but after it does the alignment it +// will not. +TEST(AllocatorTest, TestBigAlignment) { + MockSlabAllocator SlabAlloc; + BumpPtrAllocator Alloc(4096, 4096, SlabAlloc); + uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); + MemSlab *Slab = SlabAlloc.GetLastSlab(); + EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); +} + } // anonymous namespace |