From 7d509134dcec17f6094032196b21af5c67943f0f Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Sat, 25 Jul 2009 21:26:02 +0000 Subject: [PATCH] Added a test and fixed a bug in BumpPtrAllocator relating to large alignment values. Hopefully this fixes PR4622. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77088 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Allocator.cpp | 4 +-- 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 230c421f1fe..36da4432073 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 cc3296a8d01..463760d2f0e 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 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 -- 2.34.1