Avoid leaking the memory allocated for GlobalVariables in the interpreter, by
authorJeffrey Yasskin <jyasskin@google.com>
Sat, 27 Mar 2010 04:53:56 +0000 (04:53 +0000)
committerJeffrey Yasskin <jyasskin@google.com>
Sat, 27 Mar 2010 04:53:56 +0000 (04:53 +0000)
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

lib/ExecutionEngine/ExecutionEngine.cpp

index d3d19df286a329c9c144fd9089eba1c41f5543b0..da21c2de9aa47bbddd60bfbf27140f4d02f9d064 100644 (file)
@@ -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.