Skip to content

Commit

Permalink
Increase thread safety/constify various globals
Browse files Browse the repository at this point in the history
  • Loading branch information
pchintalapudi committed Mar 4, 2022
1 parent c3d7edc commit 7788e7d
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 109 deletions.
1 change: 1 addition & 0 deletions doc/src/devdocs/locks.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
110 changes: 53 additions & 57 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,11 +1056,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<jl_fptr_args_t, JuliaFunction*> builtin_func_map;
static const auto &builtin_func_map() {
static std::map<jl_fptr_args_t, JuliaFunction*> 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<int> globalUniqueGeneratedNames{0};

// --- code generation ---
extern "C" {
Expand Down Expand Up @@ -3478,8 +3514,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;
}

Expand Down Expand Up @@ -3734,7 +3770,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;
Expand Down Expand Up @@ -3779,8 +3815,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);
}
Expand Down Expand Up @@ -3833,8 +3869,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);
}
Expand Down Expand Up @@ -5088,7 +5124,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);
Expand Down Expand Up @@ -5283,7 +5319,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;
Expand Down Expand Up @@ -6442,7 +6478,7 @@ static std::pair<std::unique_ptr<Module>, 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
Expand Down Expand Up @@ -6483,7 +6519,7 @@ static std::pair<std::unique_ptr<Module>, 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);
}
Expand Down Expand Up @@ -8045,7 +8081,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);
Expand Down Expand Up @@ -8108,8 +8144,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
Expand All @@ -8126,42 +8160,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;
Expand Down Expand Up @@ -8206,13 +8204,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)
Expand Down Expand Up @@ -8268,10 +8267,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()
Expand Down
92 changes: 52 additions & 40 deletions src/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,59 +14,71 @@ 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<JuliaFunction *, num_intrinsics> 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,
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];
INTRINSICS
#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<num_intrinsics> 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"
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 7788e7d

Please sign in to comment.