Skip to content

Commit 54226e2

Browse files
authored
[ORC] Make EPCDynamicLibrarySearchGenerator async
Switch the primary implementation of EPC lookupSymbols to be async, keeping a synchronous wrapper for compatibility. Use the new async implementation inside EPCDynamicLibrarySearchGenerator to work working towards a fully async search generator. Provide an asynchronous lookup API for EPCGenericDylibManager and adopt that from the SimpleRemoteEPC. This enables an end-to-end async EPCDynamicLibrarySearchGenerator. Note: currently we keep the current per-dlhandle lookup model, but a future improvement could do a single async call for a given lookup operation.
1 parent 50b8a3c commit 54226e2

File tree

8 files changed

+149
-74
lines changed

8 files changed

+149
-74
lines changed

llvm/include/llvm/ExecutionEngine/Orc/EPCGenericDylibManager.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,32 @@ class EPCGenericDylibManager {
5151

5252
/// Looks up symbols within the given dylib.
5353
Expected<std::vector<ExecutorSymbolDef>>
54-
lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup);
54+
lookup(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup) {
55+
std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
56+
auto RF = RP.get_future();
57+
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
58+
return RF.get();
59+
}
5560

5661
/// Looks up symbols within the given dylib.
5762
Expected<std::vector<ExecutorSymbolDef>>
58-
lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup);
63+
lookup(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup) {
64+
std::promise<MSVCPExpected<std::vector<ExecutorSymbolDef>>> RP;
65+
auto RF = RP.get_future();
66+
lookupAsync(H, Lookup, [&RP](auto R) { RP.set_value(std::move(R)); });
67+
return RF.get();
68+
}
69+
70+
using SymbolLookupCompleteFn =
71+
unique_function<void(Expected<std::vector<ExecutorSymbolDef>>)>;
72+
73+
/// Looks up symbols within the given dylib.
74+
void lookupAsync(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup,
75+
SymbolLookupCompleteFn Complete);
76+
77+
/// Looks up symbols within the given dylib.
78+
void lookupAsync(tpctypes::DylibHandle H, const RemoteSymbolLookupSet &Lookup,
79+
SymbolLookupCompleteFn Complete);
5980

6081
private:
6182
ExecutorProcessControl &EPC;

llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,26 @@ class ExecutorProcessControl {
290290
/// that correspond to the lookup order. If a required symbol is not
291291
/// found then this method will return an error. If a weakly referenced
292292
/// symbol is not found then it be assigned a '0' value.
293-
virtual Expected<std::vector<tpctypes::LookupResult>>
294-
lookupSymbols(ArrayRef<LookupRequest> Request) = 0;
293+
Expected<std::vector<tpctypes::LookupResult>>
294+
lookupSymbols(ArrayRef<LookupRequest> Request) {
295+
std::promise<MSVCPExpected<std::vector<tpctypes::LookupResult>>> RP;
296+
auto RF = RP.get_future();
297+
lookupSymbolsAsync(Request,
298+
[&RP](auto Result) { RP.set_value(std::move(Result)); });
299+
return RF.get();
300+
}
301+
302+
using SymbolLookupCompleteFn =
303+
unique_function<void(Expected<std::vector<tpctypes::LookupResult>>)>;
304+
305+
/// Search for symbols in the target process.
306+
///
307+
/// The result of the lookup is a 2-dimensional array of target addresses
308+
/// that correspond to the lookup order. If a required symbol is not
309+
/// found then this method will return an error. If a weakly referenced
310+
/// symbol is not found then it be assigned a '0' value.
311+
virtual void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
312+
SymbolLookupCompleteFn F) = 0;
295313

296314
/// Run function with a main-like signature.
297315
virtual Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
@@ -462,8 +480,8 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl,
462480
llvm_unreachable("Unsupported");
463481
}
464482

465-
Expected<std::vector<tpctypes::LookupResult>>
466-
lookupSymbols(ArrayRef<LookupRequest> Request) override {
483+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
484+
SymbolLookupCompleteFn F) override {
467485
llvm_unreachable("Unsupported");
468486
}
469487

@@ -510,8 +528,8 @@ class SelfExecutorProcessControl : public ExecutorProcessControl,
510528

511529
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
512530

513-
Expected<std::vector<tpctypes::LookupResult>>
514-
lookupSymbols(ArrayRef<LookupRequest> Request) override;
531+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
532+
SymbolLookupCompleteFn F) override;
515533

516534
Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
517535
ArrayRef<std::string> Args) override;

llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class SimpleRemoteEPC : public ExecutorProcessControl,
7171

7272
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
7373

74-
Expected<std::vector<tpctypes::LookupResult>>
75-
lookupSymbols(ArrayRef<LookupRequest> Request) override;
74+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
75+
SymbolLookupCompleteFn F) override;
7676

7777
Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
7878
ArrayRef<std::string> Args) override;

llvm/lib/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
10+
#include "llvm/Support/Error.h"
1011

