<div dir="ltr">If I'm reading this correctly, this changes the lifetime of the RuntimeDyld.<div>This can be problematic because we added an API a while back to be able to retain a LoadedObjectInfo object, which nowadays has a reference back to the RuntimeDyld. In Julia we used this to be able to lazily construct a DwarfContextInMemory for the loaded object (doing this lazily would be preferable for us because the majority of objects never get asked for their debug info). On the other hand, cloning a loaded object info was always a bit of a hack, so now is probably the right time to figure out how to do it properly.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 19, 2016 at 4:06 PM, Lang Hames via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: lhames<br>
Date: Tue Jan 19 15:06:38 2016<br>
New Revision: 258185<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=258185&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=258185&view=rev</a><br>
Log:<br>
[Orc] Refactor ObjectLinkingLayer::addObjectSet to defer loading objects until<br>
they're needed.<br>
<br>
Prior to this patch objects were loaded (via RuntimeDyld::loadObject) when they<br>
were added to the ObjectLinkingLayer, but were not relocated and finalized until<br>
a symbol address was requested. In the interim, another object could be loaded<br>
and finalized with the same memory manager, causing relocation/finalization of<br>
the first object to fail (as the first finalization call may have marked the<br>
allocated memory for the first object read-only).<br>
<br>
By deferring the loadObject call (and subsequent memory allocations) until an<br>
object file is needed we can avoid prematurely finalizing memory.<br>
<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h<br>
    llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br>
    llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br>
    llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h<br>
    llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h?rev=258185&r1=258184&r2=258185&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h?rev=258185&r1=258184&r2=258185&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h Tue Jan 19 15:06:38 2016<br>
@@ -15,6 +15,7 @@<br>
 #define LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H<br>
<br>
 #include "llvm/IR/GlobalValue.h"<br>
+#include "llvm/Object/SymbolicFile.h"<br>
<br>
 namespace llvm {<br>
<br>
@@ -69,7 +70,16 @@ public:<br>
     if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())<br>
       Flags |= JITSymbolFlags::Exported;<br>
     return Flags;<br>
+  }<br>
<br>
+  static JITSymbolFlags<br>
+  flagsFromObjectSymbol(const object::BasicSymbolRef &Symbol) {<br>
+    JITSymbolFlags Flags = JITSymbolFlags::None;<br>
+    if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)<br>
+      Flags |= JITSymbolFlags::Weak;<br>
+    if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)<br>
+      Flags |= JITSymbolFlags::Exported;<br>
+    return Flags;<br>
   }<br>
<br>
 private:<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h?rev=258185&r1=258184&r2=258185&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h?rev=258185&r1=258184&r2=258185&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h Tue Jan 19 15:06:38 2016<br>
@@ -37,9 +37,6 @@ public:<br>
 private:<br>
   typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;<br>
<br>
-  typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;<br>
-  typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec;<br>
-<br>
 public:<br>
   /// @brief Handle to a set of compiled modules.<br>
   typedef ObjSetHandleT ModuleSetHandleT;<br>
@@ -62,28 +59,29 @@ public:<br>
   ModuleSetHandleT addModuleSet(ModuleSetT Ms,<br>
                                 MemoryManagerPtrT MemMgr,<br>
                                 SymbolResolverPtrT Resolver) {<br>
-    OwningObjectVec Objects;<br>
-    OwningBufferVec Buffers;<br>
+    std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>><br>
+      Objects;<br>
<br>
     for (const auto &M : Ms) {<br>
-      std::unique_ptr<object::ObjectFile> Object;<br>
-      std::unique_ptr<MemoryBuffer> Buffer;<br>
+      auto Object =<br>
+        llvm::make_unique<object::OwningBinary<object::ObjectFile>>();<br>
<br>
       if (ObjCache)<br>
-        std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();<br>
+        *Object = tryToLoadFromObjectCache(*M);<br>
<br>
-      if (!Object) {<br>
-        std::tie(Object, Buffer) = Compile(*M).takeBinary();<br>
+      if (!Object->getBinary()) {<br>
+        *Object = Compile(*M);<br>
         if (ObjCache)<br>
-          ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());<br>
+          ObjCache->notifyObjectCompiled(&*M,<br>
+                                     Object->getBinary()->getMemoryBufferRef());<br>
       }<br>
<br>
       Objects.push_back(std::move(Object));<br>
-      Buffers.push_back(std::move(Buffer));<br>
     }<br>
<br>
     ModuleSetHandleT H =<br>
-      BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver));<br>
+      BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),<br>
+                             std::move(Resolver));<br>
<br>
     return H;<br>
   }<br>
