@@ -1134,6 +1134,7 @@ class function_sig_t {
11341134 AttributeList attributes; // vector of function call site attributes
11351135 Type *lrt; // input parameter of the llvm return type (from julia_struct_to_llvm)
11361136 bool retboxed; // input parameter indicating whether lrt is jl_value_t*
1137+ bool gc_safe; // input parameter indicating whether the call is safe to execute concurrently to GC
11371138 Type *prt; // out parameter of the llvm return type for the function signature
11381139 int sret; // out parameter for indicating whether return value has been moved to the first argument position
11391140 std::string err_msg;
@@ -1146,8 +1147,8 @@ class function_sig_t {
11461147 size_t nreqargs; // number of required arguments in ccall function definition
11471148 jl_codegen_params_t *ctx;
11481149
1149- function_sig_t (const char *fname, Type *lrt, jl_value_t *rt, bool retboxed, jl_svec_t *at, jl_unionall_t *unionall_env, size_t nreqargs, CallingConv::ID cc, bool llvmcall, jl_codegen_params_t *ctx)
1150- : lrt(lrt), retboxed(retboxed),
1150+ function_sig_t (const char *fname, Type *lrt, jl_value_t *rt, bool retboxed, bool gc_safe, jl_svec_t *at, jl_unionall_t *unionall_env, size_t nreqargs, CallingConv::ID cc, bool llvmcall, jl_codegen_params_t *ctx)
1151+ : lrt(lrt), retboxed(retboxed), gc_safe(gc_safe),
11511152 prt (NULL ), sret(0 ), cc(cc), llvmcall(llvmcall),
11521153 at(at), rt(rt), unionall_env(unionall_env),
11531154 nccallargs(jl_svec_len(at)), nreqargs(nreqargs),
@@ -1295,6 +1296,9 @@ std::string generate_func_sig(const char *fname)
12951296 RetAttrs = RetAttrs.addAttribute (LLVMCtx, Attribute::NonNull);
12961297 if (rt == jl_bottom_type)
12971298 FnAttrs = FnAttrs.addAttribute (LLVMCtx, Attribute::NoReturn);
1299+ if (gc_safe)
1300+ FnAttrs = FnAttrs.addAttribute (LLVMCtx, " julia.gc_safe" );
1301+
12981302 assert (attributes.isEmpty ());
12991303 attributes = AttributeList::get (LLVMCtx, FnAttrs, RetAttrs, paramattrs);
13001304 return " " ;
@@ -1412,7 +1416,7 @@ static const std::string verify_ccall_sig(jl_value_t *&rt, jl_value_t *at,
14121416
14131417const int fc_args_start = 6 ;
14141418
1415- // Expr(:foreigncall, pointer, rettype, (argtypes...), nreq, [cconv | (cconv, effects)], args..., roots...)
1419+ // Expr(:foreigncall, pointer, rettype, (argtypes...), nreq, gc_safe, [cconv | (cconv, effects)], args..., roots...)
14161420static jl_cgval_t emit_ccall (jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
14171421{
14181422 JL_NARGSV (ccall, 5 );
@@ -1424,11 +1428,15 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
14241428 assert (jl_is_quotenode (args[5 ]));
14251429 jl_value_t *jlcc = jl_quotenode_value (args[5 ]);
14261430 jl_sym_t *cc_sym = NULL ;
1431+ // TODO: Can we introduce a intrinsic token = @julia.gc_safe_begin()
1432+ // and "grow" gc safe regions so that we minimize the overhead?
1433+ bool gc_safe = false ;
14271434 if (jl_is_symbol (jlcc)) {
14281435 cc_sym = (jl_sym_t *)jlcc;
14291436 }
14301437 else if (jl_is_tuple (jlcc)) {
14311438 cc_sym = (jl_sym_t *)jl_get_nth_field_noalloc (jlcc, 0 );
1439+ gc_safe = jl_unbox_bool (jl_get_nth_field_checked (jlcc, 2 ));
14321440 }
14331441 assert (jl_is_symbol (cc_sym));
14341442 native_sym_arg_t symarg = {};
@@ -1547,7 +1555,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
15471555 }
15481556 if (rt != args[2 ] && rt != (jl_value_t *)jl_any_type)
15491557 jl_temporary_root (ctx, rt);
1550- function_sig_t sig (" ccall" , lrt, rt, retboxed,
1558+ function_sig_t sig (" ccall" , lrt, rt, retboxed, gc_safe,
15511559 (jl_svec_t *)at, unionall, nreqargs,
15521560 cc, llvmcall, &ctx.emission_context );
15531561 for (size_t i = 0 ; i < nccallargs; i++) {
0 commit comments