[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