<br>
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h?rev=258185&r1=258184&r2=258185&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h?rev=258185&r1=258184&r2=258185&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h (original)<br>
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h Tue Jan 19 15:06:38 2016<br>
@@ -26,7 +26,6 @@ namespace orc {<br>
<br>
 class ObjectLinkingLayerBase {<br>
 protected:<br>
-<br>
   /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.<br>
   ///<br>
   /// An instance of this class will be created for each set of objects added<br>
@@ -38,38 +37,32 @@ protected:<br>
     LinkedObjectSet(const LinkedObjectSet&) = delete;<br>
     void operator=(const LinkedObjectSet&) = delete;<br>
   public:<br>
-    LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,<br>
-                    RuntimeDyld::SymbolResolver &Resolver,<br>
-                    bool ProcessAllSections)<br>
-        : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),<br>
-          State(Raw) {<br>
-      RTDyld->setProcessAllSections(ProcessAllSections);<br>
-    }<br>
-<br>
+    LinkedObjectSet() = default;<br>
     virtual ~LinkedObjectSet() {}<br>
<br>
-    std::unique_ptr<RuntimeDyld::LoadedObjectInfo><br>
-    addObject(const object::ObjectFile &Obj) {<br>
-      return RTDyld->loadObject(Obj);<br>
-    }<br>
-<br>
-    RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {<br>
-      return RTDyld->getSymbol(Name);<br>
-    }<br>
+    virtual void finalize() = 0;<br>
<br>
-    bool NeedsFinalization() const { return (State == Raw); }<br>
+    virtual JITSymbol::GetAddressFtor<br>
+    getSymbolMaterializer(std::string Name) = 0;<br>
<br>
-    virtual void Finalize() = 0;<br>
+    virtual void mapSectionAddress(const void *LocalAddress,<br>
+                                   TargetAddress TargetAddr) const = 0;<br>
<br>
-    void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {<br>
-      assert((State != Finalized) &&<br>
-             "Attempting to remap sections for finalized objects.");<br>
-      RTDyld->mapSectionAddress(LocalAddress, TargetAddr);<br>
+    JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {<br>
+      auto SymEntry = SymbolTable.find(Name);<br>
+      if (SymEntry == SymbolTable.end())<br>
+        return nullptr;<br>
+      if (!SymEntry->second.isExported() && ExportedSymbolsOnly)<br>
+        return nullptr;<br>
+      if (!Finalized)<br>
+        return JITSymbol(getSymbolMaterializer(Name),<br>
+                         SymEntry->second.getFlags());<br>
+      return JITSymbol(SymEntry->second.getAddress(),<br>
+                       SymEntry->second.getFlags());<br>
     }<br>
-<br>
   protected:<br>
-    std::unique_ptr<RuntimeDyld> RTDyld;<br>
-    enum { Raw, Finalizing, Finalized } State;<br>
+    StringMap<RuntimeDyld::SymbolInfo> SymbolTable;<br>
+    bool Finalized = false;<br>
   };<br>
<br>
   typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;<br>
@@ -79,6 +72,7 @@ public:<br>
   typedef LinkedObjectSetListT::iterator ObjSetHandleT;<br>
 };<br>
