[ORC] Add a MaterializationResponsibility class to track responsibility for
authorLang Hames <lhames@gmail.com>
Mon, 16 Apr 2018 18:05:24 +0000 (18:05 +0000)
committerLang Hames <lhames@gmail.com>
Mon, 16 Apr 2018 18:05:24 +0000 (18:05 +0000)
materializing function definitions.

MaterializationUnit instances are responsible for resolving and finalizing
symbol definitions when their materialize method is called. By contract, the
MaterializationUnit must materialize all definitions it is responsible for and
no others. If it can not materialize all definitions (because of some error)
then it must notify the associated VSO about each definition that could not be
materialized. The MaterializationResponsibility class tracks this
responsibility, asserting that all required symbols are resolved and finalized,
and that no extraneous symbols are resolved or finalized. In the event of an
error it provides a convenience method for notifying the VSO about each
definition that could not be materialized.

llvm-svn: 330142

llvm/include/llvm/ExecutionEngine/Orc/Core.h
llvm/include/llvm/ExecutionEngine/Orc/Legacy.h
llvm/lib/ExecutionEngine/Orc/Core.cpp
llvm/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp
llvm/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp

index 774084e..f47d13c 100644 (file)
@@ -118,7 +118,7 @@ public:
   /// notify-finalized callback is called with the given error.
   ///
   /// It is illegal to call setFailed after both callbacks have been made.
-  void notifyFailed(Error Err);
+  void notifyMaterializationFailed(Error Err);
 
   /// @brief Set the resolved symbol information for the given symbol name.
   ///
@@ -206,6 +206,25 @@ createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
       std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
 }
 
+/// @brief Tracks responsibility for materialization.
+class MaterializationResponsibility {
+public:
+  MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
+  MaterializationResponsibility(MaterializationResponsibility &&) = default;
+  MaterializationResponsibility &
+  operator=(MaterializationResponsibility &&) = default;
+  ~MaterializationResponsibility();
+  MaterializationResponsibility takeResponsibility(SymbolNameSet Symbols);
+  const VSO &getTargetVSO() const { return V; }
+  void resolve(const SymbolMap &Symbols);
+  void finalize();
+  void notifyMaterializationFailed();
+
+private:
+  VSO &V;
+  SymbolFlagsMap SymbolFlags;
+};
+
 /// @brief A MaterializationUnit represents a set of symbol definitions that can
 ///        be materialized as a group, or individually discarded (when
 ///        overriding definitions are encountered).
@@ -224,13 +243,13 @@ public:
   /// @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;
+  virtual void materialize(MaterializationResponsibility R) = 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
   ///        symbol is a function, delete the function body or mark it available
   ///        externally).
-  virtual void discard(VSO &V, SymbolStringPtr Name) = 0;
+  virtual void discard(const VSO &V, SymbolStringPtr Name) = 0;
 
 private:
   virtual void anchor();
@@ -254,11 +273,21 @@ public:
   using SetDefinitionsResult =
       std::map<SymbolStringPtr, RelativeLinkageStrength>;
 
-  using MaterializationUnitList =
-      std::vector<std::unique_ptr<MaterializationUnit>>;
+  struct Materializer {
+  public:
+    Materializer(std::unique_ptr<MaterializationUnit> MU,
+                 MaterializationResponsibility R);
+    void operator()();
+
+  private:
+    std::unique_ptr<MaterializationUnit> MU;
+    MaterializationResponsibility R;
+  };
+
+  using MaterializerList = std::vector<Materializer>;
 
   struct LookupResult {
-    MaterializationUnitList MaterializationUnits;
+    MaterializerList Materializers;
     SymbolNameSet UnresolvedSymbols;
   };
 
@@ -321,11 +350,11 @@ public:
 private:
   class UnmaterializedInfo {
   public:
-    UnmaterializedInfo(size_t SymbolsRemaining,
-                       std::unique_ptr<MaterializationUnit> MU);
+    UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU);
+    void discard(VSO &V, SymbolStringPtr Name);
 
-    uint64_t SymbolsRemaining;
     std::unique_ptr<MaterializationUnit> MU;
+    SymbolFlagsMap Symbols;
   };
 
   using UnmaterializedInfoList = std::list<UnmaterializedInfo>;
@@ -348,6 +377,7 @@ private:
   public:
     SymbolTableEntry(JITSymbolFlags SymbolFlags,
                      UnmaterializedInfoIterator UnmaterializedInfoItr);
