[Orc][RuntimeDyld] Prevent duplicate calls to finalizeMemory on shared memory
[oota-llvm.git] / include / llvm / ExecutionEngine / Orc / ObjectLinkingLayer.h
index a1d6c48ecd0e0fc52238283b1ab1bb01c9e99f55..4dc48f114883ff29a349e708096162e7865adff0 100644 (file)
 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
 
-#include "LookasideRTDyldMM.h"
+#include "JITSymbol.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include <list>
 #include <memory>
 
 namespace llvm {
+namespace orc {
 
 class ObjectLinkingLayerBase {
 protected:
+
   /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
   ///
   /// An instance of this class will be created for each set of objects added
@@ -32,49 +35,48 @@ protected:
   /// had been provided by this instance. Higher level layers are responsible
   /// for taking any action required to handle the missing symbols.
   class LinkedObjectSet {
+    LinkedObjectSet(const LinkedObjectSet&) = delete;
+    void operator=(const LinkedObjectSet&) = delete;
   public:
-    LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM)
-        : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)),
-          State(Raw) {}
+    LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
+                    RuntimeDyld::SymbolResolver &Resolver,
+                    bool ProcessAllSections)
+        : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
+          State(Raw) {
+      RTDyld->setProcessAllSections(ProcessAllSections);
+    }
+
+    virtual ~LinkedObjectSet() {}
 
     std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
     addObject(const object::ObjectFile &Obj) {
       return RTDyld->loadObject(Obj);
     }
 
-    uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
-      if (ExportedSymbolsOnly)
-        return RTDyld->getExportedSymbolLoadAddress(Name);
-      return RTDyld->getSymbolLoadAddress(Name);
+    RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
+      return RTDyld->getSymbol(Name);
     }
 
     bool NeedsFinalization() const { return (State == Raw); }
 
-    void Finalize() {
-      State = Finalizing;
-      RTDyld->resolveRelocations();
-      RTDyld->registerEHFrames();
-      MM->finalizeMemory();
-      State = Finalized;
-    }
+    virtual void Finalize() = 0;
 
-    void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
+    void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
       assert((State != Finalized) &&
              "Attempting to remap sections for finalized objects.");
-      RTDyld->mapSectionAddress(LocalAddress, TargetAddress);
+      RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     }
 
-  private:
-    std::unique_ptr<RTDyldMemoryManager> MM;
+  protected:
     std::unique_ptr<RuntimeDyld> RTDyld;
     enum { Raw, Finalizing, Finalized } State;
   };
 
-  typedef std::list<LinkedObjectSet> LinkedObjectSetListT;
+  typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
 
 public:
   /// @brief Handle to a set of loaded objects.
-  typedef typename LinkedObjectSetListT::iterator ObjSetHandleT;
+  typedef LinkedObjectSetListT::iterator ObjSetHandleT;
 };
 
 /// @brief Default (no-op) action to perform when loading objects.
@@ -93,63 +95,65 @@ public:
 /// symbols.
 template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
 class ObjectLinkingLayer : public ObjectLinkingLayerBase {
-public:
-  /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
-  ///        RuntimeDyld::LoadedObjectInfo instances.
-  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
-      LoadedObjInfoList;
+private:
 
-  /// @brief Default construct an ObjectLinkingLayer.
-  ObjectLinkingLayer() {}
+  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+  class ConcreteLinkedObjectSet : public LinkedObjectSet {
+  public:
+    ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
+                            SymbolResolverPtrT Resolver,
+                            bool ProcessAllSections)
+      : LinkedObjectSet(*MemMgr, *Resolver, ProcessAllSections),
+        MemMgr(std::move(MemMgr)), Resolver(std::move(Resolver)) { }
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded
-  ///        functor.
-  ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded)
-      : NotifyLoaded(std::move(NotifyLoaded)) {}
+    void Finalize() override {
+      State = Finalizing;
+      RTDyld->finalizeWithMemoryManagerLocking();
+      State = Finalized;
+    }
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized
-  ///        functor.
-  ObjectLinkingLayer(std::function<void(ObjSetHandleT)> NotifyFinalized)
-      : NotifyFinalized(std::move(NotifyFinalized)) {}
+  private:
+    MemoryManagerPtrT MemMgr;
+    SymbolResolverPtrT Resolver;
+  };
 
