Skip to content

Commit 300deeb

Browse files
committed
[ORC] Make LazyReexportsManager implement ResourceManager.
This ensures that the reexports mappings are cleared when the resource tracker associated with each mapping is removed.
1 parent 43ede46 commit 300deeb

File tree

4 files changed

+129
-17
lines changed

4 files changed

+129
-17
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,11 @@ class SymbolLookupSet {
200200

201201
SymbolLookupSet() = default;
202202

203+
SymbolLookupSet(std::initializer_list<value_type> Elems) {
204+
for (auto &E : Elems)
205+
Symbols.push_back(std::move(E));
206+
}
207+
203208
explicit SymbolLookupSet(
204209
SymbolStringPtr Name,
205210
SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {

llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ lazyReexports(LazyCallThroughManager &LCTManager,
173173
LCTManager, RSManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
174174
}
175175

176-
class LazyReexportsManager {
176+
class LazyReexportsManager : public ResourceManager {
177177

178178
friend std::unique_ptr<MaterializationUnit>
179179
lazyReexports(LazyReexportsManager &, SymbolAliasMap);
@@ -194,6 +194,10 @@ class LazyReexportsManager {
194194
LazyReexportsManager(LazyReexportsManager &&) = delete;
195195
LazyReexportsManager &operator=(LazyReexportsManager &&) = delete;
196196

197+
Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
198+
void handleTransferResources(JITDylib &JD, ResourceKey DstK,
199+
ResourceKey SrcK) override;
200+
197201
private:
198202
struct CallThroughInfo {
199203
SymbolStringPtr Name;
@@ -222,10 +226,11 @@ class LazyReexportsManager {
222226
Expected<std::vector<ExecutorSymbolDef>> ReentryPoints);
223227
void resolve(ResolveSendResultFn SendResult, ExecutorAddr ReentryStubAddr);
224228

229+
ExecutionSession &ES;
225230
EmitTrampolinesFn EmitTrampolines;
226231
RedirectableSymbolManager &RSMgr;
227232

228-
std::mutex M;
233+
DenseMap<ResourceKey, ExecutorAddr> KeyToReentryAddr;
229234
DenseMap<ExecutorAddr, CallThroughInfo> CallThroughs;
230235
};
231236

llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,16 +292,39 @@ LazyReexportsManager::Create(EmitTrampolinesFn EmitTrampolines,
292292
return std::move(LRM);
293293
}
294294

295+
Error LazyReexportsManager::handleRemoveResources(JITDylib &JD, ResourceKey K) {
296+
JD.getExecutionSession().runSessionLocked([&]() {
297+
auto I = KeyToReentryAddr.find(K);
298+
if (I != KeyToReentryAddr.end()) {
299+
auto ReentryAddr = I->second;
300+
CallThroughs.erase(ReentryAddr);
301+
KeyToReentryAddr.erase(I);
302+
}
303+
});
304+
return Error::success();
305+
}
306+
307+
void LazyReexportsManager::handleTransferResources(JITDylib &JD,
308+
ResourceKey DstK,
309+
ResourceKey SrcK) {
310+
auto I = KeyToReentryAddr.find(SrcK);
311+
if (I != KeyToReentryAddr.end()) {
312+
auto ReentryAddr = I->second;
313+
KeyToReentryAddr.erase(I);
314+
KeyToReentryAddr[DstK] = ReentryAddr;
315+
}
316+
}
317+
295318
LazyReexportsManager::LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
296319
RedirectableSymbolManager &RSMgr,
297320
JITDylib &PlatformJD, Error &Err)
298-
: EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr) {
321+
: ES(PlatformJD.getExecutionSession()),
322+
EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr) {
299323

300324
using namespace shared;
301325

302326
ErrorAsOutParameter _(&Err);
303327

304-
auto &ES = PlatformJD.getExecutionSession();
305328
ExecutionSession::JITDispatchHandlerAssociationMap WFs;
306329

307330
WFs[ES.intern("__orc_rt_resolve_tag")] =
@@ -345,15 +368,22 @@ void LazyReexportsManager::emitRedirectableSymbols(
345368

346369
// Bind entry points to names.
347370
SymbolMap Redirs;
348-
{
349-
std::lock_guard<std::mutex> Lock(M);
350-
size_t I = 0;
351-
for (auto &[Name, AI] : Reexports) {
352-
const auto &ReentryPoint = (*ReentryPoints)[I++];
353-
Redirs[Name] = ReentryPoint;
354-
CallThroughs[ReentryPoint.getAddress()] = {Name, AI.Aliasee,
355-
&MR->getTargetJITDylib()};
356-
}
371+
size_t I = 0;
372+
for (auto &[Name, AI] : Reexports)
373+
Redirs[Name] = (*ReentryPoints)[I++];
374+
375+
I = 0;
376+
if (auto Err = MR->withResourceKeyDo([&](ResourceKey K) {
377+
for (auto &[Name, AI] : Reexports) {
378+
const auto &ReentryPoint = (*ReentryPoints)[I++];
379+
CallThroughs[ReentryPoint.getAddress()] = {Name, AI.Aliasee,
380+
&MR->getTargetJITDylib()};
381+
KeyToReentryAddr[K] = ReentryPoint.getAddress();
382+
}
383+
})) {
384+
MR->getExecutionSession().reportError(std::move(Err));
385+
MR->failMaterialization();
386+
return;
357387
}
358388

359389
RSMgr.emitRedirectableSymbols(std::move(MR), std::move(Redirs));
@@ -364,17 +394,15 @@ void LazyReexportsManager::resolve(ResolveSendResultFn SendResult,
364394

365395
CallThroughInfo LandingInfo;
366396

367-
{
368-
std::lock_guard<std::mutex> Lock(M);
369-
397+
ES.runSessionLocked([&]() {
370398
auto I = CallThroughs.find(ReentryStubAddr);
371399
if (I == CallThroughs.end())
372400
return SendResult(make_error<StringError>(
373401
"Reentry address " + formatv("{0:x}", ReentryStubAddr) +
374402
" not registered",
375403
inconvertibleErrorCode()));
376404
LandingInfo = I->second;
377-
}
405+
});
378406

379407
SymbolInstance LandingSym(LandingInfo.JD, std::move(LandingInfo.BodyName));
380408
LandingSym.lookupAsync([this, JD = std::move(LandingInfo.JD),

llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#include "OrcTestCommon.h"
2+
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
3+
#include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
4+
#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"
25
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
6+
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
37
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
8+
#include "llvm/Testing/Support/Error.h"
49
#include "gtest/gtest.h"
510

611
using namespace llvm;
@@ -70,3 +75,72 @@ TEST_F(LazyReexportsTest, BasicLocalCallThroughManagerOperation) {
7075
<< "CallThrough should have generated exactly one 'NotifyResolved' call";
7176
EXPECT_EQ(Result, 42) << "Failed to call through to target";
7277
}
78+
79+
static void *noReentry(void *) { abort(); }
80+
81+
TEST(JITLinkLazyReexportsTest, Basics) {
82+
OrcNativeTarget::initialize();
83+
84+
auto J = LLJITBuilder().create();
85+
if (!J) {
86+
dbgs() << toString(J.takeError()) << "\n";
87+
// consumeError(J.takeError());
88+
GTEST_SKIP();
89+
}
90+
if (!isa<ObjectLinkingLayer>((*J)->getObjLinkingLayer()))
91+
GTEST_SKIP();
92+
93+
auto &OLL = cast<ObjectLinkingLayer>((*J)->getObjLinkingLayer());
94+
95+
auto RSMgr = JITLinkRedirectableSymbolManager::Create(OLL);
96+
if (!RSMgr) {
97+
dbgs() << "Boom for RSMgr\n";
98+
consumeError(RSMgr.takeError());
99+
GTEST_SKIP();
100+
}
101+
102+
auto &ES = (*J)->getExecutionSession();
103+
104+
auto &JD = ES.createBareJITDylib("JD");
105+
cantFail(JD.define(absoluteSymbols(
106+
{{ES.intern("__orc_rt_reentry"),
107+
{ExecutorAddr::fromPtr(&noReentry),
108+
JITSymbolFlags::Exported | JITSymbolFlags::Callable}}})));
109+
110+
auto LRMgr = createJITLinkLazyReexportsManager(OLL, **RSMgr, JD);
111+
if (!LRMgr) {
112+
dbgs() << "Boom for LRMgr\n";
113+
consumeError(LRMgr.takeError());
114+
GTEST_SKIP();
115+
}
116+
117+
auto Foo = ES.intern("foo");
118+
auto Bar = ES.intern("bar");
119+
120+
auto RT = JD.createResourceTracker();
121+
cantFail(JD.define(
122+
lazyReexports(
123+
**LRMgr,
124+
{{Foo, {Bar, JITSymbolFlags::Exported | JITSymbolFlags::Callable}}}),
125+
RT));
126+
127+
// Check flags after adding Foo -> Bar lazy reexport.
128+
auto SF = cantFail(
129+
ES.lookupFlags(LookupKind::Static, makeJITDylibSearchOrder(&JD),
130+
{{Foo, SymbolLookupFlags::WeaklyReferencedSymbol}}));
131+
EXPECT_EQ(SF.size(), 1U);
132+
EXPECT_TRUE(SF.count(Foo));
133+
EXPECT_EQ(SF[Foo], JITSymbolFlags::Exported | JITSymbolFlags::Callable);
134+
135+
// Remove reexport without running it.
136+
if (auto Err = RT->remove()) {
137+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
138+
return;
139+
}
140+
141+
// Check flags after adding Foo -> Bar lazy reexport.
142+
SF = cantFail(
143+
ES.lookupFlags(LookupKind::Static, makeJITDylibSearchOrder(&JD),
144+
{{Foo, SymbolLookupFlags::WeaklyReferencedSymbol}}));
145+
EXPECT_EQ(SF.size(), 0U);
146+
}

0 commit comments

Comments
 (0)