1 //===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/JITMemoryManager.h" 11 #include "llvm/ADT/ArrayRef.h" 12 #include "llvm/IR/DerivedTypes.h" 13 #include "llvm/IR/Function.h" 14 #include "llvm/IR/GlobalValue.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 20 namespace { 21 22 Function *makeFakeFunction() { 23 std::vector<Type*> params; 24 FunctionType *FTy = 25 FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); 26 return Function::Create(FTy, GlobalValue::ExternalLinkage); 27 } 28 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 31 // function bodies. 32 TEST(JITMemoryManagerTest, NoAllocations) { 33 std::unique_ptr<JITMemoryManager> MemMgr( 34 JITMemoryManager::CreateDefaultMemManager()); 35 uintptr_t size; 36 std::string Error; 37 38 // Allocate the functions. 39 std::unique_ptr<Function> F1(makeFakeFunction()); 40 size = 1024; 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; 45 46 std::unique_ptr<Function> F2(makeFakeFunction()); 47 size = 1024; 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; 52 53 std::unique_ptr<Function> F3(makeFakeFunction()); 54 size = 1024; 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; 59 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; 67 } 68 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 std::unique_ptr<JITMemoryManager> MemMgr( 73 JITMemoryManager::CreateDefaultMemManager()); 74 uintptr_t size; 75 std::string Error; 76 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() - 80 smallFuncSize * 2); 81 82 // Allocate big functions 83 std::unique_ptr<Function> F1(makeFakeFunction()); 84 size = bigFuncSize; 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; 90 91 std::unique_ptr<Function> F2(makeFakeFunction()); 92 size = bigFuncSize; 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; 98 99 std::unique_ptr<Function> F3(makeFakeFunction()); 100 size = bigFuncSize; 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; 106 107 // Check that each large function took it's own slab. 108 EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); 109 110 // Allocate small functions 111 std::unique_ptr<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; 119 120 std::unique_ptr<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; 128 129 std::unique_ptr<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; 137 138 // Check that the small functions didn't allocate any new slabs. 139 EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); 140 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; 154 } 155 156 // Allocate five global ints of varying widths and alignment, and check their 157 // alignment and overlap. 158 TEST(JITMemoryManagerTest, TestSmallGlobalInts) { 159 std::unique_ptr<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); 165 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); 170 171 // Initialize them each one at a time and make sure they don't overlap. 172 *a = 0xff; 173 *b = 0U; 174 *c = 0U; 175 *d = 0U; 176 EXPECT_EQ(0xffU, *a); 177 EXPECT_EQ(0U, *b); 178 EXPECT_EQ(0U, *c); 179 EXPECT_EQ(0U, *d); 180 *a = 0U; 181 *b = 0xffffU; 182 EXPECT_EQ(0U, *a); 183 EXPECT_EQ(0xffffU, *b); 184 EXPECT_EQ(0U, *c); 185 EXPECT_EQ(0U, *d); 186 *b = 0U; 187 *c = 0xffffffffU; 188 EXPECT_EQ(0U, *a); 189 EXPECT_EQ(0U, *b); 190 EXPECT_EQ(0xffffffffU, *c); 191 EXPECT_EQ(0U, *d); 192 *c = 0U; 193 *d = 0xffffffffffffffffULL; 194 EXPECT_EQ(0U, *a); 195 EXPECT_EQ(0U, *b); 196 EXPECT_EQ(0U, *c); 197 EXPECT_EQ(0xffffffffffffffffULL, *d); 198 199 // Make sure we didn't allocate any extra slabs for this tiny amount of data. 200 EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); 201 } 202 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 std::unique_ptr<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); 212 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); 217 218 // Initialize them to make sure we don't segfault and make sure they don't 219 // overlap. 220 memset(a, 0x1, 8); 221 memset(g, 0x2, Size); 222 memset(b, 0x3, 8); 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); 228 229 // Check the number of slabs. 230 EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); 231 } 232 233 // Allocate lots of medium globals so that we can test moving the bump allocator 234 // to a new slab. 235 TEST(JITMemoryManagerTest, TestManyGlobals) { 236 std::unique_ptr<JITMemoryManager> MemMgr( 237 JITMemoryManager::CreateDefaultMemManager()); 238 size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); 239 size_t Size = 128; 240 int Iters = (SlabSize / Size) + 1; 241 242 // We should start with no slabs. 243 EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); 244 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()); 249 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()); 254 } 255 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 std::unique_ptr<JITMemoryManager> MemMgr( 260 JITMemoryManager::CreateDefaultMemManager()); 261 size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); 262 size_t Size = 128; 263 int Iters = (SlabSize / Size) + 1; 264 265 // We should start with no slabs. 266 EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); 267 268 // After allocating a bunch of stubs, we should have two. 269 for (int I = 0; I < Iters; ++I) 270 MemMgr->allocateStub(nullptr, Size, 8); 271 EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); 272 273 // And after much more, we should have three. 274 for (int I = 0; I < Iters; ++I) 275 MemMgr->allocateStub(nullptr, Size, 8); 276 EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); 277 } 278 279 // Check section allocation and alignment 280 TEST(JITMemoryManagerTest, AllocateSection) { 281 std::unique_ptr<JITMemoryManager> MemMgr( 282 JITMemoryManager::CreateDefaultMemManager()); 283 uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); 284 uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); 285 uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef()); 286 uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); 287 uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); 288 289 EXPECT_NE((uint8_t*)nullptr, code1); 290 EXPECT_NE((uint8_t*)nullptr, code2); 291 EXPECT_NE((uint8_t*)nullptr, data1); 292 EXPECT_NE((uint8_t*)nullptr, data2); 293 294 // Check alignment 295 EXPECT_EQ((uint64_t)code1 & 0xf, 0u); 296 EXPECT_EQ((uint64_t)code2 & 0x1f, 0u); 297 EXPECT_EQ((uint64_t)code3 & 0x3f, 0u); 298 EXPECT_EQ((uint64_t)data1 & 0xf, 0u); 299 EXPECT_EQ((uint64_t)data2 & 0x3f, 0u); 300 } 301 302 } 303