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