AllocatorTest.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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;
  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;
  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;
  77. // Fill the slab right up until the end pointer.
  78. Alloc.Allocate(4096, 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;
  87. Alloc.Allocate(8000, 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 {
  93. static size_t LastSlabSize;
  94. public:
  95. ~MockSlabAllocator() { }
  96. void *Allocate(size_t Size, size_t /*Alignment*/) {
  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. // Find the slab start.
  102. void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment);
  103. // Hold a pointer to the base so we can free the whole malloced block.
  104. ((void**)Slab)[-1] = MemBase;
  105. LastSlabSize = Size;
  106. return Slab;
  107. }
  108. void Deallocate(void *Slab, size_t Size) {
  109. free(((void**)Slab)[-1]);
  110. }
  111. static size_t GetLastSlabSize() { return LastSlabSize; }
  112. };
  113. size_t MockSlabAllocator::LastSlabSize = 0;
  114. // Allocate a large-ish block with a really large alignment so that the
  115. // allocator will think that it has space, but after it does the alignment it
  116. // will not.
  117. TEST(AllocatorTest, TestBigAlignment) {
  118. BumpPtrAllocatorImpl<MockSlabAllocator> Alloc;
  119. // First allocate a tiny bit to ensure we have to re-align things.
  120. (void)Alloc.Allocate(1, 0);
  121. // Now the big chunk with a big alignment.
  122. (void)Alloc.Allocate(3000, 2048);
  123. // We test that the last slab size is not the default 4096 byte slab, but
  124. // rather a custom sized slab that is larger.
  125. EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
  126. }
  127. } // anonymous namespace