1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

[ORC] Only notify queries that they are resolved/ready when the query state

changes.

This guards against redundant notifications.

llvm-svn: 334916
This commit is contained in:
Lang Hames 2018-06-17 18:59:01 +00:00
parent d9f71cdd4e
commit 287c3db240
3 changed files with 96 additions and 11 deletions

View File

@ -14,6 +14,7 @@
#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
#define LLVM_EXECUTIONENGINE_ORC_CORE_H
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/IR/Module.h"
@ -570,6 +571,13 @@ private:
using MaterializingInfosMap = std::map<SymbolStringPtr, MaterializingInfo>;
using LookupImplActionFlags = enum {
None = 0,
NotifyFullyResolved = 1 << 0U,
NotifyFullyReady = 1 << 1U,
LLVM_MARK_AS_BITMASK_ENUM(NotifyFullyReady)
};
VSO(ExecutionSessionBase &ES, std::string Name)
: ES(ES), VSOName(std::move(Name)) {}
@ -585,9 +593,10 @@ private:
SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
const SymbolNameSet &Names);
void lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolNameSet &Unresolved);
LookupImplActionFlags
lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolNameSet &Unresolved);
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);

View File

@ -147,6 +147,12 @@ 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,
@ -695,27 +701,33 @@ SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
SymbolNameSet Names) {
assert(Q && "Query can not be null");
LookupImplActionFlags ActionFlags = None;
std::vector<std::unique_ptr<MaterializationUnit>> MUs;
SymbolNameSet Unresolved = std::move(Names);
ES.runSessionLocked([&, this]() {
lookupImpl(Q, MUs, Unresolved);
ActionFlags = lookupImpl(Q, MUs, Unresolved);
if (FallbackDefinitionGenerator && !Unresolved.empty()) {
assert(ActionFlags == None &&
"ActionFlags set but unresolved symbols remain?");
auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
if (!FallbackDefs.empty()) {
for (auto &D : FallbackDefs)
Unresolved.erase(D);
lookupImpl(Q, MUs, FallbackDefs);
ActionFlags = lookupImpl(Q, MUs, FallbackDefs);
assert(FallbackDefs.empty() &&
"All fallback defs should have been found by lookupImpl");
}
}
});
if (Q->isFullyResolved())
assert((MUs.empty() || ActionFlags == None) &&
"If action flags are set, there should be no work to do (so no MUs)");
if (ActionFlags & NotifyFullyResolved)
Q->handleFullyResolved();
if (Q->isFullyReady())
if (ActionFlags & NotifyFullyReady)
Q->handleFullyReady();
// Dispatch any required MaterializationUnits for materialization.
@ -725,9 +737,12 @@ SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
return Unresolved;
}
void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolNameSet &Unresolved) {
VSO::LookupImplActionFlags
VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolNameSet &Unresolved) {
LookupImplActionFlags ActionFlags = None;
for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
auto TmpI = I++;
auto Name = *TmpI;
@ -742,8 +757,11 @@ void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
Unresolved.erase(TmpI);
// If the symbol has an address then resolve it.
if (SymI->second.getAddress() != 0)
if (SymI->second.getAddress() != 0) {
Q->resolve(Name, SymI->second);
if (Q->isFullyResolved())
ActionFlags |= NotifyFullyResolved;
}
// If the symbol is lazy, get the MaterialiaztionUnit for it.
if (SymI->second.getFlags().isLazy()) {
@ -775,6 +793,8 @@ void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
// The symbol is neither lazy nor materializing. Finalize it and
// continue.
Q->notifySymbolReady();
if (Q->isFullyReady())
ActionFlags |= NotifyFullyReady;
continue;
}
@ -785,6 +805,8 @@ void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
MI.PendingQueries.push_back(Q);
Q->addQueryDependence(*this, Name);
}
return ActionFlags;
}
void VSO::dump(raw_ostream &OS) {

View File

@ -163,6 +163,60 @@ TEST(CoreAPIsTest, SimpleAsynchronousSymbolQueryAgainstVSO) {
EXPECT_TRUE(OnReadyRun) << "OnReady was not run";
}
TEST(CoreAPIsTest, EmptyVSOAndQueryLookup) {
ExecutionSession ES;
auto &V = ES.createVSO("V");
bool OnResolvedRun = false;
bool OnReadyRun = false;
auto Q = std::make_shared<AsynchronousSymbolQuery>(
SymbolNameSet(),
[&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
cantFail(std::move(RR));
OnResolvedRun = true;
},
[&](Error Err) {
cantFail(std::move(Err));
OnReadyRun = true;
});
V.lookup(std::move(Q), {});
EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
}
TEST(CoreAPIsTest, ChainedVSOLookup) {
ExecutionSession ES;
auto Foo = ES.getSymbolStringPool().intern("foo");
auto FooSym = JITEvaluatedSymbol(1U, JITSymbolFlags::Exported);
auto &V1 = ES.createVSO("V1");
cantFail(V1.define(absoluteSymbols({{Foo, FooSym}})));
auto &V2 = ES.createVSO("V2");
bool OnResolvedRun = false;
bool OnReadyRun = false;
auto Q = std::make_shared<AsynchronousSymbolQuery>(
SymbolNameSet({Foo}),
[&](Expected<AsynchronousSymbolQuery::ResolutionResult> RR) {
cantFail(std::move(RR));
OnResolvedRun = true;
},
[&](Error Err) {
cantFail(std::move(Err));
OnReadyRun = true;
});
V2.lookup(Q, V1.lookup(Q, {Foo}));
EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
}
TEST(CoreAPIsTest, LookupFlagsTest) {
// Test that lookupFlags works on a predefined symbol, and does not trigger