AllocatorTest.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. #include "llvm/Support/Allocator.h"
  10. #include "gtest/gtest.h"
  11. #include <cstdlib>
  12. using namespace llvm;
  13. namespace {
  14. TEST(AllocatorTest, Basics) {
  15. BumpPtrAllocator Alloc;
  16. int *a = (int*)Alloc.Allocate(sizeof(int), 0);
  17. int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0);
  18. int *c = (int*)Alloc.Allocate(sizeof(int), 0);
  19. *a = 1;
  20. b[0] = 2;
  21. b[9] = 2;
  22. *c = 3;
  23. EXPECT_EQ(1, *a);
  24. EXPECT_EQ(2, b[0]);
  25. EXPECT_EQ(2, b[9]);
  26. EXPECT_EQ(3, *c);
  27. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  28. }
  29. // Allocate enough bytes to create three slabs.
  30. TEST(AllocatorTest, ThreeSlabs) {
  31. BumpPtrAllocator Alloc(4096, 4096);
  32. Alloc.Allocate(3000, 0);
  33. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  34. Alloc.Allocate(3000, 0);
  35. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  36. Alloc.Allocate(3000, 0);
  37. EXPECT_EQ(3U, Alloc.GetNumSlabs());
  38. }
  39. // Allocate enough bytes to create two slabs, reset the allocator, and do it
  40. // again.
  41. TEST(AllocatorTest, TestReset) {
  42. BumpPtrAllocator Alloc(4096, 4096);
  43. Alloc.Allocate(3000, 0);
  44. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  45. Alloc.Allocate(3000, 0);
  46. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  47. Alloc.Reset();
  48. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  49. Alloc.Allocate(3000, 0);
  50. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  51. Alloc.Allocate(3000, 0);
  52. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  53. }
  54. // Test some allocations at varying alignments.
  55. TEST(AllocatorTest, TestAlignment) {
  56. BumpPtrAllocator Alloc;
  57. uintptr_t a;
  58. a = (uintptr_t)Alloc.Allocate(1, 2);
  59. EXPECT_EQ(0U, a & 1);
  60. a = (uintptr_t)Alloc.Allocate(1, 4);
  61. EXPECT_EQ(0U, a & 3);
  62. a = (uintptr_t)Alloc.Allocate(1, 8);
  63. EXPECT_EQ(0U, a & 7);
  64. a = (uintptr_t)Alloc.Allocate(1, 16);
  65. EXPECT_EQ(0U, a & 15);
  66. a = (uintptr_t)Alloc.Allocate(1, 32);
  67. EXPECT_EQ(0U, a & 31);
  68. a = (uintptr_t)Alloc.Allocate(1, 64);
  69. EXPECT_EQ(0U, a & 63);
  70. a = (uintptr_t)Alloc.Allocate(1, 128);
  71. EXPECT_EQ(0U, a & 127);
  72. }
  73. // Test allocating just over the slab size. This tests a bug where before the
  74. // allocator incorrectly calculated the buffer end pointer.
  75. TEST(AllocatorTest, TestOverflow) {
  76. BumpPtrAllocator Alloc(4096, 4096);
  77. // Fill the slab right up until the end pointer.
  78. Alloc.Allocate(4096 - sizeof(MemSlab), 0);
  79. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  80. // If we don't allocate a new slab, then we will have overflowed.
  81. Alloc.Allocate(1, 0);
  82. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  83. }
  84. // Test allocating with a size larger than the initial slab size.
  85. TEST(AllocatorTest, TestSmallSlabSize) {
  86. BumpPtrAllocator Alloc(128);
  87. Alloc.Allocate(200, 0);
  88. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  89. }
  90. // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no
  91. // easy portable way to do this, so this is kind of a hack.
  92. class MockSlabAllocator : public SlabAllocator {
  93. MemSlab *LastSlab;
  94. public:
  95. virtual ~MockSlabAllocator() { }
  96. virtual MemSlab *Allocate(size_t Size) {
  97. // Allocate space for the alignment, the slab, and a void* that goes right
  98. // before the slab.
  99. size_t Alignment = 4096;
  100. void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*));
  101. // Make the slab.
  102. MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) &
  103. ~(uintptr_t)(Alignment - 1));
  104. Slab->Size = Size;
  105. Slab->NextPtr = 0;
  106. // Hold a pointer to the base so we can free the whole malloced block.
  107. ((void**)Slab)[-1] = MemBase;
  108. LastSlab = Slab;
  109. return Slab;
  110. }
  111. virtual void Deallocate(MemSlab *Slab) {
  112. free(((void**)Slab)[-1]);
  113. }
  114. MemSlab *GetLastSlab() {
  115. return LastSlab;
  116. }
  117. };
  118. // Allocate a large-ish block with a really large alignment so that the
  119. // allocator will think that it has space, but after it does the alignment it
  120. // will not.
  121. TEST(AllocatorTest, TestBigAlignment) {
  122. MockSlabAllocator SlabAlloc;
  123. BumpPtrAllocator Alloc(4096, 4096, SlabAlloc);
  124. uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048);
  125. MemSlab *Slab = SlabAlloc.GetLastSlab();
  126. EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size);
  127. }
  128. } // anonymous namespace