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());
37 // Allocate the functions.
38 OwningPtr<Function> F1(makeFakeFunction());
40 uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
41 memset(FunctionBody1, 0xFF, 1024);
42 MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024);
43 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
45 OwningPtr<Function> F2(makeFakeFunction());
47 uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
48 memset(FunctionBody2, 0xFF, 1024);
49 MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024);
50 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
52 OwningPtr<Function> F3(makeFakeFunction());
54 uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
55 memset(FunctionBody3, 0xFF, 1024);
56 MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024);
57 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
59 // Deallocate them out of order, in case that matters.
60 MemMgr->deallocateFunctionBody(FunctionBody2);
61 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
62 MemMgr->deallocateFunctionBody(FunctionBody1);
63 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
64 MemMgr->deallocateFunctionBody(FunctionBody3);
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());
76 // Big functions are a little less than the largest block size.
77 const uintptr_t smallFuncSize = 1024;
78 const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() -
81 // Allocate big functions
82 OwningPtr<Function> F1(makeFakeFunction());
84 uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
85 ASSERT_LE(bigFuncSize, size);
86 memset(FunctionBody1, 0xFF, bigFuncSize);
87 MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize);
88 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
90 OwningPtr<Function> F2(makeFakeFunction());
92 uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
93 ASSERT_LE(bigFuncSize, size);
94 memset(FunctionBody2, 0xFF, bigFuncSize);
95 MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize);
96 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
98 OwningPtr<Function> F3(makeFakeFunction());
100 uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
101 ASSERT_LE(bigFuncSize, size);
102 memset(FunctionBody3, 0xFF, bigFuncSize);
103 MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize);
104 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
106 // Check that each large function took it's own slab.
107 EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
109 // Allocate small functions
110 OwningPtr<Function> F4(makeFakeFunction());
111 size = smallFuncSize;
112 uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size);
113 ASSERT_LE(smallFuncSize, size);
114 memset(FunctionBody4, 0xFF, smallFuncSize);
115 MemMgr->endFunctionBody(F4.get(), FunctionBody4,
116 FunctionBody4 + smallFuncSize);
117 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
119 OwningPtr<Function> F5(makeFakeFunction());
120 size = smallFuncSize;
121 uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size);
122 ASSERT_LE(smallFuncSize, size);
123 memset(FunctionBody5, 0xFF, smallFuncSize);
124 MemMgr->endFunctionBody(F5.get(), FunctionBody5,
125 FunctionBody5 + smallFuncSize);
126 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
128 OwningPtr<Function> F6(makeFakeFunction());
129 size = smallFuncSize;
130 uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size);
131 ASSERT_LE(smallFuncSize, size);
132 memset(FunctionBody6, 0xFF, smallFuncSize);
133 MemMgr->endFunctionBody(F6.get(), FunctionBody6,
134 FunctionBody6 + smallFuncSize);
135 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
137 // Check that the small functions didn't allocate any new slabs.
138 EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
140 // Deallocate them out of order, in case that matters.
141 MemMgr->deallocateFunctionBody(FunctionBody2);
142 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
143 MemMgr->deallocateFunctionBody(FunctionBody1);
144 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
145 MemMgr->deallocateFunctionBody(FunctionBody4);
146 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
147 MemMgr->deallocateFunctionBody(FunctionBody3);
148 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
149 MemMgr->deallocateFunctionBody(FunctionBody5);
150 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
151 MemMgr->deallocateFunctionBody(FunctionBody6);
152 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
155 // Allocate five global ints of varying widths and alignment, and check their
156 // alignment and overlap.
157 TEST(JITMemoryManagerTest, TestSmallGlobalInts) {
158 OwningPtr<JITMemoryManager> MemMgr(
159 JITMemoryManager::CreateDefaultMemManager());
160 uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 0);
161 uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2);
162 uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4);
163 uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8);
165 // Check the alignment.
166 EXPECT_EQ(0U, ((uintptr_t)b) & 0x1);
167 EXPECT_EQ(0U, ((uintptr_t)c) & 0x3);
168 EXPECT_EQ(0U, ((uintptr_t)d) & 0x7);
170 // Initialize them each one at a time and make sure they don't overlap.
175 EXPECT_EQ(0xffU, *a);
182 EXPECT_EQ(0xffffU, *b);
189 EXPECT_EQ(0xffffffffU, *c);
192 *d = 0xffffffffffffffffULL;
196 EXPECT_EQ(0xffffffffffffffffULL, *d);
198 // Make sure we didn't allocate any extra slabs for this tiny amount of data.
199 EXPECT_EQ(1U, MemMgr->GetNumDataSlabs());
202 // Allocate a small global, a big global, and a third global, and make sure we
203 // only use two slabs for that.
204 TEST(JITMemoryManagerTest, TestLargeGlobalArray) {
205 OwningPtr<JITMemoryManager> MemMgr(
206 JITMemoryManager::CreateDefaultMemManager());
207 size_t Size = 4 * MemMgr->GetDefaultDataSlabSize();
208 uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8);
209 uint8_t *g = MemMgr->allocateGlobal(Size, 8);
210 uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8);
212 // Check the alignment.
213 EXPECT_EQ(0U, ((uintptr_t)a) & 0x7);
214 EXPECT_EQ(0U, ((uintptr_t)g) & 0x7);
215 EXPECT_EQ(0U, ((uintptr_t)b) & 0x7);
217 // Initialize them to make sure we don't segfault and make sure they don't
220 memset(g, 0x2, Size);
222 EXPECT_EQ(0x0101010101010101ULL, *a);
223 // Just check the edges.
224 EXPECT_EQ(0x02U, g[0]);
225 EXPECT_EQ(0x02U, g[Size - 1]);
226 EXPECT_EQ(0x0303030303030303ULL, *b);
228 // Check the number of slabs.
229 EXPECT_EQ(2U, MemMgr->GetNumDataSlabs());
232 // Allocate lots of medium globals so that we can test moving the bump allocator
234 TEST(JITMemoryManagerTest, TestManyGlobals) {
235 OwningPtr<JITMemoryManager> MemMgr(
236 JITMemoryManager::CreateDefaultMemManager());
237 size_t SlabSize = MemMgr->GetDefaultDataSlabSize();
239 int Iters = (SlabSize / Size) + 1;
241 // We should start with one slab.
242 EXPECT_EQ(1U, MemMgr->GetNumDataSlabs());
244 // After allocating a bunch of globals, we should have two.
245 for (int I = 0; I < Iters; ++I)
246 MemMgr->allocateGlobal(Size, 8);
247 EXPECT_EQ(2U, MemMgr->GetNumDataSlabs());
249 // And after much more, we should have three.
250 for (int I = 0; I < Iters; ++I)
251 MemMgr->allocateGlobal(Size, 8);
252 EXPECT_EQ(3U, MemMgr->GetNumDataSlabs());
255 // Allocate lots of function stubs so that we can test moving the stub bump
256 // allocator to a new slab.
257 TEST(JITMemoryManagerTest, TestManyStubs) {
258 OwningPtr<JITMemoryManager> MemMgr(
259 JITMemoryManager::CreateDefaultMemManager());
260 size_t SlabSize = MemMgr->GetDefaultStubSlabSize();
262 int Iters = (SlabSize / Size) + 1;
264 // We should start with one slab.
265 EXPECT_EQ(1U, MemMgr->GetNumStubSlabs());
267 // After allocating a bunch of stubs, we should have two.
268 for (int I = 0; I < Iters; ++I)
269 MemMgr->allocateStub(NULL, Size, 8);
270 EXPECT_EQ(2U, MemMgr->GetNumStubSlabs());
272 // And after much more, we should have three.
273 for (int I = 0; I < Iters; ++I)
274 MemMgr->allocateStub(NULL, Size, 8);
275 EXPECT_EQ(3U, MemMgr->GetNumStubSlabs());