From 883ef72f22da4a019d18599a5a985ed076bf4fd3 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 7 Jun 2019 19:33:51 +0000 Subject: [PATCH] [ORC] Update symbol lookup to use a single callback with a required symbol state rather than two callbacks. The asynchronous lookup API (which the synchronous lookup API wraps for convenience) used to take two callbacks: OnResolved (called once all requested symbols had an address assigned) and OnReady to be called once all requested symbols were safe to access). This patch updates the asynchronous lookup API to take a single 'OnComplete' callback and a required state (SymbolState) to determine when the callback should be made. This simplifies the common use case (where the client is interested in a specific state) and will generalize neatly as new states are introduced to track runtime initialization of symbols. Clients who were making use of both callbacks in a single query will now need to issue two queries (one for SymbolState::Resolved and another for SymbolState::Ready). Synchronous lookup API clients who were explicitly passing the WaitOnReady argument will now need neeed to pass a SymbolState instead (for 'WaitOnReady == true' use SymbolState::Ready, for 'WaitOnReady == false' use SymbolState::Resolved). Synchronous lookup API clients who were using default arugment values should see no change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362832 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ExecutionEngine/Orc/Core.h | 145 +++-- include/llvm/ExecutionEngine/Orc/Legacy.h | 11 +- lib/ExecutionEngine/Orc/Core.cpp | 567 +++++++----------- lib/ExecutionEngine/Orc/ExecutionUtils.cpp | 3 +- lib/ExecutionEngine/Orc/LazyReexports.cpp | 9 +- lib/ExecutionEngine/Orc/Legacy.cpp | 3 +- .../Orc/ObjectLinkingLayer.cpp | 12 +- lib/ExecutionEngine/Orc/OrcCBindingsStack.h | 11 +- lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 15 +- .../Orc/RTDyldObjectLinkingLayer.cpp | 7 +- .../ExecutionEngine/Orc/CoreAPIsTest.cpp | 199 +++--- .../Orc/LegacyAPIInteropTest.cpp | 31 +- .../Orc/RTDyldObjectLinkingLayerTest.cpp | 23 +- 13 files changed, 428 insertions(+), 608 deletions(-) diff --git a/include/llvm/ExecutionEngine/Orc/Core.h b/include/llvm/ExecutionEngine/Orc/Core.h index 45bcb9460f8..c0c54ef5566 100644 --- a/include/llvm/ExecutionEngine/Orc/Core.h +++ b/include/llvm/ExecutionEngine/Orc/Core.h @@ -33,6 +33,7 @@ class ExecutionSession; class MaterializationUnit; class MaterializationResponsibility; class JITDylib; +enum class SymbolState : uint8_t; /// VModuleKey provides a unique identifier (allocated and managed by /// ExecutionSessions) for a module added to the JIT. @@ -56,6 +57,18 @@ using SymbolDependenceMap = DenseMap; /// A list of (JITDylib*, bool) pairs. using JITDylibSearchList = std::vector>; +struct SymbolAliasMapEntry { + SymbolAliasMapEntry() = default; + SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) + : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} + + SymbolStringPtr Aliasee; + JITSymbolFlags AliasFlags; +}; + +/// A map of Symbols to (Symbol, Flags) pairs. +using SymbolAliasMap = DenseMap; + /// Render a SymbolStringPtr. raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym); @@ -87,12 +100,15 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU); /// Render a JITDylibSearchList. raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs); +/// Render a SymbolAliasMap. +raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases); + +/// Render a SymbolState. +raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S); + /// Callback to notify client that symbols have been resolved. using SymbolsResolvedCallback = std::function)>; -/// Callback to notify client that symbols are ready for execution. -using SymbolsReadyCallback = std::function; - /// Callback to register the dependencies for a given query. using RegisterDependenciesFunction = std::function; @@ -333,18 +349,6 @@ absoluteSymbols(SymbolMap Symbols, VModuleKey K = VModuleKey()) { std::move(Symbols), std::move(K)); } -struct SymbolAliasMapEntry { - SymbolAliasMapEntry() = default; - SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags) - : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {} - - SymbolStringPtr Aliasee; - JITSymbolFlags AliasFlags; -}; - -/// A map of Symbols to (Symbol, Flags) pairs. -using SymbolAliasMap = DenseMap; - /// A materialization unit for symbol aliases. Allows existing symbols to be /// aliased with alternate flags. class ReExportsMaterializationUnit : public MaterializationUnit { @@ -426,6 +430,15 @@ private: SymbolPredicate Allow; }; +/// Represents the state that a symbol has reached during materialization. +enum class SymbolState : uint8_t { + Invalid, /// No symbol should be in this state. + NeverSearched, /// Added to the symbol table, never queried. + Materializing, /// Queried, materialization begun. + Resolved, /// Assigned address, still materializing. + Ready = 0x3f /// Ready and safe for clients to access. +}; + /// A symbol query that returns results via a callback when results are /// ready. /// @@ -436,38 +449,30 @@ class AsynchronousSymbolQuery { friend class JITSymbolResolverAdapter; public: - - /// Create a query for the given symbols, notify-resolved and - /// notify-ready callbacks. + /// Create a query for the given symbols. The NotifyComplete + /// callback will be called once all queried symbols reach the given + /// minimum state. AsynchronousSymbolQuery(const SymbolNameSet &Symbols, - SymbolsResolvedCallback NotifySymbolsResolved, - SymbolsReadyCallback NotifySymbolsReady); + SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete); - /// Set the resolved symbol information for the given symbol name. - void resolve(const SymbolStringPtr &Name, JITEvaluatedSymbol Sym); + /// Notify the query that a requested symbol has reached the required state. + void notifySymbolMetRequiredState(const SymbolStringPtr &Name, + JITEvaluatedSymbol Sym); /// Returns true if all symbols covered by this query have been /// resolved. - bool isFullyResolved() const { return NotYetResolvedCount == 0; } - - /// Call the NotifySymbolsResolved callback. - /// - /// This should only be called if all symbols covered by the query have been - /// resolved. - void handleFullyResolved(); - - /// Notify the query that a requested symbol is ready for execution. - void notifySymbolReady(); + bool isComplete() const { return OutstandingSymbolsCount == 0; } - /// Returns true if all symbols covered by this query are ready. - bool isFullyReady() const { return NotYetReadyCount == 0; } - - /// Calls the NotifySymbolsReady callback. + /// Call the NotifyComplete callback. /// - /// This should only be called if all symbols covered by this query are ready. - void handleFullyReady(); + /// This should only be called if all symbols covered by the query have + /// reached the specified state. + void handleComplete(); private: + SymbolState getRequiredState() { return RequiredState; } + void addQueryDependence(JITDylib &JD, SymbolStringPtr Name); void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name); @@ -478,12 +483,11 @@ private: void detach(); - SymbolsResolvedCallback NotifySymbolsResolved; - SymbolsReadyCallback NotifySymbolsReady; + SymbolsResolvedCallback NotifyComplete; SymbolDependenceMap QueryRegistrations; SymbolMap ResolvedSymbols; - size_t NotYetResolvedCount; - size_t NotYetReadyCount; + size_t OutstandingSymbolsCount; + SymbolState RequiredState; }; /// A symbol table that supports asynchoronous symbol queries. @@ -626,28 +630,24 @@ private: DenseMap>; struct MaterializingInfo { - AsynchronousSymbolQueryList PendingQueries; SymbolDependenceMap Dependants; SymbolDependenceMap UnemittedDependencies; bool IsEmitted = false; - }; - using MaterializingInfosMap = DenseMap; + void addQuery(std::shared_ptr Q); + void removeQuery(const AsynchronousSymbolQuery &Q); + AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState); + AsynchronousSymbolQueryList takeAllQueries(); + bool hasQueriesPending() const { return !PendingQueries.empty(); } + const AsynchronousSymbolQueryList &pendingQueries() const { + return PendingQueries; + } - using LookupImplActionFlags = enum { - None = 0, - NotifyFullyResolved = 1 << 0U, - NotifyFullyReady = 1 << 1U, - LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady) + private: + AsynchronousSymbolQueryList PendingQueries; }; - enum class SymbolState : uint8_t { - Invalid, // No symbol should be in this state. - NeverSearched, // Added to the symbol table, never queried. - Materializing, // Queried, materialization begun. - Resolved, // Assigned address, still materializing. - Ready = 0x3f // Ready and safe for clients to access. - }; + using MaterializingInfosMap = DenseMap; class SymbolTableEntry { public: @@ -713,10 +713,9 @@ private: SymbolNameSet &Unresolved, bool MatchNonExported, MaterializationUnitList &MUs); - LookupImplActionFlags - lookupImpl(std::shared_ptr &Q, - std::vector> &MUs, - SymbolNameSet &Unresolved); + bool lookupImpl(std::shared_ptr &Q, + std::vector> &MUs, + SymbolNameSet &Unresolved); void detachQueryHelper(AsynchronousSymbolQuery &Q, const SymbolNameSet &QuerySymbols); @@ -833,7 +832,7 @@ public: /// Do not use -- this will be removed soon. Expected legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - bool WaiUntilReady, + SymbolState RequiredState, RegisterDependenciesFunction RegisterDependencies); /// Search the given JITDylib list for the given symbols. @@ -843,11 +842,8 @@ public: /// (hidden visibility) symbols in that dylib (true means match against /// non-exported symbols, false means do not match). /// - /// The OnResolve callback will be called once all requested symbols are - /// resolved, or if an error occurs prior to resolution. - /// - /// The OnReady callback will be called once all requested symbols are ready, - /// or if an error occurs after resolution but before all symbols are ready. + /// The NotifyComplete callback will be called once all requested symbols + /// reach the required state. /// /// If all symbols are found, the RegisterDependencies function will be called /// while the session lock is held. This gives clients a chance to register @@ -859,7 +855,7 @@ public: /// client to get an address to call) then the value NoDependenciesToRegister /// can be used. void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies); /// Blocking version of lookup above. Returns the resolved symbol map. @@ -871,9 +867,9 @@ public: /// error will be reported via reportErrors. Expected lookup(const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols, + SymbolState RequiredState = SymbolState::Ready, RegisterDependenciesFunction RegisterDependencies = - NoDependenciesToRegister, - bool WaitUntilReady = true); + NoDependenciesToRegister); /// Convenience version of blocking lookup. /// Searches each of the JITDylibs in the search order in turn for the given @@ -896,10 +892,11 @@ public: /// Materialize the given unit. void dispatchMaterialization(JITDylib &JD, std::unique_ptr MU) { - LLVM_DEBUG(runSessionLocked([&]() { - dbgs() << "Compiling, for " << JD.getName() << ", " << *MU - << "\n"; - });); + LLVM_DEBUG({ + runSessionLocked([&]() { + dbgs() << "Dispatching " << *MU << " for " << JD.getName() << "\n"; + }); + }); DispatchMaterialization(JD, std::move(MU)); } diff --git a/include/llvm/ExecutionEngine/Orc/Legacy.h b/include/llvm/ExecutionEngine/Orc/Legacy.h index e0e55265276..f9cbbf6ff18 100644 --- a/include/llvm/ExecutionEngine/Orc/Legacy.h +++ b/include/llvm/ExecutionEngine/Orc/Legacy.h @@ -148,8 +148,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, for (auto &S : Symbols) { if (JITSymbol Sym = FindSymbol(*S)) { if (auto Addr = Sym.getAddress()) { - Query.resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - Query.notifySymbolReady(); + Query.notifySymbolMetRequiredState( + S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); NewSymbolsResolved = true; } else { ES.legacyFailQuery(Query, Addr.takeError()); @@ -162,11 +162,8 @@ lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query, SymbolsNotFound.insert(S); } - if (NewSymbolsResolved && Query.isFullyResolved()) - Query.handleFullyResolved(); - - if (NewSymbolsResolved && Query.isFullyReady()) - Query.handleFullyReady(); + if (NewSymbolsResolved && Query.isComplete()) + Query.handleComplete(); return SymbolsNotFound; } diff --git a/lib/ExecutionEngine/Orc/Core.cpp b/lib/ExecutionEngine/Orc/Core.cpp index c2b7e4a24b9..e7e8f5caa39 100644 --- a/lib/ExecutionEngine/Orc/Core.cpp +++ b/lib/ExecutionEngine/Orc/Core.cpp @@ -219,6 +219,31 @@ raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs) { return OS; } +raw_ostream &operator<<(raw_ostream &OS, const SymbolAliasMap &Aliases) { + OS << "{"; + for (auto &KV : Aliases) + OS << " " << *KV.first << ": " << KV.second.Aliasee << " " + << KV.second.AliasFlags; + OS << " }\n"; + return OS; +} + +raw_ostream &operator<<(raw_ostream &OS, const SymbolState &S) { + switch (S) { + case SymbolState::Invalid: + return OS << "Invalid"; + case SymbolState::NeverSearched: + return OS << "Never-Searched"; + case SymbolState::Materializing: + return OS << "Materializing"; + case SymbolState::Resolved: + return OS << "Resolved"; + case SymbolState::Ready: + return OS << "Ready"; + } + llvm_unreachable("Invalid state"); +} + FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols) : Symbols(std::move(Symbols)) { assert(!this->Symbols.empty() && "Can not fail to resolve an empty set"); @@ -259,85 +284,46 @@ void SymbolsCouldNotBeRemoved::log(raw_ostream &OS) const { } AsynchronousSymbolQuery::AsynchronousSymbolQuery( - const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, - SymbolsReadyCallback NotifySymbolsReady) - : NotifySymbolsResolved(std::move(NotifySymbolsResolved)), - NotifySymbolsReady(std::move(NotifySymbolsReady)) { - NotYetResolvedCount = NotYetReadyCount = Symbols.size(); + const SymbolNameSet &Symbols, SymbolState RequiredState, + SymbolsResolvedCallback NotifyComplete) + : NotifyComplete(std::move(NotifyComplete)), RequiredState(RequiredState) { + assert(RequiredState >= SymbolState::Resolved && + "Cannot query for a symbols that have not reached the resolve state " + "yet"); + + OutstandingSymbolsCount = Symbols.size(); for (auto &S : Symbols) ResolvedSymbols[S] = nullptr; } -void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name, - JITEvaluatedSymbol Sym) { +void AsynchronousSymbolQuery::notifySymbolMetRequiredState( + const SymbolStringPtr &Name, JITEvaluatedSymbol Sym) { auto I = ResolvedSymbols.find(Name); assert(I != ResolvedSymbols.end() && "Resolving symbol outside the requested set"); assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name"); I->second = std::move(Sym); - --NotYetResolvedCount; + --OutstandingSymbolsCount; } -void AsynchronousSymbolQuery::handleFullyResolved() { - assert(NotYetResolvedCount == 0 && "Not fully resolved?"); +void AsynchronousSymbolQuery::handleComplete() { + assert(OutstandingSymbolsCount == 0 && + "Symbols remain, handleComplete called prematurely"); - if (!NotifySymbolsResolved) { - // handleFullyResolved may be called by handleFullyReady (see comments in - // that method), in which case this is a no-op, so bail out. - assert(!NotifySymbolsReady && - "NotifySymbolsResolved already called or an error occurred"); - return; - } - - auto TmpNotifySymbolsResolved = std::move(NotifySymbolsResolved); - NotifySymbolsResolved = SymbolsResolvedCallback(); - TmpNotifySymbolsResolved(std::move(ResolvedSymbols)); + auto TmpNotifyComplete = std::move(NotifyComplete); + NotifyComplete = SymbolsResolvedCallback(); + TmpNotifyComplete(std::move(ResolvedSymbols)); } -void AsynchronousSymbolQuery::notifySymbolReady() { - assert(NotYetReadyCount != 0 && "All symbols already emitted"); - --NotYetReadyCount; -} - -void AsynchronousSymbolQuery::handleFullyReady() { - assert(NotifySymbolsReady && - "NotifySymbolsReady already called or an error occurred"); - - auto TmpNotifySymbolsReady = std::move(NotifySymbolsReady); - NotifySymbolsReady = SymbolsReadyCallback(); - - if (NotYetResolvedCount == 0 && NotifySymbolsResolved) { - // The NotifyResolved callback of one query must have caused this query to - // become ready (i.e. there is still a handleFullyResolved callback waiting - // to be made back up the stack). Fold the handleFullyResolved call into - // this one before proceeding. This will cause the call further up the - // stack to become a no-op. - handleFullyResolved(); - } - - assert(QueryRegistrations.empty() && - "Query is still registered with some symbols"); - assert(!NotifySymbolsResolved && "Resolution not applied yet"); - TmpNotifySymbolsReady(Error::success()); -} - -bool AsynchronousSymbolQuery::canStillFail() { - return (NotifySymbolsResolved || NotifySymbolsReady); -} +bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete; } void AsynchronousSymbolQuery::handleFailed(Error Err) { assert(QueryRegistrations.empty() && ResolvedSymbols.empty() && - NotYetResolvedCount == 0 && NotYetReadyCount == 0 && + OutstandingSymbolsCount == 0 && "Query should already have been abandoned"); - if (NotifySymbolsResolved) { - NotifySymbolsResolved(std::move(Err)); - NotifySymbolsResolved = SymbolsResolvedCallback(); - } else { - assert(NotifySymbolsReady && "Failed after both callbacks issued?"); - NotifySymbolsReady(std::move(Err)); - } - NotifySymbolsReady = SymbolsReadyCallback(); + NotifyComplete(std::move(Err)); + NotifyComplete = SymbolsResolvedCallback(); } void AsynchronousSymbolQuery::addQueryDependence(JITDylib &JD, @@ -360,8 +346,7 @@ void AsynchronousSymbolQuery::removeQueryDependence( void AsynchronousSymbolQuery::detach() { ResolvedSymbols.clear(); - NotYetResolvedCount = 0; - NotYetReadyCount = 0; + OutstandingSymbolsCount = 0; for (auto &KV : QueryRegistrations) KV.first->detachQueryHelper(*this, KV.second); QueryRegistrations.clear(); @@ -548,6 +533,14 @@ void ReExportsMaterializationUnit::materialize( Aliases.erase(I); } + LLVM_DEBUG({ + ES.runSessionLocked([&]() { + dbgs() << "materializing reexports: target = " << TgtJD.getName() + << ", source = " << SrcJD.getName() << " " << RequestedAliases + << "\n"; + }); + }); + if (!Aliases.empty()) { if (SourceJD) R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported)); @@ -630,7 +623,7 @@ void ReExportsMaterializationUnit::materialize( } }; - auto OnResolve = [QueryInfo](Expected Result) { + auto OnComplete = [QueryInfo](Expected Result) { if (Result) { SymbolMap ResolutionMap; for (auto &KV : QueryInfo->Aliases) { @@ -648,10 +641,8 @@ void ReExportsMaterializationUnit::materialize( } }; - auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); }; - ES.lookup(JITDylibSearchList({{&SrcJD, MatchNonExported}}), QuerySymbols, - std::move(OnResolve), std::move(OnReady), + SymbolState::Resolved, std::move(OnComplete), std::move(RegisterDependencies)); } } @@ -776,7 +767,7 @@ void JITDylib::replace(std::unique_ptr MU) { for (auto &KV : MU->getSymbols()) { auto MII = MaterializingInfos.find(KV.first); if (MII != MaterializingInfos.end()) { - if (!MII->second.PendingQueries.empty()) + if (MII->second.hasQueriesPending()) return std::move(MU); } } @@ -817,7 +808,7 @@ JITDylib::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const { if (I == MaterializingInfos.end()) continue; - if (!I->second.PendingQueries.empty()) + if (I->second.hasQueriesPending()) RequestedSymbols.insert(KV.first); } @@ -864,8 +855,8 @@ void JITDylib::addDependencies(const SymbolStringPtr &Name, } void JITDylib::resolve(const SymbolMap &Resolved) { - auto FullyResolvedQueries = ES.runSessionLocked([&, this]() { - AsynchronousSymbolQuerySet FullyResolvedQueries; + auto CompletedQueries = ES.runSessionLocked([&, this]() { + AsynchronousSymbolQuerySet CompletedQueries; for (const auto &KV : Resolved) { auto &Name = KV.first; auto Sym = KV.second; @@ -891,25 +882,25 @@ void JITDylib::resolve(const SymbolMap &Resolved) { I->second.setState(SymbolState::Resolved); auto &MI = MaterializingInfos[Name]; - for (auto &Q : MI.PendingQueries) { - Q->resolve(Name, Sym); - if (Q->isFullyResolved()) - FullyResolvedQueries.insert(Q); + for (auto &Q : MI.takeQueriesMeeting(SymbolState::Resolved)) { + Q->notifySymbolMetRequiredState(Name, Sym); + if (Q->isComplete()) + CompletedQueries.insert(std::move(Q)); } } - return FullyResolvedQueries; + return CompletedQueries; }); - for (auto &Q : FullyResolvedQueries) { - assert(Q->isFullyResolved() && "Q not fully resolved"); - Q->handleFullyResolved(); + for (auto &Q : CompletedQueries) { + assert(Q->isComplete() && "Q not completed"); + Q->handleComplete(); } } void JITDylib::emit(const SymbolFlagsMap &Emitted) { - auto FullyReadyQueries = ES.runSessionLocked([&, this]() { - AsynchronousSymbolQuerySet ReadyQueries; + auto CompletedQueries = ES.runSessionLocked([&, this]() { + AsynchronousSymbolQuerySet CompletedQueries; for (const auto &KV : Emitted) { const auto &Name = KV.first; @@ -951,18 +942,22 @@ void JITDylib::emit(const SymbolFlagsMap &Emitted) { DependantMI.UnemittedDependencies.empty()) { assert(DependantMI.Dependants.empty() && "Dependants should be empty by now"); - for (auto &Q : DependantMI.PendingQueries) { - Q->notifySymbolReady(); - if (Q->isFullyReady()) - ReadyQueries.insert(Q); - Q->removeQueryDependence(DependantJD, DependantName); - } // Since this dependant is now ready, we erase its MaterializingInfo // and update its materializing state. - assert(DependantJD.Symbols.count(DependantName) && + auto DependantSymI = DependantJD.Symbols.find(DependantName); + assert(DependantSymI != DependantJD.Symbols.end() && "Dependant has no entry in the Symbols table"); - DependantJD.Symbols[DependantName].setState(SymbolState::Ready); + DependantSymI->second.setState(SymbolState::Ready); + + for (auto &Q : DependantMI.takeQueriesMeeting(SymbolState::Ready)) { + Q->notifySymbolMetRequiredState( + DependantName, DependantSymI->second.getSymbol()); + if (Q->isComplete()) + CompletedQueries.insert(Q); + Q->removeQueryDependence(DependantJD, DependantName); + } + DependantJD.MaterializingInfos.erase(DependantMII); } } @@ -971,25 +966,25 @@ void JITDylib::emit(const SymbolFlagsMap &Emitted) { MI.IsEmitted = true; if (MI.UnemittedDependencies.empty()) { - for (auto &Q : MI.PendingQueries) { - Q->notifySymbolReady(); - if (Q->isFullyReady()) - ReadyQueries.insert(Q); + auto SymI = Symbols.find(Name); + assert(SymI != Symbols.end() && "Symbol has no entry in Symbols table"); + SymI->second.setState(SymbolState::Ready); + for (auto &Q : MI.takeQueriesMeeting(SymbolState::Ready)) { + Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); + if (Q->isComplete()) + CompletedQueries.insert(Q); Q->removeQueryDependence(*this, Name); } - assert(Symbols.count(Name) && - "Symbol has no entry in the Symbols table"); - Symbols[Name].setState(SymbolState::Ready); MaterializingInfos.erase(MII); } } - return ReadyQueries; + return CompletedQueries; }); - for (auto &Q : FullyReadyQueries) { - assert(Q->isFullyReady() && "Q is not fully ready"); - Q->handleFullyReady(); + for (auto &Q : CompletedQueries) { + assert(Q->isComplete() && "Q is not complete"); + Q->handleComplete(); } } @@ -999,6 +994,7 @@ void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) { auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() { AsynchronousSymbolQuerySet FailedQueries; + std::vector MIIsToRemove; for (auto &Name : FailedSymbols) { auto I = Symbols.find(Name); @@ -1033,13 +1029,19 @@ void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) { // This has to be a copy, and the copy has to come before the abandon // operation: Each Q.detach() call will reach back into this // PendingQueries list to remove Q. - for (auto &Q : MII->second.PendingQueries) + for (auto &Q : MII->second.pendingQueries()) FailedQueries.insert(Q); - for (auto &Q : FailedQueries) - Q->detach(); + MIIsToRemove.push_back(std::move(MII)); + } + + // Detach failed queries. + for (auto &Q : FailedQueries) + Q->detach(); - assert(MII->second.PendingQueries.empty() && + // Remove the MaterializingInfos. + for (auto &MII : MIIsToRemove) { + assert(!MII->second.hasQueriesPending() && "Queries remain after symbol was failed"); MaterializingInfos.erase(MII); @@ -1228,19 +1230,20 @@ void JITDylib::lodgeQueryImpl( if (!SymI->second.getFlags().isExported() && !MatchNonExported) continue; - // If we matched against Name in JD, mark it to be removed from the Unresolved - // set. + // If we matched against Name in JD, mark it to be removed from the + // Unresolved set. ToRemove.push_back(Name); - if (SymI->second.getState() >= SymbolState::Resolved) { - assert(!SymI->second.hasMaterializerAttached() && - "Resolved symbols should not have materializers attached"); - Q->resolve(Name, SymI->second.getSymbol()); - if (SymI->second.getState() == SymbolState::Ready) { - Q->notifySymbolReady(); - continue; - } - } else if (SymI->second.hasMaterializerAttached()) { + // If this symbol already meets the required state for then notify the + // query and continue. + if (SymI->second.getState() >= Q->getRequiredState()) { + Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); + continue; + } + + // Otherwise this symbol does not yet meet the required state. Check whether + // it has a materializer attached, and if so prepare to run it. + if (SymI->second.hasMaterializerAttached()) { assert(SymI->second.getAddress() == 0 && "Symbol not resolved but already has address?"); auto UMII = UnmaterializedInfos.find(Name); @@ -1266,7 +1269,7 @@ void JITDylib::lodgeQueryImpl( assert(SymI->second.isInMaterializationPhase() && "By this line the symbol should be materializing"); auto &MI = MaterializingInfos[Name]; - MI.PendingQueries.push_back(Q); + MI.addQuery(Q); Q->addQueryDependence(*this, Name); } @@ -1282,22 +1285,21 @@ JITDylib::legacyLookup(std::shared_ptr Q, ES.runOutstandingMUs(); - LookupImplActionFlags ActionFlags = None; + bool QueryComplete = false; std::vector> MUs; SymbolNameSet Unresolved = std::move(Names); auto Err = ES.runSessionLocked([&, this]() -> Error { - ActionFlags = lookupImpl(Q, MUs, Unresolved); + QueryComplete = lookupImpl(Q, MUs, Unresolved); if (DefGenerator && !Unresolved.empty()) { - assert(ActionFlags == None && - "ActionFlags set but unresolved symbols remain?"); + assert(!QueryComplete && "query complete but unresolved symbols remain?"); auto NewDefs = DefGenerator(*this, Unresolved); if (!NewDefs) return NewDefs.takeError(); if (!NewDefs->empty()) { for (auto &D : *NewDefs) Unresolved.erase(D); - ActionFlags = lookupImpl(Q, MUs, *NewDefs); + QueryComplete = lookupImpl(Q, MUs, *NewDefs); assert(NewDefs->empty() && "All fallback defs should have been found by lookupImpl"); } @@ -1308,14 +1310,11 @@ JITDylib::legacyLookup(std::shared_ptr Q, if (Err) return std::move(Err); - assert((MUs.empty() || ActionFlags == None) && + assert((MUs.empty() || !QueryComplete) && "If action flags are set, there should be no work to do (so no MUs)"); - if (ActionFlags & NotifyFullyResolved) - Q->handleFullyResolved(); - - if (ActionFlags & NotifyFullyReady) - Q->handleFullyReady(); + if (QueryComplete) + Q->handleComplete(); // FIXME: Swap back to the old code below once RuntimeDyld works with // callbacks from asynchronous queries. @@ -1334,13 +1333,13 @@ JITDylib::legacyLookup(std::shared_ptr Q, return Unresolved; } -JITDylib::LookupImplActionFlags -JITDylib::lookupImpl(std::shared_ptr &Q, - std::vector> &MUs, - SymbolNameSet &Unresolved) { - LookupImplActionFlags ActionFlags = None; - std::vector ToRemove; +bool JITDylib::lookupImpl( + std::shared_ptr &Q, + std::vector> &MUs, + SymbolNameSet &Unresolved) { + bool QueryComplete = false; + std::vector ToRemove; for (auto Name : Unresolved) { // Search for the name in Symbols. Skip it if not found. @@ -1351,11 +1350,11 @@ JITDylib::lookupImpl(std::shared_ptr &Q, // If we found Name, mark it to be removed from the Unresolved set. ToRemove.push_back(Name); - // If the symbol has an address then resolve it. - if (SymI->second.getAddress() != 0) { - Q->resolve(Name, SymI->second.getSymbol()); - if (Q->isFullyResolved()) - ActionFlags |= NotifyFullyResolved; + if (SymI->second.getState() >= Q->getRequiredState()) { + Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol()); + if (Q->isComplete()) + QueryComplete = true; + continue; } // If the symbol is lazy, get the MaterialiaztionUnit for it. @@ -1380,18 +1379,13 @@ JITDylib::lookupImpl(std::shared_ptr &Q, // Add MU to the list of MaterializationUnits to be materialized. MUs.push_back(std::move(MU)); - } else if (SymI->second.getState() == SymbolState::Ready) { - Q->notifySymbolReady(); - if (Q->isFullyReady()) - ActionFlags |= NotifyFullyReady; - continue; } // Add the query to the PendingQueries list. assert(SymI->second.isInMaterializationPhase() && "By this line the symbol should be materializing"); auto &MI = MaterializingInfos[Name]; - MI.PendingQueries.push_back(Q); + MI.addQuery(Q); Q->addQueryDependence(*this, Name); } @@ -1399,7 +1393,7 @@ JITDylib::lookupImpl(std::shared_ptr &Q, for (auto &Name : ToRemove) Unresolved.erase(Name); - return ActionFlags; + return QueryComplete; } void JITDylib::dump(raw_ostream &OS) { @@ -1421,24 +1415,7 @@ void JITDylib::dump(raw_ostream &OS) { else OS << " "; - switch (KV.second.getState()) { - case SymbolState::Invalid: - OS << "Invalid"; - break; - case SymbolState::NeverSearched: - OS << "Never-Searched"; - break; - case SymbolState::Materializing: - OS << "Materializing"; - break; - case SymbolState::Resolved: - OS << "Resolved"; - break; - case SymbolState::Ready: - OS << "Ready"; - break; - // default: llvm_unreachable("Invalid state"); break; - } + OS << KV.second.getState(); if (KV.second.hasMaterializerAttached()) { OS << " (Materializer "; @@ -1456,10 +1433,10 @@ void JITDylib::dump(raw_ostream &OS) { OS << " \"" << *KV.first << "\":\n" << " IsEmitted = " << (KV.second.IsEmitted ? "true" : "false") << "\n" - << " " << KV.second.PendingQueries.size() + << " " << KV.second.pendingQueries().size() << " pending queries: { "; - for (auto &Q : KV.second.PendingQueries) - OS << Q.get() << " "; + for (const auto &Q : KV.second.pendingQueries()) + OS << Q.get() << " (" << Q->getRequiredState() << ") "; OS << "}\n Dependants:\n"; for (auto &KV2 : KV.second.Dependants) OS << " " << KV2.first->getName() << ": " << KV2.second << "\n"; @@ -1470,6 +1447,51 @@ void JITDylib::dump(raw_ostream &OS) { }); } +void JITDylib::MaterializingInfo::addQuery( + std::shared_ptr Q) { + + auto I = std::lower_bound( + PendingQueries.rbegin(), PendingQueries.rend(), Q->getRequiredState(), + [](const std::shared_ptr &V, SymbolState S) { + return V->getRequiredState() <= S; + }); + PendingQueries.insert(I.base(), std::move(Q)); +} + +void JITDylib::MaterializingInfo::removeQuery( + const AsynchronousSymbolQuery &Q) { + // FIXME: Implement 'find_as' for shared_ptr/T*. + auto I = + std::find_if(PendingQueries.begin(), PendingQueries.end(), + [&Q](const std::shared_ptr &V) { + return V.get() == &Q; + }); + assert(I != PendingQueries.end() && + "Query is not attached to this MaterializingInfo"); + PendingQueries.erase(I); +} + +JITDylib::AsynchronousSymbolQueryList +JITDylib::MaterializingInfo::takeQueriesMeeting(SymbolState RequiredState) { + AsynchronousSymbolQueryList Result; + while (!PendingQueries.empty()) { + if (PendingQueries.back()->getRequiredState() > RequiredState) + break; + + Result.push_back(std::move(PendingQueries.back())); + PendingQueries.pop_back(); + } + + return Result; +} + +JITDylib::AsynchronousSymbolQueryList +JITDylib::MaterializingInfo::takeAllQueries() { + AsynchronousSymbolQueryList Result; + std::swap(Result, PendingQueries); + return Result; +} + JITDylib::JITDylib(ExecutionSession &ES, std::string Name) : ES(ES), JITDylibName(std::move(Name)) { SearchOrder.push_back({this, true}); @@ -1533,17 +1555,7 @@ void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q, assert(MaterializingInfos.count(QuerySymbol) && "QuerySymbol does not have MaterializingInfo"); auto &MI = MaterializingInfos[QuerySymbol]; - - auto IdenticalQuery = - [&](const std::shared_ptr &R) { - return R.get() == &Q; - }; - - auto I = std::find_if(MI.PendingQueries.begin(), MI.PendingQueries.end(), - IdenticalQuery); - assert(I != MI.PendingQueries.end() && - "Query Q should be in the PendingQueries list for QuerySymbol"); - MI.PendingQueries.erase(I); + MI.removeQuery(Q); } } @@ -1621,74 +1633,36 @@ void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) { Expected ExecutionSession::legacyLookup( LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names, - bool WaitUntilReady, RegisterDependenciesFunction RegisterDependencies) { + SymbolState RequiredState, + RegisterDependenciesFunction RegisterDependencies) { #if LLVM_ENABLE_THREADS // In the threaded case we use promises to return the results. std::promise PromisedResult; - std::mutex ErrMutex; Error ResolutionError = Error::success(); - std::promise PromisedReady; - Error ReadyError = Error::success(); - auto OnResolve = [&](Expected R) { + auto NotifyComplete = [&](Expected R) { if (R) PromisedResult.set_value(std::move(*R)); else { - { - ErrorAsOutParameter _(&ResolutionError); - std::lock_guard Lock(ErrMutex); - ResolutionError = R.takeError(); - } + ErrorAsOutParameter _(&ResolutionError); + ResolutionError = R.takeError(); PromisedResult.set_value(SymbolMap()); } }; - - std::function OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - if (Err) { - ErrorAsOutParameter _(&ReadyError); - std::lock_guard Lock(ErrMutex); - ReadyError = std::move(Err); - } - PromisedReady.set_value(); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - reportError(std::move(Err)); - }; - } - #else SymbolMap Result; Error ResolutionError = Error::success(); - Error ReadyError = Error::success(); - auto OnResolve = [&](Expected R) { + auto NotifyComplete = [&](Expected R) { ErrorAsOutParameter _(&ResolutionError); if (R) Result = std::move(*R); else ResolutionError = R.takeError(); }; - - std::function OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - ErrorAsOutParameter _(&ReadyError); - if (Err) - ReadyError = std::move(Err); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - reportError(std::move(Err)); - }; - } #endif auto Query = std::make_shared( - Names, std::move(OnResolve), std::move(OnReady)); + Names, RequiredState, std::move(NotifyComplete)); // FIXME: This should be run session locked along with the registration code // and error reporting below. SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); @@ -1712,39 +1686,13 @@ Expected ExecutionSession::legacyLookup( #if LLVM_ENABLE_THREADS auto ResultFuture = PromisedResult.get_future(); auto Result = ResultFuture.get(); - - { - std::lock_guard Lock(ErrMutex); - if (ResolutionError) { - // ReadyError will never be assigned. Consume the success value. - cantFail(std::move(ReadyError)); - return std::move(ResolutionError); - } - } - - if (WaitUntilReady) { - auto ReadyFuture = PromisedReady.get_future(); - ReadyFuture.get(); - - { - std::lock_guard Lock(ErrMutex); - if (ReadyError) - return std::move(ReadyError); - } - } else - cantFail(std::move(ReadyError)); - + if (ResolutionError) + return std::move(ResolutionError); return std::move(Result); #else - if (ResolutionError) { - // ReadyError will never be assigned. Consume the success value. - cantFail(std::move(ReadyError)); + if (ResolutionError) return std::move(ResolutionError); - } - - if (ReadyError) - return std::move(ReadyError); return Result; #endif @@ -1752,9 +1700,16 @@ Expected ExecutionSession::legacyLookup( void ExecutionSession::lookup( const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols, - SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + SymbolState RequiredState, SymbolsResolvedCallback NotifyComplete, RegisterDependenciesFunction RegisterDependencies) { + LLVM_DEBUG({ + runSessionLocked([&]() { + dbgs() << "Looking up " << Symbols << " in " << SearchOrder + << " (required state: " << RequiredState << ")\n"; + }); + }); + // lookup can be re-entered recursively if running on a single thread. Run any // outstanding MUs in case this query depends on them, otherwise this lookup // will starve waiting for a result from an MU that is stuck in the queue. @@ -1762,10 +1717,9 @@ void ExecutionSession::lookup( auto Unresolved = std::move(Symbols); std::map CollectedMUsMap; - auto Q = std::make_shared( - Unresolved, std::move(OnResolve), std::move(OnReady)); - bool QueryIsFullyResolved = false; - bool QueryIsFullyReady = false; + auto Q = std::make_shared(Unresolved, RequiredState, + std::move(NotifyComplete)); + bool QueryComplete = false; auto LodgingErr = runSessionLocked([&]() -> Error { auto LodgeQuery = [&]() -> Error { @@ -1806,8 +1760,7 @@ void ExecutionSession::lookup( // Record whether this query is fully ready / resolved. We will use // this to call handleFullyResolved/handleFullyReady outside the session // lock. - QueryIsFullyResolved = Q->isFullyResolved(); - QueryIsFullyReady = Q->isFullyReady(); + QueryComplete = Q->isComplete(); // Call the register dependencies function. if (RegisterDependencies && !Q->QueryRegistrations.empty()) @@ -1819,13 +1772,11 @@ void ExecutionSession::lookup( if (LodgingErr) { Q->handleFailed(std::move(LodgingErr)); return; - } else { - if (QueryIsFullyResolved) - Q->handleFullyResolved(); - if (QueryIsFullyReady) - Q->handleFullyReady(); } + if (QueryComplete) + Q->handleComplete(); + // Move the MUs to the OutstandingMUs list, then materialize. { std::lock_guard Lock(OutstandingMUsMutex); @@ -1838,113 +1789,55 @@ void ExecutionSession::lookup( runOutstandingMUs(); } -Expected ExecutionSession::lookup( - const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols, - RegisterDependenciesFunction RegisterDependencies, bool WaitUntilReady) { +Expected +ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, + const SymbolNameSet &Symbols, + SymbolState RequiredState, + RegisterDependenciesFunction RegisterDependencies) { #if LLVM_ENABLE_THREADS // In the threaded case we use promises to return the results. std::promise PromisedResult; - std::mutex ErrMutex; Error ResolutionError = Error::success(); - std::promise PromisedReady; - Error ReadyError = Error::success(); - auto OnResolve = [&](Expected R) { + + auto NotifyComplete = [&](Expected R) { if (R) PromisedResult.set_value(std::move(*R)); else { - { - ErrorAsOutParameter _(&ResolutionError); - std::lock_guard Lock(ErrMutex); - ResolutionError = R.takeError(); - } + ErrorAsOutParameter _(&ResolutionError); + ResolutionError = R.takeError(); PromisedResult.set_value(SymbolMap()); } }; - std::function OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - if (Err) { - ErrorAsOutParameter _(&ReadyError); - std::lock_guard Lock(ErrMutex); - ReadyError = std::move(Err); - } - PromisedReady.set_value(); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - reportError(std::move(Err)); - }; - } - #else SymbolMap Result; Error ResolutionError = Error::success(); - Error ReadyError = Error::success(); - auto OnResolve = [&](Expected R) { + auto NotifyComplete = [&](Expected R) { ErrorAsOutParameter _(&ResolutionError); if (R) Result = std::move(*R); else ResolutionError = R.takeError(); }; - - std::function OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - ErrorAsOutParameter _(&ReadyError); - if (Err) - ReadyError = std::move(Err); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - reportError(std::move(Err)); - }; - } #endif // Perform the asynchronous lookup. - lookup(SearchOrder, Symbols, OnResolve, OnReady, RegisterDependencies); + lookup(SearchOrder, Symbols, RequiredState, NotifyComplete, + RegisterDependencies); #if LLVM_ENABLE_THREADS auto ResultFuture = PromisedResult.get_future(); auto Result = ResultFuture.get(); - { - std::lock_guard Lock(ErrMutex); - if (ResolutionError) { - // ReadyError will never be assigned. Consume the success value. - cantFail(std::move(ReadyError)); - return std::move(ResolutionError); - } - } - - if (WaitUntilReady) { - auto ReadyFuture = PromisedReady.get_future(); - ReadyFuture.get(); - - { - std::lock_guard Lock(ErrMutex); - if (ReadyError) - return std::move(ReadyError); - } - } else - cantFail(std::move(ReadyError)); + if (ResolutionError) + return std::move(ResolutionError); return std::move(Result); #else - if (ResolutionError) { - // ReadyError will never be assigned. Consume the success value. - cantFail(std::move(ReadyError)); + if (ResolutionError) return std::move(ResolutionError); - } - - if (ReadyError) - return std::move(ReadyError); return Result; #endif @@ -1955,8 +1848,8 @@ ExecutionSession::lookup(const JITDylibSearchList &SearchOrder, SymbolStringPtr Name) { SymbolNameSet Names({Name}); - if (auto ResultMap = lookup(SearchOrder, std::move(Names), - NoDependenciesToRegister, true)) { + if (auto ResultMap = lookup(SearchOrder, std::move(Names), SymbolState::Ready, + NoDependenciesToRegister)) { assert(ResultMap->size() == 1 && "Unexpected number of results"); assert(ResultMap->count(Name) && "Missing result for symbol"); return std::move(ResultMap->begin()->second); diff --git a/lib/ExecutionEngine/Orc/ExecutionUtils.cpp b/lib/ExecutionEngine/Orc/ExecutionUtils.cpp index 71518814136..f7fc5f8f179 100644 --- a/lib/ExecutionEngine/Orc/ExecutionUtils.cpp +++ b/lib/ExecutionEngine/Orc/ExecutionUtils.cpp @@ -129,8 +129,7 @@ Error CtorDtorRunner::run() { auto &ES = JD.getExecutionSession(); if (auto CtorDtorMap = - ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names), - NoDependenciesToRegister, true)) { + ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names))) { for (auto &KV : CtorDtorsByPriority) { for (auto &Name : KV.second) { assert(CtorDtorMap->count(Name) && "No entry for Name"); diff --git a/lib/ExecutionEngine/Orc/LazyReexports.cpp b/lib/ExecutionEngine/Orc/LazyReexports.cpp index c2565812d51..b12ef4044fe 100644 --- a/lib/ExecutionEngine/Orc/LazyReexports.cpp +++ b/lib/ExecutionEngine/Orc/LazyReexports.cpp @@ -51,18 +51,15 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) { SymbolName = I->second.second; } - auto LookupResult = ES.lookup(JITDylibSearchList({{SourceJD, true}}), - {SymbolName}, NoDependenciesToRegister, true); + auto LookupResult = + ES.lookup(JITDylibSearchList({{SourceJD, true}}), SymbolName); if (!LookupResult) { ES.reportError(LookupResult.takeError()); return ErrorHandlerAddr; } - assert(LookupResult->size() == 1 && "Unexpected number of results"); - assert(LookupResult->count(SymbolName) && "Unexpected result"); - - auto ResolvedAddr = LookupResult->begin()->second.getAddress(); + auto ResolvedAddr = LookupResult->getAddress(); std::shared_ptr NotifyResolved = nullptr; { diff --git a/lib/ExecutionEngine/Orc/Legacy.cpp b/lib/ExecutionEngine/Orc/Legacy.cpp index 9fd07d0072f..ce6368b57a8 100644 --- a/lib/ExecutionEngine/Orc/Legacy.cpp +++ b/lib/ExecutionEngine/Orc/Legacy.cpp @@ -36,8 +36,7 @@ void JITSymbolResolverAdapter::lookup(const LookupSet &Symbols, }; auto Q = std::make_shared( - InternedSymbols, OnResolvedWithUnwrap, - [this](Error Err) { ES.reportError(std::move(Err)); }); + InternedSymbols, SymbolState::Resolved, OnResolvedWithUnwrap); auto Unresolved = R.lookup(Q, InternedSymbols); if (Unresolved.empty()) { diff --git a/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp index eb0ea47e2d4..c7abce99002 100644 --- a/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp +++ b/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp @@ -69,14 +69,10 @@ public: } }; - ES.lookup( - SearchOrder, std::move(InternedSymbols), std::move(OnResolve), - // OnReady: - [&ES](Error Err) { ES.reportError(std::move(Err)); }, - // RegisterDependencies: - [this](const SymbolDependenceMap &Deps) { - registerDependencies(Deps); - }); + ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved, + std::move(OnResolve), [this](const SymbolDependenceMap &Deps) { + registerDependencies(Deps); + }); } void notifyResolved(AtomGraph &G) override { diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index b0464380b31..71f05b0e806 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -153,8 +153,8 @@ private: for (auto &S : Symbols) { if (auto Sym = findSymbol(*S)) { if (auto Addr = Sym.getAddress()) { - Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - Query->notifySymbolReady(); + Query->notifySymbolMetRequiredState( + S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); } else { Stack.ES.legacyFailQuery(*Query, Addr.takeError()); return orc::SymbolNameSet(); @@ -166,11 +166,8 @@ private: UnresolvedSymbols.insert(S); } - if (Query->isFullyResolved()) - Query->handleFullyResolved(); - - if (Query->isFullyReady()) - Query->handleFullyReady(); + if (Query->isComplete()) + Query->handleComplete(); return UnresolvedSymbols; } diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index 9d8694ee6b6..5585008bc8e 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -176,8 +176,8 @@ class OrcMCJITReplacement : public ExecutionEngine { for (auto &S : Symbols) { if (auto Sym = M.findMangledSymbol(*S)) { if (auto Addr = Sym.getAddress()) { - Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); - Query->notifySymbolReady(); + Query->notifySymbolMetRequiredState( + S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); NewSymbolsResolved = true; } else { M.ES.legacyFailQuery(*Query, Addr.takeError()); @@ -189,8 +189,8 @@ class OrcMCJITReplacement : public ExecutionEngine { } else { if (auto Sym2 = M.ClientResolver->findSymbol(*S)) { if (auto Addr = Sym2.getAddress()) { - Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym2.getFlags())); - Query->notifySymbolReady(); + Query->notifySymbolMetRequiredState( + S, JITEvaluatedSymbol(*Addr, Sym2.getFlags())); NewSymbolsResolved = true; } else { M.ES.legacyFailQuery(*Query, Addr.takeError()); @@ -204,11 +204,8 @@ class OrcMCJITReplacement : public ExecutionEngine { } } - if (NewSymbolsResolved && Query->isFullyResolved()) - Query->handleFullyResolved(); - - if (NewSymbolsResolved && Query->isFullyReady()) - Query->handleFullyReady(); + if (NewSymbolsResolved && Query->isComplete()) + Query->handleComplete(); return UnresolvedSymbols; } diff --git a/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index 373a0680d90..1a5917ea5ab 100644 --- a/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -41,9 +41,6 @@ public: OnResolved(Result); }; - // We're not waiting for symbols to be ready. Just log any errors. - auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); }; - // Register dependencies for all symbols contained in this set. auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { MR.addDependenciesForAll(Deps); @@ -52,8 +49,8 @@ public: JITDylibSearchList SearchOrder; MR.getTargetJITDylib().withSearchOrderDo( [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; }); - ES.lookup(SearchOrder, InternedSymbols, OnResolvedWithUnwrap, OnReady, - RegisterDependencies); + ES.lookup(SearchOrder, InternedSymbols, SymbolState::Resolved, + OnResolvedWithUnwrap, RegisterDependencies); } Expected getResponsibilitySet(const LookupSet &Symbols) { diff --git a/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index f5088e38761..6f9dd1fb481 100644 --- a/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -23,21 +23,16 @@ class CoreAPIsStandardTest : public CoreAPIsBasedStandardTest {}; namespace { TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { - bool OnResolutionRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; - auto OnResolution = [&](Expected Result) { + auto OnCompletion = [&](Expected Result) { EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; auto &Resolved = *Result; auto I = Resolved.find(Foo); EXPECT_NE(I, Resolved.end()) << "Could not find symbol definition"; EXPECT_EQ(I->second.getAddress(), FooAddr) << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; + OnCompletionRun = true; }; std::shared_ptr FooMR; @@ -48,65 +43,51 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) { FooMR = std::make_shared(std::move(R)); }))); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolution, OnReady, - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, + OnCompletion, NoDependenciesToRegister); - EXPECT_FALSE(OnResolutionRun) << "Should not have been resolved yet"; - EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet"; + EXPECT_FALSE(OnCompletionRun) << "Should not have been resolved yet"; FooMR->resolve({{Foo, FooSym}}); - EXPECT_TRUE(OnResolutionRun) << "Should have been resolved"; - EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet"; + EXPECT_FALSE(OnCompletionRun) << "Should not be ready yet"; FooMR->emit(); - EXPECT_TRUE(OnReadyRun) << "Should have been marked ready"; + EXPECT_TRUE(OnCompletionRun) << "Should have been marked ready"; } TEST_F(CoreAPIsStandardTest, ExecutionSessionFailQuery) { - bool OnResolutionRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; - auto OnResolution = [&](Expected Result) { + auto OnCompletion = [&](Expected Result) { EXPECT_FALSE(!!Result) << "Resolution unexpectedly returned success"; auto Msg = toString(Result.takeError()); EXPECT_EQ(Msg, "xyz") << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; + OnCompletionRun = true; }; - AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), OnResolution, OnReady); + AsynchronousSymbolQuery Q(SymbolNameSet({Foo}), SymbolState::Ready, + OnCompletion); ES.legacyFailQuery(Q, make_error("xyz", inconvertibleErrorCode())); - EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; - EXPECT_FALSE(OnReadyRun) << "OnReady unexpectedly run"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletionCallback was not run"; } TEST_F(CoreAPIsStandardTest, EmptyLookup) { - bool OnResolvedRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; - auto OnResolution = [&](Expected Result) { + auto OnCompletion = [&](Expected Result) { cantFail(std::move(Result)); - OnResolvedRun = true; - }; - - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; + OnCompletionRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {}, OnResolution, OnReady, - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {}, SymbolState::Ready, + OnCompletion, NoDependenciesToRegister); - EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query"; - EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; } TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { @@ -148,20 +129,14 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { ADD_FAILURE() << "\"Baz\" discarded unexpectedly"; }))); - bool OnResolvedRun = false; - bool OnReadyRun = false; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo, Baz}, - [&](Expected Result) { - EXPECT_TRUE(!!Result) << "OnResolved failed unexpectedly"; - consumeError(Result.takeError()); - OnResolvedRun = true; - }, - [&](Error Err) { - EXPECT_FALSE(!!Err) << "OnReady failed unexpectedly"; - consumeError(std::move(Err)); - OnReadyRun = true; - }, - NoDependenciesToRegister); + bool OnCompletionRun = false; + ES.lookup( + JITDylibSearchList({{&JD, false}}), {Foo, Baz}, SymbolState::Ready, + [&](Expected Result) { + cantFail(Result.takeError()); + OnCompletionRun = true; + }, + NoDependenciesToRegister); { // Attempt 1: Search for a missing symbol, Qux. @@ -193,8 +168,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) { EXPECT_TRUE(BarDiscarded) << "\"Bar\" should have been discarded"; EXPECT_TRUE(BarMaterializerDestructed) << "\"Bar\"'s materializer should have been destructed"; - EXPECT_TRUE(OnResolvedRun) << "OnResolved should have been run"; - EXPECT_TRUE(OnReadyRun) << "OnReady should have been run"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion should have been run"; } TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { @@ -202,24 +176,18 @@ TEST_F(CoreAPIsStandardTest, ChainedJITDylibLookup) { auto &JD2 = ES.createJITDylib("JD2"); - bool OnResolvedRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; auto Q = std::make_shared( - SymbolNameSet({Foo}), + SymbolNameSet({Foo}), SymbolState::Ready, [&](Expected Result) { cantFail(std::move(Result)); - OnResolvedRun = true; - }, - [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; + OnCompletionRun = true; }); cantFail(JD2.legacyLookup(Q, cantFail(JD.legacyLookup(Q, {Foo})))); - EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query"; - EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run for empty query"; } TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) { @@ -396,14 +364,13 @@ TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) { cantFail(JD.define(FooMU)); bool FooReady = false; - auto OnResolution = [](Expected R) { cantFail(std::move(R)); }; - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); + auto OnCompletion = [&](Expected Result) { + cantFail(std::move(Result)); FooReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution), - std::move(OnReady), NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, + OnCompletion, NoDependenciesToRegister); FooR->resolve({{Foo, FooSym}}); FooR->emit(); @@ -452,16 +419,18 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { FooResolved = true; }; - auto OnFooReady = [&](Error Err) { - cantFail(std::move(Err)); + auto OnFooReady = [&](Expected Result) { + cantFail(std::move(Result)); FooReady = true; }; - // Issue a lookup for Foo. Use NoDependenciesToRegister: We're going to add + // Issue lookups for Foo. Use NoDependenciesToRegister: We're going to add // the dependencies manually below. - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, - std::move(OnFooResolution), std::move(OnFooReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + std::move(OnFooResolution), NoDependenciesToRegister); + + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, + std::move(OnFooReady), NoDependenciesToRegister); bool BarResolved = false; bool BarReady = false; @@ -470,14 +439,16 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { BarResolved = true; }; - auto OnBarReady = [&](Error Err) { - cantFail(std::move(Err)); + auto OnBarReady = [&](Expected Result) { + cantFail(std::move(Result)); BarReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, - std::move(OnBarResolution), std::move(OnBarReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Resolved, + std::move(OnBarResolution), NoDependenciesToRegister); + + ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, + std::move(OnBarReady), NoDependenciesToRegister); bool BazResolved = false; bool BazReady = false; @@ -487,14 +458,16 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) { BazResolved = true; }; - auto OnBazReady = [&](Error Err) { - cantFail(std::move(Err)); + auto OnBazReady = [&](Expected Result) { + cantFail(std::move(Result)); BazReady = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, - std::move(OnBazResolution), std::move(OnBazReady), - NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Resolved, + std::move(OnBazResolution), NoDependenciesToRegister); + + ES.lookup(JITDylibSearchList({{&JD, false}}), {Baz}, SymbolState::Ready, + std::move(OnBazReady), NoDependenciesToRegister); // Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo. FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}}); @@ -599,30 +572,23 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) { SymbolNameSet Names({Foo}); - bool OnResolutionRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; - auto OnResolution = [&](Expected Result) { + auto OnCompletion = [&](Expected Result) { EXPECT_TRUE(!!Result) << "Resolution unexpectedly returned error"; auto I = Result->find(Foo); EXPECT_NE(I, Result->end()) << "Could not find symbol definition"; EXPECT_EQ(I->second.getAddress(), FooSym.getAddress()) << "Resolution returned incorrect result"; - OnResolutionRun = true; - }; - - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; + OnCompletionRun = true; }; - ES.lookup(JITDylibSearchList({{&JD, false}}), Names, std::move(OnResolution), - std::move(OnReady), NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), Names, SymbolState::Ready, + std::move(OnCompletion), NoDependenciesToRegister); EXPECT_TRUE(FooMaterialized) << "Foo was not materialized"; EXPECT_TRUE(BarDiscarded) << "Bar was not discarded"; - EXPECT_TRUE(OnResolutionRun) << "OnResolutionCallback was not run"; - EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; + EXPECT_TRUE(OnCompletionRun) << "OnResolutionCallback was not run"; } TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { @@ -652,24 +618,17 @@ TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) { cantFail(JD.define(MU1)); cantFail(JD.define(MU2)); - bool OnResolvedRun = false; - bool OnReadyRun = false; + bool OnCompletionRun = false; - auto OnResolution = [&](Expected Result) { + auto OnCompletion = [&](Expected Result) { cantFail(std::move(Result)); - OnResolvedRun = true; + OnCompletionRun = true; }; - auto OnReady = [&](Error Err) { - cantFail(std::move(Err)); - OnReadyRun = true; - }; - - ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, std::move(OnResolution), - std::move(OnReady), NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Bar}, SymbolState::Ready, + std::move(OnCompletion), NoDependenciesToRegister); - EXPECT_TRUE(OnResolvedRun) << "OnResolved not run"; - EXPECT_TRUE(OnReadyRun) << "OnReady not run"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion not run"; EXPECT_TRUE(BarMaterialized) << "Bar was not materialized at all"; EXPECT_TRUE(DuplicateBarDiscarded) << "Duplicate bar definition not discarded"; @@ -725,7 +684,11 @@ TEST_F(CoreAPIsStandardTest, FailResolution) { auto MU = llvm::make_unique( SymbolFlagsMap({{Foo, JITSymbolFlags::Exported | JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Weak}}), - [&](MaterializationResponsibility R) { R.failMaterialization(); }); + [&](MaterializationResponsibility R) { + dbgs() << "Before failMat:\n"; + ES.dump(dbgs()); + R.failMaterialization(); + }); cantFail(JD.define(MU)); @@ -763,6 +726,7 @@ TEST_F(CoreAPIsStandardTest, FailEmissionEarly) { ES.lookup( JITDylibSearchList({{&JD, false}}), SymbolNameSet({Baz}), + SymbolState::Resolved, [&R](Expected Result) { // Called when "baz" is resolved. We don't actually depend // on or care about baz, but use it to trigger failure of @@ -772,7 +736,6 @@ TEST_F(CoreAPIsStandardTest, FailEmissionEarly) { cantFail(std::move(Result)); R.failMaterialization(); }, - [](Error Err) { cantFail(std::move(Err)); }, [&](const SymbolDependenceMap &Deps) { R.addDependenciesForAll(Deps); }); @@ -923,14 +886,12 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) { }); cantFail(JD.define(MU)); - auto OnResolution = [](Expected Result) { + auto OnCompletion = [](Expected Result) { cantFail(std::move(Result)); }; - auto OnReady = [](Error Err) { cantFail(std::move(Err)); }; - - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, std::move(OnResolution), - std::move(OnReady), NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Ready, + std::move(OnCompletion), NoDependenciesToRegister); auto MU2 = llvm::make_unique( SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}), diff --git a/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp b/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp index dca3eeb75fe..f79d721b812 100644 --- a/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp +++ b/unittests/ExecutionEngine/Orc/LegacyAPIInteropTest.cpp @@ -42,10 +42,10 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) { EXPECT_EQ(RS.count(Bar), 1U) << "getResponsibilitySet result incorrect. Should be {'bar'}"; - bool OnResolvedRun = false; + bool OnCompletionRun = false; - auto OnResolved = [&](Expected Result) { - OnResolvedRun = true; + auto OnCompletion = [&](Expected Result) { + OnCompletionRun = true; EXPECT_TRUE(!!Result) << "Unexpected error"; EXPECT_EQ(Result->size(), 2U) << "Unexpected number of resolved symbols"; EXPECT_EQ(Result->count(Foo), 1U) << "Missing lookup result for foo"; @@ -55,18 +55,15 @@ TEST_F(LegacyAPIsStandardTest, TestLambdaSymbolResolver) { EXPECT_EQ((*Result)[Bar].getAddress(), BarSym.getAddress()) << "Incorrect address for bar"; }; - auto OnReady = [&](Error Err) { - EXPECT_FALSE(!!Err) << "Finalization should never fail in this test"; - }; - auto Q = std::make_shared(SymbolNameSet({Foo, Bar}), - OnResolved, OnReady); + auto Q = std::make_shared( + SymbolNameSet({Foo, Bar}), SymbolState::Resolved, OnCompletion); auto Unresolved = Resolver->lookup(std::move(Q), SymbolNameSet({Foo, Bar, Baz})); EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol"; EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to not be resolved"; - EXPECT_TRUE(OnResolvedRun) << "OnResolved was never run"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion was never run"; } TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) { @@ -98,10 +95,9 @@ TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) { EXPECT_FALSE(BarMaterialized) << "lookupFlags should not have materialized bar"; - bool OnResolvedRun = false; - bool OnReadyRun = false; - auto OnResolved = [&](Expected Result) { - OnResolvedRun = true; + bool OnCompletionRun = false; + auto OnCompletion = [&](Expected Result) { + OnCompletionRun = true; EXPECT_TRUE(!!Result) << "lookuWithLegacy failed to resolve"; EXPECT_EQ(Result->size(), 2U) << "Wrong number of symbols resolved"; @@ -114,17 +110,12 @@ TEST_F(LegacyAPIsStandardTest, LegacyLookupHelpersFn) { EXPECT_EQ((*Result)[Bar].getFlags(), BarSym.getFlags()) << "Wrong flags for bar"; }; - auto OnReady = [&](Error Err) { - EXPECT_FALSE(!!Err) << "Finalization unexpectedly failed"; - OnReadyRun = true; - }; - AsynchronousSymbolQuery Q({Foo, Bar}, OnResolved, OnReady); + AsynchronousSymbolQuery Q({Foo, Bar}, SymbolState::Resolved, OnCompletion); auto Unresolved = lookupWithLegacyFn(ES, Q, SymbolNameSet({Foo, Bar, Baz}), LegacyLookup); - EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run"; - EXPECT_TRUE(OnReadyRun) << "OnReady was not run"; + EXPECT_TRUE(OnCompletionRun) << "OnCompletion was not run"; EXPECT_EQ(Unresolved.size(), 1U) << "Expected one unresolved symbol"; EXPECT_EQ(Unresolved.count(Baz), 1U) << "Expected baz to be unresolved"; } diff --git a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index a5f529a37b6..440b840faaa 100644 --- a/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -61,12 +61,11 @@ static bool testSetProcessAllSections(std::unique_ptr Obj, cantFail(std::move(R)); }; - auto OnReadyDoNothing = [](Error Err) { cantFail(std::move(Err)); }; - ObjLayer.setProcessAllSections(ProcessAllSections); cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule())); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, OnResolveDoNothing, - OnReadyDoNothing, NoDependenciesToRegister); + ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + OnResolveDoNothing, NoDependenciesToRegister); + return DebugSectionSeen; } @@ -160,10 +159,10 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true); cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, - [](Expected R) { cantFail(std::move(R)); }, - [](Error Err) { cantFail(std::move(Err)); }, - NoDependenciesToRegister); + ES.lookup( + JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + [](Expected R) { cantFail(std::move(R)); }, + NoDependenciesToRegister); } TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { @@ -225,10 +224,10 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true); cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule())); - ES.lookup(JITDylibSearchList({{&JD, false}}), {Foo}, - [](Expected R) { cantFail(std::move(R)); }, - [](Error Err) { cantFail(std::move(Err)); }, - NoDependenciesToRegister); + ES.lookup( + JITDylibSearchList({{&JD, false}}), {Foo}, SymbolState::Resolved, + [](Expected R) { cantFail(std::move(R)); }, + NoDependenciesToRegister); } } // end anonymous namespace -- 2.40.0