Skip to content

Commit c7fcc25

Browse files
committed
Fix a few JITLink nits
1 parent 2e0b75c commit c7fcc25

File tree

3 files changed

+51
-27
lines changed

3 files changed

+51
-27
lines changed

doc/src/devdocs/locks.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ The following are definitely leaf locks (level 1), and must not try to acquire a
3131
> * ResourcePool<?>::mutex
3232
> * RLST_mutex
3333
> * jl_locked_stream::mutex
34+
> * debuginfo_asyncsafe
3435
>
3536
> > flisp itself is already threadsafe, this lock only protects the `jl_ast_context_list_t` pool
3637
> > likewise, the ResourcePool<?>::mutexes just protect the associated resource pool
@@ -39,6 +40,7 @@ The following is a leaf lock (level 2), and only acquires level 1 locks (safepoi
3940

4041
> * typecache
4142
> * Module->lock
43+
> * JLDebuginfoPlugin::PluginMutex
4244
4345
The following is a level 3 lock, which can only acquire level 1 or level 2 locks internally:
4446

@@ -50,10 +52,13 @@ The following is a level 4 lock, which can only recurse to acquire level 1, 2, o
5052
5153
No Julia code may be called while holding a lock above this point.
5254

53-
orc::ThreadSafeContext locks occupy a special spot in the locking diagram. They are used to protect
54-
LLVM's global non-threadsafe state, but there may be an arbitrary number of them. For now, there is
55-
only one global context, and thus acquiring it is a level 5 lock. However, acquiring such a lock
56-
should only be done at the same time that the codegen lock is acquired.
55+
orc::ThreadSafeContext (TSCtx) locks occupy a special spot in the locking hierarchy. They are used to
56+
protect LLVM's global non-threadsafe state, but there may be an arbitrary number of them. By default,
57+
all of these locks may be treated as level 5 locks for the purposes of comparing with the rest of the
58+
hierarchy. Acquiring a TSCtx should only be done from the JIT's pool of TSCtx's, and all locks on
59+
that TSCtx should be released prior to returning it to the pool. If multiple TSCtx locks must be
60+
acquired at the same time (due to recursive compilation), then locks should be acquired in the order
61+
that the TSCtxs were borrowed from the pool.
5762

5863
The following are a level 6 lock, which can only recurse to acquire locks at lower levels:
5964

src/codegen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8603,7 +8603,7 @@ extern "C" void jl_init_llvm(void)
86038603
defined(JL_USE_OPROFILE_JITEVENTS) || \
86048604
defined(JL_USE_PERF_JITEVENTS)
86058605
#ifdef JL_USE_JITLINK
8606-
#error "JIT profiling support (JL_USE_*_JITEVENTS) not yet available on platforms that use JITLink"
8606+
#pragma message("JIT profiling support (JL_USE_*_JITEVENTS) not yet available on platforms that use JITLink")
86078607
#else
86088608
const char *jit_profiling = getenv("ENABLE_JITPROFILING");
86098609

@@ -8625,6 +8625,7 @@ extern "C" void jl_init_llvm(void)
86258625
}
86268626
#endif
86278627

8628+
#ifndef JL_USE_JITLINK
86288629
#ifdef JL_USE_INTEL_JITEVENTS
86298630
if (jl_using_intel_jitevents)
86308631
jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createIntelJITEventListener());
@@ -8640,6 +8641,7 @@ extern "C" void jl_init_llvm(void)
86408641
jl_ExecutionEngine->RegisterJITEventListener(JITEventListener::createPerfJITEventListener());
86418642
#endif
86428643
#endif
8644+
#endif
86438645
#endif
86448646

86458647
cl::PrintOptionValues();

src/jitlayers.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ struct JITObjectInfo {
540540
};
541541

542542
class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
543+
std::mutex PluginMutex;
543544
std::map<MaterializationResponsibility *, std::unique_ptr<JITObjectInfo>> PendingObjs;
544545
// Resources from distinct MaterializationResponsibilitys can get merged
545546
// after emission, so we can have multiple debug objects per resource key.
@@ -560,33 +561,40 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
560561
auto NewObj =
561562
cantFail(object::ObjectFile::createObjectFile(NewBuffer->getMemBufferRef()));
562563

563-
assert(PendingObjs.count(&MR) == 0);
564-
PendingObjs[&MR] = std::unique_ptr<JITObjectInfo>(
565-
new JITObjectInfo{std::move(NewBuffer), std::move(NewObj), {}});
564+
{
565+
std::lock_guard<std::mutex> lock(PluginMutex);
566+
assert(PendingObjs.count(&MR) == 0);
567+
PendingObjs[&MR] = std::unique_ptr<JITObjectInfo>(
568+
new JITObjectInfo{std::move(NewBuffer), std::move(NewObj), {}});
569+
}
566570
}
567571

