[Orc] Teach IndirectStubsManager to manage an expandable pool of stubs, rather
authorLang Hames <lhames@gmail.com>
Thu, 29 Oct 2015 22:04:22 +0000 (22:04 +0000)
committerLang Hames <lhames@gmail.com>
Thu, 29 Oct 2015 22:04:22 +0000 (22:04 +0000)
than a pre-allocated slab of stubs. Also add a convenience method for creating a
single stub, rather than a whole block a time.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251658 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
include/llvm/ExecutionEngine/Orc/OrcTargetSupport.h
lib/ExecutionEngine/Orc/OrcTargetSupport.cpp
unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp

index 3ec6f2a..5ed8935 100644 (file)
@@ -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 <typename TargetT>
 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<void*>(static_cast<uintptr_t>(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<TargetAddress>(reinterpret_cast<uintptr_t>(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<TargetAddress>(reinterpret_cast<uintptr_t>(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<void*>(static_cast<uintptr_t>(NewAddr));
     return std::error_code();
   }
 
 private:
-  typename TargetT::IndirectStubsInfo IndirectStubsInfo;
-  StringMap<std::pair<unsigned, JITSymbolFlags>> 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<void*>(static_cast<uintptr_t>(InitAddr));
+    StubIndexes[StubName] = std::make_pair(Key, StubFlags);
+  }
+
+  std::vector<typename TargetT::IndirectStubsInfo> IndirectStubsInfos;
+  typedef std::pair<uint16_t, uint16_t> StubKey;
+  std::vector<StubKey> FreeStubs;
+  StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
 };
 
 /// @brief Build a function pointer of FunctionType with the given constant
index bf0e41e..2637ea5 100644 (file)
@@ -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.
index a7d54a2..1e2d58c 100644 (file)
@@ -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);
index bfed9bb..ecfefe4 100644 (file)
@@ -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");
   }