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:
parent
2764b3b533
commit
52289d96c4
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user