1112
namespace llvm {
1213
namespace orc {
@@ -39,32 +40,38 @@ Error EPCDynamicLibrarySearchGenerator::tryToGenerate(
3940
LookupSymbols.add(KV.first, SymbolLookupFlags::WeaklyReferencedSymbol);
4041
}
4142

42-
SymbolMap NewSymbols;
43-
4443
ExecutorProcessControl::LookupRequest Request(H, LookupSymbols);
45-
auto Result = EPC.lookupSymbols(Request);
46-
if (!Result)
47-
return Result.takeError();
48-
49-
assert(Result->size() == 1 && "Results for more than one library returned");
50-
assert(Result->front().size() == LookupSymbols.size() &&
51-
"Result has incorrect number of elements");
52-
53-
auto ResultI = Result->front().begin();
54-
for (auto &KV : LookupSymbols) {
55-
if (ResultI->getAddress())
56-
NewSymbols[KV.first] = *ResultI;
57-
++ResultI;
58-
}
44+
// Copy-capture LookupSymbols, since LookupRequest keeps a reference.
45+
EPC.lookupSymbolsAsync(Request, [this, &JD, LS = std::move(LS),
46+
LookupSymbols](auto Result) mutable {
47+
if (!Result)
48+
return LS.continueLookup(Result.takeError());
5949

60-
// If there were no resolved symbols bail out.
61-
if (NewSymbols.empty())
62-
return Error::success();
50+
assert(Result->size() == 1 && "Results for more than one library returned");
51+
assert(Result->front().size() == LookupSymbols.size() &&
52+
"Result has incorrect number of elements");
53+
54+
SymbolMap NewSymbols;
55+
auto ResultI = Result->front().begin();
56+
for (auto &KV : LookupSymbols) {
57+
if (ResultI->getAddress())
58+
NewSymbols[KV.first] = *ResultI;
59+
++ResultI;
60+
}
61+
62+
// If there were no resolved symbols bail out.
63+
if (NewSymbols.empty())
64+
return LS.continueLookup(Error::success());
65+
66+
// Define resolved symbols.
67+
Error Err = AddAbsoluteSymbols
68+
? AddAbsoluteSymbols(JD, std::move(NewSymbols))
69+
: JD.define(absoluteSymbols(std::move(NewSymbols)));
70+
71+
LS.continueLookup(std::move(Err));
72+
});
6373

64-
// Define resolved symbols.
65-
if (AddAbsoluteSymbols)
66-
return AddAbsoluteSymbols(JD, std::move(NewSymbols));
67-
return JD.define(absoluteSymbols(std::move(NewSymbols)));
74+
return Error::success();
6875
}
6976

7077
} // end namespace orc

llvm/lib/ExecutionEngine/Orc/EPCGenericDylibManager.cpp

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -81,28 +81,38 @@ Expected<tpctypes::DylibHandle> EPCGenericDylibManager::open(StringRef Path,
8181
return H;
8282
}
8383

84-
Expected<std::vector<ExecutorSymbolDef>>
85-
EPCGenericDylibManager::lookup(tpctypes::DylibHandle H,
86-
const SymbolLookupSet &Lookup) {
87-
Expected<std::vector<ExecutorSymbolDef>> Result(
88-
(std::vector<ExecutorSymbolDef>()));
89-
if (auto Err =
90-
EPC.callSPSWrapper<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
91-
SAs.Lookup, Result, SAs.Instance, H, Lookup))
92-
return std::move(Err);
93-
return Result;
84+
void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
85+
const SymbolLookupSet &Lookup,
86+
SymbolLookupCompleteFn Complete) {
87+
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
88+
SAs.Lookup,
89+
[Complete = std::move(Complete)](
90+
Error SerializationErr,
91+
Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
92+
if (SerializationErr) {
93+
cantFail(Result.takeError());
94+
Complete(std::move(SerializationErr));
95+
}
96+
Complete(std::move(Result));
97+
},
98+
SAs.Instance, H, Lookup);
9499
}
95100

96-
Expected<std::vector<ExecutorSymbolDef>>
97-
EPCGenericDylibManager::lookup(tpctypes::DylibHandle H,
98-
const RemoteSymbolLookupSet &Lookup) {
99-
Expected<std::vector<ExecutorSymbolDef>> Result(
100-
(std::vector<ExecutorSymbolDef>()));
101-
if (auto Err =
102-
EPC.callSPSWrapper<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
103-
SAs.Lookup, Result, SAs.Instance, H, Lookup))
104-
return std::move(Err);
105-
return Result;
101+
void EPCGenericDylibManager::lookupAsync(tpctypes::DylibHandle H,
102+
const RemoteSymbolLookupSet &Lookup,
103+
SymbolLookupCompleteFn Complete) {
104+
EPC.callSPSWrapperAsync<rt::SPSSimpleExecutorDylibManagerLookupSignature>(
105+
SAs.Lookup,
106+
[Complete = std::move(Complete)](
107+
Error SerializationErr,
108+
Expected<std::vector<ExecutorSymbolDef>> Result) mutable {
109+
if (SerializationErr) {
110+
cantFail(Result.takeError());
111+
Complete(std::move(SerializationErr));
112+
}
113+
Complete(std::move(Result));
114+
},
115+
SAs.Instance, H, Lookup);
106116
}
107117

