1 //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Support/Allocator.h" 11 #include "gtest/gtest.h" 12 #include <cstdlib> 13 14 using namespace llvm; 15 16 namespace { 17 18 TEST(AllocatorTest, Basics) { 19 BumpPtrAllocator Alloc; 20 int *a = (int*)Alloc.Allocate(sizeof(int), 0); 21 int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); 22 int *c = (int*)Alloc.Allocate(sizeof(int), 0); 23 *a = 1; 24 b[0] = 2; 25 b[9] = 2; 26 *c = 3; 27 EXPECT_EQ(1, *a); 28 EXPECT_EQ(2, b[0]); 29 EXPECT_EQ(2, b[9]); 30 EXPECT_EQ(3, *c); 31 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 32 } 33 34 // Allocate enough bytes to create three slabs. 35 TEST(AllocatorTest, ThreeSlabs) { 36 BumpPtrAllocator Alloc; 37 Alloc.Allocate(3000, 0); 38 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 39 Alloc.Allocate(3000, 0); 40 EXPECT_EQ(2U, Alloc.GetNumSlabs()); 41 Alloc.Allocate(3000, 0); 42 EXPECT_EQ(3U, Alloc.GetNumSlabs()); 43 } 44 45 // Allocate enough bytes to create two slabs, reset the allocator, and do it 46 // again. 47 TEST(AllocatorTest, TestReset) { 48 BumpPtrAllocator Alloc; 49 Alloc.Allocate(3000, 0); 50 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 51 Alloc.Allocate(3000, 0); 52 EXPECT_EQ(2U, Alloc.GetNumSlabs()); 53 Alloc.Reset(); 54 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 55 Alloc.Allocate(3000, 0); 56 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 57 Alloc.Allocate(3000, 0); 58 EXPECT_EQ(2U, Alloc.GetNumSlabs()); 59 } 60 61 // Test some allocations at varying alignments. 62 TEST(AllocatorTest, TestAlignment) { 63 BumpPtrAllocator Alloc; 64 uintptr_t a; 65 a = (uintptr_t)Alloc.Allocate(1, 2); 66 EXPECT_EQ(0U, a & 1); 67 a = (uintptr_t)Alloc.Allocate(1, 4); 68 EXPECT_EQ(0U, a & 3); 69 a = (uintptr_t)Alloc.Allocate(1, 8); 70 EXPECT_EQ(0U, a & 7); 71 a = (uintptr_t)Alloc.Allocate(1, 16); 72 EXPECT_EQ(0U, a & 15); 73 a = (uintptr_t)Alloc.Allocate(1, 32); 74 EXPECT_EQ(0U, a & 31); 75 a = (uintptr_t)Alloc.Allocate(1, 64); 76 EXPECT_EQ(0U, a & 63); 77 a = (uintptr_t)Alloc.Allocate(1, 128); 78 EXPECT_EQ(0U, a & 127); 79 } 80 81 // Test allocating just over the slab size. This tests a bug where before the 82 // allocator incorrectly calculated the buffer end pointer. 83 TEST(AllocatorTest, TestOverflow) { 84 BumpPtrAllocator Alloc; 85 86 // Fill the slab right up until the end pointer. 87 Alloc.Allocate(4096, 0); 88 EXPECT_EQ(1U, Alloc.GetNumSlabs()); 89 90 // If we don't allocate a new slab, then we will have overflowed. 91 Alloc.Allocate(1, 0); 92 EXPECT_EQ(2U, Alloc.GetNumSlabs()); 93 } 94 95 // Test allocating with a size larger than the initial slab size. 96 TEST(AllocatorTest, TestSmallSlabSize) { 97 BumpPtrAllocator Alloc; 98 99 Alloc.Allocate(8000, 0); 100 EXPECT_EQ(2U, Alloc.GetNumSlabs()); 101 } 102 103 // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no 104 // easy portable way to do this, so this is kind of a hack. 105 class MockSlabAllocator { 106 static size_t LastSlabSize; 107 108 public: 109 ~MockSlabAllocator() { } 110 111 void *Allocate(size_t Size, size_t /*Alignment*/) { 112 // Allocate space for the alignment, the slab, and a void* that goes right 113 // before the slab. 114 size_t Alignment = 4096; 115 void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); 116 117 // Find the slab start. 118 void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); 119 120 // Hold a pointer to the base so we can free the whole malloced block. 121 ((void**)Slab)[-1] = MemBase; 122 123 LastSlabSize = Size; 124 return Slab; 125 } 126 127 void Deallocate(void *Slab, size_t Size) { 128 free(((void**)Slab)[-1]); 129 } 130 131 static size_t GetLastSlabSize() { return LastSlabSize; } 132 }; 133 134 size_t MockSlabAllocator::LastSlabSize = 0; 135 136 // Allocate a large-ish block with a really large alignment so that the 137 // allocator will think that it has space, but after it does the alignment it 138 // will not. 139 TEST(AllocatorTest, TestBigAlignment) { 140 BumpPtrAllocatorImpl<MockSlabAllocator> Alloc; 141 142 // First allocate a tiny bit to ensure we have to re-align things. 143 (void)Alloc.Allocate(1, 0); 144 145 // Now the big chunk with a big alignment. 146 (void)Alloc.Allocate(3000, 2048); 147 148 // We test that the last slab size is not the default 4096 byte slab, but 149 // rather a custom sized slab that is larger. 150 EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u); 151 } 152 153 } // anonymous namespace 154