<br>
+<br>
 /// @brief Default (no-op) action to perform when loading objects.<br>
 class DoNothingOnNotifyLoaded {<br>
 public:<br>
@@ -95,34 +89,124 @@ public:<br>
 /// symbols.<br>
 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded><br>
 class ObjectLinkingLayer : public ObjectLinkingLayerBase {<br>
+public:<br>
+<br>
+  /// @brief Functor for receiving finalization notifications.<br>
+  typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;<br>
+<br>
 private:<br>
<br>
-  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT><br>
+  template <typename ObjSetT, typename MemoryManagerPtrT,<br>
+            typename SymbolResolverPtrT, typename FinalizerFtor><br>
   class ConcreteLinkedObjectSet : public LinkedObjectSet {<br>
   public:<br>
-    ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,<br>
+    ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,<br>
                             SymbolResolverPtrT Resolver,<br>
+                            FinalizerFtor Finalizer,<br>
                             bool ProcessAllSections)<br>
-      : LinkedObjectSet(*MemMgr, *Resolver, ProcessAllSections),<br>
-        MemMgr(std::move(MemMgr)), Resolver(std::move(Resolver)) { }<br>
+      : MemMgr(std::move(MemMgr)),<br>
+        PFC(make_unique<PreFinalizeContents>(std::move(Objects),<br>
+                                             std::move(Resolver),<br>
+                                             std::move(Finalizer),<br>
+                                             ProcessAllSections)) {<br>
+      buildInitialSymbolTable(PFC->Objects);<br>
+    }<br>
+<br>
+    void setHandle(ObjSetHandleT H) {<br>
+      PFC->Handle = H;<br>
+    }<br>
+<br>
+    void finalize() override {<br>
+      assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");<br>
+<br>
+      RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);<br>
+      RTDyld.setProcessAllSections(PFC->ProcessAllSections);<br>
+      PFC->RTDyld = &RTDyld;<br>
+<br>
+      PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),<br>
+                     [&]() {<br>
+                       updateSymbolTable(RTDyld);<br>
+                       Finalized = true;<br>
+                     });<br>
+<br>
+      // Release resources.<br>
+      PFC = nullptr;<br>
+    }<br>
+<br>
+    JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {<br>
+      return<br>
+        [this, Name]() {<br>
+          // The symbol may be materialized between the creation of this lambda<br>
+          // and its execution, so we need to double check.<br>
+          if (!Finalized)<br>
+            finalize();<br>
+          return getSymbol(Name, false).getAddress();<br>
+        };<br>
+    }<br>
<br>
-    void Finalize() override {<br>
-      State = Finalizing;<br>
-      RTDyld->finalizeWithMemoryManagerLocking();<br>
-      State = Finalized;<br>
+    void mapSectionAddress(const void *LocalAddress,<br>
+                           TargetAddress TargetAddr) const override {<br>
+      assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");<br>
+      assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");<br>
+      PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);<br>
     }<br>
<br>
   private:<br>
+<br>
+    void buildInitialSymbolTable(const ObjSetT &Objects) {<br>
+      for (const auto &Obj : Objects)<br>
+        for (auto &Symbol : getObject(*Obj).symbols()) {<br>
+          if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)<br>
+            continue;<br>
+          ErrorOr<StringRef> SymbolName = Symbol.getName();<br>
+          // FIXME: Raise an error for bad symbols.<br>
+          if (!SymbolName)<br>
+            continue;<br>
+          auto Flags = JITSymbol::flagsFromObjectSymbol(Symbol);<br>
+          SymbolTable.insert(<br>
+            std::make_pair(*SymbolName, RuntimeDyld::SymbolInfo(0, Flags)));<br>
+        }<br>
+    }<br>
+<br>
+    void updateSymbolTable(const RuntimeDyld &RTDyld) {<br>
+      for (auto &SymEntry : SymbolTable)<br>
+        SymEntry.second = RTDyld.getSymbol(SymEntry.first());<br>
+    }<br>
+<br>
+    // Contains the information needed prior to finalization: the object files,<br>
+    // memory manager, resolver, and flags needed for RuntimeDyld.<br>
+    struct PreFinalizeContents {<br>
+      PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,<br>
+                          FinalizerFtor Finalizer, bool ProcessAllSections)<br>
+        : Objects(std::move(Objects)), Resolver(std::move(Resolver)),<br>
+          Finalizer(std::move(Finalizer)),<br>
+          ProcessAllSections(ProcessAllSections) {}<br>
+<br>
+      ObjSetT Objects;<br>
+      SymbolResolverPtrT Resolver;<br>
+      FinalizerFtor Finalizer;<br>
+      bool ProcessAllSections;<br>
+      ObjSetHandleT Handle;<br>
+      RuntimeDyld *RTDyld;<br>
+    };<br>
+<br>
     MemoryManagerPtrT MemMgr;<br>
