From 8a87d1f8d6b594f1a2d027c1d1eab22dc441cdb3 Mon Sep 17 00:00:00 2001 From: Axel Naumann Date: Thu, 12 Jan 2023 16:20:40 +0100 Subject: [PATCH] JIT: find existing weak symbol without materializer: m_JIT.getSymbolAddress() invokes the symbol materializers, which compile (which is sort of okay) but also try autoloading (which totally is not okay). Instead, implement a function to search existing JIT symbols. This can be accelerated by looking up the whole set of symbols, instead of doing it symbol by symbol. I leave that refactoring for later... --- lib/Interpreter/BackendPasses.cpp | 15 ++++++++++++--- lib/Interpreter/IncrementalJIT.cpp | 15 ++++++++++++++- lib/Interpreter/IncrementalJIT.h | 4 ++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/Interpreter/BackendPasses.cpp b/lib/Interpreter/BackendPasses.cpp index 514180a4..f1a04b65 100644 --- a/lib/Interpreter/BackendPasses.cpp +++ b/lib/Interpreter/BackendPasses.cpp @@ -267,9 +267,17 @@ namespace { if (!GV.isDiscardableIfUnused(LT) || !GV.isWeakForLinker(LT)) return false; - // Find the symbol as existing, previously compiled symbol in the JIT, - // or in shared libraries (without auto-loading). - return (m_JIT.getSymbolAddress(GV.getName(), /*IncludeHostSyms*/ true)); + // Find the symbol as existing, previously compiled symbol in the JIT... + if (m_JIT.doesSymbolAlreadyExist(GV.getName())) + return true; + + // ...or in shared libraries (without auto-loading). + std::string Name = GV.getName().str(); +#if !defined(_WIN32) + return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(Name); +#else + return platform::DLSym(Name); +#endif } bool runOnVar(GlobalVariable& GV) { @@ -310,6 +318,7 @@ namespace { bool runOnModule(Module &M) override { bool ret = false; + // FIXME: use SymbolLookupSet, rather than looking up symbol by symbol. for (auto &&F: M) ret |= runOnFunc(F); for (auto &&G: M.globals()) diff --git a/lib/Interpreter/IncrementalJIT.cpp b/lib/Interpreter/IncrementalJIT.cpp index f6aa0265..e736c091 100644 --- a/lib/Interpreter/IncrementalJIT.cpp +++ b/lib/Interpreter/IncrementalJIT.cpp @@ -504,6 +504,10 @@ llvm::Error IncrementalJIT::removeModule(const Transaction& T) { m_ResourceTrackers.erase(&T); if (Error Err = RT->remove()) return Err; + auto iMod = m_CompiledModules.find(T.m_CompiledModule); + if (iMod != m_CompiledModules.end()) + m_CompiledModules.erase(iMod); + return llvm::Error::success(); } @@ -550,7 +554,7 @@ IncrementalJIT::addOrReplaceDefinition(StringRef Name, return KnownAddr; } -void* IncrementalJIT::getSymbolAddress(StringRef Name, bool IncludeHostSymbols) { +void* IncrementalJIT::getSymbolAddress(StringRef Name, bool IncludeHostSymbols){ std::unique_lock G(SkipHostProcessLookup, std::defer_lock); if (!IncludeHostSymbols) G.lock(); @@ -577,4 +581,13 @@ void* IncrementalJIT::getSymbolAddress(StringRef Name, bool IncludeHostSymbols) return jitTargetAddressToPointer(Symbol->getAddress()); } +bool IncrementalJIT::doesSymbolAlreadyExist(StringRef UnmangledName) { + auto Name = Jit->mangle(UnmangledName); + for (auto &&M: m_CompiledModules) { + if (M.first->getNamedValue(Name)) + return true; + } + return false; +} + } // namespace cling diff --git a/lib/Interpreter/IncrementalJIT.h b/lib/Interpreter/IncrementalJIT.h index 6d067a6d..c05458c2 100644 --- a/lib/Interpreter/IncrementalJIT.h +++ b/lib/Interpreter/IncrementalJIT.h @@ -78,6 +78,10 @@ public: /// should include symbols from the host process (via dlsym) or not. void* getSymbolAddress(llvm::StringRef Name, bool IncludeHostSymbols); + /// @brief Check whether the JIT already has emitted or knows how to emit + /// a symbol based on its IR name (as coming from clang's mangler). + bool doesSymbolAlreadyExist(llvm::StringRef UnmangledName); + /// Inject a symbol with a known address. Name is not linker mangled, i.e. /// as known by the IR. llvm::JITTargetAddress addOrReplaceDefinition(llvm::StringRef Name,