Home | History | Annotate | Download | only in JIT
      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