Skip to content

Commit 069919c

Browse files
committed
[ORC] Update Symbol Lookup / DefinitionGenerator system.
This patch moves definition generation out from the session lock, instead running it under a per-dylib generator lock. It also makes the DefinitionGenerator::tryToGenerate method optionally asynchronous: Generators are handed an opaque LookupState object which can be captured to stop/restart the lookup process. The new scheme provides the following benefits and guarantees: (1) Queries that do not need to attempt definition generation (because all requested symbols matched against existing definitions in the JITDylib) can proceed without being blocked by any running definition generators. (2) Definition generators can capture the LookupState to continue their work asynchronously. This allows generators to run for an arbitrary amount of time without blocking a thread. Definition generators that do not need to run asynchronously can return without capturing the LookupState to eliminate unnecessary recursion and improve lookup performance. (3) Definition generators still do not need to worry about concurrency or re-entrance: Since they are still run under a (per-dylib) lock, generators will never be re-entered concurrently, or given overlapping symbol sets to generate. Finally, the new system distinguishes between symbols that are candidates for generation (generation candidates) and symbols that failed to match for a query (due to symbol visibility). This fixes a bug where an unresolved symbol could trigger generation of a duplicate definition for an existing hidden symbol.
1 parent 5d2e359 commit 069919c

File tree

9 files changed

+820
-337
lines changed

9 files changed

+820
-337
lines changed

llvm/include/llvm/ExecutionEngine/Orc/Core.h

Lines changed: 93 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class MaterializationUnit;
3636
class MaterializationResponsibility;
3737
class JITDylib;
3838
class ResourceTracker;
39+
class InProgressLookupState;
3940

4041
enum class SymbolState : uint8_t;
4142