-  /// @brief Construct an ObjectLinkingLayer with the given CreateMemoryManager
-  ///        functor.
-  ObjectLinkingLayer(
-      std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
-      : CreateMemoryManager(std::move(CreateMemoryManager)) {}
+  template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+  std::unique_ptr<LinkedObjectSet>
+  createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver,
+                        bool ProcessAllSections) {
+    typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
+    return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver),
+                                  ProcessAllSections);
+  }
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
-  ///        NotifyFinalized functors.
-  ObjectLinkingLayer(NotifyLoadedFtor NotifyLoaded,
-                     std::function<void(ObjSetHandleT)> NotifyFinalized)
-      : NotifyLoaded(std::move(NotifyLoaded)),
-        NotifyFinalized(std::move(NotifyFinalized)) {}
+public:
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded and
-  ///        CreateMemoryManager functors.
-  ObjectLinkingLayer(
-      NotifyLoadedFtor NotifyLoaded,
-      std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
-      : NotifyLoaded(std::move(NotifyLoaded)),
-        CreateMemoryManager(std::move(CreateMemoryManager)) {}
+  /// @brief LoadedObjectInfo list. Contains a list of owning pointers to
+  ///        RuntimeDyld::LoadedObjectInfo instances.
+  typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
+      LoadedObjInfoList;
 
-  /// @brief Construct an ObjectLinkingLayer with the given NotifyFinalized and
-  ///        CreateMemoryManager functors.
-  ObjectLinkingLayer(
-      std::function<void(ObjSetHandleT)> NotifyFinalized,
-      std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
-      : NotifyFinalized(std::move(NotifyFinalized)),
-        CreateMemoryManager(std::move(CreateMemoryManager)) {}
+  /// @brief Functor for receiving finalization notifications.
+  typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
 
   /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
-  ///        NotifyFinalized and CreateMemoryManager functors.
+  ///        and NotifyFinalized functors.
   ObjectLinkingLayer(
-      NotifyLoadedFtor NotifyLoaded,
-      std::function<void(ObjSetHandleT)> NotifyFinalized,
-      std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager)
+      NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
+      NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
       : NotifyLoaded(std::move(NotifyLoaded)),
         NotifyFinalized(std::move(NotifyFinalized)),
-        CreateMemoryManager(std::move(CreateMemoryManager)) {}
+        ProcessAllSections(false) {}
+
+  /// @brief Set the 'ProcessAllSections' flag.
+  ///
+  /// If set to true, all sections in each object file will be allocated using
+  /// the memory manager, rather than just the sections required for execution.
+  ///
+  /// This is kludgy, and may be removed in the future.
+  void setProcessAllSections(bool ProcessAllSections) {
+    this->ProcessAllSections = ProcessAllSections;
+  }
 
   /// @brief Add a set of objects (or archives) that will be treated as a unit
   ///        for the purposes of symbol lookup and memory management.
@@ -162,19 +166,19 @@ public:
   ///   This version of this method allows the client to pass in an
   /// RTDyldMemoryManager instance that will be used to allocate memory and look
   /// up external symbol addresses for the given objects.
-  template <typename ObjSetT>
+  template <typename ObjSetT,
+            typename MemoryManagerPtrT,
+            typename SymbolResolverPtrT>
   ObjSetHandleT addObjectSet(const ObjSetT &Objects,
-                             std::unique_ptr<RTDyldMemoryManager> MM) {
-
-    if (!MM) {
-      assert(CreateMemoryManager &&
-             "No memory manager or memory manager creator provided.");
-      MM = CreateMemoryManager();
-    }
-
-    ObjSetHandleT Handle = LinkedObjSetList.insert(
-        LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
-    LinkedObjectSet &LOS = *Handle;
+                             MemoryManagerPtrT MemMgr,
+                             SymbolResolverPtrT Resolver) {
+    ObjSetHandleT Handle =
+      LinkedObjSetList.insert(
+        LinkedObjSetList.end(),
+        createLinkedObjectSet(std::move(MemMgr), std::move(Resolver),
+                              ProcessAllSections));
+
+    LinkedObjectSet &LOS = **Handle;
     LoadedObjInfoList LoadedObjInfos;
 
     for (auto &Obj : Objects)
@@ -185,12 +189,6 @@ public:
     return Handle;
   }
 
-  /// @brief Map section addresses for the objects associated with the handle H.
-  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
-                         uint64_t TargetAddress) {
-    H->mapSectionAddress(LocalAddress, TargetAddress);
-  }
-
   /// @brief Remove the set of objects associated with handle H.
   ///
   ///   All memory allocated for the objects will be freed, and the sections and
@@ -204,51 +202,80 @@ public:
     LinkedObjSetList.erase(H);
   }
 
-  /// @brief Get the address of a loaded symbol.
-  ///
-  /// @return The address in the target process's address space of the named
-  ///         symbol. Null if no such symbol is known.
-  ///
-  ///   This method will trigger the finalization of the linked object set
-  /// containing the definition of the given symbol, if it is found.
-  uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
+  /// @brief Search for the given named symbol.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it exists.
+  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
          ++I)