-    SymbolResolverPtrT Resolver;<br>
+    std::unique_ptr<PreFinalizeContents> PFC;<br>
   };<br>
<br>
-  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT><br>
-  std::unique_ptr<LinkedObjectSet><br>
-  createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver,<br>
+  template <typename ObjSetT, typename MemoryManagerPtrT,<br>
+            typename SymbolResolverPtrT, typename FinalizerFtor><br>
+  std::unique_ptr<<br>
+    ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,<br>
+                            SymbolResolverPtrT, FinalizerFtor>><br>
+  createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,<br>
+                        SymbolResolverPtrT Resolver,<br>
+                        FinalizerFtor Finalizer,<br>
                         bool ProcessAllSections) {<br>
-    typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;<br>
-    return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver),<br>
+    typedef ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,<br>
+                                    SymbolResolverPtrT, FinalizerFtor> LOS;<br>
+    return llvm::make_unique<LOS>(std::move(Objects), std::move(MemMgr),<br>
+                                  std::move(Resolver), std::move(Finalizer),<br>
                                   ProcessAllSections);<br>
   }<br>
<br>
@@ -133,9 +217,6 @@ public:<br>
   typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>><br>
       LoadedObjInfoList;<br>
<br>
-  /// @brief Functor for receiving finalization notifications.<br>
-  typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;<br>
-<br>
   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,<br>
   ///        and NotifyFinalized functors.<br>
   ObjectLinkingLayer(<br>
@@ -169,22 +250,39 @@ public:<br>
   template <typename ObjSetT,<br>
             typename MemoryManagerPtrT,<br>
             typename SymbolResolverPtrT><br>
-  ObjSetHandleT addObjectSet(const ObjSetT &Objects,<br>
+  ObjSetHandleT addObjectSet(ObjSetT Objects,<br>
                              MemoryManagerPtrT MemMgr,<br>
                              SymbolResolverPtrT Resolver) {<br>
-    ObjSetHandleT Handle =<br>
-      LinkedObjSetList.insert(<br>
-        LinkedObjSetList.end(),<br>
-        createLinkedObjectSet(std::move(MemMgr), std::move(Resolver),<br>
-                              ProcessAllSections));<br>
<br>
-    LinkedObjectSet &LOS = **Handle;<br>
-    LoadedObjInfoList LoadedObjInfos;<br>
-<br>
-    for (auto &Obj : Objects)<br>
-      LoadedObjInfos.push_back(LOS.addObject(*Obj));<br>
-<br>
-    NotifyLoaded(Handle, Objects, LoadedObjInfos);<br>
+    auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,<br>
+                         const ObjSetT &Objs,<br>
+                         std::function<void()> LOSHandleLoad) {<br>
+      LoadedObjInfoList LoadedObjInfos;<br>
+<br>
+      for (auto &Obj : Objs)<br>
+        LoadedObjInfos.push_back(RTDyld.loadObject(getObject(*Obj)));<br>
+<br>
+      LOSHandleLoad();<br>
+<br>
+      NotifyLoaded(H, Objs, LoadedObjInfos);<br>
+<br>
+      RTDyld.finalizeWithMemoryManagerLocking();<br>
+<br>
+      if (NotifyFinalized)<br>
+        NotifyFinalized(H);<br>
+    };<br>
+<br>
+    auto LOS =<br>
+      createLinkedObjectSet(std::move(Objects), std::move(MemMgr),<br>
+                            std::move(Resolver), std::move(Finalizer),<br>
+                            ProcessAllSections);<br>
+    // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle<br>
+    // below.<br>
+    auto *LOSPtr = LOS.get();<br>
+<br>
+    ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),<br>
+                                                   std::move(LOS));<br>
+    LOSPtr->setHandle(Handle);<br>
<br>
     return Handle;<br>
   }<br>