568572
Error notifyEmitted(MaterializationResponsibility &MR) override
569573
{
570-
auto It = PendingObjs.find(&MR);
571-
if (It == PendingObjs.end())
572-
return Error::success();
573-
574-
auto NewInfo = PendingObjs[&MR].get();
575-
auto getLoadAddress = [NewInfo](const StringRef &Name) -> uint64_t {
576-
auto result = NewInfo->SectionLoadAddresses.find(Name);
577-
if (result == NewInfo->SectionLoadAddresses.end()) {
578-
LLVM_DEBUG({
579-
dbgs() << "JLDebuginfoPlugin: No load address found for section '"
580-
<< Name << "'\n";
581-
});
582-
return 0;
583-
}
584-
return result->second;
585-
};
574+
{
575+
std::lock_guard<std::mutex> lock(PluginMutex);
576+
auto It = PendingObjs.find(&MR);
577+
if (It == PendingObjs.end())
578+
return Error::success();
579+
580+
auto NewInfo = PendingObjs[&MR].get();
581+
auto getLoadAddress = [NewInfo](const StringRef &Name) -> uint64_t {
582+
auto result = NewInfo->SectionLoadAddresses.find(Name);
583+
if (result == NewInfo->SectionLoadAddresses.end()) {
584+
LLVM_DEBUG({
585+
dbgs() << "JLDebuginfoPlugin: No load address found for section '"
586+
<< Name << "'\n";
587+
});
588+
return 0;
589+
}
590+
return result->second;
591+
};
586592

587-
jl_register_jit_object(*NewInfo->Object, getLoadAddress, nullptr);
593+
jl_register_jit_object(*NewInfo->Object, getLoadAddress, nullptr);
594+
}
588595

589596
cantFail(MR.withResourceKeyDo([&](ResourceKey K) {
597+
std::lock_guard<std::mutex> lock(PluginMutex);
590598
RegisteredObjs[K].push_back(std::move(PendingObjs[&MR]));
591599
PendingObjs.erase(&MR);
592600
}));
@@ -596,19 +604,22 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
596604

597605
Error notifyFailed(MaterializationResponsibility &MR) override
598606
{
607+
std::lock_guard<std::mutex> lock(PluginMutex);
599608
PendingObjs.erase(&MR);
600609
return Error::success();
601610
}
602611

603612
Error notifyRemovingResources(ResourceKey K) override
604613
{
614+
std::lock_guard<std::mutex> lock(PluginMutex);
605615
RegisteredObjs.erase(K);
606616
// TODO: If we ever unload code, need to notify debuginfo registry.
607617
return Error::success();
608618
}
609619

610620
void notifyTransferringResources(ResourceKey DstKey, ResourceKey SrcKey) override
611621
{
622+
std::lock_guard<std::mutex> lock(PluginMutex);
612623
auto SrcIt = RegisteredObjs.find(SrcKey);
613624
if (SrcIt != RegisteredObjs.end()) {
614625
for (std::unique_ptr<JITObjectInfo> &Info : SrcIt->second)
@@ -620,13 +631,16 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
620631
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &,
621632
jitlink::PassConfiguration &PassConfig) override
622633
{
634+
std::lock_guard<std::mutex> lock(PluginMutex);
623635
auto It = PendingObjs.find(&MR);
624636
if (It == PendingObjs.end())
625637
return;
626638

627639
JITObjectInfo &Info = *It->second;
628-
PassConfig.PostAllocationPasses.push_back([&Info](jitlink::LinkGraph &G) -> Error {
640+
PassConfig.PostAllocationPasses.push_back([&Info, this](jitlink::LinkGraph &G) -> Error {
641+
std::lock_guard<std::mutex> lock(PluginMutex);
629642
for (const jitlink::Section &Sec : G.sections()) {
643+
#ifdef _OS_DARWIN_
630644
// Canonical JITLink section names have the segment name included, e.g.
631645
// "__TEXT,__text" or "__DWARF,__debug_str". There are some special internal
632646
// sections without a comma separator, which we can just ignore.
@@ -639,6 +653,9 @@ class JLDebuginfoPlugin : public ObjectLinkingLayer::Plugin {
639653
continue;
640654
}
641655
auto SecName = Sec.getName().substr(SepPos + 1);
656+
#else
657+
auto SecName = Sec.getName();
658+
#endif
642659
// https://github.com/llvm/llvm-project/commit/118e953b18ff07d00b8f822dfbf2991e41d6d791
643660
#if JL_LLVM_VERSION >= 140000
644661
Info.SectionLoadAddresses[SecName] = jitlink::SectionRange(Sec).getStart().getValue();
@@ -1051,7 +1068,7 @@ JuliaOJIT::JuliaOJIT()
10511068
OptSelLayer(Pipelines)
10521069
{
10531070
#ifdef JL_USE_JITLINK
1054-
# if defined(_OS_DARWIN_) && defined(LLVM_SHLIB)
1071+
# if defined(LLVM_SHLIB)
10551072
// When dynamically linking against LLVM, use our custom EH frame registration code
10561073
// also used with RTDyld to inform both our and the libc copy of libunwind.
10571074
auto ehRegistrar = std::make_unique<JLEHFrameRegistrar>();

0 commit comments

Comments
 (0)