@@ -215,9 +216,19 @@ class SymbolLookupSet {
215216

216217
/// Add an element to the set. The client is responsible for checking that
217218
/// duplicates are not added.
218-
void add(SymbolStringPtr Name,
219-
SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
219+
SymbolLookupSet &
220+
add(SymbolStringPtr Name,
221+
SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
220222
Symbols.push_back(std::make_pair(std::move(Name), Flags));
223+
return *this;
224+
}
225+
226+
/// Quickly append one lookup set to another.
227+
SymbolLookupSet &append(SymbolLookupSet Other) {
228+
Symbols.reserve(Symbols.size() + Other.size());
229+
for (auto &KV : Other)
230+
Symbols.push_back(std::move(KV));
231+
return *this;
221232
}
222233

223234
bool empty() const { return Symbols.empty(); }
@@ -783,6 +794,7 @@ enum class SymbolState : uint8_t {
783794
/// makes a callback when all symbols are available.
784795
class AsynchronousSymbolQuery {
785796
friend class ExecutionSession;
797+
friend class InProgressFullLookupState;
786798
friend class JITDylib;
787799
friend class JITSymbolResolverAdapter;
788800
friend class MaterializationResponsibility;
@@ -829,6 +841,22 @@ class AsynchronousSymbolQuery {
829841
SymbolState RequiredState;
830842
};
831843

844+
/// Wraps state for a lookup-in-progress.
845+
/// DefinitionGenerators can optionally take ownership of a LookupState object
846+
/// to suspend a lookup-in-progress while they search for definitions.
847+
class LookupState {
848+
friend class ExecutionSession;
849+
850+
public:
851+
/// Continue the lookup. This can be called by DefinitionGenerators
852+
/// to re-start a captured query-application operation.
853+
void continueLookup(Error Err);
854+
855+
private:
856+
LookupState(std::unique_ptr<InProgressLookupState> IPLS);
857+
std::unique_ptr<InProgressLookupState> IPLS;
858+
};
859+
832860
/// Definition generators can be attached to JITDylibs to generate new
833861
/// definitions for otherwise unresolved symbols during lookup.
834862
class DefinitionGenerator {
@@ -841,7 +869,7 @@ class DefinitionGenerator {
841869
/// JDLookupFlags specifies whether the search should match against
842870
/// hidden symbols. Finally, Symbols describes the set of unresolved
843871
/// symbols and their associated lookup flags.
844-
virtual Error tryToGenerate(LookupKind K, JITDylib &JD,
872+
virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
845873
JITDylibLookupFlags JDLookupFlags,
846874
const SymbolLookupSet &LookupSet) = 0;
847875
};
@@ -979,13 +1007,6 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib> {
9791007
/// left unmodified (no symbols are removed).
9801008
Error remove(const SymbolNameSet &Names);
9811009

982-
/// Search the given JITDylib for the symbols in Symbols. If found, store
983-
/// the flags for each symbol in Flags. If any required symbols are not found
984-
/// then an error will be returned.
985-
Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
986-
JITDylibLookupFlags JDLookupFlags,
987-
SymbolLookupSet LookupSet);
988-
9891010
/// Dump current JITDylib state to OS.
9901011
void dump(raw_ostream &OS);
9911012

@@ -1104,19 +1125,19 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib> {
11041125
void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
11051126
ResourceTracker &RT);
11061127

1107-
void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K,
1108-
JITDylibLookupFlags JDLookupFlags,
1109-
SymbolLookupSet &Unresolved);
1128+
// void lookupFlagsImpl(SymbolFlagsMap &Result, LookupKind K,
1129+
// JITDylibLookupFlags JDLookupFlags,
1130+
// SymbolLookupSet &Unresolved);
11101131

1111-
Error lodgeQuery(UnmaterializedInfosList &UMIs,
1112-
std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K,
1113-
JITDylibLookupFlags JDLookupFlags,
1114-
SymbolLookupSet &Unresolved);
1132+
// Error lodgeQuery(UnmaterializedInfosList &UMIs,
1133+
// std::shared_ptr<AsynchronousSymbolQuery> &Q, LookupKind K,
1134+
// JITDylibLookupFlags JDLookupFlags,
1135+
// SymbolLookupSet &Unresolved);
11151136

1116-
Error lodgeQueryImpl(UnmaterializedInfosList &UMIs,
1117-
std::shared_ptr<AsynchronousSymbolQuery> &Q,
1118-
LookupKind K, JITDylibLookupFlags JDLookupFlags,
1119-
SymbolLookupSet &Unresolved);
1137+
// Error lodgeQueryImpl(UnmaterializedInfosList &UMIs,
1138+
// std::shared_ptr<AsynchronousSymbolQuery> &Q,
1139+
// LookupKind K, JITDylibLookupFlags JDLookupFlags,
1140+
// SymbolLookupSet &Unresolved);
11201141

11211142
void detachQueryHelper(AsynchronousSymbolQuery &Q,
11221143
const SymbolNameSet &QuerySymbols);
@@ -1154,11 +1175,12 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib> {
11541175

11551176
ExecutionSession &ES;
11561177
std::string JITDylibName;
1178+
std::mutex GeneratorsMutex;
11571179
bool Open = true;
11581180
SymbolTable Symbols;
11591181
UnmaterializedInfosMap UnmaterializedInfos;
11601182
MaterializingInfosMap MaterializingInfos;
1161-
std::vector<std::unique_ptr<DefinitionGenerator>> DefGenerators;
1183+
std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
11621184
JITDylibSearchOrder LinkOrder;
11631185
ResourceTrackerSP DefaultTracker;
11641186

@@ -1199,7 +1221,10 @@ class Platform {
11991221

12001222
/// An ExecutionSession represents a running JIT program.
12011223
class ExecutionSession {
1224+
friend class InProgressLookupFlagsState;
1225+
friend class InProgressFullLookupState;
12021226
friend class JITDylib;
1227+
friend class LookupState;
12031228
friend class MaterializationResponsibility;
12041229
friend class ResourceTracker;
12051230

@@ -1290,7 +1315,18 @@ class ExecutionSession {
12901315
return *this;
12911316
}
12921317

1293-
/// Search the given JITDylib list for the given symbols.
1318+
/// Search the given JITDylibs to find the flags associated with each of the
1319+
/// given symbols.
1320+
void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1321+
SymbolLookupSet Symbols,
1322+
unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1323+
1324+
/// Blocking version of lookupFlags.
1325+
Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
1326+
JITDylibSearchOrder SearchOrder,
1327+
SymbolLookupSet Symbols);
1328+
1329+
/// Search the given JITDylibs for the given symbols.
12941330
///
12951331
/// SearchOrder lists the JITDylibs to search. For each dylib, the associated
12961332
/// boolean indicates whether the search should match against non-exported
@@ -1372,7 +1408,7 @@ class ExecutionSession {
13721408
MU->materialize(std::move(MR));
13731409
}
13741410

1375-
void runOutstandingMUs();
1411+
void dispatchOutstandingMUs();
13761412

13771413
static std::unique_ptr<MaterializationResponsibility>
13781414
createMaterializationResponsibility(ResourceTracker &RT,
@@ -1390,8 +1426,36 @@ class ExecutionSession {
13901426
void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
13911427
void destroyResourceTracker(ResourceTracker &RT);
13921428

1393-
1394-
/// State machine functions for MaterializationResponsibility.
1429+
// State machine functions for query application..
1430+
1431+
/// IL_updateCandidatesFor is called to remove already-defined symbols that
1432+
/// match a given query from the set of candidate symbols to generate
1433+
/// definitions for (no need to generate a definition if one already exists).
1434+
Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
1435+
SymbolLookupSet &Candidates,
1436+
SymbolLookupSet *NonCandidates);
1437+
1438+
/// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
1439+
/// definition generation. It is called when a lookup is performed, and again
1440+
/// each time that LookupState::continueLookup is called.
1441+
void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
1442+
Error Err);
1443+
1444+
/// OL_completeLookup is run once phase 1 successfully completes for a lookup
1445+
/// call. It attempts to attach the symbol to all symbol table entries and
1446+
/// collect all MaterializationUnits to dispatch. If this method fails then
1447+
/// all MaterializationUnits will be left un-materialized.
1448+
void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
1449+
std::shared_ptr<AsynchronousSymbolQuery> Q,
1450+
RegisterDependenciesFunction RegisterDependencies);
1451+
1452+
/// OL_completeLookupFlags is run once phase 1 successfully completes for a
1453+
/// lookupFlags call.
1454+
void OL_completeLookupFlags(
1455+
std::unique_ptr<InProgressLookupState> IPLS,
1456+
unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1457+
1458+
// State machine functions for MaterializationResponsibility.
13951459
void OL_destroyMaterializationResponsibility(
13961460
MaterializationResponsibility &MR);
13971461
SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
@@ -1454,8 +1518,8 @@ Error MaterializationResponsibility::withResourceKeyDo(Func &&F) const {
14541518
template <typename GeneratorT>
14551519
GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
14561520
auto &G = *DefGenerator;
1457-
ES.runSessionLocked(
1458-
[&]() { DefGenerators.push_back(std::move(DefGenerator)); });
1521+
std::lock_guard<std::mutex> Lock(GeneratorsMutex);
1522+
DefGenerators.push_back(std::move(DefGenerator));
14591523
return G;
14601524
}
14611525

@@ -1546,7 +1610,7 @@ class ReexportsGenerator : public DefinitionGenerator {
15461610
JITDylibLookupFlags SourceJDLookupFlags,
15471611
SymbolPredicate Allow = SymbolPredicate());
15481612

1549-
Error tryToGenerate(LookupKind K, JITDylib &JD,
1613+
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
15501614
JITDylibLookupFlags JDLookupFlags,
15511615
const SymbolLookupSet &LookupSet) override;
15521616

llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class DynamicLibrarySearchGenerator : public DefinitionGenerator {
254254
return Load(nullptr, GlobalPrefix, std::move(Allow));
255255
}
256256

257-
Error tryToGenerate(LookupKind K, JITDylib &JD,
257+
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
258258
JITDylibLookupFlags JDLookupFlags,
259259
const SymbolLookupSet &Symbols) override;
260260

@@ -292,7 +292,7 @@ class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
292292
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
293293
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
294294

295-
Error tryToGenerate(LookupKind K, JITDylib &JD,
295+
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
296296
JITDylibLookupFlags JDLookupFlags,
297297
const SymbolLookupSet &Symbols) override;
298298

llvm/include/llvm/ExecutionEngine/Orc/TPCDynamicLibrarySearchGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class TPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
5050
return Load(TPC, nullptr);
5151
}
5252

53-
Error tryToGenerate(LookupKind K, JITDylib &JD,
53+
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
5454
JITDylibLookupFlags JDLookupFlags,
5555
const SymbolLookupSet &Symbols) override;
5656

0 commit comments

Comments
 (0)