@@ -224,33 +322,7 @@ public:<br>
   ///         given object set.<br>
   JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,<br>
                          bool ExportedSymbolsOnly) {<br>
-    if (auto Sym = (*H)->getSymbol(Name)) {<br>
-      if (Sym.isExported() || !ExportedSymbolsOnly) {<br>
-        auto Addr = Sym.getAddress();<br>
-        auto Flags = Sym.getFlags();<br>
-        if (!(*H)->NeedsFinalization()) {<br>
-          // If this instance has already been finalized then we can just return<br>
-          // the address.<br>
-          return JITSymbol(Addr, Flags);<br>
-        } else {<br>
-          // If this instance needs finalization return a functor that will do<br>
-          // it. The functor still needs to double-check whether finalization is<br>
-          // required, in case someone else finalizes this set before the<br>
-          // functor is called.<br>
-          auto GetAddress =<br>
-            [this, Addr, H]() {<br>
-              if ((*H)->NeedsFinalization()) {<br>
-                (*H)->Finalize();<br>
-                if (NotifyFinalized)<br>
-                  NotifyFinalized(H);<br>
-              }<br>
-              return Addr;<br>
-            };<br>
-          return JITSymbol(std::move(GetAddress), Flags);<br>
-        }<br>
-      }<br>
-    }<br>
-    return nullptr;<br>
+    return (*H)->getSymbol(Name, ExportedSymbolsOnly);<br>
   }<br>
<br>
   /// @brief Map section addresses for the objects associated with the handle H.<br>
@@ -263,12 +335,21 @@ public:<br>
   ///        given handle.<br>
   /// @param H Handle for object set to emit/finalize.<br>
   void emitAndFinalize(ObjSetHandleT H) {<br>
-    (*H)->Finalize();<br>
-    if (NotifyFinalized)<br>
-      NotifyFinalized(H);<br>
+    (*H)->finalize();<br>
   }<br>
<br>
 private:<br>
+<br>
+  static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {<br>
+    return Obj;<br>
+  }<br>
+<br>
+  template <typename ObjT><br>
+  static const object::ObjectFile&<br>
+  getObject(const object::OwningBinary<ObjT> &Obj) {<br>
+    return *Obj.getBinary();<br>
+  }<br>
+<br>
   LinkedObjectSetListT LinkedObjSetList;<br>
   NotifyLoadedFtor NotifyLoaded;<br>
   NotifyFinalizedFtor NotifyFinalized;<br>
<br>
Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h?rev=258185&r1=258184&r2=258185&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h?rev=258185&r1=258184&r2=258185&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h (original)<br>
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h Tue Jan 19 15:06:38 2016<br>
@@ -178,11 +178,10 @@ public:<br>
   }<br>
<br>
   void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {<br>
-    std::unique_ptr<object::ObjectFile> Obj;<br>
-    std::unique_ptr<MemoryBuffer> Buf;<br>
-    std::tie(Obj, Buf) = O.takeBinary();<br>
-    std::vector<std::unique_ptr<object::ObjectFile>> Objs;<br>
-    Objs.push_back(std::move(Obj));<br>
+    std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs;<br>
+    Objs.push_back(<br>
+      llvm::make_unique<object::OwningBinary<object::ObjectFile>>(<br>
+        std::move(O)));<br>
     ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);<br>
   }<br>
<br>
@@ -284,12 +283,12 @@ private:<br>
<br>
   class NotifyObjectLoadedT {<br>
   public:<br>
-    typedef std::vector<std::unique_ptr<object::ObjectFile>> ObjListT;<br>
     typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>><br>
         LoadedObjInfoListT;<br>
<br>
     NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}<br>
<br>
+    template <typename ObjListT><br>
     void operator()(ObjectLinkingLayerBase::ObjSetHandleT H,<br>
                     const ObjListT &Objects,<br>
                     const LoadedObjInfoListT &Infos) const {<br>
@@ -298,10 +297,21 @@ private:<br>
       assert(Objects.size() == Infos.size() &&<br>
              "Incorrect number of Infos for Objects.");<br>
       for (unsigned I = 0; I < Objects.size(); ++I)<br>
-        M.MemMgr.notifyObjectLoaded(&M, *Objects[I]);<br>
+        M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I]));<br>
     }<br>
<br>
   private:<br>
