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"
22 Function
*makeFakeFunction() {
23 std::vector
<const Type
*> params
;
24 const FunctionType
*FTy
=
25 FunctionType::get(Type::getVoidTy(getGlobalContext()), params
, false);
26 return Function::Create(FTy
, GlobalValue::ExternalLinkage
);
29 // Allocate three simple functions that fit in the initial slab. This exercises
30 // the code in the case that we don't have to allocate more memory to store the
32 TEST(JITMemoryManagerTest
, NoAllocations
) {
33 OwningPtr
<JITMemoryManager
> MemMgr(
34 JITMemoryManager::CreateDefaultMemManager());
38 // Allocate the functions.
39 OwningPtr
<Function
> F1(makeFakeFunction());
41 uint8_t *FunctionBody1
= MemMgr
->startFunctionBody(F1
.get(), size
);
42 memset(FunctionBody1
, 0xFF, 1024);
43 MemMgr
->endFunctionBody(F1
.get(), FunctionBody1
, FunctionBody1
+ 1024);
44 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
46 OwningPtr
<Function
> F2(makeFakeFunction());
48 uint8_t *FunctionBody2
= MemMgr
->startFunctionBody(F2
.get(), size
);
49 memset(FunctionBody2
, 0xFF, 1024);
50 MemMgr
->endFunctionBody(F2
.get(), FunctionBody2
, FunctionBody2
+ 1024);
51 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
53 OwningPtr
<Function
> F3(makeFakeFunction());
55 uint8_t *FunctionBody3
= MemMgr
->startFunctionBody(F3
.get(), size
);
56 memset(FunctionBody3
, 0xFF, 1024);
57 MemMgr
->endFunctionBody(F3
.get(), FunctionBody3
, FunctionBody3
+ 1024);
58 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
60 // Deallocate them out of order, in case that matters.
61 MemMgr
->deallocateFunctionBody(FunctionBody2
);
62 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
63 MemMgr
->deallocateFunctionBody(FunctionBody1
);
64 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
65 MemMgr
->deallocateFunctionBody(FunctionBody3
);
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());
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 uint8_t *FunctionBody1
= MemMgr
->startFunctionBody(F1
.get(), size
);
86 ASSERT_LE(bigFuncSize
, size
);
87 memset(FunctionBody1
, 0xFF, bigFuncSize
);
88 MemMgr
->endFunctionBody(F1
.get(), FunctionBody1
, FunctionBody1
+ bigFuncSize
);
89 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
91 OwningPtr
<Function
> F2(makeFakeFunction());
93 uint8_t *FunctionBody2
= MemMgr
->startFunctionBody(F2
.get(), size
);
94 ASSERT_LE(bigFuncSize
, size
);
95 memset(FunctionBody2
, 0xFF, bigFuncSize
);
96 MemMgr
->endFunctionBody(F2
.get(), FunctionBody2
, FunctionBody2
+ bigFuncSize
);
97 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
99 OwningPtr
<Function
> F3(makeFakeFunction());
101 uint8_t *FunctionBody3
= MemMgr
->startFunctionBody(F3
.get(), size
);
102 ASSERT_LE(bigFuncSize
, size
);
103 memset(FunctionBody3
, 0xFF, bigFuncSize
);
104 MemMgr
->endFunctionBody(F3
.get(), FunctionBody3
, FunctionBody3
+ 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 uint8_t *FunctionBody4
= MemMgr
->startFunctionBody(F4
.get(), size
);
114 ASSERT_LE(smallFuncSize
, size
);
115 memset(FunctionBody4
, 0xFF, smallFuncSize
);
116 MemMgr
->endFunctionBody(F4
.get(), FunctionBody4
,
117 FunctionBody4
+ smallFuncSize
);
118 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
120 OwningPtr
<Function
> F5(makeFakeFunction());
121 size
= smallFuncSize
;
122 uint8_t *FunctionBody5
= MemMgr
->startFunctionBody(F5
.get(), size
);
123 ASSERT_LE(smallFuncSize
, size
);
124 memset(FunctionBody5
, 0xFF, smallFuncSize
);
125 MemMgr
->endFunctionBody(F5
.get(), FunctionBody5
,
126 FunctionBody5
+ smallFuncSize
);
127 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
129 OwningPtr
<Function
> F6(makeFakeFunction());
130 size
= smallFuncSize
;
131 uint8_t *FunctionBody6
= MemMgr
->startFunctionBody(F6
.get(), size
);
132 ASSERT_LE(smallFuncSize
, size
);
133 memset(FunctionBody6
, 0xFF, smallFuncSize
);
134 MemMgr
->endFunctionBody(F6
.get(), FunctionBody6
,
135 FunctionBody6
+ smallFuncSize
);
136 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
138 // Check that the small functions didn't allocate any new slabs.
139 EXPECT_EQ(3U, MemMgr
->GetNumCodeSlabs());
141 // Deallocate them out of order, in case that matters.
142 MemMgr
->deallocateFunctionBody(FunctionBody2
);
143 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
144 MemMgr
->deallocateFunctionBody(FunctionBody1
);
145 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
146 MemMgr
->deallocateFunctionBody(FunctionBody4
);
147 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
148 MemMgr
->deallocateFunctionBody(FunctionBody3
);
149 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
150 MemMgr
->deallocateFunctionBody(FunctionBody5
);
151 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
152 MemMgr
->deallocateFunctionBody(FunctionBody6
);
153 EXPECT_TRUE(MemMgr
->CheckInvariants(Error
)) << Error
;
156 // Allocate five global ints of varying widths and alignment, and check their
157 // alignment and overlap.
158 TEST(JITMemoryManagerTest
, TestSmallGlobalInts
) {
159 OwningPtr
<JITMemoryManager
> MemMgr(
160 JITMemoryManager::CreateDefaultMemManager());
161 uint8_t *a
= (uint8_t *)MemMgr
->allocateGlobal(8, 0);
162 uint16_t *b
= (uint16_t*)MemMgr
->allocateGlobal(16, 2);
163 uint32_t *c
= (uint32_t*)MemMgr
->allocateGlobal(32, 4);
164 uint64_t *d
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
166 // Check the alignment.
167 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x1);
168 EXPECT_EQ(0U, ((uintptr_t)c
) & 0x3);
169 EXPECT_EQ(0U, ((uintptr_t)d
) & 0x7);
171 // Initialize them each one at a time and make sure they don't overlap.
176 EXPECT_EQ(0xffU
, *a
);
183 EXPECT_EQ(0xffffU
, *b
);
190 EXPECT_EQ(0xffffffffU
, *c
);
193 *d
= 0xffffffffffffffffULL
;
197 EXPECT_EQ(0xffffffffffffffffULL
, *d
);
199 // Make sure we didn't allocate any extra slabs for this tiny amount of data.
200 EXPECT_EQ(1U, MemMgr
->GetNumDataSlabs());
203 // Allocate a small global, a big global, and a third global, and make sure we
204 // only use two slabs for that.
205 TEST(JITMemoryManagerTest
, TestLargeGlobalArray
) {
206 OwningPtr
<JITMemoryManager
> MemMgr(
207 JITMemoryManager::CreateDefaultMemManager());
208 size_t Size
= 4 * MemMgr
->GetDefaultDataSlabSize();
209 uint64_t *a
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
210 uint8_t *g
= MemMgr
->allocateGlobal(Size
, 8);
211 uint64_t *b
= (uint64_t*)MemMgr
->allocateGlobal(64, 8);
213 // Check the alignment.
214 EXPECT_EQ(0U, ((uintptr_t)a
) & 0x7);
215 EXPECT_EQ(0U, ((uintptr_t)g
) & 0x7);
216 EXPECT_EQ(0U, ((uintptr_t)b
) & 0x7);
218 // Initialize them to make sure we don't segfault and make sure they don't
221 memset(g
, 0x2, Size
);
223 EXPECT_EQ(0x0101010101010101ULL
, *a
);
224 // Just check the edges.
225 EXPECT_EQ(0x02U
, g
[0]);
226 EXPECT_EQ(0x02U
, g
[Size
- 1]);
227 EXPECT_EQ(0x0303030303030303ULL
, *b
);
229 // Check the number of slabs.
230 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
233 // Allocate lots of medium globals so that we can test moving the bump allocator
235 TEST(JITMemoryManagerTest
, TestManyGlobals
) {
236 OwningPtr
<JITMemoryManager
> MemMgr(
237 JITMemoryManager::CreateDefaultMemManager());
238 size_t SlabSize
= MemMgr
->GetDefaultDataSlabSize();
240 int Iters
= (SlabSize
/ Size
) + 1;
242 // We should start with no slabs.
243 EXPECT_EQ(0U, MemMgr
->GetNumDataSlabs());
245 // After allocating a bunch of globals, we should have two.
246 for (int I
= 0; I
< Iters
; ++I
)
247 MemMgr
->allocateGlobal(Size
, 8);
248 EXPECT_EQ(2U, MemMgr
->GetNumDataSlabs());
250 // And after much more, we should have three.
251 for (int I
= 0; I
< Iters
; ++I
)
252 MemMgr
->allocateGlobal(Size
, 8);
253 EXPECT_EQ(3U, MemMgr
->GetNumDataSlabs());
256 // Allocate lots of function stubs so that we can test moving the stub bump
257 // allocator to a new slab.
258 TEST(JITMemoryManagerTest
, TestManyStubs
) {
259 OwningPtr
<JITMemoryManager
> MemMgr(
260 JITMemoryManager::CreateDefaultMemManager());
261 size_t SlabSize
= MemMgr
->GetDefaultStubSlabSize();
263 int Iters
= (SlabSize
/ Size
) + 1;
265 // We should start with no slabs.
266 EXPECT_EQ(0U, MemMgr
->GetNumDataSlabs());
268 // After allocating a bunch of stubs, we should have two.
269 for (int I
= 0; I
< Iters
; ++I
)
270 MemMgr
->allocateStub(NULL
, Size
, 8);
271 EXPECT_EQ(2U, MemMgr
->GetNumStubSlabs());
273 // And after much more, we should have three.
274 for (int I
= 0; I
< Iters
; ++I
)
275 MemMgr
->allocateStub(NULL
, Size
, 8);
276 EXPECT_EQ(3U, MemMgr
->GetNumStubSlabs());