• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===//
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 "gtest/gtest.h"
11 #include "llvm/ADT/OwningPtr.h"
12 #include "llvm/ExecutionEngine/JITMemoryManager.h"
13 #include "llvm/DerivedTypes.h"
14 #include "llvm/Function.h"
15 #include "llvm/GlobalValue.h"
16 #include "llvm/LLVMContext.h"
17 #include "llvm/ADT/ArrayRef.h"
18 
19 using namespace llvm;
20 
21 namespace {
22 
makeFakeFunction()23 Function *makeFakeFunction() {
24   std::vector<Type*> params;
25   FunctionType *FTy =
26       FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false);
27   return Function::Create(FTy, GlobalValue::ExternalLinkage);
28 }
29 
30 // Allocate three simple functions that fit in the initial slab.  This exercises
31 // the code in the case that we don't have to allocate more memory to store the
32 // function bodies.
TEST(JITMemoryManagerTest,NoAllocations)33 TEST(JITMemoryManagerTest, NoAllocations) {
34   OwningPtr<JITMemoryManager> MemMgr(
35       JITMemoryManager::CreateDefaultMemManager());
36   uintptr_t size;
37   std::string Error;
38 
39   // Allocate the functions.
40   OwningPtr<Function> F1(makeFakeFunction());
41   size = 1024;
42   uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
43   memset(FunctionBody1, 0xFF, 1024);
44   MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024);
45   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
46 
47   OwningPtr<Function> F2(makeFakeFunction());
48   size = 1024;
49   uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
50   memset(FunctionBody2, 0xFF, 1024);
51   MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024);
52   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
53 
54   OwningPtr<Function> F3(makeFakeFunction());
55   size = 1024;
56   uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
57   memset(FunctionBody3, 0xFF, 1024);
58   MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024);
59   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
60 
61   // Deallocate them out of order, in case that matters.
62   MemMgr->deallocateFunctionBody(FunctionBody2);
63   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
64   MemMgr->deallocateFunctionBody(FunctionBody1);
65   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
66   MemMgr->deallocateFunctionBody(FunctionBody3);
67   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
68 }
69 
70 // Make three large functions that take up most of the space in the slab.  Then
71 // try allocating three smaller functions that don't require additional slabs.
TEST(JITMemoryManagerTest,TestCodeAllocation)72 TEST(JITMemoryManagerTest, TestCodeAllocation) {
73   OwningPtr<JITMemoryManager> MemMgr(
74       JITMemoryManager::CreateDefaultMemManager());
75   uintptr_t size;
76   std::string Error;
77 
78   // Big functions are a little less than the largest block size.
79   const uintptr_t smallFuncSize = 1024;
80   const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() -
81                                  smallFuncSize * 2);
82 
83   // Allocate big functions
84   OwningPtr<Function> F1(makeFakeFunction());
85   size = bigFuncSize;
86   uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
87   ASSERT_LE(bigFuncSize, size);
88   memset(FunctionBody1, 0xFF, bigFuncSize);
89   MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize);
90   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
91 
92   OwningPtr<Function> F2(makeFakeFunction());
93   size = bigFuncSize;
94   uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
95   ASSERT_LE(bigFuncSize, size);
96   memset(FunctionBody2, 0xFF, bigFuncSize);
97   MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize);
98   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
99 
100   OwningPtr<Function> F3(makeFakeFunction());
101   size = bigFuncSize;
102   uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
103   ASSERT_LE(bigFuncSize, size);
104   memset(FunctionBody3, 0xFF, bigFuncSize);
105   MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize);
106   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
107 
108   // Check that each large function took it's own slab.
109   EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
110 
111   // Allocate small functions
112   OwningPtr<Function> F4(makeFakeFunction());
113   size = smallFuncSize;
114   uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size);
115   ASSERT_LE(smallFuncSize, size);
116   memset(FunctionBody4, 0xFF, smallFuncSize);
117   MemMgr->endFunctionBody(F4.get(), FunctionBody4,
118                           FunctionBody4 + smallFuncSize);
119   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
120 
121   OwningPtr<Function> F5(makeFakeFunction());
122   size = smallFuncSize;
123   uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size);
124   ASSERT_LE(smallFuncSize, size);
125   memset(FunctionBody5, 0xFF, smallFuncSize);
126   MemMgr->endFunctionBody(F5.get(), FunctionBody5,
127                           FunctionBody5 + smallFuncSize);
128   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
129 
130   OwningPtr<Function> F6(makeFakeFunction());
131   size = smallFuncSize;
132   uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size);
133   ASSERT_LE(smallFuncSize, size);
134   memset(FunctionBody6, 0xFF, smallFuncSize);
135   MemMgr->endFunctionBody(F6.get(), FunctionBody6,
136                           FunctionBody6 + smallFuncSize);
137   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
138 
139   // Check that the small functions didn't allocate any new slabs.
140   EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
141 
142   // Deallocate them out of order, in case that matters.
143   MemMgr->deallocateFunctionBody(FunctionBody2);
144   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
145   MemMgr->deallocateFunctionBody(FunctionBody1);
146   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
147   MemMgr->deallocateFunctionBody(FunctionBody4);
148   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
149   MemMgr->deallocateFunctionBody(FunctionBody3);
150   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
151   MemMgr->deallocateFunctionBody(FunctionBody5);
152   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
153   MemMgr->deallocateFunctionBody(FunctionBody6);
154   EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
155 }
156 
157 // Allocate five global ints of varying widths and alignment, and check their
158 // alignment and overlap.
TEST(JITMemoryManagerTest,TestSmallGlobalInts)159 TEST(JITMemoryManagerTest, TestSmallGlobalInts) {
160   OwningPtr<JITMemoryManager> MemMgr(
161       JITMemoryManager::CreateDefaultMemManager());
162   uint8_t  *a = (uint8_t *)MemMgr->allocateGlobal(8,  0);
163   uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2);
164   uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4);
165   uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8);
166 
167   // Check the alignment.
168   EXPECT_EQ(0U, ((uintptr_t)b) & 0x1);
169   EXPECT_EQ(0U, ((uintptr_t)c) & 0x3);
170   EXPECT_EQ(0U, ((uintptr_t)d) & 0x7);
171 
172   // Initialize them each one at a time and make sure they don't overlap.
173   *a = 0xff;
174   *b = 0U;
175   *c = 0U;
176   *d = 0U;
177   EXPECT_EQ(0xffU, *a);
178   EXPECT_EQ(0U, *b);
179   EXPECT_EQ(0U, *c);
180   EXPECT_EQ(0U, *d);
181   *a = 0U;
182   *b = 0xffffU;
183   EXPECT_EQ(0U, *a);
184   EXPECT_EQ(0xffffU, *b);
185   EXPECT_EQ(0U, *c);
186   EXPECT_EQ(0U, *d);
187   *b = 0U;
188   *c = 0xffffffffU;
189   EXPECT_EQ(0U, *a);
190   EXPECT_EQ(0U, *b);
191   EXPECT_EQ(0xffffffffU, *c);
192   EXPECT_EQ(0U, *d);
193   *c = 0U;
194   *d = 0xffffffffffffffffULL;
195   EXPECT_EQ(0U, *a);
196   EXPECT_EQ(0U, *b);
197   EXPECT_EQ(0U, *c);
198   EXPECT_EQ(0xffffffffffffffffULL, *d);
199 
200   // Make sure we didn't allocate any extra slabs for this tiny amount of data.
201   EXPECT_EQ(1U, MemMgr->GetNumDataSlabs());
202 }
203 
204 // Allocate a small global, a big global, and a third global, and make sure we
205 // only use two slabs for that.
TEST(JITMemoryManagerTest,TestLargeGlobalArray)206 TEST(JITMemoryManagerTest, TestLargeGlobalArray) {
207   OwningPtr<JITMemoryManager> MemMgr(
208       JITMemoryManager::CreateDefaultMemManager());
209   size_t Size = 4 * MemMgr->GetDefaultDataSlabSize();
210   uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8);
211   uint8_t *g = MemMgr->allocateGlobal(Size, 8);
212   uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8);
213 
214   // Check the alignment.
215   EXPECT_EQ(0U, ((uintptr_t)a) & 0x7);
216   EXPECT_EQ(0U, ((uintptr_t)g) & 0x7);
217   EXPECT_EQ(0U, ((uintptr_t)b) & 0x7);
218 
219   // Initialize them to make sure we don't segfault and make sure they don't
220   // overlap.
221   memset(a, 0x1, 8);
222   memset(g, 0x2, Size);
223   memset(b, 0x3, 8);
224   EXPECT_EQ(0x0101010101010101ULL, *a);
225   // Just check the edges.
226   EXPECT_EQ(0x02U, g[0]);
227   EXPECT_EQ(0x02U, g[Size - 1]);
228   EXPECT_EQ(0x0303030303030303ULL, *b);
229 
230   // Check the number of slabs.
231   EXPECT_EQ(2U, MemMgr->GetNumDataSlabs());
232 }
233 
234 // Allocate lots of medium globals so that we can test moving the bump allocator
235 // to a new slab.
TEST(JITMemoryManagerTest,TestManyGlobals)236 TEST(JITMemoryManagerTest, TestManyGlobals) {
237   OwningPtr<JITMemoryManager> MemMgr(
238       JITMemoryManager::CreateDefaultMemManager());
239   size_t SlabSize = MemMgr->GetDefaultDataSlabSize();
240   size_t Size = 128;
241   int Iters = (SlabSize / Size) + 1;
242 
243   // We should start with no slabs.
244   EXPECT_EQ(0U, MemMgr->GetNumDataSlabs());
245 
246   // After allocating a bunch of globals, we should have two.
247   for (int I = 0; I < Iters; ++I)
248     MemMgr->allocateGlobal(Size, 8);
249   EXPECT_EQ(2U, MemMgr->GetNumDataSlabs());
250 
251   // And after much more, we should have three.
252   for (int I = 0; I < Iters; ++I)
253     MemMgr->allocateGlobal(Size, 8);
254   EXPECT_EQ(3U, MemMgr->GetNumDataSlabs());
255 }
256 
257 // Allocate lots of function stubs so that we can test moving the stub bump
258 // allocator to a new slab.
TEST(JITMemoryManagerTest,TestManyStubs)259 TEST(JITMemoryManagerTest, TestManyStubs) {
260   OwningPtr<JITMemoryManager> MemMgr(
261       JITMemoryManager::CreateDefaultMemManager());
262   size_t SlabSize = MemMgr->GetDefaultStubSlabSize();
263   size_t Size = 128;
264   int Iters = (SlabSize / Size) + 1;
265 
266   // We should start with no slabs.
267   EXPECT_EQ(0U, MemMgr->GetNumDataSlabs());
268 
269   // After allocating a bunch of stubs, we should have two.
270   for (int I = 0; I < Iters; ++I)
271     MemMgr->allocateStub(NULL, Size, 8);
272   EXPECT_EQ(2U, MemMgr->GetNumStubSlabs());
273 
274   // And after much more, we should have three.
275   for (int I = 0; I < Iters; ++I)
276     MemMgr->allocateStub(NULL, Size, 8);
277   EXPECT_EQ(3U, MemMgr->GetNumStubSlabs());
278 }
279 
280 }
281