+<br>
+    static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {<br>
+      return Obj;<br>
+    }<br>
+<br>
+    template <typename ObjT><br>
+    static const object::ObjectFile&<br>
+    getObject(const object::OwningBinary<ObjT> &Obj) {<br>
+      return *Obj.getBinary();<br>
+    }<br>
+<br>
     OrcMCJITReplacement &M;<br>
   };<br>
<br>
<br>
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp?rev=258185&r1=258184&r2=258185&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp?rev=258185&r1=258184&r2=258185&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp (original)<br>
+++ llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp Tue Jan 19 15:06:38 2016<br>
@@ -12,6 +12,7 @@<br>
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"<br>
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"<br>
 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"<br>
+#include "llvm/ExecutionEngine/Orc/NullResolver.h"<br>
 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/LLVMContext.h"<br>
@@ -29,6 +30,13 @@ class ObjectLinkingLayerExecutionTest :<br>
 class SectionMemoryManagerWrapper : public SectionMemoryManager {<br>
 public:<br>
   int FinalizationCount = 0;<br>
+  int NeedsToReserveAllocationSpaceCount = 0;<br>
+<br>
+  bool needsToReserveAllocationSpace() override {<br>
+    ++NeedsToReserveAllocationSpaceCount;<br>
+    return SectionMemoryManager::needsToReserveAllocationSpace();<br>
+  }<br>
+<br>
   bool finalizeMemory(std::string *ErrMsg = 0) override {<br>
     ++FinalizationCount;<br>
     return SectionMemoryManager::finalizeMemory(ErrMsg);<br>
@@ -178,4 +186,68 @@ TEST_F(ObjectLinkingLayerExecutionTest,<br>
       << "Extra call to finalize";<br>
 }<br>
<br>
+TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) {<br>
+<br>
+  if (!TM)<br>
+    return;<br>
+<br>
+  ObjectLinkingLayer<> ObjLayer;<br>
+  SimpleCompiler Compile(*TM);<br>
+<br>
+  // Create a pair of unrelated modules:<br>
+  //<br>
+  // Module 1:<br>
+  //   int foo() { return 42; }<br>
+  // Module 2:<br>
+  //   int bar() { return 7; }<br>
+  //<br>
+  // Both modules will share a memory manager. We want to verify that the<br>
+  // second object is not loaded before the first one is finalized. To do this<br>
+  // in a portable way, we abuse the<br>
+  // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is<br>
+  // called once per object before any sections are allocated.<br>
+<br>
+  ModuleBuilder MB1(getGlobalContext(), "", "dummy");<br>
+  {<br>
+    MB1.getModule()->setDataLayout(TM->createDataLayout());<br>
+    Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");<br>
+    BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",<br>
+                                              BarImpl);<br>
+    IRBuilder<> Builder(BarEntry);<br>
+    IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);<br>
+    Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);<br>
+    Builder.CreateRet(FourtyTwo);<br>
+  }<br>
+<br>
+  auto Obj1 = Compile(*MB1.getModule());<br>
+  std::vector<object::ObjectFile*> Obj1Set;<br>
+  Obj1Set.push_back(Obj1.getBinary());<br>
+<br>
+  ModuleBuilder MB2(getGlobalContext(), "", "dummy");<br>
+  {<br>
+    MB2.getModule()->setDataLayout(TM->createDataLayout());<br>
+    Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");<br>
+    BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",<br>
+                                              BarImpl);<br>
+    IRBuilder<> Builder(BarEntry);<br>
+    IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);<br>
+    Value *Seven = ConstantInt::getSigned(Int32Ty, 7);<br>
+    Builder.CreateRet(Seven);<br>
+  }<br>
+  auto Obj2 = Compile(*MB2.getModule());<br>
+  std::vector<object::ObjectFile*> Obj2Set;<br>
+  Obj2Set.push_back(Obj2.getBinary());<br>
+<br>
+  SectionMemoryManagerWrapper SMMW;<br>
+  NullResolver NR;<br>
+  auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);<br>
+  ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);<br>
+  ObjLayer.emitAndFinalize(H);<br>
+<br>
+  // Only one call to needsToReserveAllocationSpace should have been made.<br>
+  EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)<br>
+      << "More than one call to needsToReserveAllocationSpace "<br>
+         "(multiple unrelated objects loaded prior to finalization)";<br>
+}<br>
+<br>
 }<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>