+    SymbolTableEntry(JITSymbolFlags SymbolFlags);
     SymbolTableEntry(JITEvaluatedSymbol Sym);
     SymbolTableEntry(SymbolTableEntry &&Other);
     SymbolTableEntry &operator=(SymbolTableEntry &&Other);
@@ -360,8 +390,8 @@ private:
     void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
                      UnmaterializedInfoIterator NewUMII);
 
-    // Move entry to materializing state, detach from UMII.
-    std::unique_ptr<MaterializationUnit> initMaterialize(VSO &V);
+    // Notify this entry that it is being materialized.
+    void notifyMaterializing();
 
     // Move entry to resolved state.
     void resolve(VSO &V, JITEvaluatedSymbol Sym);
@@ -380,8 +410,6 @@ private:
     void destroy();
   };
 
-  void detach(UnmaterializedInfoIterator UMII);
-
   std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
   UnmaterializedInfoList UnmaterializedInfos;
   MaterializingInfoMap MaterializingInfos;
@@ -431,20 +459,11 @@ public:
 /// ExecutionSession.
 class MaterializeOnCurrentThread {
 public:
-  MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {}
-
-  void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
-    if (auto Err = MU->materialize(V))
-      ES.reportError(std::move(Err));
-  }
-
-private:
-  ExecutionSession &ES;
+  void operator()(VSO::Materializer M) { M(); }
 };
 
 /// Materialization function object wrapper for the lookup method.
-using MaterializationDispatcher =
-    std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>;
+using MaterializationDispatcher = std::function<void(VSO::Materializer M)>;
 
 /// @brief Look up a set of symbols by searching a list of VSOs.
 ///
index 73debf3..8ea3f7b 100644 (file)
@@ -79,11 +79,11 @@ SymbolNameSet lookupWithLegacyFn(AsynchronousSymbolQuery &Query,
         Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
         Query.finalizeSymbol();
       } else {
-        Query.notifyFailed(Addr.takeError());
+        Query.notifyMaterializationFailed(Addr.takeError());
         return SymbolNameSet();
       }
     } else if (auto Err = Sym.takeError()) {
-      Query.notifyFailed(std::move(Err));
+      Query.notifyMaterializationFailed(std::move(Err));
       return SymbolNameSet();
     } else
       SymbolsNotFound.insert(S);
index 3d7ef7d..da0c604 100644 (file)
@@ -123,7 +123,7 @@ AsynchronousSymbolQuery::AsynchronousSymbolQuery(
   OutstandingResolutions = OutstandingFinalizations = Symbols.size();
 }
 
