diff options
author | Lang Hames <lhames@gmail.com> | 2018-07-20 22:22:19 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2018-07-20 22:22:19 +0000 |
commit | 845fa153ca1815d7f873aaf7369fd00ad0dc1e24 (patch) | |
tree | 2293ea311bb011e133912acbe3b6a2b6ccb59760 /lib/ExecutionEngine/Orc | |
parent | c53ade08d702ebaff787b13a5d4ffa3b8a744da2 (diff) |
Re-apply r337595 with fix for LLVM_ENABLE_THREADS=Off.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337626 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/Orc')
-rw-r--r-- | lib/ExecutionEngine/Orc/Core.cpp | 749 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/Legacy.cpp | 10 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcCBindingsStack.h | 4 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/OrcMCJITReplacement.h | 8 | ||||
-rw-r--r-- | lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp | 28 |
5 files changed, 518 insertions, 281 deletions
diff --git a/lib/ExecutionEngine/Orc/Core.cpp b/lib/ExecutionEngine/Orc/Core.cpp index 65f11782288..2bfe0803a53 100644 --- a/lib/ExecutionEngine/Orc/Core.cpp +++ b/lib/ExecutionEngine/Orc/Core.cpp @@ -23,6 +23,9 @@ namespace orc { char FailedToMaterialize::ID = 0; char SymbolsNotFound::ID = 0; +RegisterDependenciesFunction NoDependenciesToRegister = + RegisterDependenciesFunction(); + void MaterializationUnit::anchor() {} raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) { @@ -138,20 +141,361 @@ void SymbolsNotFound::log(raw_ostream &OS) const { OS << "Symbols not found: " << Symbols; } -void ExecutionSessionBase::failQuery(AsynchronousSymbolQuery &Q, Error Err) { - bool DeliveredError = true; - runSessionLocked([&]() -> void { +void ExecutionSessionBase::legacyFailQuery(AsynchronousSymbolQuery &Q, + Error Err) { + assert(!!Err && "Error should be in failure state"); + + bool SendErrorToQuery; + runSessionLocked([&]() { Q.detach(); - if (Q.canStillFail()) - Q.handleFailed(std::move(Err)); - else - DeliveredError = false; + SendErrorToQuery = Q.canStillFail(); }); - if (!DeliveredError) + if (SendErrorToQuery) + Q.handleFailed(std::move(Err)); + else reportError(std::move(Err)); } +Expected<SymbolMap> ExecutionSessionBase::legacyLookup( + ExecutionSessionBase &ES, LegacyAsyncLookupFunction AsyncLookup, + SymbolNameSet Names, bool WaitUntilReady, + RegisterDependenciesFunction RegisterDependencies) { +#if LLVM_ENABLE_THREADS + // In the threaded case we use promises to return the results. + std::promise<SymbolMap> PromisedResult; + std::mutex ErrMutex; + Error ResolutionError = Error::success(); + std::promise<void> PromisedReady; + Error ReadyError = Error::success(); + auto OnResolve = [&](Expected<SymbolMap> R) { + if (R) + PromisedResult.set_value(std::move(*R)); + else { + { + ErrorAsOutParameter _(&ResolutionError); + std::lock_guard<std::mutex> Lock(ErrMutex); + ResolutionError = R.takeError(); + } + PromisedResult.set_value(SymbolMap()); + } + }; + + std::function<void(Error)> OnReady; + if (WaitUntilReady) { + OnReady = [&](Error Err) { + if (Err) { + ErrorAsOutParameter _(&ReadyError); + std::lock_guard<std::mutex> Lock(ErrMutex); + ReadyError = std::move(Err); + } + PromisedReady.set_value(); + }; + } else { + OnReady = [&](Error Err) { + if (Err) + ES.reportError(std::move(Err)); + }; + } + +#else + SymbolMap Result; + Error ResolutionError = Error::success(); + Error ReadyError = Error::success(); + + auto OnResolve = [&](Expected<SymbolMap> R) { + ErrorAsOutParameter _(&ResolutionError); + if (R) + Result = std::move(*R); + else + ResolutionError = R.takeError(); + }; + + std::function<void(Error)> OnReady; + if (WaitUntilReady) { + OnReady = [&](Error Err) { + ErrorAsOutParameter _(&ReadyError); + if (Err) + ReadyError = std::move(Err); + }; + } else { + OnReady = [&](Error Err) { + if (Err) + ES.reportError(std::move(Err)); + }; + } +#endif + + auto Query = std::make_shared<AsynchronousSymbolQuery>( + Names, std::move(OnResolve), std::move(OnReady)); + // FIXME: This should be run session locked along with the registration code + // and error reporting below. + SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); + + // If the query was lodged successfully then register the dependencies, + // otherwise fail it with an error. + if (UnresolvedSymbols.empty()) + RegisterDependencies(Query->QueryRegistrations); + else { + bool DeliverError = runSessionLocked([&]() { + Query->detach(); + return Query->canStillFail(); + }); + auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols)); + if (DeliverError) + Query->handleFailed(std::move(Err)); + else + ES.reportError(std::move(Err)); + } + +#if LLVM_ENABLE_THREADS + auto ResultFuture = PromisedResult.get_future(); + auto Result = ResultFuture.get(); + + { + std::lock_guard<std::mutex> 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<std::mutex> Lock(ErrMutex); + if (ReadyError) + return std::move(ReadyError); + } + } else + cantFail(std::move(ReadyError)); + + return std::move(Result); + +#else + if (ResolutionError) { + // ReadyError will never be assigned. Consume the success value. + cantFail(std::move(ReadyError)); + return std::move(ResolutionError); + } + + if (ReadyError) + return std::move(ReadyError); + + return Result; +#endif +} + +void ExecutionSessionBase::lookup( + const VSOList &VSOs, const SymbolNameSet &Symbols, + SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady, + RegisterDependenciesFunction RegisterDependencies) { + + // lookup can be re-entered recursively if running on a single thread. Run any + // outstanding MUs in case this query depends on them, otherwise the main + // thread will starve waiting for a result from an MU that it failed to run. + runOutstandingMUs(); + + auto Unresolved = std::move(Symbols); + std::map<VSO *, MaterializationUnitList> MUsMap; + auto Q = std::make_shared<AsynchronousSymbolQuery>( + Symbols, std::move(OnResolve), std::move(OnReady)); + bool QueryIsFullyResolved = false; + bool QueryIsFullyReady = false; + bool QueryFailed = false; + + runSessionLocked([&]() { + for (auto *V : VSOs) { + assert(V && "VSOList entries must not be null"); + assert(!MUsMap.count(V) && + "VSOList should not contain duplicate entries"); + V->lodgeQuery(Q, Unresolved, MUsMap[V]); + } + + if (Unresolved.empty()) { + // Query lodged successfully. + + // 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(); + + // Call the register dependencies function. + if (RegisterDependencies && !Q->QueryRegistrations.empty()) + RegisterDependencies(Q->QueryRegistrations); + } else { + // Query failed due to unresolved symbols. + QueryFailed = true; + + // Disconnect the query from its dependencies. + Q->detach(); + + // Replace the MUs. + for (auto &KV : MUsMap) + for (auto &MU : KV.second) + KV.first->replace(std::move(MU)); + } + }); + + if (QueryFailed) { + Q->handleFailed(make_error<SymbolsNotFound>(std::move(Unresolved))); + return; + } else { + if (QueryIsFullyResolved) + Q->handleFullyResolved(); + if (QueryIsFullyReady) + Q->handleFullyReady(); + } + + // Move the MUs to the OutstandingMUs list, then materialize. + { + std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); + + for (auto &KV : MUsMap) + for (auto &MU : KV.second) + OutstandingMUs.push_back(std::make_pair(KV.first, std::move(MU))); + } + + runOutstandingMUs(); +} + +Expected<SymbolMap> +ExecutionSessionBase::lookup(const VSOList &VSOs, const SymbolNameSet &Symbols, + RegisterDependenciesFunction RegisterDependencies, + bool WaitUntilReady) { +#if LLVM_ENABLE_THREADS + // In the threaded case we use promises to return the results. + std::promise<SymbolMap> PromisedResult; + std::mutex ErrMutex; + Error ResolutionError = Error::success(); + std::promise<void> PromisedReady; + Error ReadyError = Error::success(); + auto OnResolve = [&](Expected<SymbolMap> R) { + if (R) + PromisedResult.set_value(std::move(*R)); + else { + { + ErrorAsOutParameter _(&ResolutionError); + std::lock_guard<std::mutex> Lock(ErrMutex); + ResolutionError = R.takeError(); + } + PromisedResult.set_value(SymbolMap()); + } + }; + + std::function<void(Error)> OnReady; + if (WaitUntilReady) { + OnReady = [&](Error Err) { + if (Err) { + ErrorAsOutParameter _(&ReadyError); + std::lock_guard<std::mutex> 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<SymbolMap> R) { + ErrorAsOutParameter _(&ResolutionError); + if (R) + Result = std::move(*R); + else + ResolutionError = R.takeError(); + }; + + std::function<void(Error)> 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(VSOs, Symbols, OnResolve, OnReady, RegisterDependencies); + +#if LLVM_ENABLE_THREADS + auto ResultFuture = PromisedResult.get_future(); + auto Result = ResultFuture.get(); + + { + std::lock_guard<std::mutex> 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<std::mutex> Lock(ErrMutex); + if (ReadyError) + return std::move(ReadyError); + } + } else + cantFail(std::move(ReadyError)); + + return std::move(Result); + +#else + if (ResolutionError) { + // ReadyError will never be assigned. Consume the success value. + cantFail(std::move(ReadyError)); + return std::move(ResolutionError); + } + + if (ReadyError) + return std::move(ReadyError); + + return Result; +#endif +} + +void ExecutionSessionBase::runOutstandingMUs() { + while (1) { + std::pair<VSO *, std::unique_ptr<MaterializationUnit>> VSOAndMU; + + { + std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); + if (!OutstandingMUs.empty()) { + VSOAndMU = std::move(OutstandingMUs.back()); + OutstandingMUs.pop_back(); + } + } + + if (VSOAndMU.first) { + assert(VSOAndMU.second && "VSO, but no MU?"); + dispatchMaterialization(*VSOAndMU.first, std::move(VSOAndMU.second)); + } else + break; + } +} + AsynchronousSymbolQuery::AsynchronousSymbolQuery( const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved, SymbolsReadyCallback NotifySymbolsReady) @@ -161,12 +505,6 @@ AsynchronousSymbolQuery::AsynchronousSymbolQuery( for (auto &S : Symbols) ResolvedSymbols[S] = nullptr; - - // If the query is empty it is trivially resolved/ready. - if (Symbols.empty()) { - handleFullyResolved(); - handleFullyReady(); - } } void AsynchronousSymbolQuery::resolve(const SymbolStringPtr &Name, @@ -183,8 +521,7 @@ void AsynchronousSymbolQuery::handleFullyResolved() { assert(NotYetResolvedCount == 0 && "Not fully resolved?"); assert(NotifySymbolsResolved && "NotifySymbolsResolved already called or error occurred"); - NotifySymbolsResolved( - ResolutionResult(std::move(ResolvedSymbols), QueryRegistrations)); + NotifySymbolsResolved(std::move(ResolvedSymbols)); NotifySymbolsResolved = SymbolsResolvedCallback(); } @@ -349,7 +686,8 @@ MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) { void MaterializationResponsibility::addDependencies( const SymbolDependenceMap &Dependencies) { - V.addDependencies(SymbolFlags, Dependencies); + for (auto &KV : SymbolFlags) + V.addDependencies(KV.first, Dependencies); } AbsoluteSymbolsMaterializationUnit::AbsoluteSymbolsMaterializationUnit( @@ -384,8 +722,9 @@ ReExportsMaterializationUnit::ReExportsMaterializationUnit( void ReExportsMaterializationUnit::materialize( MaterializationResponsibility R) { - VSO &SrcV = SourceVSO ? *SourceVSO : R.getTargetVSO(); - auto &ES = SrcV.getExecutionSession(); + auto &ES = R.getTargetVSO().getExecutionSession(); + VSO &TgtV = R.getTargetVSO(); + VSO &SrcV = SourceVSO ? *SourceVSO : TgtV; // Find the set of requested aliases and aliasees. Return any unrequested // aliases back to the VSO so as to not prematurely materialize any aliasees. @@ -434,9 +773,8 @@ void ReExportsMaterializationUnit::materialize( auto Tmp = I++; // Chain detected. Skip this symbol for this round. - if (&SrcV == &R.getTargetVSO() && - (QueryAliases.count(Tmp->second.Aliasee) || - RequestedAliases.count(Tmp->second.Aliasee))) + if (&SrcV == &TgtV && (QueryAliases.count(Tmp->second.Aliasee) || + RequestedAliases.count(Tmp->second.Aliasee))) continue; ResponsibilitySymbols.insert(Tmp->first); @@ -459,49 +797,32 @@ void ReExportsMaterializationUnit::materialize( QueryInfos.pop_back(); - auto OnResolve = - [QueryInfo, - &SrcV](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) { - if (RR) { - SymbolMap ResolutionMap; - SymbolNameSet Resolved; - for (auto &KV : QueryInfo->Aliases) { - assert(RR->Symbols.count(KV.second.Aliasee) && - "Result map missing entry?"); - ResolutionMap[KV.first] = JITEvaluatedSymbol( - RR->Symbols[KV.second.Aliasee].getAddress(), - KV.second.AliasFlags); - - // FIXME: We're creating a SymbolFlagsMap and a std::map of - // std::sets just to add one dependency here. This needs a - // re-think. - Resolved.insert(KV.first); - } - QueryInfo->R.resolve(ResolutionMap); - - SymbolDependenceMap Deps; - Deps[&SrcV] = std::move(Resolved); - QueryInfo->R.addDependencies(Deps); + auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { + R.addDependencies(Deps); + }; - QueryInfo->R.finalize(); - } else { - auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession(); - ES.reportError(RR.takeError()); - QueryInfo->R.failMaterialization(); - } - }; + auto OnResolve = [QueryInfo](Expected<SymbolMap> Result) { + if (Result) { + SymbolMap ResolutionMap; + for (auto &KV : QueryInfo->Aliases) { + assert(Result->count(KV.second.Aliasee) && + "Result map missing entry?"); + ResolutionMap[KV.first] = JITEvaluatedSymbol( + (*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags); + } + QueryInfo->R.resolve(ResolutionMap); + QueryInfo->R.finalize(); + } else { + auto &ES = QueryInfo->R.getTargetVSO().getExecutionSession(); + ES.reportError(Result.takeError()); + QueryInfo->R.failMaterialization(); + } + }; auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); }; - auto Q = std::make_shared<AsynchronousSymbolQuery>( - QuerySymbols, std::move(OnResolve), std::move(OnReady)); - - auto Unresolved = SrcV.lookup(Q, std::move(QuerySymbols)); - - if (!Unresolved.empty()) { - ES.failQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved))); - return; - } + ES.lookup({&SrcV}, QuerySymbols, std::move(OnResolve), std::move(OnReady), + std::move(RegisterDependencies)); } } @@ -642,40 +963,35 @@ SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) { }); } -void VSO::addDependencies(const SymbolFlagsMap &Dependants, +void VSO::addDependencies(const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) { - ES.runSessionLocked([&, this]() { - for (auto &KV : Dependants) { - const auto &Name = KV.first; - assert(Symbols.count(Name) && "Name not in symbol table"); - assert((Symbols[Name].getFlags().isLazy() || - Symbols[Name].getFlags().isMaterializing()) && - "Symbol is not lazy or materializing"); - - auto &MI = MaterializingInfos[Name]; - assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol"); - - for (auto &KV : Dependencies) { - assert(KV.first && "Null VSO in dependency?"); - auto &OtherVSO = *KV.first; - auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO]; - - for (auto &OtherSymbol : KV.second) { - auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol]; - - if (OtherMI.IsFinalized) - transferFinalizedNodeDependencies(MI, Name, OtherMI); - else if (&OtherVSO != this || OtherSymbol != Name) { - OtherMI.Dependants[this].insert(Name); - DepsOnOtherVSO.insert(OtherSymbol); - } - } - - if (DepsOnOtherVSO.empty()) - MI.UnfinalizedDependencies.erase(&OtherVSO); + assert(Symbols.count(Name) && "Name not in symbol table"); + assert((Symbols[Name].getFlags().isLazy() || + Symbols[Name].getFlags().isMaterializing()) && + "Symbol is not lazy or materializing"); + + auto &MI = MaterializingInfos[Name]; + assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol"); + + for (auto &KV : Dependencies) { + assert(KV.first && "Null VSO in dependency?"); + auto &OtherVSO = *KV.first; + auto &DepsOnOtherVSO = MI.UnfinalizedDependencies[&OtherVSO]; + + for (auto &OtherSymbol : KV.second) { + auto &OtherMI = OtherVSO.MaterializingInfos[OtherSymbol]; + + if (OtherMI.IsFinalized) + transferFinalizedNodeDependencies(MI, Name, OtherMI); + else if (&OtherVSO != this || OtherSymbol != Name) { + OtherMI.Dependants[this].insert(Name); + DepsOnOtherVSO.insert(OtherSymbol); } } - }); + + if (DepsOnOtherVSO.empty()) + MI.UnfinalizedDependencies.erase(&OtherVSO); + } } void VSO::resolve(const SymbolMap &Resolved) { @@ -856,25 +1172,6 @@ void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) { Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols)); } -void VSO::runOutstandingMUs() { - while (1) { - std::unique_ptr<MaterializationUnit> MU; - - { - std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); - if (!OutstandingMUs.empty()) { - MU = std::move(OutstandingMUs.back()); - OutstandingMUs.pop_back(); - } - } - - if (MU) - ES.dispatchMaterialization(*this, std::move(MU)); - else - break; - } -} - void VSO::setSearchOrder(VSOList NewSearchOrder, bool SearchThisVSOFirst) { if (SearchThisVSOFirst && NewSearchOrder.front() != this) NewSearchOrder.insert(NewSearchOrder.begin(), this); @@ -939,11 +1236,89 @@ SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags, return Unresolved; } -SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Names) { +void VSO::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q, + SymbolNameSet &Unresolved, MaterializationUnitList &MUs) { assert(Q && "Query can not be null"); - runOutstandingMUs(); + lodgeQueryImpl(Q, Unresolved, MUs); + if (FallbackDefinitionGenerator && !Unresolved.empty()) { + auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved); + if (!FallbackDefs.empty()) { + for (auto &D : FallbackDefs) + Unresolved.erase(D); + lodgeQueryImpl(Q, FallbackDefs, MUs); + assert(FallbackDefs.empty() && + "All fallback defs should have been found by lookupImpl"); + } + } +} + +void VSO::lodgeQueryImpl( + std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved, + std::vector<std::unique_ptr<MaterializationUnit>> &MUs) { + for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) { + auto TmpI = I++; + auto Name = *TmpI; + + // Search for the name in Symbols. Skip it if not found. + auto SymI = Symbols.find(Name); + if (SymI == Symbols.end()) + continue; + + // If we found Name in V, remove it frome the Unresolved set and add it + // to the added set. + Unresolved.erase(TmpI); + + // If the symbol has an address then resolve it. + if (SymI->second.getAddress() != 0) + Q->resolve(Name, SymI->second); + + // If the symbol is lazy, get the MaterialiaztionUnit for it. + if (SymI->second.getFlags().isLazy()) { + assert(SymI->second.getAddress() == 0 && + "Lazy symbol should not have a resolved address"); + assert(!SymI->second.getFlags().isMaterializing() && + "Materializing and lazy should not both be set"); + auto UMII = UnmaterializedInfos.find(Name); + assert(UMII != UnmaterializedInfos.end() && + "Lazy symbol should have UnmaterializedInfo"); + auto MU = std::move(UMII->second->MU); + assert(MU != nullptr && "Materializer should not be null"); + + // Move all symbols associated with this MaterializationUnit into + // materializing state. + for (auto &KV : MU->getSymbols()) { + auto SymK = Symbols.find(KV.first); + auto Flags = SymK->second.getFlags(); + Flags &= ~JITSymbolFlags::Lazy; + Flags |= JITSymbolFlags::Materializing; + SymK->second.setFlags(Flags); + UnmaterializedInfos.erase(KV.first); + } + + // Add MU to the list of MaterializationUnits to be materialized. + MUs.push_back(std::move(MU)); + } else if (!SymI->second.getFlags().isMaterializing()) { + // The symbol is neither lazy nor materializing. Finalize it and + // continue. + Q->notifySymbolReady(); + continue; + } + + // Add the query to the PendingQueries list. + assert(SymI->second.getFlags().isMaterializing() && + "By this line the symbol should be materializing"); + auto &MI = MaterializingInfos[Name]; + MI.PendingQueries.push_back(Q); + Q->addQueryDependence(*this, Name); + } +} + +SymbolNameSet VSO::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, + SymbolNameSet Names) { + assert(Q && "Query can not be null"); + + ES.runOutstandingMUs(); LookupImplActionFlags ActionFlags = None; std::vector<std::unique_ptr<MaterializationUnit>> MUs; @@ -978,11 +1353,11 @@ SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q, // callbacks from asynchronous queries. // Add MUs to the OutstandingMUs list. { - std::lock_guard<std::recursive_mutex> Lock(OutstandingMUsMutex); + std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex); for (auto &MU : MUs) - OutstandingMUs.push_back(std::move(MU)); + ES.OutstandingMUs.push_back(make_pair(this, std::move(MU))); } - runOutstandingMUs(); + ES.runOutstandingMUs(); // Dispatch any required MaterializationUnits for materialization. // for (auto &MU : MUs) @@ -1243,133 +1618,6 @@ VSO &ExecutionSession::createVSO(std::string Name) { }); } -Expected<SymbolMap> blockingLookup(ExecutionSessionBase &ES, - AsynchronousLookupFunction AsyncLookup, - SymbolNameSet Names, bool WaitUntilReady, - MaterializationResponsibility *MR) { - -#if LLVM_ENABLE_THREADS - // In the threaded case we use promises to return the results. - std::promise<SymbolMap> PromisedResult; - std::mutex ErrMutex; - Error ResolutionError = Error::success(); - std::promise<void> PromisedReady; - Error ReadyError = Error::success(); - auto OnResolve = - [&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) { - if (Result) { - if (MR) - MR->addDependencies(Result->Dependencies); - PromisedResult.set_value(std::move(Result->Symbols)); - } else { - { - ErrorAsOutParameter _(&ResolutionError); - std::lock_guard<std::mutex> Lock(ErrMutex); - ResolutionError = Result.takeError(); - } - PromisedResult.set_value(SymbolMap()); - } - }; - - std::function<void(Error)> OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - if (Err) { - ErrorAsOutParameter _(&ReadyError); - std::lock_guard<std::mutex> Lock(ErrMutex); - ReadyError = std::move(Err); - } - PromisedReady.set_value(); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - ES.reportError(std::move(Err)); - }; - } - -#else - SymbolMap Result; - Error ResolutionError = Error::success(); - Error ReadyError = Error::success(); - - auto OnResolve = [&](Expected<AsynchronousSymbolQuery::ResolutionResult> R) { - ErrorAsOutParameter _(&ResolutionError); - if (R) { - if (MR) - MR->addDependencies(R->Dependencies); - Result = std::move(R->Symbols); - } else - ResolutionError = R.takeError(); - }; - - std::function<void(Error)> OnReady; - if (WaitUntilReady) { - OnReady = [&](Error Err) { - ErrorAsOutParameter _(&ReadyError); - if (Err) - ReadyError = std::move(Err); - }; - } else { - OnReady = [&](Error Err) { - if (Err) - ES.reportError(std::move(Err)); - }; - } -#endif - - auto Query = std::make_shared<AsynchronousSymbolQuery>( - Names, std::move(OnResolve), std::move(OnReady)); - - SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names)); - - // If there are unresolved symbols then the query will never return. - // Fail it with ES.failQuery. - if (!UnresolvedSymbols.empty()) - ES.failQuery(*Query, - make_error<SymbolsNotFound>(std::move(UnresolvedSymbols))); - -#if LLVM_ENABLE_THREADS - auto ResultFuture = PromisedResult.get_future(); - auto Result = ResultFuture.get(); - - { - std::lock_guard<std::mutex> 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<std::mutex> Lock(ErrMutex); - if (ReadyError) - return std::move(ReadyError); - } - } else - cantFail(std::move(ReadyError)); - - return std::move(Result); - -#else - if (ResolutionError) { - // ReadyError will never be assigned. Consume the success value. - cantFail(std::move(ReadyError)); - return std::move(ResolutionError); - } - - if (ReadyError) - return std::move(ReadyError); - - return Result; -#endif -} - Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) { if (VSOs.empty()) @@ -1377,18 +1625,7 @@ Expected<SymbolMap> lookup(const VSOList &VSOs, SymbolNameSet Names) { auto &ES = (*VSOs.begin())->getExecutionSession(); - auto LookupFn = [&](std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Unresolved) { - for (auto *V : VSOs) { - assert(V && "VSOs entries must not be null"); - if (Unresolved.empty()) - break; - Unresolved = V->lookup(Q, std::move(Unresolved)); - } - return Unresolved; - }; - - return blockingLookup(ES, std::move(LookupFn), Names, true); + return ES.lookup(VSOs, Names, NoDependenciesToRegister, true); } /// Look up a symbol by searching a list of VSOs. diff --git a/lib/ExecutionEngine/Orc/Legacy.cpp b/lib/ExecutionEngine/Orc/Legacy.cpp index 6fde6898a16..22775ef14f8 100644 --- a/lib/ExecutionEngine/Orc/Legacy.cpp +++ b/lib/ExecutionEngine/Orc/Legacy.cpp @@ -29,8 +29,14 @@ JITSymbolResolverAdapter::lookup(const LookupSet &Symbols) { return R.lookup(std::move(Q), std::move(Unresolved)); }; - auto InternedResult = blockingLookup(ES, std::move(LookupFn), - std::move(InternedSymbols), false, MR); + auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { + if (MR) + MR->addDependencies(Deps); + }; + + auto InternedResult = + ES.legacyLookup(ES, std::move(LookupFn), std::move(InternedSymbols), + false, RegisterDependencies); if (!InternedResult) return InternedResult.takeError(); diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h index 6c44f4367ec..b9f8a370d2f 100644 --- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h +++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h @@ -156,11 +156,11 @@ private: Query->resolve(S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); Query->notifySymbolReady(); } else { - Stack.ES.failQuery(*Query, Addr.takeError()); + Stack.ES.legacyFailQuery(*Query, Addr.takeError()); return orc::SymbolNameSet(); } } else if (auto Err = Sym.takeError()) { - Stack.ES.failQuery(*Query, std::move(Err)); + Stack.ES.legacyFailQuery(*Query, std::move(Err)); return orc::SymbolNameSet(); } else UnresolvedSymbols.insert(S); diff --git a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h index ded53ac3106..abe89ce70af 100644 --- a/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h +++ b/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h @@ -178,11 +178,11 @@ class OrcMCJITReplacement : public ExecutionEngine { Query->notifySymbolReady(); NewSymbolsResolved = true; } else { - M.ES.failQuery(*Query, Addr.takeError()); + M.ES.legacyFailQuery(*Query, Addr.takeError()); return SymbolNameSet(); } } else if (auto Err = Sym.takeError()) { - M.ES.failQuery(*Query, std::move(Err)); + M.ES.legacyFailQuery(*Query, std::move(Err)); return SymbolNameSet(); } else { if (auto Sym2 = M.ClientResolver->findSymbol(*S)) { @@ -191,11 +191,11 @@ class OrcMCJITReplacement : public ExecutionEngine { Query->notifySymbolReady(); NewSymbolsResolved = true; } else { - M.ES.failQuery(*Query, Addr.takeError()); + M.ES.legacyFailQuery(*Query, Addr.takeError()); return SymbolNameSet(); } } else if (auto Err = Sym2.takeError()) { - M.ES.failQuery(*Query, std::move(Err)); + M.ES.legacyFailQuery(*Query, std::move(Err)); return SymbolNameSet(); } else UnresolvedSymbols.insert(S); diff --git a/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index 7cdc6b352d1..6edf616660e 100644 --- a/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -16,30 +16,23 @@ using namespace llvm::orc; class VSOSearchOrderResolver : public JITSymbolResolver { public: - VSOSearchOrderResolver(ExecutionSession &ES, - MaterializationResponsibility &MR) - : ES(ES), MR(MR) {} + VSOSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {} Expected<LookupResult> lookup(const LookupSet &Symbols) { + auto &ES = MR.getTargetVSO().getExecutionSession(); SymbolNameSet InternedSymbols; for (auto &S : Symbols) InternedSymbols.insert(ES.getSymbolStringPool().intern(S)); - auto AsyncLookup = [&](std::shared_ptr<AsynchronousSymbolQuery> Q, - SymbolNameSet Names) { - SymbolNameSet Unresolved = std::move(Names); - MR.getTargetVSO().withSearchOrderDo([&](const VSOList &SearchOrder) { - for (auto *V : SearchOrder) { - assert(V && "VSOList entry can not be null"); - Unresolved = V->lookup(Q, std::move(Unresolved)); - } - }); - return Unresolved; + auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) { + MR.addDependencies(Deps); }; - auto InternedResult = blockingLookup( - ES, std::move(AsyncLookup), std::move(InternedSymbols), false, &MR); + auto InternedResult = + MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) { + return ES.lookup(VSOs, InternedSymbols, RegisterDependencies, false); + }); if (!InternedResult) return InternedResult.takeError(); @@ -52,6 +45,8 @@ public: } Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) { + auto &ES = MR.getTargetVSO().getExecutionSession(); + SymbolNameSet InternedSymbols; for (auto &S : Symbols) @@ -75,7 +70,6 @@ public: } private: - ExecutionSession &ES; MaterializationResponsibility &MR; }; @@ -106,7 +100,7 @@ void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R, auto MemoryManager = GetMemoryManager(K); - VSOSearchOrderResolver Resolver(ES, R); + VSOSearchOrderResolver Resolver(R); auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver); RTDyld->setProcessAllSections(ProcessAllSections); |