AllocatorTest.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  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), alignof(int));
  17. int *b = (int*)Alloc.Allocate(sizeof(int) * 10, alignof(int));
  18. int *c = (int*)Alloc.Allocate(sizeof(int), alignof(int));
  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. BumpPtrAllocator Alloc2 = std::move(Alloc);
  29. EXPECT_EQ(0U, Alloc.GetNumSlabs());
  30. EXPECT_EQ(1U, Alloc2.GetNumSlabs());
  31. // Make sure the old pointers still work. These are especially interesting
  32. // under ASan or Valgrind.
  33. EXPECT_EQ(1, *a);
  34. EXPECT_EQ(2, b[0]);
  35. EXPECT_EQ(2, b[9]);
  36. EXPECT_EQ(3, *c);
  37. Alloc = std::move(Alloc2);
  38. EXPECT_EQ(0U, Alloc2.GetNumSlabs());
  39. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  40. }
  41. // Allocate enough bytes to create three slabs.
  42. TEST(AllocatorTest, ThreeSlabs) {
  43. BumpPtrAllocator Alloc;
  44. Alloc.Allocate(3000, 1);
  45. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  46. Alloc.Allocate(3000, 1);
  47. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  48. Alloc.Allocate(3000, 1);
  49. EXPECT_EQ(3U, Alloc.GetNumSlabs());
  50. }
  51. // Allocate enough bytes to create two slabs, reset the allocator, and do it
  52. // again.
  53. TEST(AllocatorTest, TestReset) {
  54. BumpPtrAllocator Alloc;
  55. // Allocate something larger than the SizeThreshold=4096.
  56. (void)Alloc.Allocate(5000, 1);
  57. Alloc.Reset();
  58. // Calling Reset should free all CustomSizedSlabs.
  59. EXPECT_EQ(0u, Alloc.GetNumSlabs());
  60. Alloc.Allocate(3000, 1);
  61. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  62. Alloc.Allocate(3000, 1);
  63. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  64. Alloc.Reset();
  65. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  66. Alloc.Allocate(3000, 1);
  67. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  68. Alloc.Allocate(3000, 1);
  69. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  70. }
  71. // Test some allocations at varying alignments.
  72. TEST(AllocatorTest, TestAlignment) {
  73. BumpPtrAllocator Alloc;
  74. uintptr_t a;
  75. a = (uintptr_t)Alloc.Allocate(1, 2);
  76. EXPECT_EQ(0U, a & 1);
  77. a = (uintptr_t)Alloc.Allocate(1, 4);
  78. EXPECT_EQ(0U, a & 3);
  79. a = (uintptr_t)Alloc.Allocate(1, 8);
  80. EXPECT_EQ(0U, a & 7);
  81. a = (uintptr_t)Alloc.Allocate(1, 16);
  82. EXPECT_EQ(0U, a & 15);
  83. a = (uintptr_t)Alloc.Allocate(1, 32);
  84. EXPECT_EQ(0U, a & 31);
  85. a = (uintptr_t)Alloc.Allocate(1, 64);
  86. EXPECT_EQ(0U, a & 63);
  87. a = (uintptr_t)Alloc.Allocate(1, 128);
  88. EXPECT_EQ(0U, a & 127);
  89. }
  90. // Test allocating just over the slab size. This tests a bug where before the
  91. // allocator incorrectly calculated the buffer end pointer.
  92. TEST(AllocatorTest, TestOverflow) {
  93. BumpPtrAllocator Alloc;
  94. // Fill the slab right up until the end pointer.
  95. Alloc.Allocate(4096, 1);
  96. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  97. // If we don't allocate a new slab, then we will have overflowed.
  98. Alloc.Allocate(1, 1);
  99. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  100. }
  101. // Test allocating with a size larger than the initial slab size.
  102. TEST(AllocatorTest, TestSmallSlabSize) {
  103. BumpPtrAllocator Alloc;
  104. Alloc.Allocate(8000, 1);
  105. EXPECT_EQ(1U, Alloc.GetNumSlabs());
  106. }
  107. // Test requesting alignment that goes past the end of the current slab.
  108. TEST(AllocatorTest, TestAlignmentPastSlab) {
  109. BumpPtrAllocator Alloc;
  110. Alloc.Allocate(4095, 1);
  111. // Aligning the current slab pointer is likely to move it past the end of the
  112. // slab, which would confuse any unsigned comparisons with the difference of
  113. // the end pointer and the aligned pointer.
  114. Alloc.Allocate(1024, 8192);
  115. EXPECT_EQ(2U, Alloc.GetNumSlabs());
  116. }
  117. // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no
  118. // easy portable way to do this, so this is kind of a hack.
  119. class MockSlabAllocator {
  120. static size_t LastSlabSize;
  121. public:
  122. ~MockSlabAllocator() { }
  123. void *Allocate(size_t Size, size_t /*Alignment*/) {
  124. // Allocate space for the alignment, the slab, and a void* that goes right
  125. // before the slab.
  126. size_t Alignment = 4096;
  127. void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*));
  128. // Find the slab start.
  129. void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment);
  130. // Hold a pointer to the base so we can free the whole malloced block.
  131. ((void**)Slab)[-1] = MemBase;
  132. LastSlabSize = Size;
  133. return Slab;
  134. }
  135. void Deallocate(void *Slab, size_t Size) {
  136. free(((void**)Slab)[-1]);
  137. }
  138. static size_t GetLastSlabSize() { return LastSlabSize; }
  139. };
  140. size_t MockSlabAllocator::LastSlabSize = 0;
  141. // Allocate a large-ish block with a really large alignment so that the
  142. // allocator will think that it has space, but after it does the alignment it
  143. // will not.
  144. TEST(AllocatorTest, TestBigAlignment) {
  145. BumpPtrAllocatorImpl<MockSlabAllocator> Alloc;
  146. // First allocate a tiny bit to ensure we have to re-align things.
  147. (void)Alloc.Allocate(1, 1);
  148. // Now the big chunk with a big alignment.
  149. (void)Alloc.Allocate(3000, 2048);
  150. // We test that the last slab size is not the default 4096 byte slab, but
  151. // rather a custom sized slab that is larger.
  152. EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
  153. }
  154. } // anonymous namespace