Skip to content

Commit 37c85de

Browse files
committed
Make cfunction optmization in codegen valid
1 parent 26c8d85 commit 37c85de

File tree

4 files changed

+37
-7
lines changed

4 files changed

+37
-7
lines changed

base/inference.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,10 @@ function abstract_call(f::ANY, fargs, argtypes::Vector{Any}, vtypes::VarTable, s
12101210
end
12111211
end
12121212
end
1213+
if istopfunction(tm, f, :cfunction) && length(fargs) == 4
1214+
# This can be skipped if codegen cannot inline the call
1215+
update_valid_age!(sv.params.world, sv.params.world, sv)
1216+
end
12131217

12141218
atype = argtypes_to_type(argtypes)
12151219
t = pure_eval_call(f, argtypes, atype, vtypes, sv)

src/ccall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1635,7 +1635,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
16351635
frt = jl_tparam0(frt);
16361636
Value *llvmf = NULL;
16371637
JL_TRY {
1638-
llvmf = jl_cfunction_object((jl_function_t*)f, frt, (jl_tupletype_t*)fargt);
1638+
llvmf = jl_cfunction_object((jl_function_t*)f, frt, (jl_tupletype_t*)fargt, ctx->world);
16391639
}
16401640
JL_CATCH {
16411641
llvmf = NULL;

src/codegen.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,17 +1225,19 @@ jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *_F, size_t wo
12251225
return fptr;
12261226
}
12271227

1228-
static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tupletype_t *argt);
1228+
static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tupletype_t *argt, size_t world);
12291229
// get the address of a C-callable entry point for a function
12301230
extern "C" JL_DLLEXPORT
12311231
void *jl_function_ptr(jl_function_t *f, jl_value_t *rt, jl_value_t *argt)
12321232
{
1233+
jl_ptls_t ptls = jl_get_ptls_states();
12331234
JL_GC_PUSH1(&argt);
12341235
if (jl_is_tuple(argt)) {
12351236
// TODO: maybe deprecation warning, better checking
12361237
argt = (jl_value_t*)jl_apply_tuple_type_v((jl_value_t**)jl_data_ptr(argt), jl_nfields(argt));
12371238
}
1238-
Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt);
1239+
Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt,
1240+
ptls->world_age);
12391241
JL_GC_POP();
12401242
return (void*)getAddressForFunction(llvmf);
12411243
}
@@ -1255,8 +1257,10 @@ void *jl_function_ptr_by_llvm_name(char *name) {
12551257
extern "C" JL_DLLEXPORT
12561258
void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name)
12571259
{
1260+
jl_ptls_t ptls = jl_get_ptls_states();
12581261
assert(jl_is_tuple_type(argt));
1259-
Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt);
1262+
Function *llvmf = jl_cfunction_object(f, rt, (jl_tupletype_t*)argt,
1263+
ptls->world_age);
12601264
if (llvmf) {
12611265
// force eager emission of the function (llvm 3.3 gets confused otherwise and tries to do recursive compilation)
12621266
uint64_t Addr = getAddressForFunction(llvmf);
@@ -3739,7 +3743,7 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
37393743
ctx.f = cw;
37403744
ctx.linfo = lam;
37413745
ctx.code = NULL;
3742-
ctx.world = jl_world_counter;
3746+
ctx.world = world;
37433747
ctx.sret = false;
37443748
ctx.spvals_ptr = NULL;
37453749
ctx.params = &jl_default_cgparams;
@@ -4000,7 +4004,7 @@ const struct jl_typemap_info cfunction_cache = {
40004004
// Get the LLVM Function* for the C-callable entry point for a certain function
40014005
// and argument types.
40024006
// here argt does not include the leading function type argument
4003-
static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_tupletype_t *argt)
4007+
static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_tupletype_t *argt, size_t world)
40044008
{
40054009
// validate and unpack the arguments
40064010
JL_TYPECHK(cfunction, type, declrt);
@@ -4051,7 +4055,6 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t
40514055
cfunc_sig = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)cfunc_sig);
40524056

40534057
// check the cache
4054-
size_t world = jl_world_counter;
40554058
if (jl_cfunction_list.unknown != jl_nothing) {
40564059
jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(jl_cfunction_list, (jl_tupletype_t*)cfunc_sig, NULL, 1, 0, /*offs*/0, world);
40574060
if (sf) {

test/misc.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,29 @@ let
466466
@test c_18711 == 1
467467
end
468468

469+
g19801(a) = a
470+
f19801() = cfunction(g19801, Int, (Int,))
471+
f19801_dynamic = f19801
472+
# Run a single function twice to make sure the function is recompiled
473+
function test19801(first, ptr0=f19801())
474+
if first
475+
@test ccall(ptr0, Int, (Int,), 1) == 1
476+
@eval g19801(a::Int) = a + 1
477+
# Check that both static and dynamic version returns the old pointer
478+
@test f19801() == ptr0
479+
@test f19801_dynamic() == ptr0
480+
@test ccall(f19801(), Int, (Int,), 1) == 1
481+
else
482+
@test ccall(ptr0, Int, (Int,), 1) == 1
483+
@test f19801() != ptr0
484+
@test f19801_dynamic() == f19801()
485+
@test ccall(f19801(), Int, (Int,), 1) == 2
486+
end
487+
return ptr0
488+
end
489+
ptr19801 = test19801(true)
490+
test19801(false, ptr19801)
491+
469492
let
470493
old_have_color = Base.have_color
471494
try

0 commit comments

Comments
 (0)