/// into.
const VSO &getTargetVSO() const { return V; }
+ /// Returns the names of any symbols covered by this
+ /// MaterializationResponsibility object that have queries pending. This
+ /// information can be used to return responsibility for unrequested symbols
+ /// back to the VSO 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.
void replace(std::unique_ptr<MaterializationUnit> MU);
+ SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags);
+
void addDependencies(const SymbolFlagsMap &Dependents,
const SymbolDependenceMap &Dependencies);
"All symbols should have been explicitly materialized or failed");
}
+SymbolNameSet MaterializationResponsibility::getRequestedSymbols() {
+ return V.getRequestedSymbols(SymbolFlags);
+}
+
void MaterializationResponsibility::resolve(const SymbolMap &Symbols) {
for (auto &KV : Symbols) {
auto I = SymbolFlags.find(KV.first);
"Can not replace symbol that is not materializing");
assert(UnmaterializedInfos.count(KV.first) == 0 &&
"Symbol being replaced should have no UnmaterializedInfo");
- assert(MaterializingInfos.count(KV.first) &&
- "Symbol being replaced should have a MaterializingInfo");
}
#endif // NDEBUG
// If any symbol has pending queries against it then we need to
// materialize MU immediately.
- for (auto &KV : MU->getSymbols())
- if (!MaterializingInfos[KV.first].PendingQueries.empty())
- return std::move(MU);
+ for (auto &KV : MU->getSymbols()) {
+ auto MII = MaterializingInfos.find(KV.first);
+ if (MII != MaterializingInfos.end()) {
+ if (!MII->second.PendingQueries.empty())
+ return std::move(MU);
+ }
+ }
// Otherwise, make MU responsible for all the symbols.
auto UMI = std::make_shared<UnmaterializedInfo>(std::move(MU));
"Materializing flags should be managed internally.");
auto SymI = Symbols.find(KV.first);
- SymI->second.getFlags() = KV.second;
- SymI->second.getFlags() |= JITSymbolFlags::Lazy;
+ JITSymbolFlags ReplaceFlags = KV.second;
+ ReplaceFlags |= JITSymbolFlags::Lazy;
+ SymI->second = JITEvaluatedSymbol(SymI->second.getAddress(),
+ std::move(ReplaceFlags));
UnmaterializedInfos[KV.first] = UMI;
}
ES.dispatchMaterialization(*this, std::move(MustRunMU));
}
+SymbolNameSet VSO::getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) {
+ return ES.runSessionLocked([&]() {
+ SymbolNameSet RequestedSymbols;
+
+ for (auto &KV : SymbolFlags) {
+ assert(Symbols.count(KV.first) && "VSO does not cover this symbol?");
+ assert(Symbols[KV.first].getFlags().isMaterializing() &&
+ "getRequestedSymbols can only be called for materializing "
+ "symbols");
+ auto I = MaterializingInfos.find(KV.first);
+ if (I == MaterializingInfos.end())
+ continue;
+
+ if (!I->second.PendingQueries.empty())
+ RequestedSymbols.insert(KV.first);
+ }
+
+ return RequestedSymbols;
+ });
+}
+
void VSO::addDependencies(const SymbolFlagsMap &Dependants,
const SymbolDependenceMap &Dependencies) {
ES.runSessionLocked([&, this]() {
}
Expected<SymbolMap> lookup(const VSO::VSOList &VSOs, SymbolNameSet Names) {
+
#if LLVM_ENABLE_THREADS
// In the threaded case we use promises to return the results.
std::promise<SymbolMap> PromisedResult;
#endif
}
+TEST(CoreAPIsTest, TestGetRequestedSymbolsAndDelegate) {
+ ExecutionSession ES;
+ auto Foo = ES.getSymbolStringPool().intern("foo");
+ auto Bar = ES.getSymbolStringPool().intern("bar");
+
+ JITEvaluatedSymbol FooSym(0xdeadbeef, JITSymbolFlags::Exported);
+ JITEvaluatedSymbol BarSym(0xcafef00d, JITSymbolFlags::Exported);
+
+ SymbolNameSet Names({Foo, Bar});
+
+ bool FooMaterialized = false;
+ bool BarMaterialized = false;
+
+ auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+ SymbolFlagsMap({{Foo, FooSym.getFlags()}, {Bar, BarSym.getFlags()}}),
+ [&](MaterializationResponsibility R) {
+ auto Requested = R.getRequestedSymbols();
+ EXPECT_EQ(Requested.size(), 1U) << "Expected one symbol requested";
+ EXPECT_EQ(*Requested.begin(), Foo) << "Expected \"Foo\" requested";
+
+ auto NewMU = llvm::make_unique<SimpleMaterializationUnit>(
+ SymbolFlagsMap({{Bar, BarSym.getFlags()}}),
+ [&](MaterializationResponsibility R2) {
+ R2.resolve(SymbolMap({{Bar, BarSym}}));
+ R2.finalize();
+ BarMaterialized = true;
+ });
+
+ R.delegate(std::move(NewMU));
+
+ R.resolve(SymbolMap({{Foo, FooSym}}));
+ R.finalize();
+
+ FooMaterialized = true;
+ });
+
+ auto &V = ES.createVSO("V");
+
+ cantFail(V.define(MU));
+
+ EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet";
+ EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet";
+
+ auto FooSymResult = cantFail(lookup({&V}, Foo));
+ EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress())
+ << "Address mismatch for Foo";
+
+ EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now";
+ EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized";
+
+ auto BarSymResult = cantFail(lookup({&V}, Bar));
+ EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress())
+ << "Address mismatch for Bar";
+ EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now";
+}
+
} // namespace