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

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 2 09:06:37 PST 2016


HI Keno,

You're right. If I recall correctly the change to RuntimeDyld's lifetime
was orthogonal to the the actual aim of this patch (enabling shared memory
managers). I believe it was just a convenient memory optimization - the
idea was to extract the symbol table and ditch the RuntimeDyld instance as
early as possible.

I'd love to tackle loaded-object-info problem "The Right Way", but I'm
short on time at the moment. If the shortened RuntimeDyld lifetime is a
problem for you I can just remove the optimization for now.

Cheers,
Lang.


On Tue, Mar 1, 2016 at 9:33 PM, Keno Fischer <keno at juliacomputing.com>
wrote:

> 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/2d7fb088/attachment.html>


More information about the llvm-commits mailing list