diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index f01209cc73e52..0e9f04c8e402b 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -28,6 +28,7 @@ The following are definitely leaf locks (level 1), and must not try to acquire a > * gc_perm_lock > * flisp > * jl_in_stackwalk (Win32) +> * PM_mutex[i] > > > flisp itself is already threadsafe, this lock only protects the `jl_ast_context_list_t` pool diff --git a/src/ccall.cpp b/src/ccall.cpp index bbcc1a3ba075f..cf61d0103bf2d 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -40,7 +40,7 @@ static bool runtime_sym_gvs(jl_codegen_params_t &emission_context, LLVMContext & else { std::string name = "ccalllib_"; name += llvm::sys::path::filename(f_lib); - name += std::to_string(globalUnique++); + name += std::to_string(globalUniqueGeneratedNames++); runtime_lib = true; auto &libgv = emission_context.libMapGV[f_lib]; if (libgv.first == NULL) { @@ -60,7 +60,7 @@ static bool runtime_sym_gvs(jl_codegen_params_t &emission_context, LLVMContext & std::string name = "ccall_"; name += f_name; name += "_"; - name += std::to_string(globalUnique++); + name += std::to_string(globalUniqueGeneratedNames++); auto T_pvoidfunc = JuliaType::get_pvoidfunc_ty(M->getContext()); llvmgv = new GlobalVariable(*M, T_pvoidfunc, false, GlobalVariable::ExternalLinkage, @@ -169,7 +169,7 @@ static Value *runtime_sym_lookup( std::string gvname = "libname_"; gvname += f_name; gvname += "_"; - gvname += std::to_string(globalUnique++); + gvname += std::to_string(globalUniqueGeneratedNames++); llvmgv = new GlobalVariable(*jl_Module, T_pvoidfunc, false, GlobalVariable::ExternalLinkage, Constant::getNullValue(T_pvoidfunc), gvname); @@ -196,7 +196,7 @@ static GlobalVariable *emit_plt_thunk( libptrgv = prepare_global_in(M, libptrgv); llvmgv = prepare_global_in(M, llvmgv); std::string fname; - raw_string_ostream(fname) << "jlplt_" << f_name << "_" << globalUnique++; + raw_string_ostream(fname) << "jlplt_" << f_name << "_" << globalUniqueGeneratedNames++; Function *plt = Function::Create(functype, GlobalVariable::ExternalLinkage, fname, M); @@ -799,7 +799,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar // Make sure to find a unique name std::string ir_name; while (true) { - raw_string_ostream(ir_name) << (ctx.f->getName().str()) << "u" << globalUnique++; + raw_string_ostream(ir_name) << (ctx.f->getName().str()) << "u" << globalUniqueGeneratedNames++; if (jl_Module->getFunction(ir_name) == NULL) break; } diff --git a/src/codegen.cpp b/src/codegen.cpp index ca51b8dcaf5d2..8b3d22e7241a9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1058,11 +1058,47 @@ static const auto pointer_from_objref_func = new JuliaFunction{ }; static const auto jltuple_func = new JuliaFunction{XSTR(jl_f_tuple), get_func_sig, get_func_attrs}; -static std::map builtin_func_map; +static const auto &builtin_func_map() { + static std::map builtins = { { jl_f_is_addr, new JuliaFunction{XSTR(jl_f_is), get_func_sig, get_func_attrs} }, + { jl_f_typeof_addr, new JuliaFunction{XSTR(jl_f_typeof), get_func_sig, get_func_attrs} }, + { jl_f_sizeof_addr, new JuliaFunction{XSTR(jl_f_sizeof), get_func_sig, get_func_attrs} }, + { jl_f_issubtype_addr, new JuliaFunction{XSTR(jl_f_issubtype), get_func_sig, get_func_attrs} }, + { jl_f_isa_addr, new JuliaFunction{XSTR(jl_f_isa), get_func_sig, get_func_attrs} }, + { jl_f_typeassert_addr, new JuliaFunction{XSTR(jl_f_typeassert), get_func_sig, get_func_attrs} }, + { jl_f_ifelse_addr, new JuliaFunction{XSTR(jl_f_ifelse), get_func_sig, get_func_attrs} }, + { jl_f__apply_iterate_addr, new JuliaFunction{XSTR(jl_f__apply_iterate), get_func_sig, get_func_attrs} }, + { jl_f__apply_pure_addr, new JuliaFunction{XSTR(jl_f__apply_pure), get_func_sig, get_func_attrs} }, + { jl_f__call_latest_addr, new JuliaFunction{XSTR(jl_f__call_latest), get_func_sig, get_func_attrs} }, + { jl_f__call_in_world_addr, new JuliaFunction{XSTR(jl_f__call_in_world), get_func_sig, get_func_attrs} }, + { jl_f__call_in_world_total_addr, new JuliaFunction{XSTR(jl_f__call_in_world_total), get_func_sig, get_func_attrs} }, + { jl_f_throw_addr, new JuliaFunction{XSTR(jl_f_throw), get_func_sig, get_func_attrs} }, + { jl_f_tuple_addr, jltuple_func }, + { jl_f_svec_addr, new JuliaFunction{XSTR(jl_f_svec), get_func_sig, get_func_attrs} }, + { jl_f_applicable_addr, new JuliaFunction{XSTR(jl_f_applicable), get_func_sig, get_func_attrs} }, + { jl_f_invoke_addr, new JuliaFunction{XSTR(jl_f_invoke), get_func_sig, get_func_attrs} }, + { jl_f_invoke_kwsorter_addr, new JuliaFunction{XSTR(jl_f_invoke_kwsorter), get_func_sig, get_func_attrs} }, + { jl_f_isdefined_addr, new JuliaFunction{XSTR(jl_f_isdefined), get_func_sig, get_func_attrs} }, + { jl_f_getfield_addr, new JuliaFunction{XSTR(jl_f_getfield), get_func_sig, get_func_attrs} }, + { jl_f_setfield_addr, new JuliaFunction{XSTR(jl_f_setfield), get_func_sig, get_func_attrs} }, + { jl_f_swapfield_addr, new JuliaFunction{XSTR(jl_f_swapfield), get_func_sig, get_func_attrs} }, + { jl_f_modifyfield_addr, new JuliaFunction{XSTR(jl_f_modifyfield), get_func_sig, get_func_attrs} }, + { jl_f_fieldtype_addr, new JuliaFunction{XSTR(jl_f_fieldtype), get_func_sig, get_func_attrs} }, + { jl_f_nfields_addr, new JuliaFunction{XSTR(jl_f_nfields), get_func_sig, get_func_attrs} }, + { jl_f__expr_addr, new JuliaFunction{XSTR(jl_f__expr), get_func_sig, get_func_attrs} }, + { jl_f__typevar_addr, new JuliaFunction{XSTR(jl_f__typevar), get_func_sig, get_func_attrs} }, + { jl_f_arrayref_addr, new JuliaFunction{XSTR(jl_f_arrayref), get_func_sig, get_func_attrs} }, + { jl_f_const_arrayref_addr, new JuliaFunction{XSTR(jl_f_const_arrayref), get_func_sig, get_func_attrs} }, + { jl_f_arrayset_addr, new JuliaFunction{XSTR(jl_f_arrayset), get_func_sig, get_func_attrs} }, + { jl_f_arraysize_addr, new JuliaFunction{XSTR(jl_f_arraysize), get_func_sig, get_func_attrs} }, + { jl_f_apply_type_addr, new JuliaFunction{XSTR(jl_f_apply_type), get_func_sig, get_func_attrs} }, + { jl_f_donotdelete_addr, new JuliaFunction{XSTR(jl_f_donotdelete), get_func_sig, get_donotdelete_func_attrs} } + }; + return builtins; +} static const auto jl_new_opaque_closure_jlcall_func = new JuliaFunction{XSTR(jl_new_opaque_closure_jlcall), get_func_sig, get_func_attrs}; -static int globalUnique = 0; +static std::atomic globalUniqueGeneratedNames{0}; // --- code generation --- extern "C" { @@ -3512,8 +3548,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, // For now we emit this as a vararg call to the builtin // (which doesn't look at the arguments). In the future, // this should be an LLVM builtin. - auto it = builtin_func_map.find(jl_f_donotdelete_addr); - if (it == builtin_func_map.end()) { + auto it = builtin_func_map().find(jl_f_donotdelete_addr); + if (it == builtin_func_map().end()) { return false; } @@ -3768,7 +3804,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, const jl_cgval_t &lival, const } } if (need_to_emit) { - raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << globalUnique++; + raw_string_ostream(name) << (specsig ? "j_" : "j1_") << name_from_method_instance(mi) << "_" << globalUniqueGeneratedNames++; protoname = StringRef(name); } jl_returninfo_t::CallingConv cc = jl_returninfo_t::CallingConv::Boxed; @@ -3813,8 +3849,8 @@ static jl_cgval_t emit_invoke_modify(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_ if (f.constant && f.constant == jl_builtin_modifyfield) { if (emit_f_opfield(ctx, &ret, jl_builtin_modifyfield, argv, nargs - 1, &lival)) return ret; - auto it = builtin_func_map.find(jl_f_modifyfield_addr); - assert(it != builtin_func_map.end()); + auto it = builtin_func_map().find(jl_f_modifyfield_addr); + assert(it != builtin_func_map().end()); Value *oldnew = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, JLCALL_F_CC); return mark_julia_type(ctx, oldnew, true, rt); } @@ -3867,8 +3903,8 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt) } // special case for known builtin not handled by emit_builtin_call - auto it = builtin_func_map.find(jl_get_builtin_fptr(f.constant)); - if (it != builtin_func_map.end()) { + auto it = builtin_func_map().find(jl_get_builtin_fptr(f.constant)); + if (it != builtin_func_map().end()) { Value *ret = emit_jlcall(ctx, it->second, Constant::getNullValue(ctx.types().T_prjlvalue), &argv[1], nargs - 1, JLCALL_F_CC); return mark_julia_type(ctx, ret, true, rt); } @@ -5136,7 +5172,7 @@ static Function *emit_tojlinvoke(jl_code_instance_t *codeinst, Module *M, jl_cod { jl_codectx_t ctx(M->getContext(), params); std::string name; - raw_string_ostream(name) << "tojlinvoke" << globalUnique++; + raw_string_ostream(name) << "tojlinvoke" << globalUniqueGeneratedNames++; Function *f = Function::Create(ctx.types().T_jlfunc, GlobalVariable::InternalLinkage, name, M); @@ -5331,7 +5367,7 @@ static Function* gen_cfun_wrapper( } std::string funcName; - raw_string_ostream(funcName) << "jlcapi_" << name << "_" << globalUnique++; + raw_string_ostream(funcName) << "jlcapi_" << name << "_" << globalUniqueGeneratedNames++; Module *M = into; AttributeList attributes = sig.attributes; @@ -6491,7 +6527,7 @@ static std::pair, jl_llvm_functions_t> if (unadorned_name[0] == '@') unadorned_name++; #endif - funcName << unadorned_name << "_" << globalUnique++; + funcName << unadorned_name << "_" << globalUniqueGeneratedNames++; declarations.specFunctionObject = funcName.str(); // allocate Function declarations and wrapper objects @@ -6532,7 +6568,7 @@ static std::pair, jl_llvm_functions_t> }(); std::string wrapName; - raw_string_ostream(wrapName) << "jfptr_" << unadorned_name << "_" << globalUnique++; + raw_string_ostream(wrapName) << "jfptr_" << unadorned_name << "_" << globalUniqueGeneratedNames++; declarations.functionObject = wrapName; (void)gen_invoke_wrapper(lam, jlrettype, returninfo, retarg, declarations.functionObject, M, ctx.emission_context); } @@ -8094,7 +8130,7 @@ static void init_jit_functions(void) add_named_global(jldeclareconst_func, &jl_declare_constant); add_named_global(jlgetbindingorerror_func, &jl_get_binding_or_error); add_named_global(jlboundp_func, &jl_boundp); - for (auto it : builtin_func_map) + for (auto it : builtin_func_map()) add_named_global(it.second, it.first); add_named_global(jlapplygeneric_func, &jl_apply_generic); add_named_global(jlinvoke_func, &jl_invoke); @@ -8158,8 +8194,6 @@ static void init_jit_functions(void) #undef BOX_F } -char jl_using_gdb_jitevents = 0; - #ifdef JL_USE_INTEL_JITEVENTS char jl_using_intel_jitevents; // Non-zero if running under Intel VTune Amplifier #endif @@ -8176,42 +8210,6 @@ void jl_init_debuginfo(void); extern "C" void jl_init_llvm(void) { - builtin_func_map = - { { jl_f_is_addr, new JuliaFunction{XSTR(jl_f_is), get_func_sig, get_func_attrs} }, - { jl_f_typeof_addr, new JuliaFunction{XSTR(jl_f_typeof), get_func_sig, get_func_attrs} }, - { jl_f_sizeof_addr, new JuliaFunction{XSTR(jl_f_sizeof), get_func_sig, get_func_attrs} }, - { jl_f_issubtype_addr, new JuliaFunction{XSTR(jl_f_issubtype), get_func_sig, get_func_attrs} }, - { jl_f_isa_addr, new JuliaFunction{XSTR(jl_f_isa), get_func_sig, get_func_attrs} }, - { jl_f_typeassert_addr, new JuliaFunction{XSTR(jl_f_typeassert), get_func_sig, get_func_attrs} }, - { jl_f_ifelse_addr, new JuliaFunction{XSTR(jl_f_ifelse), get_func_sig, get_func_attrs} }, - { jl_f__apply_iterate_addr, new JuliaFunction{XSTR(jl_f__apply_iterate), get_func_sig, get_func_attrs} }, - { jl_f__apply_pure_addr, new JuliaFunction{XSTR(jl_f__apply_pure), get_func_sig, get_func_attrs} }, - { jl_f__call_latest_addr, new JuliaFunction{XSTR(jl_f__call_latest), get_func_sig, get_func_attrs} }, - { jl_f__call_in_world_addr, new JuliaFunction{XSTR(jl_f__call_in_world), get_func_sig, get_func_attrs} }, - { jl_f__call_in_world_total_addr, new JuliaFunction{XSTR(jl_f__call_in_world_total), get_func_sig, get_func_attrs} }, - { jl_f_throw_addr, new JuliaFunction{XSTR(jl_f_throw), get_func_sig, get_func_attrs} }, - { jl_f_tuple_addr, jltuple_func }, - { jl_f_svec_addr, new JuliaFunction{XSTR(jl_f_svec), get_func_sig, get_func_attrs} }, - { jl_f_applicable_addr, new JuliaFunction{XSTR(jl_f_applicable), get_func_sig, get_func_attrs} }, - { jl_f_invoke_addr, new JuliaFunction{XSTR(jl_f_invoke), get_func_sig, get_func_attrs} }, - { jl_f_invoke_kwsorter_addr, new JuliaFunction{XSTR(jl_f_invoke_kwsorter), get_func_sig, get_func_attrs} }, - { jl_f_isdefined_addr, new JuliaFunction{XSTR(jl_f_isdefined), get_func_sig, get_func_attrs} }, - { jl_f_getfield_addr, new JuliaFunction{XSTR(jl_f_getfield), get_func_sig, get_func_attrs} }, - { jl_f_setfield_addr, new JuliaFunction{XSTR(jl_f_setfield), get_func_sig, get_func_attrs} }, - { jl_f_swapfield_addr, new JuliaFunction{XSTR(jl_f_swapfield), get_func_sig, get_func_attrs} }, - { jl_f_modifyfield_addr, new JuliaFunction{XSTR(jl_f_modifyfield), get_func_sig, get_func_attrs} }, - { jl_f_fieldtype_addr, new JuliaFunction{XSTR(jl_f_fieldtype), get_func_sig, get_func_attrs} }, - { jl_f_nfields_addr, new JuliaFunction{XSTR(jl_f_nfields), get_func_sig, get_func_attrs} }, - { jl_f__expr_addr, new JuliaFunction{XSTR(jl_f__expr), get_func_sig, get_func_attrs} }, - { jl_f__typevar_addr, new JuliaFunction{XSTR(jl_f__typevar), get_func_sig, get_func_attrs} }, - { jl_f_arrayref_addr, new JuliaFunction{XSTR(jl_f_arrayref), get_func_sig, get_func_attrs} }, - { jl_f_const_arrayref_addr, new JuliaFunction{XSTR(jl_f_const_arrayref), get_func_sig, get_func_attrs} }, - { jl_f_arrayset_addr, new JuliaFunction{XSTR(jl_f_arrayset), get_func_sig, get_func_attrs} }, - { jl_f_arraysize_addr, new JuliaFunction{XSTR(jl_f_arraysize), get_func_sig, get_func_attrs} }, - { jl_f_apply_type_addr, new JuliaFunction{XSTR(jl_f_apply_type), get_func_sig, get_func_attrs} }, - { jl_f_donotdelete_addr, new JuliaFunction{XSTR(jl_f_donotdelete), get_func_sig, get_donotdelete_func_attrs} } - }; - jl_default_debug_info_kind = (int) DICompileUnit::DebugEmissionKind::FullDebug; imaging_mode = jl_options.image_codegen || (jl_generating_output() && !jl_options.incremental); jl_default_cgparams.generic_context = jl_nothing; @@ -8256,13 +8254,14 @@ extern "C" void jl_init_llvm(void) jl_ExecutionEngine = new JuliaOJIT(new LLVMContext()); + bool jl_using_gdb_jitevents = false; // Register GDB event listener #if defined(JL_DEBUG_BUILD) - jl_using_gdb_jitevents = 1; + jl_using_gdb_jitevents = true; # else const char *jit_gdb = getenv("ENABLE_GDBLISTENER"); if (jit_gdb && atoi(jit_gdb)) { - jl_using_gdb_jitevents = 1; + jl_using_gdb_jitevents = true; } #endif if (jl_using_gdb_jitevents) @@ -8318,10 +8317,7 @@ extern "C" JL_DLLEXPORT void jl_init_codegen_impl(void) { jl_init_llvm(); // Now that the execution engine exists, initialize all modules - jl_init_jit(); init_jit_functions(); - - jl_init_intrinsic_functions_codegen(); } extern "C" JL_DLLEXPORT void jl_teardown_codegen_impl() diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 4ca4794ab7733..2c2f82bad8531 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -14,7 +14,11 @@ FunctionType *get_intr_args3(LLVMContext &C) { return FunctionType::get(JuliaTyp FunctionType *get_intr_args4(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); } FunctionType *get_intr_args5(LLVMContext &C) { return FunctionType::get(JuliaType::get_prjlvalue_ty(C), {JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C), JuliaType::get_prjlvalue_ty(C)}, false); } -static JuliaFunction *runtime_func[num_intrinsics] = { +const auto &runtime_func() { + static struct runtime_funcs_t { + std::array runtime_func; + runtime_funcs_t() : + runtime_func{ #define ADD_I(name, nargs) new JuliaFunction{XSTR(jl_##name), get_intr_args##nargs, nullptr}, #define ADD_HIDDEN ADD_I #define ALIAS(alias, base) nullptr, @@ -22,12 +26,8 @@ static JuliaFunction *runtime_func[num_intrinsics] = { #undef ADD_I #undef ADD_HIDDEN #undef ALIAS -}; - -static bool float_func[num_intrinsics]; - -static void jl_init_intrinsic_functions_codegen(void) -{ + } + { #define ADD_I(name, nargs) #define ADD_HIDDEN(name, nargs) #define ALIAS(alias, base) runtime_func[alias] = runtime_func[base]; @@ -35,38 +35,50 @@ static void jl_init_intrinsic_functions_codegen(void) #undef ADD_I #undef ADD_HIDDEN #undef ALIAS + } + } runtime_funcs; + return runtime_funcs.runtime_func; +} + +const auto &float_func() { + static struct float_funcs_t { + std::bitset float_func; + float_funcs_t() { + float_func[neg_float] = true; + float_func[neg_float_fast] = true; + float_func[add_float] = true; + float_func[sub_float] = true; + float_func[mul_float] = true; + float_func[div_float] = true; + float_func[rem_float] = true; + float_func[add_float_fast] = true; + float_func[sub_float_fast] = true; + float_func[mul_float_fast] = true; + float_func[div_float_fast] = true; + float_func[rem_float_fast] = true; + float_func[fma_float] = true; + float_func[muladd_float] = true; + float_func[eq_float] = true; + float_func[ne_float] = true; + float_func[lt_float] = true; + float_func[le_float] = true; + float_func[eq_float_fast] = true; + float_func[ne_float_fast] = true; + float_func[lt_float_fast] = true; + float_func[le_float_fast] = true; + float_func[fpiseq] = true; + float_func[abs_float] = true; + float_func[copysign_float] = true; + float_func[ceil_llvm] = true; + float_func[floor_llvm] = true; + float_func[trunc_llvm] = true; + float_func[rint_llvm] = true; + float_func[sqrt_llvm] = true; + float_func[sqrt_llvm_fast] = true; + } + } float_funcs; - float_func[neg_float] = true; - float_func[neg_float_fast] = true; - float_func[add_float] = true; - float_func[sub_float] = true; - float_func[mul_float] = true; - float_func[div_float] = true; - float_func[rem_float] = true; - float_func[add_float_fast] = true; - float_func[sub_float_fast] = true; - float_func[mul_float_fast] = true; - float_func[div_float_fast] = true; - float_func[rem_float_fast] = true; - float_func[fma_float] = true; - float_func[muladd_float] = true; - float_func[eq_float] = true; - float_func[ne_float] = true; - float_func[lt_float] = true; - float_func[le_float] = true; - float_func[eq_float_fast] = true; - float_func[ne_float_fast] = true; - float_func[lt_float_fast] = true; - float_func[le_float_fast] = true; - float_func[fpiseq] = true; - float_func[abs_float] = true; - float_func[copysign_float] = true; - float_func[ceil_llvm] = true; - float_func[floor_llvm] = true; - float_func[trunc_llvm] = true; - float_func[rint_llvm] = true; - float_func[sqrt_llvm] = true; - float_func[sqrt_llvm_fast] = true; + return float_funcs.float_func; } extern "C" @@ -423,7 +435,7 @@ static jl_value_t *staticeval_bitstype(const jl_cgval_t &targ) static jl_cgval_t emit_runtime_call(jl_codectx_t &ctx, JL_I::intrinsic f, const jl_cgval_t *argv, size_t nargs) { - Function *func = prepare_call(runtime_func[f]); + Function *func = prepare_call(runtime_func()[f]); Value **argvalues = (Value**)alloca(sizeof(Value*) * nargs); for (size_t i = 0; i < nargs; ++i) { argvalues[i] = boxed(ctx, argv[i]); @@ -1177,7 +1189,7 @@ static jl_cgval_t emit_intrinsic(jl_codectx_t &ctx, intrinsic f, jl_value_t **ar if (!jl_is_primitivetype(xinfo.typ)) return emit_runtime_call(ctx, f, argv, nargs); Type *xtyp = bitstype_to_llvm(xinfo.typ, ctx.builder.getContext()); - if (float_func[f]) + if (float_func()[f]) xtyp = FLOATT(xtyp); else xtyp = INTT(xtyp); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index bc8d5eb216130..ac8ef9591a563 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -52,8 +52,6 @@ using namespace llvm; #define DEBUG_TYPE "jitlayers" -void jl_init_jit(void) { } - // Snooping on which functions are being compiled, and how long it takes JL_STREAM *dump_compiles_stream = NULL; extern "C" JL_DLLEXPORT @@ -476,7 +474,7 @@ static auto countBasicBlocks(const Function &F) } OptimizerResultT JuliaOJIT::OptimizerT::operator()(orc::ThreadSafeModule TSM, orc::MaterializationResponsibility &R) { - TSM.withModuleDo([&](Module &M){ + TSM.withModuleDo([&](Module &M) { uint64_t start_time = 0; if (dump_llvm_opt_stream != NULL) { // Print LLVM function statistics _before_ optimization @@ -500,7 +498,11 @@ OptimizerResultT JuliaOJIT::OptimizerT::operator()(orc::ThreadSafeModule TSM, or JL_TIMING(LLVM_OPT); - PM.run(M); + { + //Lock around our pass manager + std::lock_guard lock(this->mutex); + PM.run(M); + } uint64_t end_time = 0; if (dump_llvm_opt_stream != NULL) { @@ -937,10 +939,10 @@ JuliaOJIT::JuliaOJIT(LLVMContext *LLVMCtx) CompileLayer2(ES, ObjectLayer, std::make_unique(createJTMBFromTM(*TM, 2))), CompileLayer3(ES, ObjectLayer, std::make_unique(createJTMBFromTM(*TM, 3))), OptimizeLayers{ - {ES, CompileLayer0, OptimizerT(PM0, 0)}, - {ES, CompileLayer1, OptimizerT(PM1, 1)}, - {ES, CompileLayer2, OptimizerT(PM2, 2)}, - {ES, CompileLayer3, OptimizerT(PM3, 3)}, + {ES, CompileLayer0, OptimizerT(PM0, PM_mutexes[0], 0)}, + {ES, CompileLayer1, OptimizerT(PM1, PM_mutexes[1], 1)}, + {ES, CompileLayer2, OptimizerT(PM2, PM_mutexes[2], 2)}, + {ES, CompileLayer3, OptimizerT(PM3, PM_mutexes[3], 3)}, }, OptSelLayer(OptimizeLayers) { @@ -1088,9 +1090,9 @@ uint64_t JuliaOJIT::getFunctionAddress(StringRef Name) return cantFail(addr.getAddress()); } -static int globalUniqueGeneratedNames; StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_code_instance_t *codeinst) { + static int globalUnique = 0; std::string *fname = &ReverseLocalSymbolTable[(void*)(uintptr_t)Addr]; if (fname->empty()) { std::string string_fname; @@ -1110,7 +1112,7 @@ StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_code_instance_t *cod stream_fname << "jlsys_"; } const char* unadorned_name = jl_symbol_name(codeinst->def->def.method->name); - stream_fname << unadorned_name << "_" << globalUniqueGeneratedNames++; + stream_fname << unadorned_name << "_" << globalUnique++; *fname = std::move(stream_fname.str()); // store to ReverseLocalSymbolTable addGlobalMapping(*fname, Addr); } diff --git a/src/jitlayers.h b/src/jitlayers.h index 94e73665b3fba..16f6eb6bc372f 100644 --- a/src/jitlayers.h +++ b/src/jitlayers.h @@ -167,9 +167,6 @@ static const inline char *name_from_method_instance(jl_method_instance_t *li) return jl_is_method(li->def.method) ? jl_symbol_name(li->def.method->name) : "top-level scope"; } - -void jl_init_jit(void); - typedef JITSymbol JL_JITSymbol; // The type that is similar to SymbolInfo on LLVM 4.0 is actually // `JITEvaluatedSymbol`. However, we only use this type when a JITSymbol @@ -191,12 +188,13 @@ class JuliaOJIT { typedef object::OwningBinary OwningObj; private: struct OptimizerT { - OptimizerT(legacy::PassManager &PM, int optlevel) : optlevel(optlevel), PM(PM) {} + OptimizerT(legacy::PassManager &PM, std::mutex &mutex, int optlevel) : optlevel(optlevel), PM(PM), mutex(mutex) {} OptimizerResultT operator()(orc::ThreadSafeModule M, orc::MaterializationResponsibility &R); private: int optlevel; legacy::PassManager &PM; + std::mutex &mutex; }; // Custom object emission notification handler for the JuliaOJIT template @@ -252,6 +250,7 @@ class JuliaOJIT { legacy::PassManager PM1; legacy::PassManager PM2; legacy::PassManager PM3; + std::mutex PM_mutexes[4]; std::unique_ptr TMs[4]; orc::ThreadSafeContext TSCtx;