llvm.org GIT mirror llvm / 1e86132
Move the Function*->allocated blocks map from the JITMemoryManager to the JITEmitter. I'm gradually making Functions auto-remove themselves from the JIT when they're destroyed. In this case, the Function needs to be removed from the JITEmitter, but the map recording which Functions need to be removed lived behind the JITMemoryManager interface, which made things difficult. This patch replaces the deallocateMemForFunction(Function*) method with a pair of methods deallocateFunctionBody(void *) and deallocateExceptionTable(void *) corresponding to the two startFoo/endFoo pairs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84651 91177308-0d34-0410-b5e6-96231b3b80d8 Jeffrey Yasskin 10 years ago
4 changed file(s) with 89 addition(s) and 84 deletion(s). Raw diff Collapse all Expand all
131131 ///
132132 virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0;
133133
134 /// deallocateMemForFunction - Free JIT memory for the specified function.
135 /// This is never called when the JIT is currently emitting a function.
136 virtual void deallocateMemForFunction(const Function *F) = 0;
134 /// deallocateFunctionBody - Free the specified function body. The argument
135 /// must be the return value from a call to startFunctionBody() that hasn't
136 /// been deallocated yet. This is never called when the JIT is currently
137 /// emitting a function.
138 virtual void deallocateFunctionBody(void *Body) = 0;
137139
138140 /// startExceptionTable - When we finished JITing the function, if exception
139141 /// handling is set, we emit the exception table.
144146 /// the exception table.
145147 virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
146148 uint8_t *TableEnd, uint8_t* FrameRegister) = 0;
149
150 /// deallocateExceptionTable - Free the specified exception table's memory.
151 /// The argument must be the return value from a call to startExceptionTable()
152 /// that hasn't been deallocated yet. This is never called when the JIT is
153 /// currently emitting an exception table.
154 virtual void deallocateExceptionTable(void *ET) = 0;
147155
148156 /// CheckInvariants - For testing only. Return true if all internal
149157 /// invariants are preserved, or return false and set ErrorStr to a helpful
4141 #include "llvm/System/Disassembler.h"
4242 #include "llvm/System/Memory.h"
4343 #include "llvm/Target/TargetInstrInfo.h"
44 #include "llvm/ADT/DenseMap.h"
4445 #include "llvm/ADT/SmallPtrSet.h"
4546 #include "llvm/ADT/SmallVector.h"
4647 #include "llvm/ADT/Statistic.h"
546547 /// JITEventListeners. This is reset in startFunction and used in
547548 /// finishFunction.
548549 JITEvent_EmittedFunctionDetails EmissionDetails;
550
551 struct EmittedCode {
552 void *FunctionBody;
553 void *ExceptionTable;
554 EmittedCode() : FunctionBody(0), ExceptionTable(0) {}
555 };
556 DenseMap EmittedFunctions;
549557
550558 // CurFnStubUses - For a given Function, a vector of stubs that it
551559 // references. This facilitates the JIT detecting that a stub is no
10101018 BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
10111019 ActualSize);
10121020 BufferEnd = BufferBegin+ActualSize;
1013
1021 EmittedFunctions[F.getFunction()].FunctionBody = BufferBegin;
1022
10141023 // Ensure the constant pool/jump table info is at least 4-byte aligned.
10151024 emitAlignment(16);
10161025
12001209 BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
12011210 ActualSize);
12021211 BufferEnd = BufferBegin+ActualSize;
1212 EmittedFunctions[F.getFunction()].ExceptionTable = BufferBegin;
12031213 uint8_t *EhStart;
12041214 uint8_t *FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd,
12051215 EhStart);
12431253 /// deallocateMemForFunction - Deallocate all memory for the specified
12441254 /// function body. Also drop any references the function has to stubs.
12451255 void JITEmitter::deallocateMemForFunction(const Function *F) {
1246 MemMgr->deallocateMemForFunction(F);
1256 DenseMap::iterator Emitted =
1257 EmittedFunctions.find(F);
1258 if (Emitted != EmittedFunctions.end()) {
1259 MemMgr->deallocateFunctionBody(Emitted->second.FunctionBody);
1260 MemMgr->deallocateExceptionTable(Emitted->second.ExceptionTable);
1261 EmittedFunctions.erase(Emitted);
1262 }
12471263
12481264 // TODO: Do we need to unregister exception handling information from libgcc
12491265 // here?
296296
297297 uint8_t *GOTBase; // Target Specific reserved memory
298298 void *DlsymTable; // Stub external symbol information
299
300 std::map FunctionBlocks;
301 std::map TableBlocks;
302299 public:
303300 DefaultJITMemoryManager();
304301 ~DefaultJITMemoryManager();
413410 "Mismatched function start/end!");
414411
415412 uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock;
416 FunctionBlocks[F] = CurBlock;
417413
418414 // Release the memory at the end of this block that isn't needed.
419415 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
463459 "Mismatched table start/end!");
464460
465461 uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
466 TableBlocks[F] = CurBlock;
467462
468463 // Release the memory at the end of this block that isn't needed.
469464 FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
477472 return DlsymTable;
478473 }
479474
480 /// deallocateMemForFunction - Deallocate all memory for the specified
481 /// function body.
482 void deallocateMemForFunction(const Function *F) {
483 std::map::iterator
484 I = FunctionBlocks.find(F);
485 if (I == FunctionBlocks.end()) return;
486
475 void deallocateBlock(void *Block) {
487476 // Find the block that is allocated for this function.
488 MemoryRangeHeader *MemRange = I->second;
477 MemoryRangeHeader *MemRange = static_cast(Block) - 1;
489478 assert(MemRange->ThisAllocated && "Block isn't allocated!");
490479
491480 // Fill the buffer with garbage!
495484
496485 // Free the memory.
497486 FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
498
499 // Finally, remove this entry from FunctionBlocks.
500 FunctionBlocks.erase(I);
501
502 I = TableBlocks.find(F);
503 if (I == TableBlocks.end()) return;
504
505 // Find the block that is allocated for this function.
506 MemRange = I->second;
507 assert(MemRange->ThisAllocated && "Block isn't allocated!");
508
509 // Fill the buffer with garbage!
510 if (PoisonMemory) {
511 memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
512 }
513
514 // Free the memory.
515 FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
516
517 // Finally, remove this entry from TableBlocks.
518 TableBlocks.erase(I);
487 }
488
489 /// deallocateFunctionBody - Deallocate all memory for the specified
490 /// function body.
491 void deallocateFunctionBody(void *Body) {
492 deallocateBlock(Body);
493 }
494
495 /// deallocateExceptionTable - Deallocate memory for the specified
496 /// exception table.
497 void deallocateExceptionTable(void *ET) {
498 deallocateBlock(ET);
519499 }
520500
521501 /// setMemoryWritable - When code generation is in progress,
3131 OwningPtr MemMgr(
3232 JITMemoryManager::CreateDefaultMemManager());
3333 uintptr_t size;
34 uint8_t *start;
3534 std::string Error;
3635
3736 // Allocate the functions.
3837 OwningPtr F1(makeFakeFunction());
3938 size = 1024;
40 start = MemMgr->startFunctionBody(F1.get(), size);
41 memset(start, 0xFF, 1024);
42 MemMgr->endFunctionBody(F1.get(), start, start + 1024);
39 uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
40 memset(FunctionBody1, 0xFF, 1024);
41 MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024);
4342 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
4443
4544 OwningPtr F2(makeFakeFunction());
4645 size = 1024;
47 start = MemMgr->startFunctionBody(F2.get(), size);
48 memset(start, 0xFF, 1024);
49 MemMgr->endFunctionBody(F2.get(), start, start + 1024);
46 uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
47 memset(FunctionBody2, 0xFF, 1024);
48 MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024);
5049 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
5150
5251 OwningPtr F3(makeFakeFunction());
5352 size = 1024;
54 start = MemMgr->startFunctionBody(F3.get(), size);
55 memset(start, 0xFF, 1024);
56 MemMgr->endFunctionBody(F3.get(), start, start + 1024);
53 uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
54 memset(FunctionBody3, 0xFF, 1024);
55 MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024);
5756 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
5857
5958 // Deallocate them out of order, in case that matters.
60 MemMgr->deallocateMemForFunction(F2.get());
61 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
62 MemMgr->deallocateMemForFunction(F1.get());
63 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
64 MemMgr->deallocateMemForFunction(F3.get());
59 MemMgr->deallocateFunctionBody(FunctionBody2);
60 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
61 MemMgr->deallocateFunctionBody(FunctionBody1);
62 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
63 MemMgr->deallocateFunctionBody(FunctionBody3);
6564 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
6665 }
6766
7170 OwningPtr MemMgr(
7271 JITMemoryManager::CreateDefaultMemManager());
7372 uintptr_t size;
74 uint8_t *start;
7573 std::string Error;
7674
7775 // Big functions are a little less than the largest block size.
8280 // Allocate big functions
8381 OwningPtr F1(makeFakeFunction());
8482 size = bigFuncSize;
85 start = MemMgr->startFunctionBody(F1.get(), size);
83 uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size);
8684 ASSERT_LE(bigFuncSize, size);
87 memset(start, 0xFF, bigFuncSize);
88 MemMgr->endFunctionBody(F1.get(), start, start + bigFuncSize);
85 memset(FunctionBody1, 0xFF, bigFuncSize);
86 MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize);
8987 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
9088
9189 OwningPtr F2(makeFakeFunction());
9290 size = bigFuncSize;
93 start = MemMgr->startFunctionBody(F2.get(), size);
91 uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size);
9492 ASSERT_LE(bigFuncSize, size);
95 memset(start, 0xFF, bigFuncSize);
96 MemMgr->endFunctionBody(F2.get(), start, start + bigFuncSize);
93 memset(FunctionBody2, 0xFF, bigFuncSize);
94 MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize);
9795 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
9896
9997 OwningPtr F3(makeFakeFunction());
10098 size = bigFuncSize;
101 start = MemMgr->startFunctionBody(F3.get(), size);
99 uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size);
102100 ASSERT_LE(bigFuncSize, size);
103 memset(start, 0xFF, bigFuncSize);
104 MemMgr->endFunctionBody(F3.get(), start, start + bigFuncSize);
101 memset(FunctionBody3, 0xFF, bigFuncSize);
102 MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize);
105103 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
106104
107105 // Check that each large function took it's own slab.
110108 // Allocate small functions
111109 OwningPtr F4(makeFakeFunction());
112110 size = smallFuncSize;
113 start = MemMgr->startFunctionBody(F4.get(), size);
111 uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size);
114112 ASSERT_LE(smallFuncSize, size);
115 memset(start, 0xFF, smallFuncSize);
116 MemMgr->endFunctionBody(F4.get(), start, start + smallFuncSize);
113 memset(FunctionBody4, 0xFF, smallFuncSize);
114 MemMgr->endFunctionBody(F4.get(), FunctionBody4,
115 FunctionBody4 + smallFuncSize);
117116 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
118117
119118 OwningPtr F5(makeFakeFunction());
120119 size = smallFuncSize;
121 start = MemMgr->startFunctionBody(F5.get(), size);
120 uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size);
122121 ASSERT_LE(smallFuncSize, size);
123 memset(start, 0xFF, smallFuncSize);
124 MemMgr->endFunctionBody(F5.get(), start, start + smallFuncSize);
122 memset(FunctionBody5, 0xFF, smallFuncSize);
123 MemMgr->endFunctionBody(F5.get(), FunctionBody5,
124 FunctionBody5 + smallFuncSize);
125125 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
126126
127127 OwningPtr F6(makeFakeFunction());
128128 size = smallFuncSize;
129 start = MemMgr->startFunctionBody(F6.get(), size);
129 uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size);
130130 ASSERT_LE(smallFuncSize, size);
131 memset(start, 0xFF, smallFuncSize);
132 MemMgr->endFunctionBody(F6.get(), start, start + smallFuncSize);
131 memset(FunctionBody6, 0xFF, smallFuncSize);
132 MemMgr->endFunctionBody(F6.get(), FunctionBody6,
133 FunctionBody6 + smallFuncSize);
133134 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
134135
135136 // Check that the small functions didn't allocate any new slabs.
136137 EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs());
137138
138139 // Deallocate them out of order, in case that matters.
139 MemMgr->deallocateMemForFunction(F2.get());
140 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
141 MemMgr->deallocateMemForFunction(F1.get());
142 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
143 MemMgr->deallocateMemForFunction(F4.get());
144 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
145 MemMgr->deallocateMemForFunction(F3.get());
146 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
147 MemMgr->deallocateMemForFunction(F5.get());
148 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
149 MemMgr->deallocateMemForFunction(F6.get());
140 MemMgr->deallocateFunctionBody(FunctionBody2);
141 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
142 MemMgr->deallocateFunctionBody(FunctionBody1);
143 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
144 MemMgr->deallocateFunctionBody(FunctionBody4);
145 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
146 MemMgr->deallocateFunctionBody(FunctionBody3);
147 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
148 MemMgr->deallocateFunctionBody(FunctionBody5);
149 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
150 MemMgr->deallocateFunctionBody(FunctionBody6);
150151 EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error;
151152 }
152153