Skip to content

Commit 3b9eb34

Browse files
committed
[ORC] Replace ORC's baked-in dependence tracking with WaitingOnGraph.
WaitingOnGraph tracks waiting-on relationships between nodes (intended to represent symbols in an ORC program) in order to identify nodes that are *Ready* (i.e. are not waiting on any other nodes) or have *Failed* (are waiting on some node that cannot be produced). WaitingOnGraph replaces ORC's baked-in data structures that were tracking the same information (EmissionDepUnit, EmissionDepUnitInfo, ...). Isolating this information in a separate data structure simplifies the code, allows us to unit test it, and simplifies performance testing. The WaitingOnGraph uses several techniques to improve performance relative to the old data structures, including symbol coalescing ("SuperNodes") and symbol keys that don't perform unnecessary reference counting (NonOwningSymbolStringPtr). This commit includes unit tests for common dependence-tracking issues that have led to ORC bugs in the past.
1 parent 885d416 commit 3b9eb34

File tree

9 files changed

+1417
-739
lines changed

9 files changed

+1417
-739
lines changed

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

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
2727
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
2828
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
29+
#include "llvm/ExecutionEngine/Orc/WaitingOnGraph.h"
2930
#include "llvm/Support/Compiler.h"
3031
#include "llvm/Support/Debug.h"
3132
#include "llvm/Support/ExtensibleRTTI.h"
@@ -49,6 +50,9 @@ class InProgressLookupState;
4950

5051
enum class SymbolState : uint8_t;
5152

53+
using WaitingOnGraph =
54+
detail::WaitingOnGraph<JITDylib *, NonOwningSymbolStringPtr>;
55+
5256
using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
5357
using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
5458

@@ -1131,20 +1135,6 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
11311135
using UnmaterializedInfosList =
11321136
std::vector<std::shared_ptr<UnmaterializedInfo>>;
11331137

