JITMemoryManager.cpp revision 96c96b46e962c801c610ba878751d8c0ee1359c9
1//===-- JITMemoryManager.cpp - Memory Allocator for JIT'd code ------------===// 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// This file defines the DefaultJITMemoryManager class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "llvm/GlobalValue.h" 15#include "llvm/ExecutionEngine/JITMemoryManager.h" 16#include "llvm/Support/Compiler.h" 17#include "llvm/System/Memory.h" 18#include <map> 19#include <vector> 20#include <cassert> 21#include <cstdio> 22#include <cstdlib> 23#include <cstring> 24using namespace llvm; 25 26 27JITMemoryManager::~JITMemoryManager() {} 28 29//===----------------------------------------------------------------------===// 30// Memory Block Implementation. 31//===----------------------------------------------------------------------===// 32 33namespace { 34 /// MemoryRangeHeader - For a range of memory, this is the header that we put 35 /// on the block of memory. It is carefully crafted to be one word of memory. 36 /// Allocated blocks have just this header, free'd blocks have FreeRangeHeader 37 /// which starts with this. 38 struct FreeRangeHeader; 39 struct MemoryRangeHeader { 40 /// ThisAllocated - This is true if this block is currently allocated. If 41 /// not, this can be converted to a FreeRangeHeader. 42 unsigned ThisAllocated : 1; 43 44 /// PrevAllocated - Keep track of whether the block immediately before us is 45 /// allocated. If not, the word immediately before this header is the size 46 /// of the previous block. 47 unsigned PrevAllocated : 1; 48 49 /// BlockSize - This is the size in bytes of this memory block, 50 /// including this header. 51 uintptr_t BlockSize : (sizeof(intptr_t)*8 - 2); 52 53 54 /// getBlockAfter - Return the memory block immediately after this one. 55 /// 56 MemoryRangeHeader &getBlockAfter() const { 57 return *(MemoryRangeHeader*)((char*)this+BlockSize); 58 } 59 60 /// getFreeBlockBefore - If the block before this one is free, return it, 61 /// otherwise return null. 62 FreeRangeHeader *getFreeBlockBefore() const { 63 if (PrevAllocated) return 0; 64 intptr_t PrevSize = ((intptr_t *)this)[-1]; 65 return (FreeRangeHeader*)((char*)this-PrevSize); 66 } 67 68 /// FreeBlock - Turn an allocated block into a free block, adjusting 69 /// bits in the object headers, and adding an end of region memory block. 70 FreeRangeHeader *FreeBlock(FreeRangeHeader *FreeList); 71 72 /// TrimAllocationToSize - If this allocated block is significantly larger 73 /// than NewSize, split it into two pieces (where the former is NewSize 74 /// bytes, including the header), and add the new block to the free list. 75 FreeRangeHeader *TrimAllocationToSize(FreeRangeHeader *FreeList, 76 uint64_t NewSize); 77 }; 78 79 /// FreeRangeHeader - For a memory block that isn't already allocated, this 80 /// keeps track of the current block and has a pointer to the next free block. 81 /// Free blocks are kept on a circularly linked list. 82 struct FreeRangeHeader : public MemoryRangeHeader { 83 FreeRangeHeader *Prev; 84 FreeRangeHeader *Next; 85 86 /// getMinBlockSize - Get the minimum size for a memory block. Blocks 87 /// smaller than this size cannot be created. 88 static unsigned getMinBlockSize() { 89 return sizeof(FreeRangeHeader)+sizeof(intptr_t); 90 } 91 92 /// SetEndOfBlockSizeMarker - The word at the end of every free block is 93 /// known to be the size of the free block. Set it for this block. 94 void SetEndOfBlockSizeMarker() { 95 void *EndOfBlock = (char*)this + BlockSize; 96 ((intptr_t *)EndOfBlock)[-1] = BlockSize; 97 } 98 99 FreeRangeHeader *RemoveFromFreeList() { 100 assert(Next->Prev == this && Prev->Next == this && "Freelist broken!"); 101 Next->Prev = Prev; 102 return Prev->Next = Next; 103 } 104 105 void AddToFreeList(FreeRangeHeader *FreeList) { 106 Next = FreeList; 107 Prev = FreeList->Prev; 108 Prev->Next = this; 109 Next->Prev = this; 110 } 111 112 /// GrowBlock - The block after this block just got deallocated. Merge it 113 /// into the current block. 114 void GrowBlock(uintptr_t NewSize); 115 116 /// AllocateBlock - Mark this entire block allocated, updating freelists 117 /// etc. This returns a pointer to the circular free-list. 118 FreeRangeHeader *AllocateBlock(); 119 }; 120} 121 122 123/// AllocateBlock - Mark this entire block allocated, updating freelists 124/// etc. This returns a pointer to the circular free-list. 125FreeRangeHeader *FreeRangeHeader::AllocateBlock() { 126 assert(!ThisAllocated && !getBlockAfter().PrevAllocated && 127 "Cannot allocate an allocated block!"); 128 // Mark this block allocated. 129 ThisAllocated = 1; 130 getBlockAfter().PrevAllocated = 1; 131 132 // Remove it from the free list. 133 return RemoveFromFreeList(); 134} 135 136/// FreeBlock - Turn an allocated block into a free block, adjusting 137/// bits in the object headers, and adding an end of region memory block. 138/// If possible, coalesce this block with neighboring blocks. Return the 139/// FreeRangeHeader to allocate from. 140FreeRangeHeader *MemoryRangeHeader::FreeBlock(FreeRangeHeader *FreeList) { 141 MemoryRangeHeader *FollowingBlock = &getBlockAfter(); 142 assert(ThisAllocated && "This block is already allocated!"); 143 assert(FollowingBlock->PrevAllocated && "Flags out of sync!"); 144 145 FreeRangeHeader *FreeListToReturn = FreeList; 146 147 // If the block after this one is free, merge it into this block. 148 if (!FollowingBlock->ThisAllocated) { 149 FreeRangeHeader &FollowingFreeBlock = *(FreeRangeHeader *)FollowingBlock; 150 // "FreeList" always needs to be a valid free block. If we're about to 151 // coalesce with it, update our notion of what the free list is. 152 if (&FollowingFreeBlock == FreeList) { 153 FreeList = FollowingFreeBlock.Next; 154 FreeListToReturn = 0; 155 assert(&FollowingFreeBlock != FreeList && "No tombstone block?"); 156 } 157 FollowingFreeBlock.RemoveFromFreeList(); 158 159 // Include the following block into this one. 160 BlockSize += FollowingFreeBlock.BlockSize; 161 FollowingBlock = &FollowingFreeBlock.getBlockAfter(); 162 163 // Tell the block after the block we are coalescing that this block is 164 // allocated. 165 FollowingBlock->PrevAllocated = 1; 166 } 167 168 assert(FollowingBlock->ThisAllocated && "Missed coalescing?"); 169 170 if (FreeRangeHeader *PrevFreeBlock = getFreeBlockBefore()) { 171 PrevFreeBlock->GrowBlock(PrevFreeBlock->BlockSize + BlockSize); 172 return FreeListToReturn ? FreeListToReturn : PrevFreeBlock; 173 } 174 175 // Otherwise, mark this block free. 176 FreeRangeHeader &FreeBlock = *(FreeRangeHeader*)this; 177 FollowingBlock->PrevAllocated = 0; 178 FreeBlock.ThisAllocated = 0; 179 180 // Link this into the linked list of free blocks. 181 FreeBlock.AddToFreeList(FreeList); 182 183 // Add a marker at the end of the block, indicating the size of this free 184 // block. 185 FreeBlock.SetEndOfBlockSizeMarker(); 186 return FreeListToReturn ? FreeListToReturn : &FreeBlock; 187} 188 189/// GrowBlock - The block after this block just got deallocated. Merge it 190/// into the current block. 191void FreeRangeHeader::GrowBlock(uintptr_t NewSize) { 192 assert(NewSize > BlockSize && "Not growing block?"); 193 BlockSize = NewSize; 194 SetEndOfBlockSizeMarker(); 195 getBlockAfter().PrevAllocated = 0; 196} 197 198/// TrimAllocationToSize - If this allocated block is significantly larger 199/// than NewSize, split it into two pieces (where the former is NewSize 200/// bytes, including the header), and add the new block to the free list. 201FreeRangeHeader *MemoryRangeHeader:: 202TrimAllocationToSize(FreeRangeHeader *FreeList, uint64_t NewSize) { 203 assert(ThisAllocated && getBlockAfter().PrevAllocated && 204 "Cannot deallocate part of an allocated block!"); 205 206 // Don't allow blocks to be trimmed below minimum required size 207 NewSize = std::max<uint64_t>(FreeRangeHeader::getMinBlockSize(), NewSize); 208 209 // Round up size for alignment of header. 210 unsigned HeaderAlign = __alignof(FreeRangeHeader); 211 NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1); 212 213 // Size is now the size of the block we will remove from the start of the 214 // current block. 215 assert(NewSize <= BlockSize && 216 "Allocating more space from this block than exists!"); 217 218 // If splitting this block will cause the remainder to be too small, do not 219 // split the block. 220 if (BlockSize <= NewSize+FreeRangeHeader::getMinBlockSize()) 221 return FreeList; 222 223 // Otherwise, we splice the required number of bytes out of this block, form 224 // a new block immediately after it, then mark this block allocated. 225 MemoryRangeHeader &FormerNextBlock = getBlockAfter(); 226 227 // Change the size of this block. 228 BlockSize = NewSize; 229 230 // Get the new block we just sliced out and turn it into a free block. 231 FreeRangeHeader &NewNextBlock = (FreeRangeHeader &)getBlockAfter(); 232 NewNextBlock.BlockSize = (char*)&FormerNextBlock - (char*)&NewNextBlock; 233 NewNextBlock.ThisAllocated = 0; 234 NewNextBlock.PrevAllocated = 1; 235 NewNextBlock.SetEndOfBlockSizeMarker(); 236 FormerNextBlock.PrevAllocated = 0; 237 NewNextBlock.AddToFreeList(FreeList); 238 return &NewNextBlock; 239} 240 241//===----------------------------------------------------------------------===// 242// Memory Block Implementation. 243//===----------------------------------------------------------------------===// 244 245namespace { 246 /// DefaultJITMemoryManager - Manage memory for the JIT code generation. 247 /// This splits a large block of MAP_NORESERVE'd memory into two 248 /// sections, one for function stubs, one for the functions themselves. We 249 /// have to do this because we may need to emit a function stub while in the 250 /// middle of emitting a function, and we don't know how large the function we 251 /// are emitting is. 252 class VISIBILITY_HIDDEN DefaultJITMemoryManager : public JITMemoryManager { 253 std::vector<sys::MemoryBlock> Blocks; // Memory blocks allocated by the JIT 254 FreeRangeHeader *FreeMemoryList; // Circular list of free blocks. 255 256 // When emitting code into a memory block, this is the block. 257 MemoryRangeHeader *CurBlock; 258 259 unsigned char *CurStubPtr, *StubBase; 260 unsigned char *GOTBase; // Target Specific reserved memory 261 void *DlsymTable; // Stub external symbol information 262 263 // Centralize memory block allocation. 264 sys::MemoryBlock getNewMemoryBlock(unsigned size); 265 266 std::map<const Function*, MemoryRangeHeader*> FunctionBlocks; 267 std::map<const Function*, MemoryRangeHeader*> TableBlocks; 268 public: 269 DefaultJITMemoryManager(); 270 ~DefaultJITMemoryManager(); 271 272 void AllocateGOT(); 273 void SetDlsymTable(void *); 274 275 unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize, 276 unsigned Alignment); 277 278 /// startFunctionBody - When a function starts, allocate a block of free 279 /// executable memory, returning a pointer to it and its actual size. 280 unsigned char *startFunctionBody(const Function *F, uintptr_t &ActualSize) { 281 282 FreeRangeHeader* candidateBlock = FreeMemoryList; 283 FreeRangeHeader* head = FreeMemoryList; 284 FreeRangeHeader* iter = head->Next; 285 286 uintptr_t largest = candidateBlock->BlockSize; 287 288 // Search for the largest free block 289 while (iter != head) { 290 if (iter->BlockSize > largest) { 291 largest = iter->BlockSize; 292 candidateBlock = iter; 293 } 294 iter = iter->Next; 295 } 296 297 // Select this candidate block for allocation 298 CurBlock = candidateBlock; 299 300 // Allocate the entire memory block. 301 FreeMemoryList = candidateBlock->AllocateBlock(); 302 ActualSize = CurBlock->BlockSize-sizeof(MemoryRangeHeader); 303 return (unsigned char *)(CurBlock+1); 304 } 305 306 /// endFunctionBody - The function F is now allocated, and takes the memory 307 /// in the range [FunctionStart,FunctionEnd). 308 void endFunctionBody(const Function *F, unsigned char *FunctionStart, 309 unsigned char *FunctionEnd) { 310 assert(FunctionEnd > FunctionStart); 311 assert(FunctionStart == (unsigned char *)(CurBlock+1) && 312 "Mismatched function start/end!"); 313 314 uintptr_t BlockSize = FunctionEnd - (unsigned char *)CurBlock; 315 FunctionBlocks[F] = CurBlock; 316 317 // Release the memory at the end of this block that isn't needed. 318 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); 319 } 320 321 /// allocateSpace - Allocate a memory block of the given size. 322 unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) { 323 CurBlock = FreeMemoryList; 324 FreeMemoryList = FreeMemoryList->AllocateBlock(); 325 326 unsigned char *result = (unsigned char *)CurBlock+1; 327 328 if (Alignment == 0) Alignment = 1; 329 result = (unsigned char*)(((intptr_t)result+Alignment-1) & 330 ~(intptr_t)(Alignment-1)); 331 332 uintptr_t BlockSize = result + Size - (unsigned char *)CurBlock; 333 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); 334 335 return result; 336 } 337 338 /// startExceptionTable - Use startFunctionBody to allocate memory for the 339 /// function's exception table. 340 unsigned char* startExceptionTable(const Function* F, 341 uintptr_t &ActualSize) { 342 return startFunctionBody(F, ActualSize); 343 } 344 345 /// endExceptionTable - The exception table of F is now allocated, 346 /// and takes the memory in the range [TableStart,TableEnd). 347 void endExceptionTable(const Function *F, unsigned char *TableStart, 348 unsigned char *TableEnd, 349 unsigned char* FrameRegister) { 350 assert(TableEnd > TableStart); 351 assert(TableStart == (unsigned char *)(CurBlock+1) && 352 "Mismatched table start/end!"); 353 354 uintptr_t BlockSize = TableEnd - (unsigned char *)CurBlock; 355 TableBlocks[F] = CurBlock; 356 357 // Release the memory at the end of this block that isn't needed. 358 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize); 359 } 360 361 unsigned char *getGOTBase() const { 362 return GOTBase; 363 } 364 365 void *getDlsymTable() const { 366 return DlsymTable; 367 } 368 369 /// deallocateMemForFunction - Deallocate all memory for the specified 370 /// function body. 371 void deallocateMemForFunction(const Function *F) { 372 std::map<const Function*, MemoryRangeHeader*>::iterator 373 I = FunctionBlocks.find(F); 374 if (I == FunctionBlocks.end()) return; 375 376 // Find the block that is allocated for this function. 377 MemoryRangeHeader *MemRange = I->second; 378 assert(MemRange->ThisAllocated && "Block isn't allocated!"); 379 380 // Fill the buffer with garbage! 381#ifndef NDEBUG 382 memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange)); 383#endif 384 385 // Free the memory. 386 FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); 387 388 // Finally, remove this entry from FunctionBlocks. 389 FunctionBlocks.erase(I); 390 391 I = TableBlocks.find(F); 392 if (I == TableBlocks.end()) return; 393 394 // Find the block that is allocated for this function. 395 MemRange = I->second; 396 assert(MemRange->ThisAllocated && "Block isn't allocated!"); 397 398 // Fill the buffer with garbage! 399#ifndef NDEBUG 400 memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange)); 401#endif 402 403 // Free the memory. 404 FreeMemoryList = MemRange->FreeBlock(FreeMemoryList); 405 406 // Finally, remove this entry from TableBlocks. 407 TableBlocks.erase(I); 408 } 409 410 /// setMemoryWritable - When code generation is in progress, 411 /// the code pages may need permissions changed. 412 void setMemoryWritable(void) 413 { 414 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) 415 sys::Memory::setWritable(Blocks[i]); 416 } 417 /// setMemoryExecutable - When code generation is done and we're ready to 418 /// start execution, the code pages may need permissions changed. 419 void setMemoryExecutable(void) 420 { 421 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) 422 sys::Memory::setExecutable(Blocks[i]); 423 } 424 }; 425} 426 427DefaultJITMemoryManager::DefaultJITMemoryManager() { 428 // Allocate a 16M block of memory for functions. 429#if defined(__APPLE__) && defined(__arm__) 430 sys::MemoryBlock MemBlock = getNewMemoryBlock(4 << 20); 431#else 432 sys::MemoryBlock MemBlock = getNewMemoryBlock(16 << 20); 433#endif 434 435 unsigned char *MemBase = static_cast<unsigned char*>(MemBlock.base()); 436 437 // Allocate stubs backwards from the base, allocate functions forward 438 // from the base. 439 StubBase = MemBase; 440 CurStubPtr = MemBase + 512*1024; // Use 512k for stubs, working backwards. 441 442 // We set up the memory chunk with 4 mem regions, like this: 443 // [ START 444 // [ Free #0 ] -> Large space to allocate functions from. 445 // [ Allocated #1 ] -> Tiny space to separate regions. 446 // [ Free #2 ] -> Tiny space so there is always at least 1 free block. 447 // [ Allocated #3 ] -> Tiny space to prevent looking past end of block. 448 // END ] 449 // 450 // The last three blocks are never deallocated or touched. 451 452 // Add MemoryRangeHeader to the end of the memory region, indicating that 453 // the space after the block of memory is allocated. This is block #3. 454 MemoryRangeHeader *Mem3 = (MemoryRangeHeader*)(MemBase+MemBlock.size())-1; 455 Mem3->ThisAllocated = 1; 456 Mem3->PrevAllocated = 0; 457 Mem3->BlockSize = 0; 458 459 /// Add a tiny free region so that the free list always has one entry. 460 FreeRangeHeader *Mem2 = 461 (FreeRangeHeader *)(((char*)Mem3)-FreeRangeHeader::getMinBlockSize()); 462 Mem2->ThisAllocated = 0; 463 Mem2->PrevAllocated = 1; 464 Mem2->BlockSize = FreeRangeHeader::getMinBlockSize(); 465 Mem2->SetEndOfBlockSizeMarker(); 466 Mem2->Prev = Mem2; // Mem2 *is* the free list for now. 467 Mem2->Next = Mem2; 468 469 /// Add a tiny allocated region so that Mem2 is never coalesced away. 470 MemoryRangeHeader *Mem1 = (MemoryRangeHeader*)Mem2-1; 471 Mem1->ThisAllocated = 1; 472 Mem1->PrevAllocated = 0; 473 Mem1->BlockSize = (char*)Mem2 - (char*)Mem1; 474 475 // Add a FreeRangeHeader to the start of the function body region, indicating 476 // that the space is free. Mark the previous block allocated so we never look 477 // at it. 478 FreeRangeHeader *Mem0 = (FreeRangeHeader*)CurStubPtr; 479 Mem0->ThisAllocated = 0; 480 Mem0->PrevAllocated = 1; 481 Mem0->BlockSize = (char*)Mem1-(char*)Mem0; 482 Mem0->SetEndOfBlockSizeMarker(); 483 Mem0->AddToFreeList(Mem2); 484 485 // Start out with the freelist pointing to Mem0. 486 FreeMemoryList = Mem0; 487 488 GOTBase = NULL; 489 DlsymTable = NULL; 490} 491 492void DefaultJITMemoryManager::AllocateGOT() { 493 assert(GOTBase == 0 && "Cannot allocate the got multiple times"); 494 GOTBase = new unsigned char[sizeof(void*) * 8192]; 495 HasGOT = true; 496} 497 498void DefaultJITMemoryManager::SetDlsymTable(void *ptr) { 499 DlsymTable = ptr; 500} 501 502DefaultJITMemoryManager::~DefaultJITMemoryManager() { 503 for (unsigned i = 0, e = Blocks.size(); i != e; ++i) 504 sys::Memory::ReleaseRWX(Blocks[i]); 505 506 delete[] GOTBase; 507 Blocks.clear(); 508} 509 510unsigned char *DefaultJITMemoryManager::allocateStub(const GlobalValue* F, 511 unsigned StubSize, 512 unsigned Alignment) { 513 CurStubPtr -= StubSize; 514 CurStubPtr = (unsigned char*)(((intptr_t)CurStubPtr) & 515 ~(intptr_t)(Alignment-1)); 516 if (CurStubPtr < StubBase) { 517 // FIXME: allocate a new block 518 fprintf(stderr, "JIT ran out of memory for function stubs!\n"); 519 abort(); 520 } 521 return CurStubPtr; 522} 523 524sys::MemoryBlock DefaultJITMemoryManager::getNewMemoryBlock(unsigned size) { 525 // Allocate a new block close to the last one. 526 const sys::MemoryBlock *BOld = Blocks.empty() ? 0 : &Blocks.front(); 527 std::string ErrMsg; 528 sys::MemoryBlock B = sys::Memory::AllocateRWX(size, BOld, &ErrMsg); 529 if (B.base() == 0) { 530 fprintf(stderr, 531 "Allocation failed when allocating new memory in the JIT\n%s\n", 532 ErrMsg.c_str()); 533 abort(); 534 } 535 Blocks.push_back(B); 536 return B; 537} 538 539 540JITMemoryManager *JITMemoryManager::CreateDefaultMemManager() { 541 return new DefaultJITMemoryManager(); 542} 543