[llvm] r258185 - [Orc] Refactor ObjectLinkingLayer::addObjectSet to defer loading objects until

Keno Fischer via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 1 21:33:12 PST 2016


If I'm reading this correctly, this changes the lifetime of the RuntimeDyld.
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.

On Tue, Jan 19, 2016 at 4:06 PM, Lang Hames via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

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


More information about the llvm-commits mailing list