[llvm] r327946 - [ORC] Rename SymbolSource to MaterializationUnit, and make the materialization

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 19 20:49:29 PDT 2018


Author: lhames
Date: Mon Mar 19 20:49:29 2018
New Revision: 327946

URL: http://llvm.org/viewvc/llvm-project?rev=327946&view=rev
Log:
[ORC] Rename SymbolSource to MaterializationUnit, and make the materialization
operation all-or-nothing, rather than allowing materialization on a per-symbol
basis.

This addresses a shortcoming of per-symbol materialization: If a
MaterializationUnit (/SymbolSource) wants to materialize more symbols than
requested (which is likely: most materializers will want to materialize whole
modules) then it needs a way to notify the symbol table about the extra symbols
being materialized. This process (checking what has been requested against what
is being provided and notifying the symbol table about the difference) has to
be repeated at every level of the JIT stack. Making materialization
all-or-nothing eliminates this issue, simplifying both materializer
implementations and the symbol table (VSO class) API. The cost is that
per-symbol materialization (e.g. for individual symbols in a module) now
requires multiple MaterializationUnits.

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
    llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp
    llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
    llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h?rev=327946&r1=327945&r2=327946&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/Core.h Mon Mar 19 20:49:29 2018
@@ -157,22 +157,25 @@ createSymbolResolver(LookupFlagsFn &&Loo
       std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
 }
 
-/// @brief Represents a source of symbol definitions which may be materialized
-///        (turned into data / code through some materialization process) or
-///        discarded (if the definition is overridden by a stronger one).
+/// @brief A MaterializationUnit represents a set of symbol definitions that can
+///        be materialized as a group, or individually discarded (when
+///        overriding definitions are encountered).
 ///
