#include "llvm/System/Disassembler.h"
#include "llvm/System/Memory.h"
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
/// finishFunction.
JITEvent_EmittedFunctionDetails EmissionDetails;
+ struct EmittedCode {
+ void *FunctionBody;
+ void *ExceptionTable;
+ EmittedCode() : FunctionBody(0), ExceptionTable(0) {}
+ };
+ DenseMap<const Function *, EmittedCode> EmittedFunctions;
+
// CurFnStubUses - For a given Function, a vector of stubs that it
// references. This facilitates the JIT detecting that a stub is no
// longer used, so that it may be deallocated.
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
ActualSize);
BufferEnd = BufferBegin+ActualSize;
-
+ EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin;
+
// Ensure the constant pool/jump table info is at least 4-byte aligned.
emitAlignment(16);
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
ActualSize);
BufferEnd = BufferBegin+ActualSize;
+ EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
uint8_t *EhStart;
uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
EhStart);
/// deallocateMemForFunction - Deallocate all memory for the specified
/// function body. Also drop any references the function has to stubs.
void JITEmitter::deallocateMemForFunction(const Function *F) {
- MemMgr->deallocateMemForFunction(F);
+ DenseMap<const Function *, EmittedCode>::iterator Emitted =
+ EmittedFunctions.find(F);
+ if (Emitted != EmittedFunctions.end()) {
+ MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody);
+ MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable);
+ EmittedFunctions.erase(Emitted);
+ }
// TODO: Do we need to unregister exception handling information from libgcc
// here?
uint8_t *GOTBase; // Target Specific reserved memory
void *DlsymTable; // Stub external symbol information
-
- std::map<const Function*, MemoryRangeHeader*> FunctionBlocks;
- std::map<const Function*, MemoryRangeHeader*> TableBlocks;
public:
DefaultJITMemoryManager();
~DefaultJITMemoryManager();
"Mismatched function start/end!");
uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock;
- FunctionBlocks[F] = CurBlock;
// Release the memory at the end of this block that isn't needed.
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
"Mismatched table start/end!");
uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
- TableBlocks[F] = CurBlock;
// Release the memory at the end of this block that isn't needed.
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
return DlsymTable;
}
- /// deallocateMemForFunction - Deallocate all memory for the specified
- /// function body.
- void deallocateMemForFunction(const Function *F) {
- std::map<const Function*, MemoryRangeHeader*>::iterator
- I = FunctionBlocks.find(F);
- if (I == FunctionBlocks.end()) return;
-
+ void deallocateBlock(void *Block) {
// Find the block that is allocated for this function.
- MemoryRangeHeader *MemRange = I->second;
+ MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
assert(MemRange->ThisAllocated && "Block isn't allocated!");
// Fill the buffer with garbage!
// Free the memory.
FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
-
- // Finally, remove this entry from FunctionBlocks.
- FunctionBlocks.erase(I);
-
- I = TableBlocks.find(F);
- if (I == TableBlocks.end()) return;
-
- // Find the block that is allocated for this function.
- MemRange = I->second;
- assert(MemRange->ThisAllocated && "Block isn't allocated!");
+ }
- // Fill the buffer with garbage!
- if (PoisonMemory) {
- memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
- }
+ /// deallocateFunctionBody - Deallocate all memory for the specified
+ /// function body.
+ void deallocateFunctionBody(void *Body) {
+ deallocateBlock(Body);
+ }
- // Free the memory.
- FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
-
- // Finally, remove this entry from TableBlocks.
- TableBlocks.erase(I);
+ /// deallocateExceptionTable - Deallocate memory for the specified
+ /// exception table.
+ void deallocateExceptionTable(void *ET) {
+ deallocateBlock(ET);
}
/// setMemoryWritable - When code generation is in progress,
OwningPtr<JITMemoryManager> MemMgr(
JITMemoryManager::CreateDefaultMemManager());
uintptr_t size;
- uint8_t *start;
std::string Error;
// Allocate the functions.
OwningPtr<Function> F1(makeFakeFunction());
size = 1024;
- start = MemMgr->startFunctionBody(F1.get(), size);
- memset(start, 0xFF, 1024);
- MemMgr->endFunctionBody(F1.get(), start, start + 1024);
+ uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
+ memset(FunctionBody1, 0xFF, 1024);
+ MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F2(makeFakeFunction());
size = 1024;
- start = MemMgr->startFunctionBody(F2.get(), size);
- memset(start, 0xFF, 1024);
- MemMgr->endFunctionBody(F2.get(), start, start + 1024);
+ uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
+ memset(FunctionBody2, 0xFF, 1024);
+ MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F3(makeFakeFunction());
size = 1024;
- start = MemMgr->startFunctionBody(F3.get(), size);
- memset(start, 0xFF, 1024);
- MemMgr->endFunctionBody(F3.get(), start, start + 1024);
+ uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
+ memset(FunctionBody3, 0xFF, 1024);
+ MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
// Deallocate them out of order, in case that matters.
- MemMgr->deallocateMemForFunction(F2.get());
+ MemMgr->deallocateFunctionBody(FunctionBody2);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F1.get());
+ MemMgr->deallocateFunctionBody(FunctionBody1);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F3.get());
+ MemMgr->deallocateFunctionBody(FunctionBody3);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
}
OwningPtr<JITMemoryManager> MemMgr(
JITMemoryManager::CreateDefaultMemManager());
uintptr_t size;
- uint8_t *start;
std::string Error;
// Big functions are a little less than the largest block size.
// Allocate big functions
OwningPtr<Function> F1(makeFakeFunction());
size = bigFuncSize;
- start = MemMgr->startFunctionBody(F1.get(), size);
+ uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
ASSERT_LE(bigFuncSize, size);
- memset(start, 0xFF, bigFuncSize);
- MemMgr->endFunctionBody(F1.get(), start, start + bigFuncSize);
+ memset(FunctionBody1, 0xFF, bigFuncSize);
+ MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F2(makeFakeFunction());
size = bigFuncSize;
- start = MemMgr->startFunctionBody(F2.get(), size);
+ uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
ASSERT_LE(bigFuncSize, size);
- memset(start, 0xFF, bigFuncSize);
- MemMgr->endFunctionBody(F2.get(), start, start + bigFuncSize);
+ memset(FunctionBody2, 0xFF, bigFuncSize);
+ MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F3(makeFakeFunction());
size = bigFuncSize;
- start = MemMgr->startFunctionBody(F3.get(), size);
+ uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
ASSERT_LE(bigFuncSize, size);
- memset(start, 0xFF, bigFuncSize);
- MemMgr->endFunctionBody(F3.get(), start, start + bigFuncSize);
+ memset(FunctionBody3, 0xFF, bigFuncSize);
+ MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
// Check that each large function took it's own slab.
// Allocate small functions
OwningPtr<Function> F4(makeFakeFunction());
size = smallFuncSize;
- start = MemMgr->startFunctionBody(F4.get(), size);
+ uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size);
ASSERT_LE(smallFuncSize, size);
- memset(start, 0xFF, smallFuncSize);
- MemMgr->endFunctionBody(F4.get(), start, start + smallFuncSize);
+ memset(FunctionBody4, 0xFF, smallFuncSize);
+ MemMgr->endFunctionBody(F4.get(), FunctionBody4,
+ FunctionBody4 + smallFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F5(makeFakeFunction());
size = smallFuncSize;
- start = MemMgr->startFunctionBody(F5.get(), size);
+ uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size);
ASSERT_LE(smallFuncSize, size);
- memset(start, 0xFF, smallFuncSize);
- MemMgr->endFunctionBody(F5.get(), start, start + smallFuncSize);
+ memset(FunctionBody5, 0xFF, smallFuncSize);
+ MemMgr->endFunctionBody(F5.get(), FunctionBody5,
+ FunctionBody5 + smallFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
OwningPtr<Function> F6(makeFakeFunction());
size = smallFuncSize;
- start = MemMgr->startFunctionBody(F6.get(), size);
+ uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size);
ASSERT_LE(smallFuncSize, size);
- memset(start, 0xFF, smallFuncSize);
- MemMgr->endFunctionBody(F6.get(), start, start + smallFuncSize);
+ memset(FunctionBody6, 0xFF, smallFuncSize);
+ MemMgr->endFunctionBody(F6.get(), FunctionBody6,
+ FunctionBody6 + smallFuncSize);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
// Check that the small functions didn't allocate any new slabs.
EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
// Deallocate them out of order, in case that matters.
- MemMgr->deallocateMemForFunction(F2.get());
+ MemMgr->deallocateFunctionBody(FunctionBody2);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F1.get());
+ MemMgr->deallocateFunctionBody(FunctionBody1);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F4.get());
+ MemMgr->deallocateFunctionBody(FunctionBody4);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F3.get());
+ MemMgr->deallocateFunctionBody(FunctionBody3);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F5.get());
+ MemMgr->deallocateFunctionBody(FunctionBody5);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
- MemMgr->deallocateMemForFunction(F6.get());
+ MemMgr->deallocateFunctionBody(FunctionBody6);
EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
}