///
/// 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
+/// emit symbols, or abandon materialization by notifying any unmaterialized
/// symbols of an error.
class MaterializationResponsibility {
friend class MaterializationUnit;
/// Destruct a MaterializationResponsibility instance. In debug mode
/// this asserts that all symbols being tracked have been either
- /// finalized or notified of an error.
+ /// emitted or notified of an error.
~MaterializationResponsibility();
/// Returns the target JITDylib that these symbols are being materialized
/// back to the JITDylib via the delegate method.
SymbolNameSet getRequestedSymbols();
- /// 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.
+ /// Notifies the target JITDylib that the given symbols have been resolved.
+ /// This will update the given symbols' addresses in the JITDylib, and notify
+ /// any pending queries on the given symbols of their resolution. The given
+ /// symbols must be ones covered by this MaterializationResponsibility
+ /// instance. Individual calls to this method may resolve a subset of the
+ /// symbols, but all symbols must have been resolved prior to calling emit.
void resolve(const SymbolMap &Symbols);
- /// Finalizes all symbols tracked by this instance.
- void finalize();
+ /// Notifies the target JITDylib (and any pending queries on that JITDylib)
+ /// that all symbols covered by this MaterializationResponsibility instance
+ /// have been emitted.
+ void emit();
/// Adds new symbols to the JITDylib and this responsibility instance.
/// JITDylib entries start out in the materializing state.
/// callbacks, metadata).
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
- /// Notify all unfinalized symbols that an error has occurred.
+ /// Notify all not-yet-emitted covered by this MaterializationResponsibility
+ /// instance that an error has occurred.
/// This will remove all symbols covered by this MaterializationResponsibilty
- /// from V, and send an error to any queries waiting on these symbols.
+ /// from the target JITDylib, and send an error to any queries waiting on
+ /// these symbols.
void failMaterialization();
/// Transfers responsibility to the given MaterializationUnit for all
struct MaterializingInfo {
AsynchronousSymbolQueryList PendingQueries;
SymbolDependenceMap Dependants;
- SymbolDependenceMap UnfinalizedDependencies;
- bool IsFinalized = false;
+ SymbolDependenceMap UnemittedDependencies;
+ bool IsEmitted = false;
};
using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
- void transferFinalizedNodeDependencies(MaterializingInfo &DependantMI,
- const SymbolStringPtr &DependantName,
- MaterializingInfo &FinalizedMI);
+ void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
+ const SymbolStringPtr &DependantName,
+ MaterializingInfo &EmittedMI);
Error defineMaterializing(const SymbolFlagsMap &SymbolFlags);
void resolve(const SymbolMap &Resolved);
- void finalize(const SymbolFlagsMap &Finalized);
+ void emit(const SymbolFlagsMap &Emitted);
void notifyFailed(const SymbolNameSet &FailedSymbols);
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
- using NotifyFinalizedFunction = std::function<void(VModuleKey)>;
+ using NotifyEmittedFunction = std::function<void(VModuleKey)>;
using GetMemoryManagerFunction =
std::function<std::shared_ptr<RuntimeDyld::MemoryManager>(VModuleKey)>;
/// Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// and NotifyFinalized functors.
+ /// and NotifyEmitted functors.
RTDyldObjectLinkingLayer2(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
- NotifyFinalizedFunction NotifyFinalized = NotifyFinalizedFunction());
+ NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction());
/// Emit the object.
void emit(MaterializationResponsibility R, VModuleKey K,
mutable std::mutex RTDyldLayerMutex;
GetMemoryManagerFunction GetMemoryManager;
NotifyLoadedFunction NotifyLoaded;
- NotifyFinalizedFunction NotifyFinalized;
+ NotifyEmittedFunction NotifyEmitted;
bool ProcessAllSections;
std::map<VModuleKey, RuntimeDyld *> ActiveRTDylds;
std::map<VModuleKey, std::shared_ptr<RuntimeDyld::MemoryManager>> MemMgrs;
}
void AsynchronousSymbolQuery::notifySymbolReady() {
- assert(NotYetReadyCount != 0 && "All symbols already finalized");
+ assert(NotYetReadyCount != 0 && "All symbols already emitted");
--NotYetReadyCount;
}
JD.resolve(Symbols);
}
-void MaterializationResponsibility::finalize() {
+void MaterializationResponsibility::emit() {
#ifndef NDEBUG
for (auto &KV : SymbolFlags)
assert(!KV.second.isMaterializing() &&
- "Failed to resolve symbol before finalization");
+ "Failed to resolve symbol before emission");
#endif // NDEBUG
- JD.finalize(SymbolFlags);
+ JD.emit(SymbolFlags);
SymbolFlags.clear();
}
void AbsoluteSymbolsMaterializationUnit::materialize(
MaterializationResponsibility R) {
R.resolve(Symbols);
- R.finalize();
+ R.emit();
}
void AbsoluteSymbolsMaterializationUnit::discard(const JITDylib &JD,
(*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
}
QueryInfo->R.resolve(ResolutionMap);
- QueryInfo->R.finalize();
+ QueryInfo->R.emit();
} else {
auto &ES = QueryInfo->R.getTargetJITDylib().getExecutionSession();
ES.reportError(Result.takeError());
"Symbol is not lazy or materializing");
auto &MI = MaterializingInfos[Name];
- assert(!MI.IsFinalized && "Can not add dependencies to finalized symbol");
+ assert(!MI.IsEmitted && "Can not add dependencies to an emitted symbol");
for (auto &KV : Dependencies) {
assert(KV.first && "Null JITDylib in dependency?");
auto &OtherJITDylib = *KV.first;
- auto &DepsOnOtherJITDylib = MI.UnfinalizedDependencies[&OtherJITDylib];
+ auto &DepsOnOtherJITDylib = MI.UnemittedDependencies[&OtherJITDylib];
for (auto &OtherSymbol : KV.second) {
#ifndef NDEBUG
- // Assert that this symbol exists and has not been finalized already.
+ // Assert that this symbol exists and has not been emitted already.
auto SymI = OtherJITDylib.Symbols.find(OtherSymbol);
assert(SymI != OtherJITDylib.Symbols.end() &&
(SymI->second.getFlags().isLazy() ||
SymI->second.getFlags().isMaterializing()) &&
- "Dependency on finalized symbol");
+ "Dependency on emitted symbol");
#endif
auto &OtherMI = OtherJITDylib.MaterializingInfos[OtherSymbol];
- if (OtherMI.IsFinalized)
- transferFinalizedNodeDependencies(MI, Name, OtherMI);
+ if (OtherMI.IsEmitted)
+ transferEmittedNodeDependencies(MI, Name, OtherMI);
else if (&OtherJITDylib != this || OtherSymbol != Name) {
OtherMI.Dependants[this].insert(Name);
DepsOnOtherJITDylib.insert(OtherSymbol);
}
if (DepsOnOtherJITDylib.empty())
- MI.UnfinalizedDependencies.erase(&OtherJITDylib);
+ MI.UnemittedDependencies.erase(&OtherJITDylib);
}
}
}
}
-void JITDylib::finalize(const SymbolFlagsMap &Finalized) {
+void JITDylib::emit(const SymbolFlagsMap &Emitted) {
auto FullyReadyQueries = ES.runSessionLocked([&, this]() {
AsynchronousSymbolQuerySet ReadyQueries;
- for (const auto &KV : Finalized) {
+ for (const auto &KV : Emitted) {
const auto &Name = KV.first;
auto MII = MaterializingInfos.find(Name);
auto &MI = MII->second;
- // For each dependant, transfer this node's unfinalized dependencies to
- // it. If the dependant node is fully finalized then notify any pending
- // queries.
+ // For each dependant, transfer this node's emitted dependencies to
+ // it. If the dependant node is ready (i.e. has no unemitted
+ // dependencies) then notify any pending queries.
for (auto &KV : MI.Dependants) {
auto &DependantJD = *KV.first;
for (auto &DependantName : KV.second) {
auto &DependantMI = DependantMII->second;
// Remove the dependant's dependency on this node.
- assert(DependantMI.UnfinalizedDependencies[this].count(Name) &&
+ assert(DependantMI.UnemittedDependencies[this].count(Name) &&
"Dependant does not count this symbol as a dependency?");
- DependantMI.UnfinalizedDependencies[this].erase(Name);
- if (DependantMI.UnfinalizedDependencies[this].empty())
- DependantMI.UnfinalizedDependencies.erase(this);
-
- // Transfer unfinalized dependencies from this node to the dependant.
- DependantJD.transferFinalizedNodeDependencies(DependantMI,
- DependantName, MI);
-
- // If the dependant is finalized and this node was the last of its
- // unfinalized dependencies then notify any pending queries on the
- // dependant node.
- if (DependantMI.IsFinalized &&
- DependantMI.UnfinalizedDependencies.empty()) {
+ DependantMI.UnemittedDependencies[this].erase(Name);
+ if (DependantMI.UnemittedDependencies[this].empty())
+ DependantMI.UnemittedDependencies.erase(this);
+
+ // Transfer unemitted dependencies from this node to the dependant.
+ DependantJD.transferEmittedNodeDependencies(DependantMI,
+ DependantName, MI);
+
+ // If the dependant is emitted and this node was the last of its
+ // unemitted dependencies then the dependant node is now ready, so
+ // notify any pending queries on the dependant node.
+ if (DependantMI.IsEmitted &&
+ DependantMI.UnemittedDependencies.empty()) {
assert(DependantMI.Dependants.empty() &&
"Dependants should be empty by now");
for (auto &Q : DependantMI.PendingQueries) {
Q->removeQueryDependence(DependantJD, DependantName);
}
- // If this dependant node was fully finalized we can erase its
- // MaterializingInfo and update its materializing state.
+ // Since this dependant is now ready, we erase its MaterializingInfo
+ // and update its materializing state.
assert(DependantJD.Symbols.count(DependantName) &&
"Dependant has no entry in the Symbols table");
auto &DependantSym = DependantJD.Symbols[DependantName];
}
}
MI.Dependants.clear();
- MI.IsFinalized = true;
+ MI.IsEmitted = true;
- if (MI.UnfinalizedDependencies.empty()) {
+ if (MI.UnemittedDependencies.empty()) {
for (auto &Q : MI.PendingQueries) {
Q->notifySymbolReady();
if (Q->isFullyReady())
// 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.
+ // The symbol is neither lazy nor materializing, so it must be
+ // ready. Notify the query and continue.
Q->notifySymbolReady();
continue;
}
// 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.
+ // The symbol is neither lazy nor materializing, so it must be ready.
+ // Notify the query and continue.
Q->notifySymbolReady();
if (Q->isFullyReady())
ActionFlags |= NotifyFullyReady;
OS << " MaterializingInfos entries:\n";
for (auto &KV : MaterializingInfos) {
OS << " \"" << *KV.first << "\":\n"
- << " IsFinalized = " << (KV.second.IsFinalized ? "true" : "false")
+ << " IsEmitted = " << (KV.second.IsEmitted ? "true" : "false")
<< "\n"
<< " " << KV.second.PendingQueries.size()
<< " pending queries: { ";
OS << "}\n Dependants:\n";
for (auto &KV2 : KV.second.Dependants)
OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
- OS << " Unfinalized Dependencies:\n";
- for (auto &KV2 : KV.second.UnfinalizedDependencies)
+ OS << " Unemitted Dependencies:\n";
+ for (auto &KV2 : KV.second.UnemittedDependencies)
OS << " " << KV2.first->getName() << ": " << KV2.second << "\n";
}
});
}
}
-void JITDylib::transferFinalizedNodeDependencies(
+void JITDylib::transferEmittedNodeDependencies(
MaterializingInfo &DependantMI, const SymbolStringPtr &DependantName,
- MaterializingInfo &FinalizedMI) {
- for (auto &KV : FinalizedMI.UnfinalizedDependencies) {
+ MaterializingInfo &EmittedMI) {
+ for (auto &KV : EmittedMI.UnemittedDependencies) {
auto &DependencyJD = *KV.first;
- SymbolNameSet *UnfinalizedDependenciesOnDependencyJD = nullptr;
+ SymbolNameSet *UnemittedDependenciesOnDependencyJD = nullptr;
for (auto &DependencyName : KV.second) {
auto &DependencyMI = DependencyJD.MaterializingInfos[DependencyName];
// If we haven't looked up the dependencies for DependencyJD yet, do it
// now and cache the result.
- if (!UnfinalizedDependenciesOnDependencyJD)
- UnfinalizedDependenciesOnDependencyJD =
- &DependantMI.UnfinalizedDependencies[&DependencyJD];
+ if (!UnemittedDependenciesOnDependencyJD)
+ UnemittedDependenciesOnDependencyJD =
+ &DependantMI.UnemittedDependencies[&DependencyJD];
DependencyMI.Dependants[this].insert(DependantName);
- UnfinalizedDependenciesOnDependencyJD->insert(DependencyName);
+ UnemittedDependenciesOnDependencyJD->insert(DependencyName);
}
}
}
SymbolMap Result;
Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
R.resolve(Result);
- R.finalize();
+ R.emit();
}
void discard(const JITDylib &JD, SymbolStringPtr Name) {
RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2(
ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
- NotifyLoadedFunction NotifyLoaded, NotifyFinalizedFunction NotifyFinalized)
+ NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted)
: ObjectLayer(ES), GetMemoryManager(GetMemoryManager),
NotifyLoaded(std::move(NotifyLoaded)),
- NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {}
+ NotifyEmitted(std::move(NotifyEmitted)), ProcessAllSections(false) {}
void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R,
VModuleKey K,
return;
}
- R.finalize();
+ R.emit();
- if (NotifyFinalized)
- NotifyFinalized(K);
+ if (NotifyEmitted)
+ NotifyEmitted(K);
}
void RTDyldObjectLinkingLayer2::mapSectionAddress(
EXPECT_TRUE(OnResolutionRun) << "Should have been resolved";
EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
- FooMR->finalize();
+ FooMR->emit();
EXPECT_TRUE(OnReadyRun) << "Should have been marked ready";
}
[&](MaterializationResponsibility R) {
BarMaterialized = true;
R.resolve({{Bar, BarSym}});
- R.finalize();
+ R.emit();
});
cantFail(JD.define(BarMU));
NoDependenciesToRegister);
FooR->resolve({{Foo, FooSym}});
- FooR->finalize();
+ FooR->emit();
EXPECT_TRUE(FooReady)
<< "Self-dependency prevented symbol from being marked ready";
TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
// Test that a circular symbol dependency between three symbols in a JITDylib
// does not prevent any symbol from becoming 'ready' once all symbols are
- // finalized.
+ // emitted.
// Create three MaterializationResponsibility objects: one for each of Foo,
// Bar and Baz. These are optional because MaterializationResponsibility
EXPECT_FALSE(BarResolved) << "\"Bar\" should not be resolved yet";
EXPECT_FALSE(BazResolved) << "\"Baz\" should not be resolved yet";
- // Resolve the symbols (but do not finalized them).
+ // Resolve the symbols (but do not emit them).
FooR->resolve({{Foo, FooSym}});
BarR->resolve({{Bar, BarSym}});
BazR->resolve({{Baz, BazSym}});
EXPECT_FALSE(BarReady) << "\"Bar\" should not be ready yet";
EXPECT_FALSE(BazReady) << "\"Baz\" should not be ready yet";
- // Finalize two of the symbols.
- FooR->finalize();
- BarR->finalize();
+ // Emit two of the symbols.
+ FooR->emit();
+ BarR->emit();
// Verify that nothing is ready until the circular dependence is resolved.
EXPECT_FALSE(FooReady) << "\"Foo\" still should not be ready";
EXPECT_FALSE(BarReady) << "\"Bar\" still should not be ready";
EXPECT_FALSE(BazReady) << "\"Baz\" still should not be ready";
- // Finalize the last symbol.
- BazR->finalize();
+ // Emit the last symbol.
+ BazR->emit();
// Verify that everything becomes ready once the circular dependence resolved.
EXPECT_TRUE(FooReady) << "\"Foo\" should be ready now";
[&](MaterializationResponsibility R) {
assert(BarDiscarded && "Bar should have been discarded by this point");
R.resolve(SymbolMap({{Foo, FooSym}}));
- R.finalize();
+ R.emit();
FooMaterialized = true;
},
[&](const JITDylib &JD, SymbolStringPtr Name) {
cantFail(
R.defineMaterializing(SymbolFlagsMap({{Bar, BarSym.getFlags()}})));
R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
- R.finalize();
+ R.emit();
});
cantFail(JD.define(MU));
SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}}),
[&](MaterializationResponsibility R) {
R.resolve({{Foo, FooSym}});
- R.finalize();
+ R.emit();
});
cantFail(JD.define(MU));
SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
[&](MaterializationResponsibility R2) {
R2.resolve(SymbolMap({{Bar, BarSym}}));
- R2.finalize();
+ R2.emit();
BarMaterialized = true;
});
R.replace(std::move(NewMU));
R.resolve(SymbolMap({{Foo, FooSym}}));
- R.finalize();
+ R.emit();
FooMaterialized = true;
});
auto R2 = R.delegate({Bar});
R.resolve({{Foo, FooSym}});
- R.finalize();
+ R.emit();
R2.resolve({{Bar, BarSym}});
- R2.finalize();
+ R2.emit();
});
cantFail(JD.define(MU));
consumeError(std::move(Err));
FooResponsibility->resolve(SymbolMap({{Foo, FooSym}}));
- FooResponsibility->finalize();
+ FooResponsibility->emit();
}
} // namespace