-void AsynchronousSymbolQuery::notifyFailed(Error Err) {
+void AsynchronousSymbolQuery::notifyMaterializationFailed(Error Err) {
   if (OutstandingResolutions != 0)
     NotifySymbolsResolved(std::move(Err));
   else if (OutstandingFinalizations != 0)
@@ -159,9 +159,76 @@ void AsynchronousSymbolQuery::finalizeSymbol() {
     NotifySymbolsReady(Error::success());
 }
 
+MaterializationResponsibility::MaterializationResponsibility(
+    VSO &V, SymbolFlagsMap SymbolFlags)
+    : V(V), SymbolFlags(std::move(SymbolFlags)) {
+  assert(!this->SymbolFlags.empty() && "Materializing nothing?");
+}
+
+MaterializationResponsibility::~MaterializationResponsibility() {
+  assert(SymbolFlags.empty() &&
+         "All symbols should have been explicitly materialized or failed");
+}
+
+MaterializationResponsibility
+MaterializationResponsibility::takeResponsibility(SymbolNameSet Symbols) {
+  SymbolFlagsMap ExtractedFlags;
+
+  for (auto &S : Symbols) {
+    auto I = SymbolFlags.find(S);
+    ExtractedFlags.insert(*I);
+    SymbolFlags.erase(I);
+  }
+
+  return MaterializationResponsibility(V, std::move(ExtractedFlags));
+}
+
+void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
+#ifndef NDEBUG
+  for (auto &KV : Symbols) {
+    auto I = SymbolFlags.find(KV.first);
+    assert(I != SymbolFlags.end() &&
+           "Resolving symbol outside this responsibility set");
+    assert(KV.second.getFlags() == I->second &&
+           "Resolving symbol with incorrect flags");
+  }
+#endif
+  V.resolve(Symbols);
+}
+
+void MaterializationResponsibility::finalize() {
+  SymbolNameSet SymbolNames;
+  for (auto &KV : SymbolFlags)
+    SymbolNames.insert(KV.first);
+  SymbolFlags.clear();
+  V.finalize(SymbolNames);
+}
+
+void MaterializationResponsibility::notifyMaterializationFailed() {
+  SymbolNameSet SymbolNames;
+  for (auto &KV : SymbolFlags)
+    SymbolNames.insert(KV.first);
+  SymbolFlags.clear();
+  V.notifyMaterializationFailed(SymbolNames);
+}
+
+VSO::Materializer::Materializer(std::unique_ptr<MaterializationUnit> MU,
+                                MaterializationResponsibility R)
+    : MU(std::move(MU)), R(std::move(R)) {}
+
+void VSO::Materializer::operator()() { MU->materialize(std::move(R)); }
+
 VSO::UnmaterializedInfo::UnmaterializedInfo(
-    size_t SymbolsRemaining, std::unique_ptr<MaterializationUnit> MU)
-    : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {}
+    std::unique_ptr<MaterializationUnit> MU)
+    : MU(std::move(MU)), Symbols(this->MU->getSymbols()) {}
+
+void VSO::UnmaterializedInfo::discard(VSO &V, SymbolStringPtr Name) {
+  assert(MU && "No materializer attached");
+  MU->discard(V, Name);
+  auto I = Symbols.find(Name);
+  assert(I != Symbols.end() && "Symbol not found in this MU");
+  Symbols.erase(I);
+}
 
 VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags,
                                         UnmaterializedInfoIterator UMII)
@@ -204,9 +271,9 @@ void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name,
   assert(!Flags.isMaterializing() &&
          "Attempting to replace definition during materialization?");
   if (Flags.isLazy()) {
-    if (UMII->MU)
-      UMII->MU->discard(V, Name);
-    V.detach(UMII);
+    UMII->discard(V, Name);
+    if (UMII->Symbols.empty())
+      V.UnmaterializedInfos.erase(UMII);
   }
   destroy();
   Flags = Sym.getFlags();
@@ -219,39 +286,34 @@ void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name,
   assert(!Flags.isMaterializing() &&
          "Attempting to replace definition during materialization?");
   if (Flags.isLazy()) {
-    if (UMII->MU)
-      UMII->MU->discard(V, Name);
-    V.detach(UMII);
+    UMII->discard(V, Name);
+    if (UMII->Symbols.empty())
+      V.UnmaterializedInfos.erase(UMII);
   }
   destroy();
   Flags = NewFlags;
   UMII = std::move(NewUMII);
 }
 
