Let SourceInfo take charage of and LLVM module.

I.e., a module never escapes from its associated SourceInfo object.

Change-Id: Ib7fe914052e8b1b06b879737f57828739d54e0f0
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index a299806..4545c0e 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -44,8 +44,6 @@
 
 #include "llvm/Analysis/Passes.h"
 
-#include "llvm/Bitcode/ReaderWriter.h"
-
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
@@ -60,7 +58,6 @@
 
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 
@@ -277,28 +274,14 @@
 #endif
     mpSymbolLookupFn(NULL),
     mpSymbolLookupContext(NULL),
-    mContext(NULL),
     mModule(NULL),
     mHasLinked(false) /* Turn off linker */ {
   llvm::remove_fatal_error_handler();
   llvm::install_fatal_error_handler(LLVMErrorHandler, &mError);
-  mContext = new llvm::LLVMContext();
   return;
 }
 
 
-llvm::Module *Compiler::parseBitcodeFile(llvm::MemoryBuffer *MEM) {
-  llvm::Module *result = llvm::ParseBitcodeFile(MEM, *mContext, &mError);
-
-  if (!result) {
-    ALOGE("Unable to ParseBitcodeFile: %s\n", mError.c_str());
-    return NULL;
-  }
-
-  return result;
-}
-
-
 int Compiler::linkModule(llvm::Module *moduleWith) {
   if (llvm::Linker::LinkModules(mModule, moduleWith,
                                 llvm::Linker::DestroySource,
@@ -916,9 +899,6 @@
 
 
 Compiler::~Compiler() {
-  delete mModule;
-  delete mContext;
-
 #if USE_MCJIT
   rsloaderDisposeExec(mRSExecutable);
 #endif
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 2d4faf7..5082d9e 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -40,9 +40,7 @@
 
 
 namespace llvm {
-  class LLVMContext;
   class Module;
-  class MemoryBuffer;
   class NamedMDNode;
   class TargetData;
 }
@@ -110,7 +108,6 @@
     BCCSymbolLookupFn mpSymbolLookupFn;
     void *mpSymbolLookupContext;
 
-    llvm::LLVMContext *mContext;
     llvm::Module *mModule;
 
     bool mHasLinked;
@@ -143,8 +140,6 @@
     }
 #endif
 
-    llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM);
-
     int readModule(llvm::Module *module) {
       mModule = module;
       return hasError();
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 2751299..9e59495 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -76,9 +76,8 @@
     break;
   }
 
-  for (size_t i = 0; i < 2; ++i) {
+  for (size_t i = 0; i < 2; ++i)
     delete mSourceList[i];
-  }
 }
 
 
@@ -346,28 +345,25 @@
                                       mpExtSymbolLookupFnContext);
   }
 
