Skip to content

Commit 00351da

Browse files
authored
Fix LLVM TaskDispatcher implementation issues (#58950)
Fixes #58229 (LLVM JITLink stack overflow issue) I tried submitting this promise/future implementation upstream (llvm/llvm-project@main...vtjnash:llvm-project:jn/cowait-jit) so that I would not need to duplicate nearly as much code here to fix this bug, but upstream is currently opposed to fixing this bug and instead insists it is preferable for each downstream project to implement this fix themselves adding extra maintenance burden for us for now. Sigh.
1 parent 9d6344a commit 00351da

File tree

3 files changed

+474
-16
lines changed

3 files changed

+474
-16
lines changed

src/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ $(BUILDDIR)/gc-alloc-profiler.o $(BUILDDIR)/gc-alloc-profiler.dbg.obj: $(SRCDIR)
374374
$(BUILDDIR)/gc-page-profiler.o $(BUILDDIR)/gc-page-profiler.dbg.obj: $(SRCDIR)/gc-page-profiler.h
375375
$(BUILDDIR)/init.o $(BUILDDIR)/init.dbg.obj: $(SRCDIR)/builtin_proto.h
376376
$(BUILDDIR)/interpreter.o $(BUILDDIR)/interpreter.dbg.obj: $(SRCDIR)/builtin_proto.h
377-
$(BUILDDIR)/jitlayers.o $(BUILDDIR)/jitlayers.dbg.obj: $(SRCDIR)/jitlayers.h $(SRCDIR)/llvm-codegen-shared.h
377+
$(BUILDDIR)/jitlayers.o $(BUILDDIR)/jitlayers.dbg.obj: $(SRCDIR)/jitlayers.h $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/llvm-julia-task-dispatcher.h
378378
$(BUILDDIR)/jltypes.o $(BUILDDIR)/jltypes.dbg.obj: $(SRCDIR)/builtin_proto.h
379379
$(build_shlibdir)/libllvmcalltest.$(SHLIB_EXT): $(SRCDIR)/llvm-codegen-shared.h $(BUILDDIR)/julia_version.h
380380
$(BUILDDIR)/llvm-alloc-helpers.o $(BUILDDIR)/llvm-alloc-helpers.dbg.obj: $(SRCDIR)/llvm-codegen-shared.h $(SRCDIR)/llvm-pass-helpers.h $(SRCDIR)/llvm-alloc-helpers.h

src/jitlayers.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <string>
77

88
#include "llvm/IR/Mangler.h"
9+
#include <llvm/ADT/BitmaskEnum.h>
910
#include <llvm/ADT/Statistic.h>
1011
#include <llvm/ADT/StringMap.h>
1112
#include <llvm/Analysis/TargetLibraryInfo.h>
@@ -50,6 +51,7 @@ using namespace llvm;
5051
#include "jitlayers.h"
5152
#include "julia_assert.h"
5253
#include "processor.h"
54+
#include "llvm-julia-task-dispatcher.h"
5355

5456
#if JL_LLVM_VERSION >= 180000
5557
# include <llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h>
@@ -723,17 +725,8 @@ static void jl_compile_codeinst_now(jl_code_instance_t *codeinst)
723725
if (!decls.specFunctionObject.empty())
724726
NewDefs.push_back(decls.specFunctionObject);
725727
}
726-
// Split batches to avoid stack overflow in the JIT linker.
727-
// FIXME: Patch ORCJITs InPlaceTaskDispatcher to not recurse on task dispatches but
728-
// push the tasks to a queue to be drained later. This avoids the stackoverflow caused by recursion
729-
// in the linker when compiling a large number of functions at once.
730-
SmallVector<uint64_t, 0> Addrs;
731-
for (size_t i = 0; i < NewDefs.size(); i += 1000) {
732-
auto end = std::min(i + 1000, NewDefs.size());
733-
SmallVector<StringRef> batch(NewDefs.begin() + i, NewDefs.begin() + end);
734-
auto AddrsBatch = jl_ExecutionEngine->findSymbols(batch);
735-
Addrs.append(AddrsBatch);
736-
}
728+
auto Addrs = jl_ExecutionEngine->findSymbols(NewDefs);
729+
737730
size_t nextaddr = 0;
738731
for (auto &this_code : linkready) {
739732
auto it = invokenames.find(this_code);
@@ -1901,7 +1894,7 @@ llvm::DataLayout jl_create_datalayout(TargetMachine &TM) {
19011894
JuliaOJIT::JuliaOJIT()
19021895
: TM(createTargetMachine()),
19031896
DL(jl_create_datalayout(*TM)),
1904-
ES(cantFail(orc::SelfExecutorProcessControl::Create())),
1897+
ES(cantFail(orc::SelfExecutorProcessControl::Create(nullptr, std::make_unique<::JuliaTaskDispatcher>()))),
19051898
GlobalJD(ES.createBareJITDylib("JuliaGlobals")),
19061899
JD(ES.createBareJITDylib("JuliaOJIT")),
19071900
ExternalJD(ES.createBareJITDylib("JuliaExternal")),
@@ -2159,7 +2152,7 @@ SmallVector<uint64_t> JuliaOJIT::findSymbols(ArrayRef<StringRef> Names)
21592152
Unmangled[NonOwningSymbolStringPtr(Mangled)] = Unmangled.size();
21602153
Exports.add(std::move(Mangled));
21612154
}
2162-
SymbolMap Syms = cantFail(ES.lookup(orc::makeJITDylibSearchOrder(ArrayRef(&JD)), std::move(Exports)));
2155+
SymbolMap Syms = cantFail(::safelookup(ES, orc::makeJITDylibSearchOrder(ArrayRef(&JD)), std::move(Exports)));
21632156
SmallVector<uint64_t> Addrs(Names.size());
21642157
for (auto it : Syms) {
21652158
Addrs[Unmangled.at(orc::NonOwningSymbolStringPtr(it.first))] = it.second.getAddress().getValue();
@@ -2171,7 +2164,7 @@ Expected<ExecutorSymbolDef> JuliaOJIT::findSymbol(StringRef Name, bool ExportedS
21712164
{
21722165
orc::JITDylib* SearchOrders[3] = {&JD, &GlobalJD, &ExternalJD};
21732166
ArrayRef<orc::JITDylib*> SearchOrder = ArrayRef<orc::JITDylib*>(&SearchOrders[0], ExportedSymbolsOnly ? 3 : 1);
2174-
auto Sym = ES.lookup(SearchOrder, Name);
2167+
auto Sym = ::safelookup(ES, SearchOrder, Name);
21752168
return Sym;
21762169
}
21772170

@@ -2184,7 +2177,7 @@ Expected<ExecutorSymbolDef> JuliaOJIT::findExternalJDSymbol(StringRef Name, bool
21842177
{
21852178
orc::JITDylib* SearchOrders[3] = {&ExternalJD, &GlobalJD, &JD};
21862179
ArrayRef<orc::JITDylib*> SearchOrder = ArrayRef<orc::JITDylib*>(&SearchOrders[0], ExternalJDOnly ? 1 : 3);
2187-
auto Sym = ES.lookup(SearchOrder, getMangledName(Name));
2180+
auto Sym = ::safelookup(ES, SearchOrder, getMangledName(Name));
21882181
return Sym;
21892182
}
21902183

0 commit comments

Comments
 (0)