-std::unique_ptr<MaterializationUnit>
-VSO::SymbolTableEntry::initMaterialize(VSO &V) {
-  assert(Flags.isLazy() && "Can't materialize non-lazy symbol");
-  auto TmpMU = std::move(UMII->MU);
-  V.detach(UMII);
-  destroy();
+void VSO::SymbolTableEntry::notifyMaterializing() {
+  assert(Flags.isLazy() && "Can only start materializing from lazy state");
+  UMII.~UnmaterializedInfoIterator();
   Flags &= ~JITSymbolFlags::Lazy;
   Flags |= JITSymbolFlags::Materializing;
   Address = 0;
-  return TmpMU;
 }
 
 void VSO::SymbolTableEntry::resolve(VSO &V, JITEvaluatedSymbol Sym) {
-  if (Flags.isLazy()) {
-    assert(!UMII->MU && "Resolving with MaterializationUnit still attached?");
-    V.detach(UMII);
-  }
-  destroy();
+  assert(!Flags.isLazy() && Flags.isMaterializing() &&
+         "Can only resolve in materializing state");
   Flags = Sym.getFlags();
   Flags |= JITSymbolFlags::Materializing;
   Address = Sym.getAddress();
+  assert(Address != 0 && "Can not resolve to null");
 }
 
 void VSO::SymbolTableEntry::finalize() {
+  assert(Address != 0 && "Cannot finalize with null address");
   assert(Flags.isMaterializing() && !Flags.isLazy() &&
          "Symbol should be in materializing state");
   Flags &= ~JITSymbolFlags::Materializing;
@@ -262,14 +324,6 @@ void VSO::SymbolTableEntry::destroy() {
     UMII.~UnmaterializedInfoIterator();
 }
 
-void VSO::detach(UnmaterializedInfoIterator UMII) {
-  assert(UMII->SymbolsRemaining > 0 &&
-         "Detaching from empty UnmaterializedInfo?");
-  --UMII->SymbolsRemaining;
-  if (UMII->SymbolsRemaining == 0)
-    UnmaterializedInfos.erase(UMII);
-}
-
 VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old,
                                                  JITSymbolFlags New) {
   if (Old == None)
@@ -325,14 +379,11 @@ Error VSO::define(SymbolMap NewSymbols) {
 
 Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
 
-  auto NewSymbols = MU->getSymbols();
-
-  auto UMII = UnmaterializedInfos.insert(
-      UnmaterializedInfos.end(),
-      UnmaterializedInfo(NewSymbols.size(), std::move(MU)));
+  auto UMII = UnmaterializedInfos.insert(UnmaterializedInfos.end(),
+                                         UnmaterializedInfo(std::move(MU)));
 
   Error Err = Error::success();
-  for (auto &KV : NewSymbols) {
+  for (auto &KV : UMII->Symbols) {
     auto I = Symbols.find(KV.first);
 
     assert(I == Symbols.end() ||
@@ -345,8 +396,7 @@ Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
 
     // Discard weaker definitions.
     if (LinkageResult == ExistingDefinitionIsStronger) {
-      UMII->MU->discard(*this, KV.first);
-      detach(UMII);
+      UMII->discard(*this, KV.first);
       continue;
     }
 
@@ -356,7 +406,7 @@ Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
                        make_error<orc::DuplicateDefinition>(*KV.first));
       // Duplicate definitions are discarded, so remove the duplicates from
       // materializer.
-      detach(UMII);
+      UMII->discard(*this, KV.first);
       continue;
     }
 
@@ -368,6 +418,9 @@ Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
           std::make_pair(KV.first, SymbolTableEntry(KV.second, UMII)));
   }
 
+  if (UMII->Symbols.empty())
+    UnmaterializedInfos.erase(UMII);
+
   return Err;
 }
 
@@ -417,10 +470,12 @@ void VSO::notifyMaterializationFailed(const SymbolNameSet &Names) {
   }
 
   for (auto &KV : ResolutionFailures)
-    KV.first->notifyFailed(make_error<FailedToResolve>(std::move(KV.second)));
+    KV.first->notifyMaterializationFailed(
+        make_error<FailedToResolve>(std::move(KV.second)));
 
   for (auto &KV : FinalizationFailures)
-    KV.first->notifyFailed(make_error<FailedToFinalize>(std::move(KV.second)));
+    KV.first->notifyMaterializationFailed(
+        make_error<FailedToFinalize>(std::move(KV.second)));
 }
 
 void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) {
@@ -461,7 +516,7 @@ SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) {
 
 VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
                               SymbolNameSet Names) {
-  MaterializationUnitList MaterializationUnits;
+  MaterializerList Materializers;
 
   for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
     auto Tmp = I++;
@@ -474,11 +529,26 @@ VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     // The symbol is in the VSO. Erase it from Names and proceed.
     Names.erase(Tmp);
 
-    // If this symbol has not been materialized yet, move it to materializing,
-    // then fall through to the materializing case below.
+    // If this symbol has not been materialized yet grab its materializer,
+    // move all of its sibling symbols to the materializing state, and
+    // delete its unmaterialized info.
     if (SymI->second.Flags.isLazy()) {
-      if (auto MU = SymI->second.initMaterialize(*this))
-        MaterializationUnits.push_back(std::move(MU));
+      assert(SymI->second.UMII->MU &&
+             "Lazy symbol has no materializer attached");
+      auto MU = std::move(SymI->second.UMII->MU);
+      auto SymbolFlags = std::move(SymI->second.UMII->Symbols);
+      UnmaterializedInfos.erase(SymI->second.UMII);
+
+      for (auto &KV : SymbolFlags) {
+        auto SiblingI = Symbols.find(KV.first);
+        MaterializingInfos.insert(
+            std::make_pair(SiblingI->first, MaterializingInfo()));
+        SiblingI->second.notifyMaterializing();
+      }
+
+      Materializers.push_back(Materializer(
+          std::move(MU),
+          MaterializationResponsibility(*this, std::move(SymbolFlags))));
     }
 
     // If this symbol already has a fully materialized value, just use it.
@@ -492,10 +562,7 @@ VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     // If this symbol is materializing, then get (or create) its
     // MaterializingInfo struct and appaend the query.
     auto J = MaterializingInfos.find(SymI->first);
-    if (J == MaterializingInfos.end())
-      J = MaterializingInfos
-              .insert(std::make_pair(SymI->first, MaterializingInfo()))
-              .first;
+    assert(J != MaterializingInfos.end() && "Missing MaterializingInfo");
 
     if (SymI->second.Address) {
       auto Sym = JITEvaluatedSymbol(SymI->second.Address, SymI->second.Flags);
@@ -510,7 +577,7 @@ VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
     }
   }
 
