summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine
diff options
context:
space:
mode:
authorJeffrey Yasskin <jyasskin@google.com>2010-03-27 04:53:56 +0000
committerJeffrey Yasskin <jyasskin@google.com>2010-03-27 04:53:56 +0000
commit47b7112418a8c6ca23039ad5239cbc16091911a0 (patch)
tree4184663c182b3ba4c91c314175a417f8466af115 /lib/ExecutionEngine
parent2cd1a12fe07be753e331a12389aa1ceb49de836b (diff)
downloadllvm-47b7112418a8c6ca23039ad5239cbc16091911a0.tar.gz
llvm-47b7112418a8c6ca23039ad5239cbc16091911a0.tar.bz2
llvm-47b7112418a8c6ca23039ad5239cbc16091911a0.tar.xz
Avoid leaking the memory allocated for GlobalVariables in the interpreter, by
freeing that memory when the GV is destroyed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@99706 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine')
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp35
1 files changed, 32 insertions, 3 deletions
diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp
index d3d19df286..da21c2de9a 100644
--- a/lib/ExecutionEngine/ExecutionEngine.cpp
+++ b/lib/ExecutionEngine/ExecutionEngine.cpp
@@ -66,10 +66,39 @@ ExecutionEngine::~ExecutionEngine() {
delete Modules[i];
}
+namespace {
+// This class automatically deletes the memory block when the GlobalVariable is
+// destroyed.
+class GVMemoryBlock : public CallbackVH {
+ GVMemoryBlock(const GlobalVariable *GV)
+ : CallbackVH(const_cast<GlobalVariable*>(GV)) {}
+
+public:
+ // Returns the address the GlobalVariable should be written into. The
+ // GVMemoryBlock object prefixes that.
+ static char *Create(const GlobalVariable *GV, const TargetData& TD) {
+ const Type *ElTy = GV->getType()->getElementType();
+ size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy);
+ void *RawMemory = ::operator new(
+ TargetData::RoundUpAlignment(sizeof(GVMemoryBlock),
+ TD.getPreferredAlignment(GV))
+ + GVSize);
+ new(RawMemory) GVMemoryBlock(GV);
+ return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock);
+ }
+
+ virtual void deleted() {
+ // We allocated with operator new and with some extra memory hanging off the
+ // end, so don't just delete this. I'm not sure if this is actually
+ // required.
+ this->~GVMemoryBlock();
+ ::operator delete(this);
+ }
+};
+} // anonymous namespace
+
char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) {
- const Type *ElTy = GV->getType()->getElementType();
- size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy);
- return new char[GVSize];
+ return GVMemoryBlock::Create(GV, *getTargetData());
}
/// removeModule - Remove a Module from the list of modules.