-/// SymbolSources are used when providing lazy definitions of symbols to VSOs.
-/// The VSO will call materialize when the address of a symbol is requested via
-/// the lookup method. The VSO will call discard if a stronger definition is
-/// added or already present.
-class SymbolSource {
+/// MaterializationUnits are used when providing lazy definitions of symbols to
+/// VSOs. The VSO will call materialize when the address of a symbol is
+/// requested via the lookup method. The VSO will call discard if a stronger
+/// definition is added or already present.
+class MaterializationUnit {
 public:
-  virtual ~SymbolSource() {}
+  virtual ~MaterializationUnit() {}
 
-  /// @brief Implementations of this method should materialize the given
-  ///        symbols (plus any additional symbols required) by adding a
-  ///        Materializer to the ExecutionSession's MaterializationQueue.
-  virtual Error materialize(VSO &V, SymbolNameSet Symbols) = 0;
+  /// @brief Return the set of symbols that this source provides.
+  virtual SymbolFlagsMap getSymbols() = 0;
+
+  /// @brief Implementations of this method should materialize all symbols
+  ///        in the materialzation unit, except for those that have been
+  ///        previously discarded.
+  virtual Error materialize(VSO &V) = 0;
 
   /// @brief Implementations of this method should discard the given symbol
   ///        from the source (e.g. if the source is an LLVM IR Module and the
@@ -201,10 +204,12 @@ public:
 
   using SetDefinitionsResult =
       std::map<SymbolStringPtr, RelativeLinkageStrength>;
-  using SourceWorkMap = std::map<std::shared_ptr<SymbolSource>, SymbolNameSet>;
+
+  using MaterializationUnitList =
+      std::vector<std::unique_ptr<MaterializationUnit>>;
 
   struct LookupResult {
-    SourceWorkMap MaterializationWork;
+    MaterializationUnitList MaterializationUnits;
     SymbolNameSet UnresolvedSymbols;
   };
 
@@ -231,8 +236,7 @@ public:
   Error define(SymbolMap NewSymbols);
 
   /// @brief Adds the given symbols to the mapping as lazy symbols.
-  Error defineLazy(const SymbolFlagsMap &NewSymbols,
-                   std::shared_ptr<SymbolSource> Source);
+  Error defineLazy(std::unique_ptr<MaterializationUnit> Source);
 
   /// @brief Add the given symbol/address mappings to the dylib, but do not
   ///        mark the symbols as finalized yet.
@@ -265,50 +269,54 @@ public:
 private:
   class MaterializationInfo {
   public:
-    MaterializationInfo(JITSymbolFlags Flags,
-                        std::shared_ptr<SymbolSource> Query);
-    JITSymbolFlags getFlags() const;
-    JITTargetAddress getAddress() const;
-    void replaceWithSource(VSO &V, SymbolStringPtr Name,
-                           JITSymbolFlags NewFlags,
-                           std::shared_ptr<SymbolSource> NewSource);
-    std::shared_ptr<SymbolSource>
-    query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
-    void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
-    void finalize();
+    using QueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
 
-  private:
-    JITSymbolFlags Flags;
-    JITTargetAddress Address = 0;
-    std::shared_ptr<SymbolSource> Source;
-    std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingResolution;
-    std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingFinalization;
+    MaterializationInfo(size_t SymbolsRemaining,
+                        std::unique_ptr<MaterializationUnit> MU);
+
+    uint64_t SymbolsRemaining;
+    std::unique_ptr<MaterializationUnit> MU;
+    SymbolMap Symbols;
+    std::map<SymbolStringPtr, QueryList> PendingResolution;
+    std::map<SymbolStringPtr, QueryList> PendingFinalization;
   };
 
+  using MaterializationInfoSet = std::set<std::unique_ptr<MaterializationInfo>>;
+
+  using MaterializationInfoIterator = MaterializationInfoSet::iterator;
+
   class SymbolTableEntry {
   public:
-    SymbolTableEntry(JITSymbolFlags Flags,
-                     std::shared_ptr<SymbolSource> Source);
+    SymbolTableEntry(JITSymbolFlags SymbolFlags,
+                     MaterializationInfoIterator MaterializationInfoItr);
     SymbolTableEntry(JITEvaluatedSymbol Sym);
     SymbolTableEntry(SymbolTableEntry &&Other);
     ~SymbolTableEntry();
+
+    SymbolTableEntry &operator=(JITEvaluatedSymbol Sym);
+
     JITSymbolFlags getFlags() const;
-    void replaceWithSource(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
-                           std::shared_ptr<SymbolSource> NewSource);
-    std::shared_ptr<SymbolSource>
+    void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
+                     MaterializationInfoIterator NewMaterializationInfoItr);
+    std::unique_ptr<MaterializationUnit>
     query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
     void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
-    void finalize();
+    void finalize(VSO &V, SymbolStringPtr Name);
+    void discard(VSO &V, SymbolStringPtr Name);
 
   private:
+    void destroy();
+
     JITSymbolFlags Flags;
+    MaterializationInfoIterator MII;
     union {
       JITTargetAddress Address;
-      std::unique_ptr<MaterializationInfo> MatInfo;
+      MaterializationInfoIterator MaterializationInfoItr;
     };
   };
 
   std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
+  MaterializationInfoSet MaterializationInfos;
 };
 
 /// @brief An ExecutionSession represents a running JIT program.
@@ -350,15 +358,14 @@ public:
   ErrorReporter ReportError = logErrorsToStdErr;
 };
 
-/// Runs SymbolSource materializations on the current thread and reports errors
-/// to the given ExecutionSession.
+/// Runs Materializers on the current thread and reports errors to the given
+/// ExecutionSession.
 class MaterializeOnCurrentThread {
 public:
   MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {}
 
-  void operator()(VSO &V, std::shared_ptr<SymbolSource> Source,
-                  SymbolNameSet Names) {
-    if (auto Err = Source->materialize(V, std::move(Names)))
+  void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
+    if (auto Err = MU->materialize(V))
       ES.reportError(std::move(Err));
   }
 
@@ -367,8 +374,8 @@ private:
 };
 
 /// Materialization function object wrapper for the lookup method.
-using MaterializationDispatcher = std::function<void(
-    VSO &V, std::shared_ptr<SymbolSource> S, SymbolNameSet Names)>;
+using MaterializationDispatcher =
+    std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>;
 
 /// @brief Look up a set of symbols by searching a list of VSOs.
 ///

