Skip to content

Commit 0fd1f04

Browse files
authored
Optimize jl_get_world_counter ccall (JuliaLang#55032)
This is useful for hot loops that perform an `invoke_latest`-like operation, such as the upcoming `TypedCallable`
1 parent 6cb71e7 commit 0fd1f04

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/ccall.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ TRANSFORMED_CCALL_STAT(jl_gc_safepoint);
2323
TRANSFORMED_CCALL_STAT(jl_get_ptls_states);
2424
TRANSFORMED_CCALL_STAT(jl_threadid);
2525
TRANSFORMED_CCALL_STAT(jl_get_tls_world_age);
26+
TRANSFORMED_CCALL_STAT(jl_get_world_counter);
2627
TRANSFORMED_CCALL_STAT(jl_gc_enable_disable_finalizers_internal);
2728
TRANSFORMED_CCALL_STAT(jl_get_current_task);
2829
TRANSFORMED_CCALL_STAT(jl_set_next_task);
@@ -1706,6 +1707,30 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
17061707
return mark_or_box_ccall_result(ctx, world_age, retboxed, rt, unionall, static_rt);
17071708
}
17081709
}
1710+
else if (is_libjulia_func(jl_get_world_counter)) {
1711+
++CCALL_STAT(jl_get_world_counter);
1712+
assert(lrt == ctx.types().T_size);
1713+
assert(!isVa && !llvmcall && nccallargs == 0);
1714+
JL_GC_POP();
1715+
jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_const);
1716+
1717+
// jl_task_t *ct = jl_current_task;
1718+
// if (ct->ptls->in_pure_callback)
1719+
// return ~(size_t)0;
1720+
// return jl_atomic_load_acquire(&jl_world_counter);
1721+
Type *T_int16 = getInt16Ty(ctx.builder.getContext());
1722+
Value *offset = ConstantInt::get(ctx.types().T_size, offsetof(jl_tls_states_t, in_pure_callback) / sizeof(int16_t));
1723+
Value *field_ptr = ctx.builder.CreateInBoundsGEP(T_int16, get_current_ptls(ctx), offset);
1724+
Instruction *in_pure_callback = ai.decorateInst(ctx.builder.CreateAlignedLoad(T_int16,
1725+
field_ptr, Align(sizeof(int16_t)), "in_pure_callback"));
1726+
Value *cond = ctx.builder.CreateICmpEQ(in_pure_callback, ConstantInt::get(T_int16, 0));
1727+
1728+
Value *world_counter = ctx.builder.CreateAlignedLoad(ctx.types().T_size,
1729+
prepare_global_in(jl_Module, jlgetworld_global), ctx.types().alignof_ptr);
1730+
cast<LoadInst>(world_counter)->setOrdering(AtomicOrdering::Acquire);
1731+
Value *ret = ctx.builder.CreateSelect(cond, world_counter, ConstantInt::get(ctx.types().T_size, ~(size_t)0));
1732+
return mark_or_box_ccall_result(ctx, ret, retboxed, rt, unionall, static_rt);
1733+
}
17091734
else if (is_libjulia_func(jl_gc_disable_finalizers_internal)
17101735
#ifdef NDEBUG
17111736
|| is_libjulia_func(jl_gc_enable_finalizers_internal)

test/ccall.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,3 +1948,18 @@ cglobal_non_static2() = cglobal(the_sym)
19481948

19491949
@test isa(cglobal_non_static1(), Ptr)
19501950
@test isa(cglobal_non_static2(), Ptr)
1951+
1952+
@generated function generated_world_counter()
1953+
return :($(Base.get_world_counter()))
1954+
end
1955+
function world_counter()
1956+
return Base.get_world_counter()
1957+
end
1958+
let llvm = sprint(code_llvm, world_counter, ())
1959+
# check that we got a reasonable value for the world age
1960+
@test (world_counter() != 0) && (world_counter() != -1)
1961+
# no call to the runtime should be left over
1962+
@test !occursin("call i64", llvm)
1963+
# the world age should be -1 in generated functions (or other pure contexts)
1964+
@test (generated_world_counter() == reinterpret(UInt, -1))
1965+
end

0 commit comments

Comments
 (0)