-  // Parse Bitcode File (if necessary)
-  for (size_t i = 0; i < 2; ++i) {
-    if (mSourceList[i] && mSourceList[i]->prepareModule(mCompiled) != 0) {
-      ALOGE("Unable to parse bitcode for source[%lu]\n", (unsigned long)i);
-      return 1;
-    }
-  }
-
-  // Set the main source module
-  if (!mSourceList[0] || !mSourceList[0]->getModule()) {
-    ALOGE("Source bitcode is not setted.\n");
+  if (!mSourceList[0]) {
+    ALOGE("Source bitcode is not set.\n");
     return 1;
   }
 
-  if (mCompiled->readModule(mSourceList[0]->takeModule()) != 0) {
+  // Parse Bitcode File (if necessary)
+  if (mSourceList[0]->prepareModule() != 0)
+    return 1;
+
+  // Set the main source module
+  if (mCompiled->readModule(mSourceList[0]->getModule()) != 0) {
     ALOGE("Unable to read source module\n");
     return 1;
   }
 
   // Link the source module with the library module
-  if (mSourceList[1]) {
-    if (mCompiled->linkModule(mSourceList[1]->takeModule()) != 0) {
+  if (mSourceList[1] &&
+      mSourceList[1]->prepareModule(mSourceList[0]->getContext())) {
+    if (mCompiled->linkModule(mSourceList[1]->getModule()) != 0) {
       ALOGE("Unable to link library module\n");
       return 1;
     }
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index e4acc16..f7bf48b 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -77,10 +77,6 @@
 
     ~ScriptCompiled();
 
-    llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM) {
-      return mCompiler.parseBitcodeFile(MEM);
-    }
-
     int readModule(llvm::Module *module) {
       return mCompiler.readModule(module);
     }
diff --git a/lib/ExecutionEngine/SourceInfo.cpp b/lib/ExecutionEngine/SourceInfo.cpp
index 019ecb1..9c49fcc 100644
--- a/lib/ExecutionEngine/SourceInfo.cpp
+++ b/lib/ExecutionEngine/SourceInfo.cpp
@@ -34,6 +34,9 @@
 #include <bcc/bcc.h>
 #include <bcc/bcc_cache.h>
 
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/Module.h>
+#include <llvm/LLVMContext.h>
 #include <llvm/ADT/OwningPtr.h>
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Support/MemoryBuffer.h>
@@ -114,7 +117,7 @@
   }
 
   result->type = SourceKind::Module;
-  result->module.reset(module);
+  result->module = module;
   result->flags = flags;
 
 #if USE_CACHE
@@ -133,44 +136,63 @@
 }
 
 
-int SourceInfo::prepareModule(ScriptCompiled *SC) {
+int SourceInfo::prepareModule(llvm::LLVMContext *context) {
+  if (module)
+    return 0;
+
+  llvm::OwningPtr<llvm::MemoryBuffer> mem;
+  std::string errmsg;
+
   switch (type) {
   case SourceKind::Buffer:
     {
-      llvm::OwningPtr<llvm::MemoryBuffer> MEM(
-        llvm::MemoryBuffer::getMemBuffer(
+      mem.reset(llvm::MemoryBuffer::getMemBuffer(
           llvm::StringRef(buffer.bitcode, buffer.bitcodeSize)));
 
-      if (!MEM.get()) {
+      if (!mem.get()) {
         ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
-             buffer.bitcode, (unsigned long)buffer.bitcodeSize);
+              buffer.bitcode, (unsigned long)buffer.bitcodeSize);
         return 1;
       }
-
-      module.reset(SC->parseBitcodeFile(MEM.get()));
     }
     break;
 
   case SourceKind::File:
     {
-      llvm::OwningPtr<llvm::MemoryBuffer> MEM;
-
-      if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, MEM)) {
-        ALOGE("Unable to MemoryBuffer::getFile(path=%s)\n", file.path);
+      if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) {
+        ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n",
+              file.path, ec.message().c_str());
         return 1;
       }
-
-      module.reset(SC->parseBitcodeFile(MEM.get()));
     }
     break;
 
   default:
+    return 0;
     break;
   }
 
-  return (module.get()) ? 0 : 1;
+  if (context)
+    shared_context = true;
+  else
+    context = new llvm::LLVMContext();
+
+  module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg);
+  if (module == NULL) {
+    ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
+    if (!shared_context)
+      delete context;
+  }
+
+  return (module == NULL);
 }
 
+SourceInfo::~SourceInfo() {
+  llvm::LLVMContext *context = &module->getContext();
+  delete module;
+  if (!shared_context)
+    delete context;
+}
 
 #if USE_CACHE
 template <typename T> void SourceInfo::introDependency(T &checker) {
diff --git a/lib/ExecutionEngine/SourceInfo.h b/lib/ExecutionEngine/SourceInfo.h
index b6a4c54..9026f1c 100644
--- a/lib/ExecutionEngine/SourceInfo.h
+++ b/lib/ExecutionEngine/SourceInfo.h
@@ -19,14 +19,15 @@
 
 #include "Config.h"
 
-#include <llvm/ADT/OwningPtr.h>
 #include <llvm/Module.h>
 
 #include <stddef.h>
 
-namespace bcc {
-  class ScriptCompiled;
+namespace llvm {
+  class LLVMContext;
+}
 
+namespace bcc {
   namespace SourceKind {
     enum SourceType {
       File,
@@ -39,9 +40,12 @@
   private:
     SourceKind::SourceType type;
 
-    llvm::OwningPtr<llvm::Module> module;
     // Note: module should not be a part of union.  Since, we are going to
     // use module to store the pointer to parsed bitcode.
+    llvm::Module *module;
+    // If true, the LLVM context behind the module is shared with others.
+    // Therefore, don't try to destroy the context it when destroy the module.
+    bool shared_context;
 
     union {
       struct {
@@ -62,7 +66,7 @@
 #endif
 
   private:
-    SourceInfo() { }
+    SourceInfo() : module(NULL), shared_context(false) { }
 
   public:
     static SourceInfo *createFromBuffer(char const *resName,
@@ -76,19 +80,22 @@
     static SourceInfo *createFromModule(llvm::Module *module,
                                         unsigned long flags);
 
-    llvm::Module *takeModule() {
-      return module.take();
+    inline llvm::Module *getModule() const {
+      return module;
     }
 
-    llvm::Module *getModule() const {
-      return module.get();
+    inline llvm::LLVMContext *getContext() const {
+      return (module) ? &module->getContext() : NULL;
     }
 
-    int prepareModule(ScriptCompiled *);
+    // Share with the given context if it's provided.
+    int prepareModule(llvm::LLVMContext *context = NULL);
 
 #if USE_CACHE
     template <typename T> void introDependency(T &checker);
 #endif
+
+    ~SourceInfo();
   };