Modified: llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp?rev=327946&r1=327945&r2=327946&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/Core.cpp Mon Mar 19 20:49:29 2018
@@ -1,4 +1,4 @@
-//===--------- Core.cpp - Core ORC APIs (SymbolSource, VSO, etc.) ---------===//
+//===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -17,8 +17,8 @@
 namespace llvm {
 namespace orc {
 
+void MaterializationUnit::anchor() {}
 void SymbolResolver::anchor() {}
-void SymbolSource::anchor() {}
 
 AsynchronousSymbolQuery::AsynchronousSymbolQuery(
     const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
@@ -69,68 +69,13 @@ void AsynchronousSymbolQuery::notifySymb
 }
 
 VSO::MaterializationInfo::MaterializationInfo(
-    JITSymbolFlags Flags, std::shared_ptr<SymbolSource> Source)
-    : Flags(std::move(Flags)), Source(std::move(Source)) {}
+    size_t SymbolsRemaining, std::unique_ptr<MaterializationUnit> MU)
+    : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {}
 
-JITSymbolFlags VSO::MaterializationInfo::getFlags() const { return Flags; }
-
-JITTargetAddress VSO::MaterializationInfo::getAddress() const {
-  return Address;
-}
-
-void VSO::MaterializationInfo::replaceWithSource(
-    VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags,
-    std::shared_ptr<SymbolSource> NewSource) {
-  assert(Address == 0 && PendingResolution.empty() &&
-         PendingFinalization.empty() &&
-         "Cannot replace source during or after materialization");
-  Source->discard(V, Name);
-  Flags = std::move(NewFlags);
-  Source = std::move(NewSource);
-}
-
-std::shared_ptr<SymbolSource> VSO::MaterializationInfo::query(
-    SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query) {
-  if (Address == 0) {
-    PendingResolution.push_back(std::move(Query));
-    auto S = std::move(Source);
-    Source = nullptr;
-    return S;
-  }
-
-  Query->setDefinition(Name, JITEvaluatedSymbol(Address, Flags));
-  PendingFinalization.push_back(std::move(Query));
-  return nullptr;
-}
-
-void VSO::MaterializationInfo::resolve(VSO &V, SymbolStringPtr Name,
-                                       JITEvaluatedSymbol Sym) {
-  if (Source) {
-    Source->discard(V, Name);
-    Source = nullptr;
-  }
-
-  // FIXME: Sanity check flags?
-  Flags = Sym.getFlags();
-  Address = Sym.getAddress();
-  for (auto &Query : PendingResolution) {
-    Query->setDefinition(Name, std::move(Sym));
-    PendingFinalization.push_back(std::move(Query));
-  }
-  PendingResolution = {};
-}
-
-void VSO::MaterializationInfo::finalize() {
-  for (auto &Query : PendingFinalization)
-    Query->notifySymbolFinalized();
-  PendingFinalization = {};
-}
-
-VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags,
-                                        std::shared_ptr<SymbolSource> Source)
+VSO::SymbolTableEntry::SymbolTableEntry(
+    JITSymbolFlags Flags, MaterializationInfoIterator MaterializationInfoItr)
     : Flags(JITSymbolFlags::FlagNames(Flags | JITSymbolFlags::NotMaterialized)),
