From e6f71a642e5b5917333c38bfefaf360da9516c20 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Wed, 18 Sep 2024 11:23:30 -0400 Subject: [PATCH 1/2] Inline fptr lookup for `Core.throw_methoderror` and `Core.current_scope` I'm not sure why we don't require these addresses to be available for all builtins, but this mildly improves our codegen for these. ```julia julia> foo() = Core.current_scope() ``` Before: ```llvm define nonnull ptr @julia_foo_2488() #0 { top: %0 = call ptr @jl_get_builtin_fptr(ptr nonnull @"+Core.#current_scope#2491.jit") %Builtin_ret = call nonnull ptr %0(ptr nonnull @"jl_global#2492.jit", ptr null, i32 0) ret ptr %Builtin_ret } ``` After: ```llvm define nonnull ptr @julia_foo_1066() #0 { top: %jl_f_current_scope_ret = call nonnull ptr @jl_f_current_scope(ptr null, ptr null, i32 0) ret ptr %jl_f_current_scope_ret } ``` --- src/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 73a5f844b31da..186a2e244b1ba 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1619,6 +1619,7 @@ static const auto &builtin_func_map() { { 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_throw_methoderror_addr, new JuliaFunction<>{XSTR(jl_f_throw_methoderror), 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} }, @@ -1644,7 +1645,8 @@ static const auto &builtin_func_map() { { jl_f_donotdelete_addr, new JuliaFunction<>{XSTR(jl_f_donotdelete), get_donotdelete_sig, get_donotdelete_func_attrs} }, { jl_f_compilerbarrier_addr, new JuliaFunction<>{XSTR(jl_f_compilerbarrier), get_func_sig, get_func_attrs} }, { jl_f_finalizer_addr, new JuliaFunction<>{XSTR(jl_f_finalizer), get_func_sig, get_func_attrs} }, - { jl_f__svec_ref_addr, new JuliaFunction<>{XSTR(jl_f__svec_ref), get_func_sig, get_func_attrs} } + { jl_f__svec_ref_addr, new JuliaFunction<>{XSTR(jl_f__svec_ref), get_func_sig, get_func_attrs} }, + { jl_f_current_scope, new JuliaFunction<>{XSTR(jl_f_current_scope), get_func_sig, get_func_attrs} }, }; return builtins; } From 12e4999e97ca4289ef8f475d9a848575c8e36153 Mon Sep 17 00:00:00 2001 From: Cody Tapscott Date: Wed, 18 Sep 2024 11:57:53 -0400 Subject: [PATCH 2/2] Specialize codegen for `Core.current_scope` --- src/builtins.c | 2 +- src/codegen.cpp | 11 ++++++++++- src/staticdata.c | 3 ++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/builtins.c b/src/builtins.c index 75c4d02c898b2..96c4cec0f5087 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2444,7 +2444,7 @@ void jl_init_primitives(void) JL_GC_DISABLED add_builtin_func("finalizer", jl_f_finalizer); add_builtin_func("_compute_sparams", jl_f__compute_sparams); add_builtin_func("_svec_ref", jl_f__svec_ref); - add_builtin_func("current_scope", jl_f_current_scope); + jl_builtin_current_scope = add_builtin_func("current_scope", jl_f_current_scope); add_builtin_func("throw_methoderror", jl_f_throw_methoderror); // builtin types diff --git a/src/codegen.cpp b/src/codegen.cpp index 186a2e244b1ba..2fb1c7ae5b983 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1646,7 +1646,7 @@ static const auto &builtin_func_map() { { jl_f_compilerbarrier_addr, new JuliaFunction<>{XSTR(jl_f_compilerbarrier), get_func_sig, get_func_attrs} }, { jl_f_finalizer_addr, new JuliaFunction<>{XSTR(jl_f_finalizer), get_func_sig, get_func_attrs} }, { jl_f__svec_ref_addr, new JuliaFunction<>{XSTR(jl_f__svec_ref), get_func_sig, get_func_attrs} }, - { jl_f_current_scope, new JuliaFunction<>{XSTR(jl_f_current_scope), get_func_sig, get_func_attrs} }, + { jl_f_current_scope_addr, new JuliaFunction<>{XSTR(jl_f_current_scope), get_func_sig, get_func_attrs} }, }; return builtins; } @@ -2119,6 +2119,7 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i); static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const Twine &msg); static Value *get_current_task(jl_codectx_t &ctx); static Value *get_current_ptls(jl_codectx_t &ctx); +static Value *get_scope_field(jl_codectx_t &ctx); static Value *get_tls_world_age_field(jl_codectx_t &ctx); static void CreateTrap(IRBuilder<> &irbuilder, bool create_new_block = true); static CallInst *emit_jlcall(jl_codectx_t &ctx, FunctionCallee theFptr, Value *theF, @@ -4943,6 +4944,14 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f, return true; } + else if (f == jl_builtin_current_scope && (nargs == 0)) { + jl_aliasinfo_t scope_ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_gcframe); + Instruction *v = scope_ai.decorateInst( + ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, get_scope_field(ctx), ctx.types().alignof_ptr)); + *ret = mark_julia_type(ctx, v, /*boxed*/ true, rt); + return true; + } + else if (f == jl_builtin_donotdelete) { // For now we emit this as a vararg call to the builtin // (which doesn't look at the arguments). In the future, diff --git a/src/staticdata.c b/src/staticdata.c index b991dfe8f37f3..363aa46b62221 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -100,7 +100,7 @@ extern "C" { // TODO: put WeakRefs on the weak_refs list during deserialization // TODO: handle finalizers -#define NUM_TAGS 192 +#define NUM_TAGS 193 // An array of references that need to be restored from the sysimg // This is a manually constructed dual of the gvars array, which would be produced by codegen for Julia code, for C. @@ -312,6 +312,7 @@ jl_value_t **const*const get_tags(void) { INSERT_TAG(jl_builtin_modifyglobal); INSERT_TAG(jl_builtin_replaceglobal); INSERT_TAG(jl_builtin_setglobalonce); + INSERT_TAG(jl_builtin_current_scope); // n.b. must update NUM_TAGS when you add something here #undef INSERT_TAG assert(i == NUM_TAGS - 1);