1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[ORC] Make VSO symbol resolution/finalization operations private.

This forces these operations to be carried out via a
MaterializationResponsibility instance, ensuring responsibility is explicitly
tracked.

llvm-svn: 330356
This commit is contained in:
Lang Hames 2018-04-19 18:42:49 +00:00
parent 2764b3b533
commit 52289d96c4
2 changed files with 156 additions and 96 deletions

View File

@ -207,19 +207,49 @@ createSymbolResolver(LookupFlagsFn &&LookupFlags, LookupFn &&Lookup) {
}
/// @brief Tracks responsibility for materialization.
///
/// An instance of this class is passed to MaterializationUnits when their
/// materialize method is called. It allows MaterializationUnits to resolve and
/// finalize symbols, or abandon materialization by notifying any unmaterialized
/// symbols of an error.
class MaterializationResponsibility {
public:
/// @brief Create a MaterializationResponsibility for the given VSO and
/// initial symbols.
MaterializationResponsibility(VSO &V, SymbolFlagsMap SymbolFlags);
MaterializationResponsibility(MaterializationResponsibility &&) = default;
MaterializationResponsibility &
operator=(MaterializationResponsibility &&) = default;
/// @brief Destruct a MaterializationResponsibility instance. In debug mode
/// this asserts that all symbols being tracked have been either
/// finalized or notified of an error.
~MaterializationResponsibility();
MaterializationResponsibility takeResponsibility(SymbolNameSet Symbols);
/// @brief Returns the target VSO that these symbols are being materialized
/// into.
const VSO &getTargetVSO() const { return V; }
/// @brief Resolves the given symbols. Individual calls to this method may
/// resolve a subset of the symbols, but all symbols must have been
/// resolved prior to calling finalize.
void resolve(const SymbolMap &Symbols);
/// @brief Finalizes all symbols tracked by this instance.
void finalize();
/// @brief Notify all unfinalized symbols that an error has occurred.
/// This method should be called if materialization of any symbol is
/// abandoned.
void notifyMaterializationFailed();
/// @brief Transfers responsibility for the given symbols to a new
/// MaterializationResponsibility class. This is useful if a
/// MaterializationUnit wants to transfer responsibility for a subset
/// of symbols to another MaterializationUnit or utility.
MaterializationResponsibility delegate(SymbolNameSet Symbols);
private:
VSO &V;
SymbolFlagsMap SymbolFlags;
@ -262,6 +292,7 @@ private:
/// (since a VSO's address is fixed).
class VSO {
friend class ExecutionSession;
friend class MaterializationResponsibility;
public:
enum RelativeLinkageStrength {
@ -316,16 +347,6 @@ public:
/// @brief Adds the given symbols to the mapping as lazy symbols.
Error defineLazy(std::unique_ptr<MaterializationUnit> Source);
/// @brief Add the given symbol/address mappings to the dylib, but do not
/// mark the symbols as finalized yet.
void resolve(const SymbolMap &SymbolValues);
/// @brief Finalize the given symbols.
void finalize(const SymbolNameSet &SymbolsToFinalize);
/// @brief Notify the VSO that the given symbols failed to materialized.
void notifyMaterializationFailed(const SymbolNameSet &Names);
/// @brief Look up the flags for the given symbols.
///
/// Returns the flags for the give symbols, together with the set of symbols
@ -348,6 +369,16 @@ public:
SymbolNameSet Symbols);
private:
/// @brief Add the given symbol/address mappings to the dylib, but do not
/// mark the symbols as finalized yet.
void resolve(const SymbolMap &SymbolValues);
/// @brief Finalize the given symbols.
void finalize(const SymbolNameSet &SymbolsToFinalize);
/// @brief Notify the VSO that the given symbols failed to materialized.
void notifyMaterializationFailed(const SymbolNameSet &Names);
class UnmaterializedInfo {
public:
UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU);
@ -390,6 +421,11 @@ private:
void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
UnmaterializedInfoIterator NewUMII);
// Abandon old definition and move to materializing state.
// There is no need to call notifyMaterializing after this.
void replaceMaterializing(VSO &V, SymbolStringPtr Name,
JITSymbolFlags NewFlags);
// Notify this entry that it is being materialized.
void notifyMaterializing();

View File

@ -170,19 +170,6 @@ MaterializationResponsibility::~MaterializationResponsibility() {
"All symbols should have been explicitly materialized or failed");
}
MaterializationResponsibility
MaterializationResponsibility::takeResponsibility(SymbolNameSet Symbols) {
SymbolFlagsMap ExtractedFlags;
for (auto &S : Symbols) {
auto I = SymbolFlags.find(S);
ExtractedFlags.insert(*I);
SymbolFlags.erase(I);
}
return MaterializationResponsibility(V, std::move(ExtractedFlags));
}
void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
#ifndef NDEBUG
for (auto &KV : Symbols) {
@ -212,6 +199,19 @@ void MaterializationResponsibility::notifyMaterializationFailed() {
V.notifyMaterializationFailed(SymbolNames);
}
MaterializationResponsibility
MaterializationResponsibility::delegate(SymbolNameSet Symbols) {
SymbolFlagsMap ExtractedFlags;
for (auto &S : Symbols) {
auto I = SymbolFlags.find(S);
ExtractedFlags.insert(*I);
SymbolFlags.erase(I);
}
return MaterializationResponsibility(V, std::move(ExtractedFlags));
}
VSO::Materializer::Materializer(std::unique_ptr<MaterializationUnit> MU,
MaterializationResponsibility R)
: MU(std::move(MU)), R(std::move(R)) {}
@ -239,6 +239,14 @@ VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags,
this->Flags |= JITSymbolFlags::Lazy;
}
VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags)
: Flags(Flags), Address(0) {
// We *don't* expect isMaterializing to be set here. That's for the VSO to do.
assert(!Flags.isLazy() && "Initial flags include lazy?");
assert(!Flags.isMaterializing() && "Initial flags include materializing");
this->Flags |= JITSymbolFlags::Materializing;
}
VSO::SymbolTableEntry::SymbolTableEntry(JITEvaluatedSymbol Sym)
: Flags(Sym.getFlags()), Address(Sym.getAddress()) {
assert(!Flags.isLazy() && !Flags.isMaterializing() &&
@ -295,6 +303,23 @@ void VSO::SymbolTableEntry::replaceWith(VSO &V, SymbolStringPtr Name,
UMII = std::move(NewUMII);
}
void VSO::SymbolTableEntry::replaceMaterializing(VSO &V, SymbolStringPtr Name,
JITSymbolFlags NewFlags) {
assert(!NewFlags.isWeak() &&
"Can't define a lazy symbol in materializing mode");
assert(!NewFlags.isLazy() && !NewFlags.isMaterializing() &&
"Flags should not be in lazy or materializing state");
if (Flags.isLazy()) {
UMII->discard(V, Name);
if (UMII->Symbols.empty())
V.UnmaterializedInfos.erase(UMII);
}
destroy();
Flags = NewFlags;
Flags |= JITSymbolFlags::Materializing;
Address = 0;
}
void VSO::SymbolTableEntry::notifyMaterializing() {
assert(Flags.isLazy() && "Can only start materializing from lazy state");
UMII.~UnmaterializedInfoIterator();
@ -378,7 +403,6 @@ Error VSO::define(SymbolMap NewSymbols) {
}
Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
auto UMII = UnmaterializedInfos.insert(UnmaterializedInfos.end(),
UnmaterializedInfo(std::move(MU)));
@ -424,77 +448,6 @@ Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
return Err;
}
void VSO::resolve(const SymbolMap &SymbolValues) {
for (auto &KV : SymbolValues) {
auto I = Symbols.find(KV.first);
assert(I != Symbols.end() && "Resolving symbol not present in this dylib");
I->second.resolve(*this, KV.second);
auto J = MaterializingInfos.find(KV.first);
if (J == MaterializingInfos.end())
continue;
assert(J->second.PendingFinalization.empty() &&
"Queries already pending finalization?");
for (auto &Q : J->second.PendingResolution)
Q->resolve(KV.first, KV.second);
J->second.PendingFinalization = std::move(J->second.PendingResolution);
J->second.PendingResolution = MaterializingInfo::QueryList();
}
}
void VSO::notifyMaterializationFailed(const SymbolNameSet &Names) {
assert(!Names.empty() && "Failed to materialize empty set?");
std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
ResolutionFailures;
std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
FinalizationFailures;
for (auto &S : Names) {
auto I = Symbols.find(S);
assert(I != Symbols.end() && "Symbol not present in this VSO");
auto J = MaterializingInfos.find(S);
if (J != MaterializingInfos.end()) {
if (J->second.PendingFinalization.empty()) {
for (auto &Q : J->second.PendingResolution)
ResolutionFailures[Q].insert(S);
} else {
for (auto &Q : J->second.PendingFinalization)
FinalizationFailures[Q].insert(S);
}
MaterializingInfos.erase(J);
}
Symbols.erase(I);
}
for (auto &KV : ResolutionFailures)
KV.first->notifyMaterializationFailed(
make_error<FailedToResolve>(std::move(KV.second)));
for (auto &KV : FinalizationFailures)
KV.first->notifyMaterializationFailed(
make_error<FailedToFinalize>(std::move(KV.second)));
}
void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) {
for (auto &S : SymbolsToFinalize) {
auto I = Symbols.find(S);
assert(I != Symbols.end() && "Finalizing symbol not present in this dylib");
auto J = MaterializingInfos.find(S);
if (J != MaterializingInfos.end()) {
assert(J->second.PendingResolution.empty() &&
"Queries still pending resolution?");
for (auto &Q : J->second.PendingFinalization)
Q->finalizeSymbol();
MaterializingInfos.erase(J);
}
I->second.finalize();
}
}
SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags, SymbolNameSet Names) {
for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
@ -580,6 +533,77 @@ VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
return {std::move(Materializers), std::move(Names)};
}
void VSO::resolve(const SymbolMap &SymbolValues) {
for (auto &KV : SymbolValues) {
auto I = Symbols.find(KV.first);
assert(I != Symbols.end() && "Resolving symbol not present in this dylib");
I->second.resolve(*this, KV.second);
auto J = MaterializingInfos.find(KV.first);
if (J == MaterializingInfos.end())
continue;
assert(J->second.PendingFinalization.empty() &&
"Queries already pending finalization?");
for (auto &Q : J->second.PendingResolution)
Q->resolve(KV.first, KV.second);
J->second.PendingFinalization = std::move(J->second.PendingResolution);
J->second.PendingResolution = MaterializingInfo::QueryList();
}
}
void VSO::notifyMaterializationFailed(const SymbolNameSet &Names) {
assert(!Names.empty() && "Failed to materialize empty set?");
std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
ResolutionFailures;
std::map<std::shared_ptr<AsynchronousSymbolQuery>, SymbolNameSet>
FinalizationFailures;
for (auto &S : Names) {
auto I = Symbols.find(S);
assert(I != Symbols.end() && "Symbol not present in this VSO");
auto J = MaterializingInfos.find(S);
if (J != MaterializingInfos.end()) {
if (J->second.PendingFinalization.empty()) {
for (auto &Q : J->second.PendingResolution)
ResolutionFailures[Q].insert(S);
} else {
for (auto &Q : J->second.PendingFinalization)
FinalizationFailures[Q].insert(S);
}
MaterializingInfos.erase(J);
}
Symbols.erase(I);
}
for (auto &KV : ResolutionFailures)
KV.first->notifyMaterializationFailed(
make_error<FailedToResolve>(std::move(KV.second)));
for (auto &KV : FinalizationFailures)
KV.first->notifyMaterializationFailed(
make_error<FailedToFinalize>(std::move(KV.second)));
}
void VSO::finalize(const SymbolNameSet &SymbolsToFinalize) {
for (auto &S : SymbolsToFinalize) {
auto I = Symbols.find(S);
assert(I != Symbols.end() && "Finalizing symbol not present in this dylib");
auto J = MaterializingInfos.find(S);
if (J != MaterializingInfos.end()) {
assert(J->second.PendingResolution.empty() &&
"Queries still pending resolution?");
for (auto &Q : J->second.PendingFinalization)
Q->finalizeSymbol();
MaterializingInfos.erase(J);
}
I->second.finalize();
}
}
Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
MaterializationDispatcher DispatchMaterialization) {
#if LLVM_ENABLE_THREADS