• Home
  • History
  • Annotate
  • 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