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 14using namespace llvm; 15 16namespace { 17 18TEST(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. 35TEST(AllocatorTest, ThreeSlabs) { 36 BumpPtrAllocator Alloc(4096, 4096); 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. 47TEST(AllocatorTest, TestReset) { 48 BumpPtrAllocator Alloc(4096, 4096); 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. 62TEST(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. 83TEST(AllocatorTest, TestOverflow) { 84 BumpPtrAllocator Alloc(4096, 4096); 85 86 // Fill the slab right up until the end pointer. 87 Alloc.Allocate(4096 - sizeof(MemSlab), 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. 96TEST(AllocatorTest, TestSmallSlabSize) { 97 BumpPtrAllocator Alloc(128); 98 99 Alloc.Allocate(200, 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. 105class MockSlabAllocator : public SlabAllocator { 106 MemSlab *LastSlab; 107 108public: 109 virtual ~MockSlabAllocator() { } 110 111 virtual MemSlab *Allocate(size_t Size) { 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 // Make the slab. 118 MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) & 119 ~(uintptr_t)(Alignment - 1)); 120 Slab->Size = Size; 121 Slab->NextPtr = 0; 122 123 // Hold a pointer to the base so we can free the whole malloced block. 124 ((void**)Slab)[-1] = MemBase; 125 126 LastSlab = Slab; 127 return Slab; 128 } 129 130 virtual void Deallocate(MemSlab *Slab) { 131 free(((void**)Slab)[-1]); 132 } 133 134 MemSlab *GetLastSlab() { 135 return LastSlab; 136 } 137}; 138 139// Allocate a large-ish block with a really large alignment so that the 140// allocator will think that it has space, but after it does the alignment it 141// will not. 142TEST(AllocatorTest, TestBigAlignment) { 143 MockSlabAllocator SlabAlloc; 144 BumpPtrAllocator Alloc(4096, 4096, SlabAlloc); 145 uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); 146 MemSlab *Slab = SlabAlloc.GetLastSlab(); 147 EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); 148} 149 150} // anonymous namespace 151