108118
} // end namespace orc

llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ SelfExecutorProcessControl::loadDylib(const char *DylibPath) {
8989
return ExecutorAddr::fromPtr(Dylib.getOSSpecificHandle());
9090
}
9191

92-
Expected<std::vector<tpctypes::LookupResult>>
93-
SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
92+
void SelfExecutorProcessControl::lookupSymbolsAsync(
93+
ArrayRef<LookupRequest> Request,
94+
ExecutorProcessControl::SymbolLookupCompleteFn Complete) {
9495
std::vector<tpctypes::LookupResult> R;
9596

9697
for (auto &Elem : Request) {
@@ -105,15 +106,16 @@ SelfExecutorProcessControl::lookupSymbols(ArrayRef<LookupRequest> Request) {
105106
// FIXME: Collect all failing symbols before erroring out.
106107
SymbolNameVector MissingSymbols;
107108
MissingSymbols.push_back(Sym);
108-
return make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols));
109+
return Complete(
110+
make_error<SymbolsNotFound>(SSP, std::move(MissingSymbols)));
109111
}
110112
// FIXME: determine accurate JITSymbolFlags.
111113
R.back().push_back(
112114
{ExecutorAddr::fromPtr(Addr), JITSymbolFlags::Exported});
113115
}
114116
}
115117

116-
return R;
118+
Complete(std::move(R));
117119
}
118120

119121
Expected<int32_t>

llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,37 @@ SimpleRemoteEPC::loadDylib(const char *DylibPath) {
2929
return DylibMgr->open(DylibPath, 0);
3030
}
3131

32-
Expected<std::vector<tpctypes::LookupResult>>
33-
SimpleRemoteEPC::lookupSymbols(ArrayRef<LookupRequest> Request) {
34-
std::vector<tpctypes::LookupResult> Result;
35-
36-
for (auto &Element : Request) {
37-
if (auto R = DylibMgr->lookup(Element.Handle, Element.Symbols)) {
38-
Result.push_back({});
39-
Result.back().reserve(R->size());
40-
for (auto Addr : *R)
41-
Result.back().push_back(Addr);
42-
} else
43-
return R.takeError();
44-
}
45-
return std::move(Result);
32+
/// Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all
33+
/// all the requests.
34+
/// FIXME: The dylib manager should support multiple LookupRequests natively.
35+
static void
36+
lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr,
37+
ArrayRef<SimpleRemoteEPC::LookupRequest> Request,
38+
std::vector<tpctypes::LookupResult> Result,
39+
SimpleRemoteEPC::SymbolLookupCompleteFn Complete) {
40+
if (Request.empty())
41+
return Complete(std::move(Result));
42+
43+
auto &Element = Request.front();
44+
DylibMgr.lookupAsync(Element.Handle, Element.Symbols,
45+
[&DylibMgr, Request, Complete = std::move(Complete),
46+
Result = std::move(Result)](auto R) mutable {
47+
if (!R)
48+
return Complete(R.takeError());
49+
Result.push_back({});
50+
Result.back().reserve(R->size());
51+
for (auto Addr : *R)
52+
Result.back().push_back(Addr);
53+
54+
lookupSymbolsAsyncHelper(
55+
DylibMgr, Request.drop_front(), std::move(Result),
56+
std::move(Complete));
57+
});
58+
}
59+
60+
void SimpleRemoteEPC::lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
61+
SymbolLookupCompleteFn Complete) {
62+
lookupSymbolsAsyncHelper(*DylibMgr, Request, {}, std::move(Complete));
4663
}
4764

4865
Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,

llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,8 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
189189
return ExecutorAddr::fromPtr((void *)nullptr);
190190
}
191191

192-
Expected<std::vector<tpctypes::LookupResult>>
193-
lookupSymbols(ArrayRef<LookupRequest> Request) override {
192+
void lookupSymbolsAsync(ArrayRef<LookupRequest> Request,
193+
SymbolLookupCompleteFn Complete) override {
194194
std::vector<ExecutorSymbolDef> Result;
195195
EXPECT_EQ(Request.size(), 1u);
196196
for (auto &LR : Request) {
@@ -205,7 +205,7 @@ TEST(ObjectLinkingLayerSearchGeneratorTest, AbsoluteSymbolsObjectLayer) {
205205
}
206206
}
207207
}
208-
return std::vector<tpctypes::LookupResult>{1, Result};
208+
Complete(std::vector<tpctypes::LookupResult>{1, Result});
209209
}
210210
};
211211

0 commit comments

Comments
 (0)