-      MatInfo(
-          llvm::make_unique<MaterializationInfo>(Flags, std::move(Source))) {
+      MaterializationInfoItr(std::move(MaterializationInfoItr)) {
   // FIXME: Assert flag sanity.
 }
 
@@ -144,37 +89,83 @@ VSO::SymbolTableEntry::SymbolTableEntry(
   if (Flags.isMaterialized())
     Address = Other.Address;
   else
-    MatInfo = std::move(Other.MatInfo);
+    MaterializationInfoItr = std::move(Other.MaterializationInfoItr);
 }
 
-VSO::SymbolTableEntry::~SymbolTableEntry() {
+VSO::SymbolTableEntry::~SymbolTableEntry() { destroy(); }
+
+VSO::SymbolTableEntry &VSO::SymbolTableEntry::
+operator=(JITEvaluatedSymbol Sym) {
+  destroy();
+  Flags = Sym.getFlags();
+  Address = Sym.getAddress();
+  return *this;
+}
+
+void VSO::SymbolTableEntry::destroy() {
   if (!Flags.isMaterialized())
-    MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr();
+    MaterializationInfoItr
+        .MaterializationInfoIterator::~MaterializationInfoIterator();
 }
 
 JITSymbolFlags VSO::SymbolTableEntry::getFlags() const { return Flags; }
 
-void VSO::SymbolTableEntry::replaceWithSource(
+void VSO::SymbolTableEntry::replaceWith(
     VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags,
-    std::shared_ptr<SymbolSource> NewSource) {
-  bool ReplaceExisting = !Flags.isMaterialized();
+    MaterializationInfoIterator NewMaterializationInfoItr) {
+  bool ReplaceExistingLazyDefinition = !Flags.isMaterialized();
   Flags = NewFlags;
-  if (ReplaceExisting)
-    MatInfo->replaceWithSource(V, Name, Flags, std::move(NewSource));
-  else
-    new (&MatInfo) std::unique_ptr<MaterializationInfo>(
-        llvm::make_unique<MaterializationInfo>(Flags, std::move(NewSource)));
+  if (ReplaceExistingLazyDefinition) {
+    // If we are replacing an existing lazy definition with a stronger one,
+    // we need to notify the old lazy definition to discard its definition.
+    assert((*MaterializationInfoItr)->MU != nullptr &&
+           (*MaterializationInfoItr)->Symbols.count(Name) == 0 &&
+           (*MaterializationInfoItr)->PendingResolution.count(Name) == 0 &&
+           (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+           "Attempt to replace materializer during materialization");
+
+    if (--(*MaterializationInfoItr)->SymbolsRemaining == 0)
+      V.MaterializationInfos.erase(MaterializationInfoItr);
+  }
+  MaterializationInfoItr = std::move(NewMaterializationInfoItr);
 }
 
-std::shared_ptr<SymbolSource>
+std::unique_ptr<MaterializationUnit>
 VSO::SymbolTableEntry::query(SymbolStringPtr Name,
                              std::shared_ptr<AsynchronousSymbolQuery> Query) {
   if (Flags.isMaterialized()) {
     Query->setDefinition(std::move(Name), JITEvaluatedSymbol(Address, Flags));
     Query->notifySymbolFinalized();
     return nullptr;
-  } else
-    return MatInfo->query(std::move(Name), std::move(Query));
+  } else {
+    if ((*MaterializationInfoItr)->MU) {
+      assert((*MaterializationInfoItr)->PendingResolution.count(Name) == 0 &&
+             (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+             "Materializer should have been activated on first query");
+      (*MaterializationInfoItr)
+          ->PendingResolution[Name]
+          .push_back(std::move(Query));
+      return std::move((*MaterializationInfoItr)->MU);
+    } else {
+      assert((*MaterializationInfoItr)->MU == nullptr &&
+             "Materializer should have been activated on first query");
+      auto SymValueItr = (*MaterializationInfoItr)->Symbols.find(Name);
+      if (SymValueItr == (*MaterializationInfoItr)->Symbols.end()) {
+        // Symbol has not been resolved yet.
+        (*MaterializationInfoItr)
+            ->PendingResolution[Name]
+            .push_back(std::move(Query));
+        return nullptr;
+      } else {
+        // Symbol has already resolved, is just waiting on finalization.
+        Query->setDefinition(Name, SymValueItr->second);
+        (*MaterializationInfoItr)
+            ->PendingFinalization[Name]
+            .push_back(std::move(Query));
+        return nullptr;
+      }
+    }
+  }
 }
 
 void VSO::SymbolTableEntry::resolve(VSO &V, SymbolStringPtr Name,
@@ -185,22 +176,69 @@ void VSO::SymbolTableEntry::resolve(VSO
     //        in VSO?
     Flags = Sym.getFlags();
     Address = Sym.getAddress();
-  } else
-    MatInfo->resolve(V, std::move(Name), std::move(Sym));
+  } else {
+    assert((*MaterializationInfoItr)->MU == nullptr &&
+           "Can not resolve a symbol that has not been materialized");
+    assert((*MaterializationInfoItr)->Symbols.count(Name) == 0 &&
+           "Symbol resolved more than once");
+
+    // Add the symbol to the MaterializationInfo Symbols table.
+    (*MaterializationInfoItr)->Symbols[Name] = Sym;
+
+    // If there are any queries waiting on this symbol then notify them that it
+    // has been resolved, then move them to the PendingFinalization list.
+    auto I = (*MaterializationInfoItr)->PendingResolution.find(Name);
+    if (I != (*MaterializationInfoItr)->PendingResolution.end()) {
+      assert((*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+             "Queries already pending finalization on newly resolved symbol");
+      auto &PendingFinalization =
+          (*MaterializationInfoItr)->PendingFinalization[Name];
+
+      for (auto &Query : I->second) {
+        Query->setDefinition(Name, Sym);
+        PendingFinalization.push_back(Query);
+      }
+
+      // Clear the PendingResolution list for this symbol.
+      (*MaterializationInfoItr)->PendingResolution.erase(I);
+    }
+  }
 }
 
-void VSO::SymbolTableEntry::finalize() {
+void VSO::SymbolTableEntry::finalize(VSO &V, SymbolStringPtr Name) {
   if (!Flags.isMaterialized()) {
-    auto TmpMatInfo = std::move(MatInfo);
-    MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr();
-    // FIXME: Assert flag sanity?
-    Flags = TmpMatInfo->getFlags();
-    Address = TmpMatInfo->getAddress();
-    TmpMatInfo->finalize();
+    auto SymI = (*MaterializationInfoItr)->Symbols.find(Name);
+    assert(SymI != (*MaterializationInfoItr)->Symbols.end() &&
+           "Finalizing an unresolved symbol");
+    auto Sym = SymI->second;
+    (*MaterializationInfoItr)->Symbols.erase(SymI);
+    auto I = (*MaterializationInfoItr)->PendingFinalization.find(Name);
+    if (I != (*MaterializationInfoItr)->PendingFinalization.end()) {
+      for (auto &Query : I->second)
+        Query->notifySymbolFinalized();
+      (*MaterializationInfoItr)->PendingFinalization.erase(I);
+    }
+
+    if (--(*MaterializationInfoItr)->SymbolsRemaining == 0)
+      V.MaterializationInfos.erase(MaterializationInfoItr);
+
+    // Destruct the iterator and re-define this entry using the final symbol
+    // value.
+    MaterializationInfoItr
+        .MaterializationInfoIterator::~MaterializationInfoIterator();
+    Flags = Sym.getFlags();
+    Address = Sym.getAddress();
   }
   assert(Flags.isMaterialized() && "Trying to finalize not-emitted symbol");
 }
 
+void VSO::SymbolTableEntry::discard(VSO &V, SymbolStringPtr Name) {
+  assert((*MaterializationInfoItr)->MU != nullptr &&
+         "Can not override a symbol after it has been materialized");
+  (*MaterializationInfoItr)->MU->discard(V, Name);
+  --(*MaterializationInfoItr)->SymbolsRemaining;
+}
+
 VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old,
                                                  JITSymbolFlags New) {
   if (Old == None)
@@ -249,16 +287,25 @@ Error VSO::define(SymbolMap NewSymbols)
     }
 
     if (I != Symbols.end()) {
-      I->second.resolve(*this, KV.first, std::move(KV.second));
-      I->second.finalize();
+      // This is an override -- discard the overridden definition and overwrite.
+      I->second.discard(*this, KV.first);
+      I->second = std::move(KV.second);
     } else
       Symbols.insert(std::make_pair(KV.first, std::move(KV.second)));
   }
   return Err;
 }
 
-Error VSO::defineLazy(const SymbolFlagsMap &NewSymbols,
-                      std::shared_ptr<SymbolSource> Source) {
+Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
+
+  auto NewSymbols = MU->getSymbols();
+
+  auto MaterializationInfoItr =
+      MaterializationInfos
+          .insert(llvm::make_unique<MaterializationInfo>(NewSymbols.size(),
+                                                         std::move(MU)))
+          .first;
+
   Error Err = Error::success();
   for (auto &KV : NewSymbols) {
     auto I = Symbols.find(KV.first);
@@ -269,22 +316,38 @@ Error VSO::defineLazy(const SymbolFlagsM
         KV.second);
 
     // Discard weaker definitions.
-    if (LinkageResult == ExistingDefinitionIsStronger)
-      Source->discard(*this, KV.first);
+    if (LinkageResult == ExistingDefinitionIsStronger) {
+      (*MaterializationInfoItr)->MU->discard(*this, KV.first);
+      assert((*MaterializationInfoItr)->SymbolsRemaining > 0 &&
+             "Discarding non-existant symbols?");
+      --(*MaterializationInfoItr)->SymbolsRemaining;
+      continue;
+    }
 
     // Report duplicate definition errors.
     if (LinkageResult == DuplicateDefinition) {
       Err = joinErrors(std::move(Err),
                        make_error<orc::DuplicateDefinition>(*KV.first));
+      // Duplicate definitions are discarded, so remove the duplicates from
+      // materializer.
+      assert((*MaterializationInfoItr)->SymbolsRemaining > 0 &&
+             "Discarding non-existant symbols?");
+      --(*MaterializationInfoItr)->SymbolsRemaining;
       continue;
     }
 
     if (I != Symbols.end())
-      I->second.replaceWithSource(*this, KV.first, KV.second, Source);
+      I->second.replaceWith(*this, KV.first, KV.second, MaterializationInfoItr);
     else
-      Symbols.emplace(
-          std::make_pair(KV.first, SymbolTableEntry(KV.second, Source)));
+      Symbols.emplace(std::make_pair(
+          KV.first, SymbolTableEntry(KV.second, MaterializationInfoItr)));
   }
+
+  // If we ended up overriding all definitions in this materializer then delete
+  // it.
+  if ((*MaterializationInfoItr)->SymbolsRemaining == 0)
+    MaterializationInfos.erase(MaterializationInfoItr);
+
   return Err;
 }
 
@@ -300,7 +363,7 @@ void VSO::finalize(SymbolNameSet Symbols
   for (auto &S : SymbolsToFinalize) {
     auto I = Symbols.find(S);
     assert(I != Symbols.end() && "Finalizing symbol not present in this dylib");
-    I->second.finalize();
+    I->second.finalize(*this, S);
   }
 }
 
@@ -325,7 +388,7 @@ SymbolNameSet VSO::lookupFlags(SymbolFla
 
 VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
                               SymbolNameSet Names) {
-  SourceWorkMap MaterializationWork;
+  MaterializationUnitList MaterializationUnits;
 
   for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
     auto Tmp = I++;
@@ -341,11 +404,11 @@ VSO::LookupResult VSO::lookup(std::share
     // Forward the query to the given SymbolTableEntry, and if it return a
     // layer to perform materialization with, add that to the
     // MaterializationWork map.
-    if (auto Source = SymI->second.query(SymI->first, Query))
-      MaterializationWork[Source].insert(SymI->first);
+    if (auto MU = SymI->second.query(SymI->first, Query))
+      MaterializationUnits.push_back(std::move(MU));
   }
 
-  return {std::move(MaterializationWork), std::move(Names)};
+  return {std::move(MaterializationUnits), std::move(Names)};
 }
 
 Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
@@ -400,24 +463,17 @@ Expected<SymbolMap> lookup(const std::ve
       Names, std::move(OnResolve), std::move(OnReady));
   SymbolNameSet UnresolvedSymbols(std::move(Names));
 
-  for (auto *VSO : VSOs) {
+  for (auto *V : VSOs) {
 
     if (UnresolvedSymbols.empty())
       break;
 
-    assert(VSO && "VSO pointers in VSOs list should be non-null");
-    auto LR = VSO->lookup(Query, UnresolvedSymbols);
+    assert(V && "VSO pointers in VSOs list should be non-null");
+    auto LR = V->lookup(Query, UnresolvedSymbols);
     UnresolvedSymbols = std::move(LR.UnresolvedSymbols);
 
-    for (auto I = LR.MaterializationWork.begin(),
-              E = LR.MaterializationWork.end();
-         I != E;) {
-      auto Tmp = I++;
-      std::shared_ptr<SymbolSource> Source = Tmp->first;
-      SymbolNameSet Names = std::move(Tmp->second);
-      LR.MaterializationWork.erase(Tmp);
-      DispatchMaterialization(*VSO, std::move(Source), std::move(Names));
-    }
+    for (auto &MU : LR.MaterializationUnits)
+      DispatchMaterialization(*V, std::move(MU));
   }
 
 #if LLVM_ENABLE_THREADS

Modified: llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp?rev=327946&r1=327945&r2=327946&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp Mon Mar 19 20:49:29 2018
@@ -19,23 +19,28 @@ using namespace llvm::orc;
 
 namespace {
 
-class SimpleSource : public SymbolSource {
+class SimpleMaterializationUnit : public MaterializationUnit {
 public:
-  using MaterializeFunction = std::function<Error(VSO &, SymbolNameSet)>;
+  using GetSymbolsFunction = std::function<SymbolFlagsMap()>;
+  using MaterializeFunction = std::function<Error(VSO &)>;
   using DiscardFunction = std::function<void(VSO &, SymbolStringPtr)>;
 
-  SimpleSource(MaterializeFunction Materialize, DiscardFunction Discard)
-      : Materialize(std::move(Materialize)), Discard(std::move(Discard)) {}
+  SimpleMaterializationUnit(GetSymbolsFunction GetSymbols,
+                            MaterializeFunction Materialize,
+                            DiscardFunction Discard)
+      : GetSymbols(std::move(GetSymbols)), Materialize(std::move(Materialize)),
+        Discard(std::move(Discard)) {}
 
-  Error materialize(VSO &V, SymbolNameSet Symbols) override {
-    return Materialize(V, std::move(Symbols));
-  }
+  SymbolFlagsMap getSymbols() override { return GetSymbols(); }
+
+  Error materialize(VSO &V) override { return Materialize(V); }
 
   void discard(VSO &V, SymbolStringPtr Name) override {
     Discard(V, std::move(Name));
   }
 
 private:
+  GetSymbolsFunction GetSymbols;
   MaterializeFunction Materialize;
   DiscardFunction Discard;
 };
@@ -142,26 +147,28 @@ TEST(CoreAPIsTest, LookupFlagsTest) {
   auto Bar = SP.intern("bar");
   auto Baz = SP.intern("baz");
 
+  JITSymbolFlags FooFlags = JITSymbolFlags::Exported;
+  JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>(
+      JITSymbolFlags::Exported | JITSymbolFlags::Weak);
+
   VSO V;
 
-  auto Source = std::make_shared<SimpleSource>(
-      [](VSO &V, SymbolNameSet Symbols) -> Error {
+  auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+      [=]() {
+        return SymbolFlagsMap({{Bar, BarFlags}});
+      },
+      [](VSO &V) -> Error {
         llvm_unreachable("Symbol materialized on flags lookup");
       },
       [](VSO &V, SymbolStringPtr Name) -> Error {
         llvm_unreachable("Symbol finalized on flags lookup");
       });
 
-  JITSymbolFlags FooFlags = JITSymbolFlags::Exported;
-  JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>(
-      JITSymbolFlags::Exported | JITSymbolFlags::Weak);
-
   SymbolMap InitialDefs;
   InitialDefs[Foo] = JITEvaluatedSymbol(0xdeadbeef, FooFlags);
   cantFail(V.define(std::move(InitialDefs)));
 
-  SymbolFlagsMap InitialLazyDefs({{Bar, BarFlags}});
-  cantFail(V.defineLazy(InitialLazyDefs, Source));
+  cantFail(V.defineLazy(std::move(MU)));
 
   SymbolNameSet Names({Foo, Bar, Baz});
 
@@ -193,12 +200,15 @@ TEST(CoreAPIsTest, AddAndMaterializeLazy
 
   VSO V;
 
-  auto Source = std::make_shared<SimpleSource>(
-      [&](VSO &V, SymbolNameSet Symbols) {
-        EXPECT_EQ(Symbols.size(), 1U)
-            << "Expected Symbols set size to be 1 ({ Foo })";
-        EXPECT_EQ(*Symbols.begin(), Foo) << "Expected Symbols == { Foo }";
-
+  auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+      [=]() {
+        return SymbolFlagsMap(
+            {{Foo, JITSymbolFlags::Exported},
+             {Bar, static_cast<JITSymbolFlags::FlagNames>(
+                       JITSymbolFlags::Exported | JITSymbolFlags::Weak)}});
+      },
+      [&](VSO &V) {
+        assert(BarDiscarded && "Bar should have been discarded by this point");
         SymbolMap SymbolsToResolve;
         SymbolsToResolve[Foo] =
             JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
@@ -214,11 +224,7 @@ TEST(CoreAPIsTest, AddAndMaterializeLazy
         BarDiscarded = true;
       });
 
-  SymbolFlagsMap InitialSymbols(
-      {{Foo, JITSymbolFlags::Exported},
-       {Bar, static_cast<JITSymbolFlags::FlagNames>(JITSymbolFlags::Exported |
-                                                    JITSymbolFlags::Weak)}});
-  cantFail(V.defineLazy(InitialSymbols, Source));
+  cantFail(V.defineLazy(std::move(MU)));
 
   SymbolMap BarOverride;
   BarOverride[Bar] = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported);
@@ -248,8 +254,8 @@ TEST(CoreAPIsTest, AddAndMaterializeLazy
 
   auto LR = V.lookup(std::move(Q), Names);
 
-  for (auto &SWKV : LR.MaterializationWork)
-    cantFail(SWKV.first->materialize(V, std::move(SWKV.second)));
+  for (auto &SWKV : LR.MaterializationUnits)
+    cantFail(SWKV->materialize(V));
 
   EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib";
   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
@@ -276,9 +282,8 @@ TEST(CoreAPIsTest, TestLambdaSymbolResol
       },
       [&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Symbols) {
         auto LR = V.lookup(std::move(Q), Symbols);
-        assert(LR.MaterializationWork.empty() &&
-               "Test generated unexpected materialization "
-               "work?");
+        assert(LR.MaterializationUnits.empty() &&
+               "Test generated unexpected materialization work?");
         return std::move(LR.UnresolvedSymbols);
       });
 
@@ -333,8 +338,11 @@ TEST(CoreAPIsTest, TestLookupWithUnthrea
   SymbolStringPool SSP;
   auto Foo = SSP.intern("foo");
 
-  auto Source = std::make_shared<SimpleSource>(
-      [&](VSO &V, SymbolNameSet Symbols) -> Error {
+  auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+      [=]() {
+        return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
+      },
+      [&](VSO &V) -> Error {
         V.resolve({{Foo, FooSym}});
         V.finalize({Foo});
         return Error::success();
@@ -345,8 +353,7 @@ TEST(CoreAPIsTest, TestLookupWithUnthrea
 
   VSO V;
 
-  SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}});
-  cantFail(V.defineLazy(InitialSymbols, Source));
+  cantFail(V.defineLazy(std::move(MU)));
 
   ExecutionSession ES(SSP);
   auto FooLookupResult =
@@ -366,8 +373,11 @@ TEST(CoreAPIsTest, TestLookupWithThreade
   SymbolStringPool SSP;
   auto Foo = SSP.intern("foo");
 
-  auto Source = std::make_shared<SimpleSource>(
-      [&](VSO &V, SymbolNameSet Symbols) -> Error {
+  auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+      [=]() {
+        return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
+      },
+      [&](VSO &V) -> Error {
         V.resolve({{Foo, FooSym}});
         V.finalize({Foo});
         return Error::success();
@@ -378,19 +388,20 @@ TEST(CoreAPIsTest, TestLookupWithThreade
 
   VSO V;
 
-  SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}});
-  cantFail(V.defineLazy(InitialSymbols, Source));
+  cantFail(V.defineLazy(std::move(MU)));
 
   ExecutionSession ES(SSP);
 
-  auto MaterializeOnNewThread =
-    [&ES](VSO &V, std::shared_ptr<SymbolSource> Source, SymbolNameSet Names) {
-      std::thread(
-        [&ES, &V, Source, Names]() {
-          if (auto Err = Source->materialize(V, std::move(Names)))
-            ES.reportError(std::move(Err));
-        }).detach();
-    };
+  auto MaterializeOnNewThread = [&ES](VSO &V,
+                                      std::unique_ptr<MaterializationUnit> MU) {
+    // FIXME: Use move capture once we move to C++14.
+    std::shared_ptr<MaterializationUnit> SharedMU = std::move(MU);
+    std::thread([&ES, &V, SharedMU]() {
+      if (auto Err = SharedMU->materialize(V))
+        ES.reportError(std::move(Err));
+    })
+        .detach();
+  };
 
   auto FooLookupResult =
     cantFail(lookup({&V}, Foo, MaterializeOnNewThread));

Modified: llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp?rev=327946&r1=327945&r2=327946&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp Mon Mar 19 20:49:29 2018
@@ -36,7 +36,7 @@ TEST(LegacyAPIInteropTest, QueryAgainstV
   auto Lookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
                     SymbolNameSet Symbols) {
     auto R = V.lookup(std::move(Query), Symbols);
-    EXPECT_TRUE(R.MaterializationWork.empty())
+    EXPECT_TRUE(R.MaterializationUnits.empty())
         << "Query resulted in unexpected materialization work";
     return std::move(R.UnresolvedSymbols);
   };




More information about the llvm-commits mailing list