-      if (uint64_t Addr = lookupSymbolAddressIn(I, Name, ExportedSymbolsOnly))
-        return Addr;
+      if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
+        return Symbol;
 
-    return 0;
+    return nullptr;
   }
 
-  /// @brief Search for a given symbol in the context of the set of loaded
-  ///        objects represented by the handle H.
-  ///
-  /// @return The address in the target process's address space of the named
-  ///         symbol. Null if the given object set does not contain a definition
-  ///         of this symbol.
-  ///
-  ///   This method will trigger the finalization of the linked object set
-  /// represented by the handle H if that set contains the requested symbol.
-  uint64_t lookupSymbolAddressIn(ObjSetHandleT H, StringRef Name,
-                                 bool ExportedSymbolsOnly) {
-    if (uint64_t Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) {
-      if (H->NeedsFinalization()) {
-        H->Finalize();
-        if (NotifyFinalized)
-          NotifyFinalized(H);
+  /// @brief Search for the given named symbol in the context of the set of
+  ///        loaded objects represented by the handle H.
+  /// @param H The handle for the object set to search in.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it is found in the
+  ///         given object set.
+  JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
+                         bool ExportedSymbolsOnly) {
+    if (auto Sym = (*H)->getSymbol(Name)) {
+      if (Sym.isExported() || !ExportedSymbolsOnly) {
+        auto Addr = Sym.getAddress();
+        auto Flags = Sym.getFlags();
+        if (!(*H)->NeedsFinalization()) {
+          // If this instance has already been finalized then we can just return
+          // the address.
+          return JITSymbol(Addr, Flags);
+        } else {
+          // If this instance needs finalization return a functor that will do
+          // it. The functor still needs to double-check whether finalization is
+          // required, in case someone else finalizes this set before the
+          // functor is called.
+          auto GetAddress =
+            [this, Addr, H]() {
+              if ((*H)->NeedsFinalization()) {
+                (*H)->Finalize();
+                if (NotifyFinalized)
+                  NotifyFinalized(H);
+              }
+              return Addr;
+            };
+          return JITSymbol(std::move(GetAddress), Flags);
+        }
       }
-      return Addr;
     }
-    return 0;
+    return nullptr;
+  }
+
+  /// @brief Map section addresses for the objects associated with the handle H.
+  void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+                         TargetAddress TargetAddr) {
+    (*H)->mapSectionAddress(LocalAddress, TargetAddr);
+  }
+
+  /// @brief Immediately emit and finalize the object set represented by the
+  ///        given handle.
+  /// @param H Handle for object set to emit/finalize.
+  void emitAndFinalize(ObjSetHandleT H) {
+    (*H)->Finalize();
+    if (NotifyFinalized)
+      NotifyFinalized(H);
   }
 
 private:
   LinkedObjectSetListT LinkedObjSetList;
   NotifyLoadedFtor NotifyLoaded;
-  std::function<void(ObjSetHandleT)> NotifyFinalized;
-  std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateMemoryManager;
+  NotifyFinalizedFtor NotifyFinalized;
+  bool ProcessAllSections;
 };
 
-} // end namespace llvm
+} // End namespace orc.
+} // End namespace llvm
 
 #endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H