1 //===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
23 Function
*makeFakeFunction() {
24 std::vector
<const Type
*> params
;
25 const FunctionType
*FTy
=
26 FunctionType::get(Type::getVoidTy(getGlobalContext()), params
, false);
27 return Function::Create(FTy
, GlobalValue::ExternalLinkage
);
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
33 TEST(JITMemoryManagerTest
, NoAllocations
) {
34 OwningPtr
<JITMemoryManager
> MemMgr(
35 JITMemoryManager::CreateDefaultMemManager());
39 // Allocate the functions.
40 OwningPtr
<Function
> F1(makeFakeFunction());
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
;
47 OwningPtr
<Function
> F2(makeFakeFunction());
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
;
54 OwningPtr
<Function
> F3(makeFakeFunction());
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
;
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
;
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.
72 TEST(JITMemoryManagerTest
, TestCodeAllocation
) {
73 OwningPtr
<JITMemoryManager
> MemMgr(
74 JITMemoryManager::CreateDefaultMemManager());
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() -
83 // Allocate big functions
84 OwningPtr
<Function
> F1(makeFakeFunction());
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
;
92 OwningPtr
<Function
> F2(makeFakeFunction());
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
;
100 OwningPtr
<Function
> F3(makeFakeFunction());
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
;
108 // Check that each large function took it's own slab.
109 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
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
;
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
;
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
;
139 // Check that the small functions didn't allocate any new slabs.
140 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
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
;
157 // Allocate five global ints of varying widths and alignment, and check their
158 // alignment and overlap.
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);
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);
172 // Initialize them each one at a time and make sure they don't overlap.
177 EXPECT_EQ(0xffU
, *a
);
184 EXPECT_EQ(0xffffU
, *b
);
191 EXPECT_EQ(0xffffffffU
, *c
);
194 *d
= 0xffffffffffffffffULL
;
198 EXPECT_EQ(0xffffffffffffffffULL
, *d
);
200 // Make sure we didn't allocate any extra slabs for this tiny amount of data.
201 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
204 // Allocate a small global, a big global, and a third global, and make sure we
205 // only use two slabs for that.
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);
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);
219 // Initialize them to make sure we don't segfault and make sure they don't
222 memset(g
, 0x2, Size
);
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
);
230 // Check the number of slabs.
231 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
234 // Allocate lots of medium globals so that we can test moving the bump allocator
236 TEST(JITMemoryManagerTest
, TestManyGlobals
) {
237 OwningPtr
<JITMemoryManager
> MemMgr(
238 JITMemoryManager::CreateDefaultMemManager());
239 size_t SlabSize
= MemMgr
->GetDefaultDataSlabSize();
241 int Iters
= (SlabSize
/ Size
) + 1;
243 // We should start with no slabs.
244 EXPECT_EQ(0U, MemMgr
->GetNumDataSlabs());
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());
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());
257 // Allocate lots of function stubs so that we can test moving the stub bump
258 // allocator to a new slab.
259 TEST(JITMemoryManagerTest
, TestManyStubs
) {
260 OwningPtr
<JITMemoryManager
> MemMgr(
261 JITMemoryManager::CreateDefaultMemManager());
262 size_t SlabSize
= MemMgr
->GetDefaultStubSlabSize();
264 int Iters
= (SlabSize
/ Size
) + 1;
266 // We should start with no slabs.
267 EXPECT_EQ(0U, MemMgr
->GetNumDataSlabs());
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());
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());