diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 3ec6f2ab269..5ed8935980f 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -234,6 +234,10 @@ public: virtual ~IndirectStubsManagerBase() {} + /// @brief Create a single stub with the given name, target address and flags. + virtual std::error_code createStub(StringRef StubName, TargetAddress StubAddr, + JITSymbolFlags StubFlags) = 0; + /// @brief Create StubInits.size() stubs with the given names, target /// addresses, and flags. virtual std::error_code createStubs(const StubInitsMap &StubInits) = 0; @@ -252,25 +256,29 @@ private: virtual void anchor(); }; -/// @brief IndirectStubsManager implementation for a concrete target, e.g. OrcX86_64. -/// (See OrcTargetSupport.h). +/// @brief IndirectStubsManager implementation for a concrete target, e.g. +/// OrcX86_64. (See OrcTargetSupport.h). template class IndirectStubsManager : public IndirectStubsManagerBase { public: - std::error_code - createStubs(const StubInitsMap &StubInits) override { - if (auto EC = TargetT::emitIndirectStubsBlock(IndirectStubsInfo, - StubInits.size(), - nullptr)) + std::error_code createStub(StringRef StubName, TargetAddress StubAddr, + JITSymbolFlags StubFlags) override { + if (auto EC = reserveStubs(1)) return EC; - unsigned I = 0; - for (auto &Entry : StubInits) { - *IndirectStubsInfo.getPtr(I) = - reinterpret_cast(static_cast(Entry.second.first)); - StubIndexes[Entry.first()] = std::make_pair(I++, Entry.second.second); - } + createStubInternal(StubName, StubAddr, StubFlags); + + return std::error_code(); + } + + std::error_code createStubs(const StubInitsMap &StubInits) override { + if (auto EC = reserveStubs(StubInits.size())) + return EC; + + for (auto &Entry : StubInits) + createStubInternal(Entry.first(), Entry.second.first, + Entry.second.second); return std::error_code(); } @@ -279,7 +287,8 @@ public: auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; - void *StubAddr = IndirectStubsInfo.getStub(I->second.first); + auto Key = I->second.first; + void *StubAddr = IndirectStubsInfos[Key.first].getStub(Key.second); assert(StubAddr && "Missing stub address"); auto StubTargetAddr = static_cast(reinterpret_cast(StubAddr)); @@ -293,23 +302,54 @@ public: auto I = StubIndexes.find(Name); if (I == StubIndexes.end()) return nullptr; - void *PtrAddr = IndirectStubsInfo.getPtr(StubIndexes[Name].first); + auto Key = I->second.first; + void *PtrAddr = IndirectStubsInfos[Key.first].getPtr(Key.second); assert(PtrAddr && "Missing pointer address"); auto PtrTargetAddr = static_cast(reinterpret_cast(PtrAddr)); - return JITSymbol(PtrTargetAddr, JITSymbolFlags::None); + return JITSymbol(PtrTargetAddr, I->second.second); } std::error_code updatePointer(StringRef Name, TargetAddress NewAddr) override { - assert(StubIndexes.count(Name) && "No stub pointer for symbol"); - *IndirectStubsInfo.getPtr(StubIndexes[Name].first) = + auto I = StubIndexes.find(Name); + assert(I != StubIndexes.end() && "No stub pointer for symbol"); + auto Key = I->second.first; + *IndirectStubsInfos[Key.first].getPtr(Key.second) = reinterpret_cast(static_cast(NewAddr)); return std::error_code(); } private: - typename TargetT::IndirectStubsInfo IndirectStubsInfo; - StringMap> StubIndexes; + + std::error_code reserveStubs(unsigned NumStubs) { + if (NumStubs <= FreeStubs.size()) + return std::error_code(); + + unsigned NewStubsRequired = NumStubs - FreeStubs.size(); + unsigned NewBlockId = IndirectStubsInfos.size(); + typename TargetT::IndirectStubsInfo ISI; + if (auto EC = TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, + nullptr)) + return EC; + for (unsigned I = 0; I < ISI.getNumStubs(); ++I) + FreeStubs.push_back(std::make_pair(NewBlockId, I)); + IndirectStubsInfos.push_back(std::move(ISI)); + return std::error_code(); + } + + void createStubInternal(StringRef StubName, TargetAddress InitAddr, + JITSymbolFlags StubFlags) { + auto Key = FreeStubs.back(); + FreeStubs.pop_back(); + *IndirectStubsInfos[Key.first].getPtr(Key.second) = + reinterpret_cast(static_cast(InitAddr)); + StubIndexes[StubName] = std::make_pair(Key, StubFlags); + } + + std::vector IndirectStubsInfos; + typedef std::pair StubKey; + std::vector FreeStubs; + StringMap> StubIndexes; }; /// @brief Build a function pointer of FunctionType with the given constant diff --git a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h index bf0e41e9f1f..2637ea593d5 100644 --- a/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h +++ b/include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h @@ -59,6 +59,8 @@ public: const static unsigned PtrSize = 8; IndirectStubsInfo() : NumStubs(0) {} + IndirectStubsInfo(IndirectStubsInfo&&); + IndirectStubsInfo& operator=(IndirectStubsInfo&&); ~IndirectStubsInfo(); /// @brief Number of stubs in this block. diff --git a/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp index a7d54a2734a..1e2d58cd562 100644 --- a/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp +++ b/lib/ExecutionEngine/Orc/OrcTargetSupport.cpp @@ -144,6 +144,22 @@ OrcX86_64::insertCompileCallbackTrampolines(Module &M, return GetLabelName; } +OrcX86_64::IndirectStubsInfo::IndirectStubsInfo(IndirectStubsInfo &&Other) { + StubsBlock = std::move(Other.StubsBlock); + PtrsBlock = std::move(Other.PtrsBlock); + Other.StubsBlock = sys::MemoryBlock(); + Other.PtrsBlock = sys::MemoryBlock(); +} + +OrcX86_64::IndirectStubsInfo& +OrcX86_64::IndirectStubsInfo::operator=(IndirectStubsInfo &&Other) { + StubsBlock = std::move(Other.StubsBlock); + PtrsBlock = std::move(Other.PtrsBlock); + Other.StubsBlock = sys::MemoryBlock(); + Other.PtrsBlock = sys::MemoryBlock(); + return *this; +} + OrcX86_64::IndirectStubsInfo::~IndirectStubsInfo() { sys::Memory::releaseMappedMemory(StubsBlock); sys::Memory::releaseMappedMemory(PtrsBlock); diff --git a/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp index bfed9bbe73a..ecfefe47c36 100644 --- a/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp @@ -33,6 +33,11 @@ public: class DummyStubsManager : public orc::IndirectStubsManagerBase { public: + std::error_code createStub(StringRef StubName, TargetAddress InitAddr, + JITSymbolFlags Flags) override { + llvm_unreachable("Not implemented"); + } + std::error_code createStubs(const StubInitsMap &StubInits) override { llvm_unreachable("Not implemented"); }