parent
7bdf096f8d
commit
ebbfbeef7d
|
@ -49,23 +49,23 @@ namespace {
|
||||||
/// ThisAllocated - This is true if this block is currently allocated. If
|
/// ThisAllocated - This is true if this block is currently allocated. If
|
||||||
/// not, this can be converted to a FreeRangeHeader.
|
/// not, this can be converted to a FreeRangeHeader.
|
||||||
unsigned ThisAllocated : 1;
|
unsigned ThisAllocated : 1;
|
||||||
|
|
||||||
/// PrevAllocated - Keep track of whether the block immediately before us is
|
/// PrevAllocated - Keep track of whether the block immediately before us is
|
||||||
/// allocated. If not, the word immediately before this header is the size
|
/// allocated. If not, the word immediately before this header is the size
|
||||||
/// of the previous block.
|
/// of the previous block.
|
||||||
unsigned PrevAllocated : 1;
|
unsigned PrevAllocated : 1;
|
||||||
|
|
||||||
/// BlockSize - This is the size in bytes of this memory block,
|
/// BlockSize - This is the size in bytes of this memory block,
|
||||||
/// including this header.
|
/// including this header.
|
||||||
uintptr_t BlockSize : (sizeof(intptr_t)*CHAR_BIT - 2);
|
uintptr_t BlockSize : (sizeof(intptr_t)*CHAR_BIT - 2);
|
||||||
|
|
||||||
|
|
||||||
/// getBlockAfter - Return the memory block immediately after this one.
|
/// getBlockAfter - Return the memory block immediately after this one.
|
||||||
///
|
///
|
||||||
MemoryRangeHeader &getBlockAfter() const {
|
MemoryRangeHeader &getBlockAfter() const {
|
||||||
return *(MemoryRangeHeader*)((char*)this+BlockSize);
|
return *(MemoryRangeHeader*)((char*)this+BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getFreeBlockBefore - If the block before this one is free, return it,
|
/// getFreeBlockBefore - If the block before this one is free, return it,
|
||||||
/// otherwise return null.
|
/// otherwise return null.
|
||||||
FreeRangeHeader *getFreeBlockBefore() const {
|
FreeRangeHeader *getFreeBlockBefore() const {
|
||||||
|
@ -73,15 +73,15 @@ namespace {
|
||||||
intptr_t PrevSize = ((intptr_t *)this)[-1];
|
intptr_t PrevSize = ((intptr_t *)this)[-1];
|
||||||
return (FreeRangeHeader*)((char*)this-PrevSize);
|
return (FreeRangeHeader*)((char*)this-PrevSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FreeBlock - Turn an allocated block into a free block, adjusting
|
/// FreeBlock - Turn an allocated block into a free block, adjusting
|
||||||
/// bits in the object headers, and adding an end of region memory block.
|
/// bits in the object headers, and adding an end of region memory block.
|
||||||
FreeRangeHeader *FreeBlock(FreeRangeHeader *FreeList);
|
FreeRangeHeader *FreeBlock(FreeRangeHeader *FreeList);
|
||||||
|
|
||||||
/// TrimAllocationToSize - If this allocated block is significantly larger
|
/// TrimAllocationToSize - If this allocated block is significantly larger
|
||||||
/// than NewSize, split it into two pieces (where the former is NewSize
|
/// than NewSize, split it into two pieces (where the former is NewSize
|
||||||
/// bytes, including the header), and add the new block to the free list.
|
/// bytes, including the header), and add the new block to the free list.
|
||||||
FreeRangeHeader *TrimAllocationToSize(FreeRangeHeader *FreeList,
|
FreeRangeHeader *TrimAllocationToSize(FreeRangeHeader *FreeList,
|
||||||
uint64_t NewSize);
|
uint64_t NewSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,13 +91,13 @@ namespace {
|
||||||
struct FreeRangeHeader : public MemoryRangeHeader {
|
struct FreeRangeHeader : public MemoryRangeHeader {
|
||||||
FreeRangeHeader *Prev;
|
FreeRangeHeader *Prev;
|
||||||
FreeRangeHeader *Next;
|
FreeRangeHeader *Next;
|
||||||
|
|
||||||
/// getMinBlockSize - Get the minimum size for a memory block. Blocks
|
/// getMinBlockSize - Get the minimum size for a memory block. Blocks
|
||||||
/// smaller than this size cannot be created.
|
/// smaller than this size cannot be created.
|
||||||
static unsigned getMinBlockSize() {
|
static unsigned getMinBlockSize() {
|
||||||
return sizeof(FreeRangeHeader)+sizeof(intptr_t);
|
return sizeof(FreeRangeHeader)+sizeof(intptr_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SetEndOfBlockSizeMarker - The word at the end of every free block is
|
/// SetEndOfBlockSizeMarker - The word at the end of every free block is
|
||||||
/// known to be the size of the free block. Set it for this block.
|
/// known to be the size of the free block. Set it for this block.
|
||||||
void SetEndOfBlockSizeMarker() {
|
void SetEndOfBlockSizeMarker() {
|
||||||
|
@ -110,7 +110,7 @@ namespace {
|
||||||
Next->Prev = Prev;
|
Next->Prev = Prev;
|
||||||
return Prev->Next = Next;
|
return Prev->Next = Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddToFreeList(FreeRangeHeader *FreeList) {
|
void AddToFreeList(FreeRangeHeader *FreeList) {
|
||||||
Next = FreeList;
|
Next = FreeList;
|
||||||
Prev = FreeList->Prev;
|
Prev = FreeList->Prev;
|
||||||
|
@ -121,7 +121,7 @@ namespace {
|
||||||
/// GrowBlock - The block after this block just got deallocated. Merge it
|
/// GrowBlock - The block after this block just got deallocated. Merge it
|
||||||
/// into the current block.
|
/// into the current block.
|
||||||
void GrowBlock(uintptr_t NewSize);
|
void GrowBlock(uintptr_t NewSize);
|
||||||
|
|
||||||
/// AllocateBlock - Mark this entire block allocated, updating freelists
|
/// AllocateBlock - Mark this entire block allocated, updating freelists
|
||||||
/// etc. This returns a pointer to the circular free-list.
|
/// etc. This returns a pointer to the circular free-list.
|
||||||
FreeRangeHeader *AllocateBlock();
|
FreeRangeHeader *AllocateBlock();
|
||||||
|
@ -137,7 +137,7 @@ FreeRangeHeader *FreeRangeHeader::AllocateBlock() {
|
||||||
// Mark this block allocated.
|
// Mark this block allocated.
|
||||||
ThisAllocated = 1;
|
ThisAllocated = 1;
|
||||||
getBlockAfter().PrevAllocated = 1;
|
getBlockAfter().PrevAllocated = 1;
|
||||||
|
|
||||||
// Remove it from the free list.
|
// Remove it from the free list.
|
||||||
return RemoveFromFreeList();
|
return RemoveFromFreeList();
|
||||||
}
|
}
|
||||||
|
@ -150,9 +150,9 @@ FreeRangeHeader *MemoryRangeHeader::FreeBlock(FreeRangeHeader *FreeList) {
|
||||||
MemoryRangeHeader *FollowingBlock = &getBlockAfter();
|
MemoryRangeHeader *FollowingBlock = &getBlockAfter();
|
||||||
assert(ThisAllocated && "This block is already free!");
|
assert(ThisAllocated && "This block is already free!");
|
||||||
assert(FollowingBlock->PrevAllocated && "Flags out of sync!");
|
assert(FollowingBlock->PrevAllocated && "Flags out of sync!");
|
||||||
|
|
||||||
FreeRangeHeader *FreeListToReturn = FreeList;
|
FreeRangeHeader *FreeListToReturn = FreeList;
|
||||||
|
|
||||||
// If the block after this one is free, merge it into this block.
|
// If the block after this one is free, merge it into this block.
|
||||||
if (!FollowingBlock->ThisAllocated) {
|
if (!FollowingBlock->ThisAllocated) {
|
||||||
FreeRangeHeader &FollowingFreeBlock = *(FreeRangeHeader *)FollowingBlock;
|
FreeRangeHeader &FollowingFreeBlock = *(FreeRangeHeader *)FollowingBlock;
|
||||||
|
@ -164,18 +164,18 @@ FreeRangeHeader *MemoryRangeHeader::FreeBlock(FreeRangeHeader *FreeList) {
|
||||||
assert(&FollowingFreeBlock != FreeList && "No tombstone block?");
|
assert(&FollowingFreeBlock != FreeList && "No tombstone block?");
|
||||||
}
|
}
|
||||||
FollowingFreeBlock.RemoveFromFreeList();
|
FollowingFreeBlock.RemoveFromFreeList();
|
||||||
|
|
||||||
// Include the following block into this one.
|
// Include the following block into this one.
|
||||||
BlockSize += FollowingFreeBlock.BlockSize;
|
BlockSize += FollowingFreeBlock.BlockSize;
|
||||||
FollowingBlock = &FollowingFreeBlock.getBlockAfter();
|
FollowingBlock = &FollowingFreeBlock.getBlockAfter();
|
||||||
|
|
||||||
// Tell the block after the block we are coalescing that this block is
|
// Tell the block after the block we are coalescing that this block is
|
||||||
// allocated.
|
// allocated.
|
||||||
FollowingBlock->PrevAllocated = 1;
|
FollowingBlock->PrevAllocated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(FollowingBlock->ThisAllocated && "Missed coalescing?");
|
assert(FollowingBlock->ThisAllocated && "Missed coalescing?");
|
||||||
|
|
||||||
if (FreeRangeHeader *PrevFreeBlock = getFreeBlockBefore()) {
|
if (FreeRangeHeader *PrevFreeBlock = getFreeBlockBefore()) {
|
||||||
PrevFreeBlock->GrowBlock(PrevFreeBlock->BlockSize + BlockSize);
|
PrevFreeBlock->GrowBlock(PrevFreeBlock->BlockSize + BlockSize);
|
||||||
return FreeListToReturn ? FreeListToReturn : PrevFreeBlock;
|
return FreeListToReturn ? FreeListToReturn : PrevFreeBlock;
|
||||||
|
@ -218,24 +218,24 @@ TrimAllocationToSize(FreeRangeHeader *FreeList, uint64_t NewSize) {
|
||||||
// Round up size for alignment of header.
|
// Round up size for alignment of header.
|
||||||
unsigned HeaderAlign = __alignof(FreeRangeHeader);
|
unsigned HeaderAlign = __alignof(FreeRangeHeader);
|
||||||
NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1);
|
NewSize = (NewSize+ (HeaderAlign-1)) & ~(HeaderAlign-1);
|
||||||
|
|
||||||
// Size is now the size of the block we will remove from the start of the
|
// Size is now the size of the block we will remove from the start of the
|
||||||
// current block.
|
// current block.
|
||||||
assert(NewSize <= BlockSize &&
|
assert(NewSize <= BlockSize &&
|
||||||
"Allocating more space from this block than exists!");
|
"Allocating more space from this block than exists!");
|
||||||
|
|
||||||
// If splitting this block will cause the remainder to be too small, do not
|
// If splitting this block will cause the remainder to be too small, do not
|
||||||
// split the block.
|
// split the block.
|
||||||
if (BlockSize <= NewSize+FreeRangeHeader::getMinBlockSize())
|
if (BlockSize <= NewSize+FreeRangeHeader::getMinBlockSize())
|
||||||
return FreeList;
|
return FreeList;
|
||||||
|
|
||||||
// Otherwise, we splice the required number of bytes out of this block, form
|
// Otherwise, we splice the required number of bytes out of this block, form
|
||||||
// a new block immediately after it, then mark this block allocated.
|
// a new block immediately after it, then mark this block allocated.
|
||||||
MemoryRangeHeader &FormerNextBlock = getBlockAfter();
|
MemoryRangeHeader &FormerNextBlock = getBlockAfter();
|
||||||
|
|
||||||
// Change the size of this block.
|
// Change the size of this block.
|
||||||
BlockSize = NewSize;
|
BlockSize = NewSize;
|
||||||
|
|
||||||
// Get the new block we just sliced out and turn it into a free block.
|
// Get the new block we just sliced out and turn it into a free block.
|
||||||
FreeRangeHeader &NewNextBlock = (FreeRangeHeader &)getBlockAfter();
|
FreeRangeHeader &NewNextBlock = (FreeRangeHeader &)getBlockAfter();
|
||||||
NewNextBlock.BlockSize = (char*)&FormerNextBlock - (char*)&NewNextBlock;
|
NewNextBlock.BlockSize = (char*)&FormerNextBlock - (char*)&NewNextBlock;
|
||||||
|
@ -283,7 +283,7 @@ namespace {
|
||||||
sys::MemoryBlock LastSlab;
|
sys::MemoryBlock LastSlab;
|
||||||
|
|
||||||
// Memory slabs allocated by the JIT. We refer to them as slabs so we don't
|
// Memory slabs allocated by the JIT. We refer to them as slabs so we don't
|
||||||
// confuse them with the blocks of memory descibed above.
|
// confuse them with the blocks of memory described above.
|
||||||
std::vector<sys::MemoryBlock> CodeSlabs;
|
std::vector<sys::MemoryBlock> CodeSlabs;
|
||||||
JITSlabAllocator BumpSlabAllocator;
|
JITSlabAllocator BumpSlabAllocator;
|
||||||
BumpPtrAllocator StubAllocator;
|
BumpPtrAllocator StubAllocator;
|
||||||
|
@ -347,7 +347,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
largest = largest - sizeof(MemoryRangeHeader);
|
largest = largest - sizeof(MemoryRangeHeader);
|
||||||
|
|
||||||
// If this block isn't big enough for the allocation desired, allocate
|
// If this block isn't big enough for the allocation desired, allocate
|
||||||
// another block of memory and add it to the free list.
|
// another block of memory and add it to the free list.
|
||||||
if (largest < ActualSize ||
|
if (largest < ActualSize ||
|
||||||
|
@ -443,30 +443,30 @@ namespace {
|
||||||
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
|
return (uint8_t*)DataAllocator.Allocate(Size, Alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// startExceptionTable - Use startFunctionBody to allocate memory for the
|
/// startExceptionTable - Use startFunctionBody to allocate memory for the
|
||||||
/// function's exception table.
|
/// function's exception table.
|
||||||
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
|
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
|
||||||
return startFunctionBody(F, ActualSize);
|
return startFunctionBody(F, ActualSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// endExceptionTable - The exception table of F is now allocated,
|
/// endExceptionTable - The exception table of F is now allocated,
|
||||||
/// and takes the memory in the range [TableStart,TableEnd).
|
/// and takes the memory in the range [TableStart,TableEnd).
|
||||||
void endExceptionTable(const Function *F, uint8_t *TableStart,
|
void endExceptionTable(const Function *F, uint8_t *TableStart,
|
||||||
uint8_t *TableEnd, uint8_t* FrameRegister) {
|
uint8_t *TableEnd, uint8_t* FrameRegister) {
|
||||||
assert(TableEnd > TableStart);
|
assert(TableEnd > TableStart);
|
||||||
assert(TableStart == (uint8_t *)(CurBlock+1) &&
|
assert(TableStart == (uint8_t *)(CurBlock+1) &&
|
||||||
"Mismatched table start/end!");
|
"Mismatched table start/end!");
|
||||||
|
|
||||||
uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
|
uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
|
||||||
|
|
||||||
// Release the memory at the end of this block that isn't needed.
|
// Release the memory at the end of this block that isn't needed.
|
||||||
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
|
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *getGOTBase() const {
|
uint8_t *getGOTBase() const {
|
||||||
return GOTBase;
|
return GOTBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocateBlock(void *Block) {
|
void deallocateBlock(void *Block) {
|
||||||
// Find the block that is allocated for this function.
|
// Find the block that is allocated for this function.
|
||||||
MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
|
MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
|
||||||
|
@ -555,16 +555,16 @@ DefaultJITMemoryManager::DefaultJITMemoryManager()
|
||||||
// END ]
|
// END ]
|
||||||
//
|
//
|
||||||
// The last three blocks are never deallocated or touched.
|
// The last three blocks are never deallocated or touched.
|
||||||
|
|
||||||
// Add MemoryRangeHeader to the end of the memory region, indicating that
|
// Add MemoryRangeHeader to the end of the memory region, indicating that
|
||||||
// the space after the block of memory is allocated. This is block #3.
|
// the space after the block of memory is allocated. This is block #3.
|
||||||
MemoryRangeHeader *Mem3 = (MemoryRangeHeader*)(MemBase+MemBlock.size())-1;
|
MemoryRangeHeader *Mem3 = (MemoryRangeHeader*)(MemBase+MemBlock.size())-1;
|
||||||
Mem3->ThisAllocated = 1;
|
Mem3->ThisAllocated = 1;
|
||||||
Mem3->PrevAllocated = 0;
|
Mem3->PrevAllocated = 0;
|
||||||
Mem3->BlockSize = sizeof(MemoryRangeHeader);
|
Mem3->BlockSize = sizeof(MemoryRangeHeader);
|
||||||
|
|
||||||
/// Add a tiny free region so that the free list always has one entry.
|
/// Add a tiny free region so that the free list always has one entry.
|
||||||
FreeRangeHeader *Mem2 =
|
FreeRangeHeader *Mem2 =
|
||||||
(FreeRangeHeader *)(((char*)Mem3)-FreeRangeHeader::getMinBlockSize());
|
(FreeRangeHeader *)(((char*)Mem3)-FreeRangeHeader::getMinBlockSize());
|
||||||
Mem2->ThisAllocated = 0;
|
Mem2->ThisAllocated = 0;
|
||||||
Mem2->PrevAllocated = 1;
|
Mem2->PrevAllocated = 1;
|
||||||
|
@ -578,7 +578,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager()
|
||||||
Mem1->ThisAllocated = 1;
|
Mem1->ThisAllocated = 1;
|
||||||
Mem1->PrevAllocated = 0;
|
Mem1->PrevAllocated = 0;
|
||||||
Mem1->BlockSize = sizeof(MemoryRangeHeader);
|
Mem1->BlockSize = sizeof(MemoryRangeHeader);
|
||||||
|
|
||||||
// Add a FreeRangeHeader to the start of the function body region, indicating
|
// Add a FreeRangeHeader to the start of the function body region, indicating
|
||||||
// that the space is free. Mark the previous block allocated so we never look
|
// that the space is free. Mark the previous block allocated so we never look
|
||||||
// at it.
|
// at it.
|
||||||
|
@ -588,7 +588,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager()
|
||||||
Mem0->BlockSize = (char*)Mem1-(char*)Mem0;
|
Mem0->BlockSize = (char*)Mem1-(char*)Mem0;
|
||||||
Mem0->SetEndOfBlockSizeMarker();
|
Mem0->SetEndOfBlockSizeMarker();
|
||||||
Mem0->AddToFreeList(Mem2);
|
Mem0->AddToFreeList(Mem2);
|
||||||
|
|
||||||
// Start out with the freelist pointing to Mem0.
|
// Start out with the freelist pointing to Mem0.
|
||||||
FreeMemoryList = Mem0;
|
FreeMemoryList = Mem0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue