From b68237ded78c7d504dd20c051fc32dc3d5f394bd Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 1 Feb 2016 23:21:13 -0500 Subject: [PATCH] fix jl_get_llvmf functionality for OrcJIT / MCJIT the logic was not equivalent to the logic for the old JIT, and thus was not going to work. this make both better by looking only at whether there is known to be debug info for this llvmf fixes #14592 --- src/cgutils.cpp | 5 -- src/codegen.cpp | 137 +++++++++++++++++++------------------------ src/debuginfo.cpp | 40 ++++++------- src/jitlayers.cpp | 27 +++++---- src/julia_internal.h | 2 +- 5 files changed, 96 insertions(+), 115 deletions(-) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 47e751b754df8..c7602e535a52d 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -407,11 +407,6 @@ class FunctionMover : public ValueMaterializer // Check whether we already emitted it once if (emitted_function_symtab.find(shadow) != emitted_function_symtab.end()) return InjectFunctionProto(F); - uint64_t addr = jl_mcjmm->getSymbolAddress(F->getName()); - if (addr) { - emitted_function_symtab[shadow] = addr; - return InjectFunctionProto(F); - } Function *oldF = destModule->getFunction(F->getName()); if (oldF) diff --git a/src/codegen.cpp b/src/codegen.cpp index ac1e9ce456d07..6107f1add7397 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -203,7 +203,6 @@ ExecutionEngine *jl_ExecutionEngine; static Module *shadow_module; static Module *builtins_module; static Module *active_module; -static RTDyldMemoryManager *jl_mcjmm; #define jl_Module (builder.GetInsertBlock()->getParent()->getParent()) #else static Module *jl_Module; @@ -1002,9 +1001,6 @@ static uint64_t getAddressForOrCompileFunction(llvm::Function *llvmf) #ifdef JL_DEBUG_BUILD llvm::raw_fd_ostream out(1,false); #endif - uint64_t addr = jl_mcjmm->getSymbolAddress(llvmf->getName()); - if (addr) - return addr; Function *ActiveF = active_module->getFunction(llvmf->getName()); // Must have been in a prior module. Safe to ask the execution engine // to emit it. @@ -1043,7 +1039,7 @@ static uint64_t getAddressForOrCompileFunction(llvm::Function *llvmf) #endif jl_finalize_module(active_module); } - addr = jl_ExecutionEngine->getFunctionAddress(llvmf->getName()); + uint64_t addr = jl_ExecutionEngine->getFunctionAddress(llvmf->getName()); assert(addr != 0); if (!imaging_mode) { active_module = new Module("julia", jl_LLVMContext); @@ -1298,6 +1294,8 @@ extern int jl_get_llvmf_info(uint64_t fptr, uint64_t *symsize, uint64_t *slide, #endif ); +extern "C" +uint64_t jl_getUnwindInfo(uint64_t dwAddr); // Get pointer to llvm::Function instance, compiling if necessary extern "C" JL_DLLEXPORT @@ -1324,88 +1322,78 @@ void *jl_get_llvmf(jl_function_t *f, jl_tupletype_t *tt, bool getwrapper, bool g linfo = jl_get_unspecialized(linfo); } -#if defined(USE_ORCJIT) || defined(USE_MCJIT) - if (linfo->functionObjects.functionObject == NULL && linfo->functionObjects.specFunctionObject == NULL) { - jl_compile_linfo(linfo, NULL); - } - if (getdeclarations) { - JL_GC_POP(); - if (getwrapper || linfo->functionObjects.specFunctionObject == NULL) - return linfo->functionObjects.functionObject; + if (!getdeclarations) { + Function *llvmDecl = nullptr; + if (!getwrapper && linfo->functionObjects.specFunctionObject != NULL) + llvmDecl = (Function*)linfo->functionObjects.specFunctionObject; else - return linfo->functionObjects.specFunctionObject; - } - - Function *llvmDecl = nullptr; - if (!getwrapper && linfo->functionObjects.specFunctionObject != NULL) - llvmDecl = (Function*)linfo->functionObjects.specFunctionObject; - else - llvmDecl = (Function*)linfo->functionObjects.functionObject; - - Function *llvmf = active_module->getFunction(llvmDecl->getName()); - // Not in active module anymore, recompile - // Now that in either case, we need to run the FPM manually, - // since this is now usually done as part of object emission - if (!llvmf) { - Function *other; - jl_llvm_functions_t declarations; - emit_function(linfo, nullptr, &declarations, nullptr); - if (getwrapper || !declarations.specFunctionObject) { - llvmf = (llvm::Function*)declarations.functionObject; - other = (llvm::Function*)declarations.specFunctionObject; + llvmDecl = (Function*)linfo->functionObjects.functionObject; +#if defined(USE_ORCJIT) || defined(USE_MCJIT) + Function *llvmf = llvmDecl ? active_module->getFunction(llvmDecl->getName()) : NULL; + // Note that in either case, we need to run the FPM manually, + // since this is now usually done as part of object emission +#else + Function *llvmf = llvmDecl && !llvmDecl->isDeclaration() ? llvmDecl : NULL; +#endif + if (!llvmf) { + Function *other; + jl_llvm_functions_t declarations; + emit_function(linfo, nullptr, &declarations, nullptr); + if (getwrapper || !declarations.specFunctionObject) { + llvmf = (llvm::Function*)declarations.functionObject; + other = (llvm::Function*)declarations.specFunctionObject; + } + else { + llvmf = (llvm::Function*)declarations.specFunctionObject; + other = (llvm::Function*)declarations.functionObject; + } + if (other) + other->eraseFromParent(); +#if defined(USE_ORCJIT) || defined(USE_MCJIT) + FPM->run(*llvmf); +#endif + llvmf->removeFromParent(); + if (llvmDecl) + llvmf->setName(llvmDecl->getName()); } else { - llvmf = (llvm::Function*)declarations.specFunctionObject; - other = (llvm::Function*)declarations.functionObject; - } - if (other) - other->eraseFromParent(); - FPM->run(*llvmf); - llvmf->removeFromParent(); - } - else { - ValueToValueMapTy VMap; - llvmf = CloneFunction(llvmf,VMap,false); - active_module->getFunctionList().push_back(llvmf); - FPM->run(*llvmf); - llvmf->removeFromParent(); - } - JL_GC_POP(); - return llvmf; -#else - if (linfo->functionObjects.specFunctionObject != NULL) { - // found in the system image: force a recompile - Function *llvmf = (Function*)linfo->functionObjects.specFunctionObject; - if (llvmf->isDeclaration()) { - linfo->functionObjects.specFunctionObject = NULL; - linfo->functionObjects.functionObject = NULL; + ValueToValueMapTy VMap; + llvmf = CloneFunction(llvmf, VMap, false); +#if defined(USE_ORCJIT) || defined(USE_MCJIT) + active_module->getFunctionList().push_back(llvmf); + FPM->run(*llvmf); + llvmf->removeFromParent(); +#endif } + JL_GC_POP(); + return llvmf; } - if (linfo->functionObjects.functionObject != NULL) { + + if (linfo->fptr && !jl_getUnwindInfo((uintptr_t)linfo->fptr)) { + // Not in in the current ExecutionEngine // found in the system image: force a recompile - Function *llvmf = (Function*)linfo->functionObjects.functionObject; - if (llvmf->isDeclaration()) { - linfo->functionObjects.specFunctionObject = NULL; - linfo->functionObjects.functionObject = NULL; - } + linfo->functionObjects.specFunctionObject = NULL; + linfo->functionObjects.functionObject = NULL; + linfo->fptr = NULL; } - if (linfo->functionObjects.functionObject == NULL && - linfo->functionObjects.specFunctionObject == NULL) { + if (linfo->functionObjects.functionObject == NULL) { jl_compile_linfo(linfo, NULL); } - JL_GC_POP(); Function *llvmf; - if (!getwrapper && linfo->functionObjects.specFunctionObject != NULL) + if (!getwrapper && linfo->functionObjects.specFunctionObject != NULL) { llvmf = (Function*)linfo->functionObjects.specFunctionObject; - else - llvmf = (Function*)linfo->functionObjects.functionObject; - if (getdeclarations) - return llvmf; + } else { - ValueToValueMapTy VMap; - return CloneFunction(llvmf,VMap,false); + llvmf = (Function*)linfo->functionObjects.functionObject; + } +#if !defined(USE_ORCJIT) && !defined(USE_MCJIT) + if (!getdeclarations) { + ValueToValueMapTy VMap; + llvmf = CloneFunction(llvmf, VMap, false); } #endif + JL_GC_POP(); + return llvmf; } extern "C" JL_DLLEXPORT @@ -5990,9 +5978,6 @@ extern "C" void jl_init_codegen(void) // turn on JIT support for libunwind to walk the stack options.JITExceptionHandling = 1; #endif -#ifdef USE_MCJIT - jl_mcjmm = new SectionMemoryManager(); -#endif #ifdef LLVM36 EngineBuilder eb((std::unique_ptr(engine_module))); diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index 44eaa2edd3a02..7ef9c270102b8 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -1154,23 +1154,36 @@ RTDyldMemoryManager *createRTDyldMemoryManagerOSX() #endif -#if defined(_OS_WINDOWS_) #ifdef USE_MCJIT extern "C" -DWORD64 jl_getUnwindInfo(ULONG64 dwAddr) +uint64_t jl_getUnwindInfo(uint64_t dwAddr) { std::map &objmap = jl_jit_events->getObjectMap(); std::map::iterator it = objmap.lower_bound(dwAddr); - DWORD64 ipstart = 0; // ip of the first instruction in the function (if found) + uint64_t ipstart = 0; // ip of the first instruction in the function (if found) if (it != objmap.end() && (intptr_t)(*it).first + (*it).second.size > dwAddr) { - ipstart = (DWORD64)(intptr_t)(*it).first; + ipstart = (uint64_t)(intptr_t)(*it).first; } uv_rwlock_rdunlock(&threadsafe); return ipstart; } +#else +extern "C" +uint64_t jl_getUnwindInfo(uint64_t dwAddr) +{ + std::map &info = jl_jit_events->getMap(); + std::map::iterator it = info.lower_bound(dwAddr); + uint64_t ipstart = 0; // ip of the first instruction in the function (if found) + if (it != info.end() && (intptr_t)(*it).first + (*it).second.lengthAdr > dwAddr) { + ipstart = (uint64_t)(intptr_t)(*it).first; + } + uv_rwlock_rdunlock(&threadsafe); + return ipstart; +} +#endif -#else //ifdef USE_MCJIT -#if defined(_CPU_X86_64_) + +#if defined(_OS_WINDOWS_) && !defined(USE_MCJIT) && defined(_CPU_X86_64_) // Custom memory manager for exception handling on Windows // we overallocate 48 bytes at the end of each function // for unwind information (see NotifyFunctionEmitted) @@ -1258,19 +1271,4 @@ JITMemoryManager *createJITMemoryManagerWin() { return new JITMemoryManagerWin(); } -#else -extern "C" -DWORD64 jl_getUnwindInfo(ULONG64 dwAddr) -{ - std::map &info = jl_jit_events->getMap(); - std::map::iterator it = info.lower_bound(dwAddr); - DWORD64 ipstart = 0; // ip of the first instruction in the function (if found) - if (it != info.end() && (intptr_t)(*it).first + (*it).second.lengthAdr > dwAddr) { - ipstart = (DWORD64)(intptr_t)(*it).first; - } - uv_rwlock_rdunlock(&threadsafe); - return ipstart; -} -#endif -#endif #endif diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 349f7ec12c830..2bf87c3e7b219 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -330,12 +330,8 @@ class JuliaOJIT { [&](const std::string &Name) { // TODO: consider moving the FunctionMover resolver here // Step 0: ObjectLinkingLayer has checked whether it is in the current module - // Step 1: Check against list of known external globals - GlobalSymbolTableT::const_iterator pos = GlobalSymbolTable.find(Name); - if (pos != GlobalSymbolTable.end()) - return RuntimeDyld::SymbolInfo((intptr_t)pos->second, JITSymbolFlags::Exported); - // Step 2: Search all previously emitted symbols - if (auto Sym = findSymbol(Name)) + // Step 1: See if it's something known to the ExecutionEngine + if (auto Sym = findSymbol(Name, true)) return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags()); // Step 2: Search the program symbols @@ -355,27 +351,34 @@ class JuliaOJIT { void removeModule(ModuleHandleT H) { CompileLayer->removeModuleSet(H); } - orc::JITSymbol findSymbol(const std::string &Name) + orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { - return CompileLayer->findSymbol(Name, true); + if (ExportedSymbolsOnly) { + // Step 1: Check against list of known external globals + GlobalSymbolTableT::const_iterator pos = GlobalSymbolTable.find(Name); + if (pos != GlobalSymbolTable.end()) + return orc::JITSymbol((uintptr_t)pos->second, JITSymbolFlags::Exported); + } + // Step 2: Search all previously emitted symbols + return CompileLayer->findSymbol(Name, ExportedSymbolsOnly); } orc::JITSymbol findUnmangledSymbol(const std::string Name) { - return findSymbol(mangle(Name)); + return findSymbol(mangle(Name), true); } uint64_t getGlobalValueAddress(const std::string &Name) { - return CompileLayer->findSymbol(mangle(Name), false).getAddress(); + return findSymbol(mangle(Name), false).getAddress(); } uint64_t getFunctionAddress(const std::string &Name) { - return CompileLayer->findSymbol(mangle(Name), false).getAddress(); + return findSymbol(mangle(Name), false).getAddress(); } - uint64_t FindFunctionNamed(const std::string &Name) + Function *FindFunctionNamed(const std::string &Name) { return 0; // Functions are not kept around } diff --git a/src/julia_internal.h b/src/julia_internal.h index efc6f40893181..b8ba32de3450f 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -268,10 +268,10 @@ jl_value_t *skip_meta(jl_array_t *body); int has_meta(jl_array_t *body, jl_sym_t *sym); // backtraces +uint64_t jl_getUnwindInfo(uint64_t dwBase); #ifdef _OS_WINDOWS_ extern HANDLE hMainThread; typedef CONTEXT *bt_context_t; -DWORD64 jl_getUnwindInfo(ULONG64 dwBase); extern volatile int jl_in_stackwalk; #else #define UNW_LOCAL_ONLY