1134-
struct EmissionDepUnit {
1135-
EmissionDepUnit(JITDylib &JD) : JD(&JD) {}
1136-
1137-
JITDylib *JD = nullptr;
1138-
DenseMap<NonOwningSymbolStringPtr, JITSymbolFlags> Symbols;
1139-
DenseMap<JITDylib *, DenseSet<NonOwningSymbolStringPtr>> Dependencies;
1140-
};
1141-
1142-
struct EmissionDepUnitInfo {
1143-
std::shared_ptr<EmissionDepUnit> EDU;
1144-
DenseSet<EmissionDepUnit *> IntraEmitUsers;
1145-
DenseMap<JITDylib *, DenseSet<NonOwningSymbolStringPtr>> NewDeps;
1146-
};
1147-
11481138
// Information about not-yet-ready symbol.
11491139
// * DefiningEDU will point to the EmissionDepUnit that defines the symbol.
11501140
// * DependantEDUs will hold pointers to any EmissionDepUnits currently
@@ -1154,9 +1144,6 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
11541144
struct MaterializingInfo {
11551145
friend class ExecutionSession;
11561146

1157-
std::shared_ptr<EmissionDepUnit> DefiningEDU;
1158-
DenseSet<EmissionDepUnit *> DependantEDUs;
1159-
11601147
LLVM_ABI void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
11611148
LLVM_ABI void removeQuery(const AsynchronousSymbolQuery &Q);
11621149
LLVM_ABI AsynchronousSymbolQueryList
@@ -1778,30 +1765,26 @@ class ExecutionSession {
17781765
LLVM_ABI Error OL_notifyResolved(MaterializationResponsibility &MR,
17791766
const SymbolMap &Symbols);
17801767

1781-
using EDUInfosMap =
1782-
DenseMap<JITDylib::EmissionDepUnit *, JITDylib::EmissionDepUnitInfo>;
1783-
1784-
template <typename HandleNewDepFn>
1785-
void propagateExtraEmitDeps(std::deque<JITDylib::EmissionDepUnit *> Worklist,
1786-
EDUInfosMap &EDUInfos,
1787-
HandleNewDepFn HandleNewDep);
1788-
EDUInfosMap simplifyDepGroups(MaterializationResponsibility &MR,
1789-
ArrayRef<SymbolDependenceGroup> EmittedDeps);
1790-
void IL_makeEDUReady(std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
1791-
JITDylib::AsynchronousSymbolQuerySet &Queries);
1792-
void IL_makeEDUEmitted(std::shared_ptr<JITDylib::EmissionDepUnit> EDU,
1793-
JITDylib::AsynchronousSymbolQuerySet &Queries);
1794-
bool IL_removeEDUDependence(JITDylib::EmissionDepUnit &EDU, JITDylib &DepJD,
1795-
NonOwningSymbolStringPtr DepSym,
1796-
EDUInfosMap &EDUInfos);
1797-
1798-
static Error makeJDClosedError(JITDylib::EmissionDepUnit &EDU,
1799-
JITDylib &ClosedJD);
1800-
static Error makeUnsatisfiedDepsError(JITDylib::EmissionDepUnit &EDU,
1801-
JITDylib &BadJD, SymbolNameSet BadDeps);
1802-
1803-
Expected<JITDylib::AsynchronousSymbolQuerySet>
1804-
IL_emit(MaterializationResponsibility &MR, EDUInfosMap EDUInfos);
1768+
// FIXME: We should be able to derive FailedSymsForQuery from each query once
1769+
// we fix how the detach operation works.
1770+
struct EmitQueries {
1771+
JITDylib::AsynchronousSymbolQuerySet Updated;
1772+
JITDylib::AsynchronousSymbolQuerySet Failed;
1773+
DenseMap<AsynchronousSymbolQuery *, std::shared_ptr<SymbolDependenceMap>>
1774+
FailedSymsForQuery;
1775+
};
1776+
1777+
WaitingOnGraph::ExternalState
1778+
IL_getSymbolState(JITDylib *JD, NonOwningSymbolStringPtr Name);
1779+
1780+
template <typename UpdateSymbolFn, typename UpdateQueryFn>
1781+
void IL_collectQueries(JITDylib::AsynchronousSymbolQuerySet &Qs,
1782+
WaitingOnGraph::ContainerElementsMap &QualifiedSymbols,
1783+
UpdateSymbolFn &&UpdateSymbol,
1784+
UpdateQueryFn &&UpdateQuery);
1785+
1786+
Expected<EmitQueries> IL_emit(MaterializationResponsibility &MR,
1787+
WaitingOnGraph::SimplifyResult SR);
18051788
LLVM_ABI Error OL_notifyEmitted(MaterializationResponsibility &MR,
18061789
ArrayRef<SymbolDependenceGroup> EmittedDeps);
18071790

@@ -1830,6 +1813,7 @@ class ExecutionSession {
18301813
std::vector<ResourceManager *> ResourceManagers;
18311814

18321815
std::vector<JITDylibSP> JDs;
1816+
WaitingOnGraph G;
18331817

18341818
// FIXME: Remove this (and runOutstandingMUs) once the linking layer works
18351819
// with callbacks from asynchronous queries.

llvm/include/llvm/ExecutionEngine/Orc/SymbolStringPool.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_EXECUTIONENGINE_ORC_SYMBOLSTRINGPOOL_H
1515

1616
#include "llvm/ADT/DenseMap.h"
17+
#include "llvm/ADT/Hashing.h"
1718
#include "llvm/ADT/StringMap.h"
1819
#include "llvm/Support/Compiler.h"
1920
#include <atomic>
@@ -71,6 +72,7 @@ class SymbolStringPool {
7172
/// from nullptr to enable comparison with these values.
7273
class SymbolStringPtrBase {
7374
friend class SymbolStringPool;
75+
friend class SymbolStringPoolEntryUnsafe;
7476
friend struct DenseMapInfo<SymbolStringPtr>;
7577
friend struct DenseMapInfo<NonOwningSymbolStringPtr>;
7678

@@ -204,7 +206,7 @@ class SymbolStringPoolEntryUnsafe {
204206
SymbolStringPoolEntryUnsafe(PoolEntry *E) : E(E) {}
205207

206208
/// Create an unsafe pool entry ref without changing the ref-count.
207-
static SymbolStringPoolEntryUnsafe from(const SymbolStringPtr &S) {
209+
static SymbolStringPoolEntryUnsafe from(const SymbolStringPtrBase &S) {
208210
return S.S;
209211
}
210212

@@ -318,6 +320,10 @@ SymbolStringPool::getRefCount(const SymbolStringPtrBase &S) const {
318320
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS,
319321
const SymbolStringPtrBase &Sym);
320322

323+
inline hash_code hash_value(const orc::NonOwningSymbolStringPtr &S) {
324+
return hash_value(orc::SymbolStringPoolEntryUnsafe::from(S).rawPtr());
325+
}
326+
321327
} // end namespace orc
322328

323329
template <>

0 commit comments

Comments
 (0)