-  return {std::move(MaterializationUnits), std::move(Names)};
+  return {std::move(Materializers), std::move(Names)};
 }
 
 Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
@@ -574,8 +641,8 @@ Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
     auto LR = V->lookup(Query, UnresolvedSymbols);
     UnresolvedSymbols = std::move(LR.UnresolvedSymbols);
 
-    for (auto &MU : LR.MaterializationUnits)
-      DispatchMaterialization(*V, std::move(MU));
+    for (auto &M : LR.Materializers)
+      DispatchMaterialization(std::move(M));
   }
 
 #if LLVM_ENABLE_THREADS
index ab0c9f0..268597c 100644 (file)
@@ -155,11 +155,11 @@ private:
           if (auto Addr = Sym.getAddress())
             Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
           else {
-            Query->notifyFailed(Addr.takeError());
+            Query->notifyMaterializationFailed(Addr.takeError());
             return orc::SymbolNameSet();
           }
         } else if (auto Err = Sym.takeError()) {
-          Query->notifyFailed(std::move(Err));
+          Query->notifyMaterializationFailed(std::move(Err));
           return orc::SymbolNameSet();
         } else
           UnresolvedSymbols.insert(S);
index 73af520..67a270e 100644 (file)
@@ -177,22 +177,22 @@ class OrcMCJITReplacement : public ExecutionEngine {
           if (auto Addr = Sym.getAddress())
             Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
           else {
-            Query->notifyFailed(Addr.takeError());
+            Query->notifyMaterializationFailed(Addr.takeError());
             return SymbolNameSet();
           }
         } else if (auto Err = Sym.takeError()) {
-          Query->notifyFailed(std::move(Err));
+          Query->notifyMaterializationFailed(std::move(Err));
           return SymbolNameSet();
         } else {
           if (auto Sym2 = M.ClientResolver->findSymbol(*S)) {
             if (auto Addr = Sym2.getAddress())
               Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
             else {
-              Query->notifyFailed(Addr.takeError());
+              Query->notifyMaterializationFailed(Addr.takeError());
               return SymbolNameSet();
             }
           } else if (auto Err = Sym2.takeError()) {
-            Query->notifyFailed(std::move(Err));
+            Query->notifyMaterializationFailed(std::move(Err));
             return SymbolNameSet();
           } else
             UnresolvedSymbols.insert(S);
index a2d815a..ee2b360 100644 (file)
@@ -22,8 +22,9 @@ namespace {
 class SimpleMaterializationUnit : public MaterializationUnit {
 public:
   using GetSymbolsFunction = std::function<SymbolFlagsMap()>;
-  using MaterializeFunction = std::function<Error(VSO &)>;
-  using DiscardFunction = std::function<void(VSO &, SymbolStringPtr)>;
+  using MaterializeFunction =
+      std::function<void(MaterializationResponsibility)>;
+  using DiscardFunction = std::function<void(const VSO &, SymbolStringPtr)>;
   using DestructorFunction = std::function<void()>;
 
   SimpleMaterializationUnit(
@@ -40,9 +41,11 @@ public:
 
   SymbolFlagsMap getSymbols() override { return GetSymbols(); }
 
-  Error materialize(VSO &V) override { return Materialize(V); }
+  void materialize(MaterializationResponsibility R) override {
+    Materialize(std::move(R));
+  }
 
-  void discard(VSO &V, SymbolStringPtr Name) override {
+  void discard(const VSO &V, SymbolStringPtr Name) override {
     Discard(V, std::move(Name));
   }
 
@@ -103,7 +106,8 @@ TEST(CoreAPIsTest, AsynchronousSymbolQueryResolutionErrorOnly) {
 
   AsynchronousSymbolQuery Q(Names, OnResolution, OnReady);
 
-  Q.notifyFailed(make_error<StringError>("xyz", inconvertibleErrorCode()));
+  Q.notifyMaterializationFailed(
+      make_error<StringError>("xyz", inconvertibleErrorCode()));
 
   EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run";
   EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run";
@@ -165,10 +169,10 @@ TEST(CoreAPIsTest, LookupFlagsTest) {
       [=]() {
         return SymbolFlagsMap({{Bar, BarFlags}});
       },
-      [](VSO &V) -> Error {
+      [](MaterializationResponsibility R) {
         llvm_unreachable("Symbol materialized on flags lookup");
       },
-      [](VSO &V, SymbolStringPtr Name) -> Error {
+      [](const VSO &V, SymbolStringPtr Name) {
         llvm_unreachable("Symbol finalized on flags lookup");
       });
 
@@ -206,10 +210,10 @@ TEST(CoreAPIsTest, DropMaterializerWhenEmpty) {
         return SymbolFlagsMap(
             {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}});
       },
-      [](VSO &V) -> Error {
+      [](MaterializationResponsibility R) {
         llvm_unreachable("Unexpected call to materialize");
       },
-      [&](VSO &V, SymbolStringPtr Name) {
+      [&](const VSO &V, SymbolStringPtr Name) {
         EXPECT_TRUE(Name == Foo || Name == Bar)
             << "Discard of unexpected symbol?";
       },
@@ -253,19 +257,16 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) {
              {Bar, static_cast<JITSymbolFlags::FlagNames>(
                        JITSymbolFlags::Exported | JITSymbolFlags::Weak)}});
       },
-      [&](VSO &V) {
+      [&](MaterializationResponsibility R) {
         assert(BarDiscarded && "Bar should have been discarded by this point");
         SymbolMap SymbolsToResolve;
         SymbolsToResolve[Foo] =
             JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
-        V.resolve(std::move(SymbolsToResolve));
-        SymbolNameSet SymbolsToFinalize;
-        SymbolsToFinalize.insert(Foo);
-        V.finalize(SymbolsToFinalize);
+        R.resolve(std::move(SymbolsToResolve));
+        R.finalize();
         FooMaterialized = true;
-        return Error::success();
       },
-      [&](VSO &V, SymbolStringPtr Name) {
+      [&](const VSO &V, SymbolStringPtr Name) {
         EXPECT_EQ(Name, Bar) << "Expected Name to be Bar";
         BarDiscarded = true;
       });
@@ -300,8 +301,8 @@ TEST(CoreAPIsTest, AddAndMaterializeLazySymbol) {
 
   auto LR = V.lookup(std::move(Q), Names);
 
-  for (auto &SWKV : LR.MaterializationUnits)
-    cantFail(SWKV->materialize(V));
+  for (auto &M : LR.Materializers)
+    M();
 
   EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib";
   EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
@@ -322,11 +323,8 @@ TEST(CoreAPIsTest, FailResolution) {
         return SymbolFlagsMap(
             {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}});
       },
-      [&](VSO &V) -> Error {
-        V.notifyMaterializationFailed(Names);
-        return Error::success();
-      },
-      [&](VSO &V, SymbolStringPtr Name) {
+      [&](MaterializationResponsibility R) { R.notifyMaterializationFailed(); },
+      [&](const VSO &V, SymbolStringPtr Name) {
         llvm_unreachable("Unexpected call to discard");
       });
 
@@ -361,8 +359,8 @@ TEST(CoreAPIsTest, FailResolution) {
       std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady);
 
   auto LR = V.lookup(std::move(Q), Names);
-  for (auto &SWKV : LR.MaterializationUnits)
-    cantFail(SWKV->materialize(V));
+  for (auto &M : LR.Materializers)
+    M();
 }
 
 TEST(CoreAPIsTest, FailFinalization) {
@@ -375,19 +373,18 @@ TEST(CoreAPIsTest, FailFinalization) {
   auto MU = llvm::make_unique<SimpleMaterializationUnit>(
       [=]() {
         return SymbolFlagsMap(
-            {{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}});
+            {{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}});
       },
-      [&](VSO &V) -> Error {
+      [&](MaterializationResponsibility R) {
         constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef;
         constexpr JITTargetAddress FakeBarAddr = 0xcafef00d;
 
         auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
         auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported);
-        V.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
-        V.notifyMaterializationFailed(Names);
-        return Error::success();
+        R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
+        R.notifyMaterializationFailed();
       },
-      [&](VSO &V, SymbolStringPtr Name) {
+      [&](const VSO &V, SymbolStringPtr Name) {
         llvm_unreachable("Unexpected call to discard");
       });
 
@@ -421,8 +418,8 @@ TEST(CoreAPIsTest, FailFinalization) {
       std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady);
 
   auto LR = V.lookup(std::move(Q), Names);
-  for (auto &SWKV : LR.MaterializationUnits)
-    cantFail(SWKV->materialize(V));
+  for (auto &M : LR.Materializers)
+    M();
 }
 
 TEST(CoreAPIsTest, TestLambdaSymbolResolver) {
@@ -443,7 +440,7 @@ TEST(CoreAPIsTest, TestLambdaSymbolResolver) {
       },
       [&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Symbols) {
         auto LR = V.lookup(std::move(Q), Symbols);
-        assert(LR.MaterializationUnits.empty() &&
+        assert(LR.Materializers.empty() &&
                "Test generated unexpected materialization work?");
         return std::move(LR.UnresolvedSymbols);
       });
@@ -503,12 +500,11 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) {
       [=]() {
         return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
       },
-      [&](VSO &V) -> Error {
-        V.resolve({{Foo, FooSym}});
-        V.finalize({Foo});
-        return Error::success();
+      [&](MaterializationResponsibility R) {
+        R.resolve({{Foo, FooSym}});
+        R.finalize();
       },
-      [](VSO &V, SymbolStringPtr Name) -> Error {
+      [](const VSO &V, SymbolStringPtr Name) {
         llvm_unreachable("Not expecting finalization");
       });
 
@@ -517,7 +513,7 @@ TEST(CoreAPIsTest, TestLookupWithUnthreadedMaterialization) {
   cantFail(V.defineLazy(std::move(MU)));
 
   auto FooLookupResult =
-      cantFail(lookup({&V}, Foo, MaterializeOnCurrentThread(ES)));
+      cantFail(lookup({&V}, Foo, MaterializeOnCurrentThread()));
 
   EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
       << "lookup returned an incorrect address";
@@ -537,12 +533,11 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) {
       [=]() {
         return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
       },
-      [&](VSO &V) -> Error {
-        V.resolve({{Foo, FooSym}});
-        V.finalize({Foo});
-        return Error::success();
+      [&](MaterializationResponsibility R) {
+        R.resolve({{Foo, FooSym}});
+        R.finalize();
       },
-      [](VSO &V, SymbolStringPtr Name) -> Error {
+      [](const VSO &V, SymbolStringPtr Name) {
         llvm_unreachable("Not expecting finalization");
       });
 
@@ -551,14 +546,10 @@ TEST(CoreAPIsTest, TestLookupWithThreadedMaterialization) {
   cantFail(V.defineLazy(std::move(MU)));
 
   std::thread MaterializationThread;
-  auto MaterializeOnNewThread = [&](VSO &V,
-                                    std::unique_ptr<MaterializationUnit> MU) {
+  auto MaterializeOnNewThread = [&](VSO::Materializer M) {
     // FIXME: Use move capture once we move to C++14.
-    std::shared_ptr<MaterializationUnit> SharedMU = std::move(MU);
-    MaterializationThread = std::thread([&ES, &V, SharedMU]() {
-      if (auto Err = SharedMU->materialize(V))
-        ES.reportError(std::move(Err));
-    });
+    auto SharedM = std::make_shared<VSO::Materializer>(std::move(M));
+    MaterializationThread = std::thread([SharedM]() { (*SharedM)(); });
   };
 
   auto FooLookupResult =
index db29024..514aafa 100644 (file)
@@ -35,7 +35,7 @@ TEST(LegacyAPIInteropTest, QueryAgainstVSO) {
   auto Lookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Query,
                     SymbolNameSet Symbols) {
     auto R = V.lookup(std::move(Query), Symbols);
-    EXPECT_TRUE(R.MaterializationUnits.empty())
+    EXPECT_TRUE(R.Materializers.empty())
         << "Query resulted in unexpected materialization work";
     return std::move(R.UnresolvedSymbols);
   };