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
= FunctionType::get(Type::VoidTy
, params
, false);
24 return Function::Create(FTy
, GlobalValue::ExternalLinkage
);
27 // Allocate three simple functions that fit in the initial slab. This exercises
28 // the code in the case that we don't have to allocate more memory to store the
30 TEST(JITMemoryManagerTest
, NoAllocations
) {
31 OwningPtr
<JITMemoryManager
> MemMgr(
32 JITMemoryManager::CreateDefaultMemManager());
37 // Allocate the functions.
38 OwningPtr
<Function
> F1(makeFakeFunction());
40 start
= MemMgr
->startFunctionBody(F1
.get(), size
);
41 memset(start
, 0xFF, 1024);
42 MemMgr
->endFunctionBody(F1
.get(), start
, start
+ 1024);
43 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
45 OwningPtr
<Function
> F2(makeFakeFunction());
47 start
= MemMgr
->startFunctionBody(F2
.get(), size
);
48 memset(start
, 0xFF, 1024);
49 MemMgr
->endFunctionBody(F2
.get(), start
, start
+ 1024);
50 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
52 OwningPtr
<Function
> F3(makeFakeFunction());
54 start
= MemMgr
->startFunctionBody(F3
.get(), size
);
55 memset(start
, 0xFF, 1024);
56 MemMgr
->endFunctionBody(F3
.get(), start
, start
+ 1024);
57 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
59 // Deallocate them out of order, in case that matters.
60 MemMgr
->deallocateMemForFunction(F2
.get());
61 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
62 MemMgr
->deallocateMemForFunction(F1
.get());
63 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
64 MemMgr
->deallocateMemForFunction(F3
.get());
65 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
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());
77 // Big functions are a little less than the largest block size.
78 const uintptr_t smallFuncSize
= 1024;
79 const uintptr_t bigFuncSize
= (MemMgr
->GetDefaultCodeSlabSize() -
82 // Allocate big functions
83 OwningPtr
<Function
> F1(makeFakeFunction());
85 start
= MemMgr
->startFunctionBody(F1
.get(), size
);
86 ASSERT_LE(bigFuncSize
, size
);
87 memset(start
, 0xFF, bigFuncSize
);
88 MemMgr
->endFunctionBody(F1
.get(), start
, start
+ bigFuncSize
);
89 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
91 OwningPtr
<Function
> F2(makeFakeFunction());
93 start
= MemMgr
->startFunctionBody(F2
.get(), size
);
94 ASSERT_LE(bigFuncSize
, size
);
95 memset(start
, 0xFF, bigFuncSize
);
96 MemMgr
->endFunctionBody(F2
.get(), start
, start
+ bigFuncSize
);
97 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
99 OwningPtr
<Function
> F3(makeFakeFunction());
101 start
= MemMgr
->startFunctionBody(F3
.get(), size
);
102 ASSERT_LE(bigFuncSize
, size
);
103 memset(start
, 0xFF, bigFuncSize
);
104 MemMgr
->endFunctionBody(F3
.get(), start
, start
+ bigFuncSize
);
105 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
107 // Check that each large function took it's own slab.
108 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
110 // Allocate small functions
111 OwningPtr
<Function
> F4(makeFakeFunction());
112 size
= smallFuncSize
;
113 start
= MemMgr
->startFunctionBody(F4
.get(), size
);
114 ASSERT_LE(smallFuncSize
, size
);
115 memset(start
, 0xFF, smallFuncSize
);
116 MemMgr
->endFunctionBody(F4
.get(), start
, start
+ smallFuncSize
);
117 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
119 OwningPtr
<Function
> F5(makeFakeFunction());
120 size
= smallFuncSize
;
121 start
= MemMgr
->startFunctionBody(F5
.get(), size
);
122 ASSERT_LE(smallFuncSize
, size
);
123 memset(start
, 0xFF, smallFuncSize
);
124 MemMgr
->endFunctionBody(F5
.get(), start
, start
+ smallFuncSize
);
125 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
127 OwningPtr
<Function
> F6(makeFakeFunction());
128 size
= smallFuncSize
;
129 start
= MemMgr
->startFunctionBody(F6
.get(), size
);
130 ASSERT_LE(smallFuncSize
, size
);
131 memset(start
, 0xFF, smallFuncSize
);
132 MemMgr
->endFunctionBody(F6
.get(), start
, start
+ smallFuncSize
);
133 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
135 // Check that the small functions didn't allocate any new slabs.
136 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
138 // Deallocate them out of order, in case that matters.
139 MemMgr
->deallocateMemForFunction(F2
.get());
140 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
141 MemMgr
->deallocateMemForFunction(F1
.get());
142 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
143 MemMgr
->deallocateMemForFunction(F4
.get());
144 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
145 MemMgr
->deallocateMemForFunction(F3
.get());
146 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
147 MemMgr
->deallocateMemForFunction(F5
.get());
148 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
149 MemMgr
->deallocateMemForFunction(F6
.get());
150 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
153 // Allocate five global ints of varying widths and alignment, and check their
154 // alignment and overlap.
155 TEST(JITMemoryManagerTest
, TestSmallGlobalInts
) {
156 OwningPtr
<JITMemoryManager
> MemMgr(
157 JITMemoryManager::CreateDefaultMemManager());
158 uint8_t *a
= (uint8_t *)MemMgr
->allocateGlobal(8, 0);
159 uint16_t *b
= (uint16_t*)MemMgr
->allocateGlobal(16, 2);
160 uint32_t *c
= (uint32_t*)MemMgr
->allocateGlobal(32, 4);
161 uint64_t *d
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
163 // Check the alignment.
164 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x1);
165 EXPECT_EQ(0U, ((uintptr_t)c
) & 0x3);
166 EXPECT_EQ(0U, ((uintptr_t)d
) & 0x7);
168 // Initialize them each one at a time and make sure they don't overlap.
173 EXPECT_EQ(0xffU
, *a
);
180 EXPECT_EQ(0xffffU
, *b
);
187 EXPECT_EQ(0xffffffffU
, *c
);
190 *d
= 0xffffffffffffffffULL
;
194 EXPECT_EQ(0xffffffffffffffffULL
, *d
);
196 // Make sure we didn't allocate any extra slabs for this tiny amount of data.
197 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
200 // Allocate a small global, a big global, and a third global, and make sure we
201 // only use two slabs for that.
202 TEST(JITMemoryManagerTest
, TestLargeGlobalArray
) {
203 OwningPtr
<JITMemoryManager
> MemMgr(
204 JITMemoryManager::CreateDefaultMemManager());
205 size_t Size
= 4 * MemMgr
->GetDefaultDataSlabSize();
206 uint64_t *a
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
207 uint8_t *g
= MemMgr
->allocateGlobal(Size
, 8);
208 uint64_t *b
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
210 // Check the alignment.
211 EXPECT_EQ(0U, ((uintptr_t)a
) & 0x7);
212 EXPECT_EQ(0U, ((uintptr_t)g
) & 0x7);
213 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x7);
215 // Initialize them to make sure we don't segfault and make sure they don't
218 memset(g
, 0x2, Size
);
220 EXPECT_EQ(0x0101010101010101ULL
, *a
);
221 // Just check the edges.
222 EXPECT_EQ(0x02U
, g
[0]);
223 EXPECT_EQ(0x02U
, g
[Size
- 1]);
224 EXPECT_EQ(0x0303030303030303ULL
, *b
);
226 // Check the number of slabs.
227 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
230 // Allocate lots of medium globals so that we can test moving the bump allocator
232 TEST(JITMemoryManagerTest
, TestManyGlobals
) {
233 OwningPtr
<JITMemoryManager
> MemMgr(
234 JITMemoryManager::CreateDefaultMemManager());
235 size_t SlabSize
= MemMgr
->GetDefaultDataSlabSize();
237 int Iters
= (SlabSize
/ Size
) + 1;
239 // We should start with one slab.
240 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
242 // After allocating a bunch of globals, we should have two.
243 for (int I
= 0; I
< Iters
; ++I
)
244 MemMgr
->allocateGlobal(Size
, 8);
245 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
247 // And after much more, we should have three.
248 for (int I
= 0; I
< Iters
; ++I
)
249 MemMgr
->allocateGlobal(Size
, 8);
250 EXPECT_EQ(3U, MemMgr
->GetNumDataSlabs());
253 // Allocate lots of function stubs so that we can test moving the stub bump
254 // allocator to a new slab.
255 TEST(JITMemoryManagerTest
, TestManyStubs
) {
256 OwningPtr
<JITMemoryManager
> MemMgr(
257 JITMemoryManager::CreateDefaultMemManager());
258 size_t SlabSize
= MemMgr
->GetDefaultStubSlabSize();
260 int Iters
= (SlabSize
/ Size
) + 1;
262 // We should start with one slab.
263 EXPECT_EQ(1U, MemMgr
->GetNumStubSlabs());
265 // After allocating a bunch of stubs, we should have two.
266 for (int I
= 0; I
< Iters
; ++I
)
267 MemMgr
->allocateStub(NULL
, Size
, 8);
268 EXPECT_EQ(2U, MemMgr
->GetNumStubSlabs());
270 // And after much more, we should have three.
271 for (int I
= 0; I
< Iters
; ++I
)
272 MemMgr
->allocateStub(NULL
, Size
, 8);
273 EXPECT_EQ(3U, MemMgr
->GetNumStubSlabs());