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"
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
);
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
31 TEST(JITMemoryManagerTest
, NoAllocations
) {
32 OwningPtr
<JITMemoryManager
> MemMgr(
33 JITMemoryManager::CreateDefaultMemManager());
38 // Allocate the functions.
39 OwningPtr
<Function
> F1(makeFakeFunction());
41 start
= MemMgr
->startFunctionBody(F1
.get(), size
);
42 memset(start
, 0xFF, 1024);
43 MemMgr
->endFunctionBody(F1
.get(), start
, start
+ 1024);
44 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
46 OwningPtr
<Function
> F2(makeFakeFunction());
48 start
= MemMgr
->startFunctionBody(F2
.get(), size
);
49 memset(start
, 0xFF, 1024);
50 MemMgr
->endFunctionBody(F2
.get(), start
, start
+ 1024);
51 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
53 OwningPtr
<Function
> F3(makeFakeFunction());
55 start
= MemMgr
->startFunctionBody(F3
.get(), size
);
56 memset(start
, 0xFF, 1024);
57 MemMgr
->endFunctionBody(F3
.get(), start
, start
+ 1024);
58 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
60 // Deallocate them out of order, in case that matters.
61 MemMgr
->deallocateMemForFunction(F2
.get());
62 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
63 MemMgr
->deallocateMemForFunction(F1
.get());
64 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
65 MemMgr
->deallocateMemForFunction(F3
.get());
66 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
69 // Make three large functions that take up most of the space in the slab. Then
70 // try allocating three smaller functions that don't require additional slabs.
71 TEST(JITMemoryManagerTest
, TestCodeAllocation
) {
72 OwningPtr
<JITMemoryManager
> MemMgr(
73 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 start
= MemMgr
->startFunctionBody(F1
.get(), size
);
87 ASSERT_LE(bigFuncSize
, size
);
88 memset(start
, 0xFF, bigFuncSize
);
89 MemMgr
->endFunctionBody(F1
.get(), start
, start
+ bigFuncSize
);
90 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
92 OwningPtr
<Function
> F2(makeFakeFunction());
94 start
= MemMgr
->startFunctionBody(F2
.get(), size
);
95 ASSERT_LE(bigFuncSize
, size
);
96 memset(start
, 0xFF, bigFuncSize
);
97 MemMgr
->endFunctionBody(F2
.get(), start
, start
+ bigFuncSize
);
98 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
100 OwningPtr
<Function
> F3(makeFakeFunction());
102 start
= MemMgr
->startFunctionBody(F3
.get(), size
);
103 ASSERT_LE(bigFuncSize
, size
);
104 memset(start
, 0xFF, bigFuncSize
);
105 MemMgr
->endFunctionBody(F3
.get(), start
, start
+ 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 start
= MemMgr
->startFunctionBody(F4
.get(), size
);
115 ASSERT_LE(smallFuncSize
, size
);
116 memset(start
, 0xFF, smallFuncSize
);
117 MemMgr
->endFunctionBody(F4
.get(), start
, start
+ smallFuncSize
);
118 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
120 OwningPtr
<Function
> F5(makeFakeFunction());
121 size
= smallFuncSize
;
122 start
= MemMgr
->startFunctionBody(F5
.get(), size
);
123 ASSERT_LE(smallFuncSize
, size
);
124 memset(start
, 0xFF, smallFuncSize
);
125 MemMgr
->endFunctionBody(F5
.get(), start
, start
+ smallFuncSize
);
126 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
128 OwningPtr
<Function
> F6(makeFakeFunction());
129 size
= smallFuncSize
;
130 start
= MemMgr
->startFunctionBody(F6
.get(), size
);
131 ASSERT_LE(smallFuncSize
, size
);
132 memset(start
, 0xFF, smallFuncSize
);
133 MemMgr
->endFunctionBody(F6
.get(), start
, start
+ smallFuncSize
);
134 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
136 // Check that the small functions didn't allocate any new slabs.
137 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
139 // Deallocate them out of order, in case that matters.
140 MemMgr
->deallocateMemForFunction(F2
.get());
141 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
142 MemMgr
->deallocateMemForFunction(F1
.get());
143 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
144 MemMgr
->deallocateMemForFunction(F4
.get());
145 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
146 MemMgr
->deallocateMemForFunction(F3
.get());
147 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
148 MemMgr
->deallocateMemForFunction(F5
.get());
149 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
150 MemMgr
->deallocateMemForFunction(F6
.get());
151 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
154 // Allocate five global ints of varying widths and alignment, and check their
155 // alignment and overlap.
156 TEST(JITMemoryManagerTest
, TestSmallGlobalInts
) {
157 OwningPtr
<JITMemoryManager
> MemMgr(
158 JITMemoryManager::CreateDefaultMemManager());
159 uint8_t *a
= (uint8_t *)MemMgr
->allocateGlobal(8, 0);
160 uint16_t *b
= (uint16_t*)MemMgr
->allocateGlobal(16, 2);
161 uint32_t *c
= (uint32_t*)MemMgr
->allocateGlobal(32, 4);
162 uint64_t *d
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
164 // Check the alignment.
165 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x1);
166 EXPECT_EQ(0U, ((uintptr_t)c
) & 0x3);
167 EXPECT_EQ(0U, ((uintptr_t)d
) & 0x7);
169 // Initialize them each one at a time and make sure they don't overlap.
174 EXPECT_EQ(0xffU
, *a
);
181 EXPECT_EQ(0xffffU
, *b
);
188 EXPECT_EQ(0xffffffffU
, *c
);
191 *d
= 0xffffffffffffffffULL
;
195 EXPECT_EQ(0xffffffffffffffffULL
, *d
);
197 // Make sure we didn't allocate any extra slabs for this tiny amount of data.
198 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
201 // Allocate a small global, a big global, and a third global, and make sure we
202 // only use two slabs for that.
203 TEST(JITMemoryManagerTest
, TestLargeGlobalArray
) {
204 OwningPtr
<JITMemoryManager
> MemMgr(
205 JITMemoryManager::CreateDefaultMemManager());
206 size_t Size
= 4 * MemMgr
->GetDefaultDataSlabSize();
207 uint64_t *a
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
208 uint8_t *g
= MemMgr
->allocateGlobal(Size
, 8);
209 uint64_t *b
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
211 // Check the alignment.
212 EXPECT_EQ(0U, ((uintptr_t)a
) & 0x7);
213 EXPECT_EQ(0U, ((uintptr_t)g
) & 0x7);
214 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x7);
216 // Initialize them to make sure we don't segfault and make sure they don't
219 memset(g
, 0x2, Size
);
221 EXPECT_EQ(0x0101010101010101ULL
, *a
);
222 // Just check the edges.
223 EXPECT_EQ(0x02U
, g
[0]);
224 EXPECT_EQ(0x02U
, g
[Size
- 1]);
225 EXPECT_EQ(0x0303030303030303ULL
, *b
);
227 // Check the number of slabs.
228 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
231 // Allocate lots of medium globals so that we can test moving the bump allocator
233 TEST(JITMemoryManagerTest
, TestManyGlobals
) {
234 OwningPtr
<JITMemoryManager
> MemMgr(
235 JITMemoryManager::CreateDefaultMemManager());
236 size_t SlabSize
= MemMgr
->GetDefaultDataSlabSize();
238 int Iters
= (SlabSize
/ Size
) + 1;
240 // We should start with one slab.
241 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
243 // After allocating a bunch of globals, we should have two.
244 for (int I
= 0; I
< Iters
; ++I
)
245 MemMgr
->allocateGlobal(Size
, 8);
246 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
248 // And after much more, we should have three.
249 for (int I
= 0; I
< Iters
; ++I
)
250 MemMgr
->allocateGlobal(Size
, 8);
251 EXPECT_EQ(3U, MemMgr
->GetNumDataSlabs());
254 // Allocate lots of function stubs so that we can test moving the stub bump
255 // allocator to a new slab.
256 TEST(JITMemoryManagerTest
, TestManyStubs
) {
257 OwningPtr
<JITMemoryManager
> MemMgr(
258 JITMemoryManager::CreateDefaultMemManager());
259 size_t SlabSize
= MemMgr
->GetDefaultStubSlabSize();
261 int Iters
= (SlabSize
/ Size
) + 1;
263 // We should start with one slab.
264 EXPECT_EQ(1U, MemMgr
->GetNumStubSlabs());
266 // After allocating a bunch of stubs, we should have two.
267 for (int I
= 0; I
< Iters
; ++I
)
268 MemMgr
->allocateStub(NULL
, Size
, 8);
269 EXPECT_EQ(2U, MemMgr
->GetNumStubSlabs());
271 // And after much more, we should have three.
272 for (int I
= 0; I
< Iters
; ++I
)
273 MemMgr
->allocateStub(NULL
, Size
, 8);
274 EXPECT_EQ(3U, MemMgr
->GetNumStubSlabs());