Skip to content

Commit e35e82b

Browse files
vtjnashtopolarity
authored andcommitted
fix @invokelatest performance regression (#58582)
A bit of hacking to get back near to the same performance as before by using the GlobalRef to optimize the getglobal lookup for now and avoiding the extra Vararg function indirection which forced some extra boxing and lookups. julia> @Btime foo(1.5) 22.892 ns (1 allocation: 16 bytes) # v1.11 141.543 ns (3 allocations: 48 bytes) # master 38.759 ns (2 allocations: 32 bytes) # PR The remaining difference is split about equally between the need now to box the world counter value for invoke_in_world and the extra cost of scanning the partition table for `Base.sin` to find the current entry. Fix #58334 (cherry picked from commit f12256b)
1 parent e3ef824 commit e35e82b

18 files changed

+70
-62
lines changed

base/reflection.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,16 +1269,17 @@ macro invoke(ex)
12691269
return esc(out)
12701270
end
12711271

1272-
apply_gr(gr::GlobalRef, @nospecialize args...) = getglobal(gr.mod, gr.name)(args...)
1273-
apply_gr_kw(@nospecialize(kwargs::NamedTuple), gr::GlobalRef, @nospecialize args...) = Core.kwcall(kwargs, getglobal(gr.mod, gr.name), args...)
1272+
getglobalref(gr::GlobalRef, world::UInt) = ccall(:jl_eval_globalref, Any, (Any, UInt), gr, world)
12741273

1275-
function invokelatest_gr(gr::GlobalRef, @nospecialize args...; kwargs...)
1274+
function invokelatest_gr(gr::GlobalRef, args...; kwargs...)
12761275
@inline
12771276
kwargs = merge(NamedTuple(), kwargs)
1277+
world = get_world_counter()
1278+
f = getglobalref(gr, world)
12781279
if isempty(kwargs)
1279-
return invokelatest(apply_gr, gr, args...)
1280+
return invoke_in_world(world, f, args...)
12801281
end
1281-
return invokelatest(apply_gr_kw, kwargs, gr, args...)
1282+
return invoke_in_world(world, Core.kwcall, kwargs, f, args...)
12821283
end
12831284

12841285
"""

src/builtins.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ JL_CALLABLE(jl_f_getglobal)
13381338
jl_atomic_error("getglobal: module binding cannot be read non-atomically");
13391339
else if (order >= jl_memory_order_seq_cst)
13401340
jl_fence();
1341-
jl_value_t *v = jl_eval_global_var(mod, sym); // relaxed load
1341+
jl_value_t *v = jl_eval_global_var(mod, sym, jl_current_task->world_age); // relaxed load
13421342
if (order >= jl_memory_order_acquire)
13431343
jl_fence();
13441344
return v;

src/gf.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -513,13 +513,13 @@ JL_DLLEXPORT jl_code_info_t *jl_gdbcodetyped1(jl_method_instance_t *mi, size_t w
513513
ct->world_age = jl_typeinf_world;
514514
jl_value_t **fargs;
515515
JL_GC_PUSHARGS(fargs, 4);
516-
jl_module_t *CC = (jl_module_t*)jl_get_global_value(jl_core_module, jl_symbol("Compiler"));
516+
jl_module_t *CC = (jl_module_t*)jl_get_global_value(jl_core_module, jl_symbol("Compiler"), ct->world_age);
517517
if (CC != NULL && jl_is_module(CC)) {
518518
JL_GC_PROMISE_ROOTED(CC);
519-
fargs[0] = jl_get_global_value(CC, jl_symbol("NativeInterpreter"));;
519+
fargs[0] = jl_get_global_value(CC, jl_symbol("NativeInterpreter"), ct->world_age);
520520
fargs[1] = jl_box_ulong(world);
521521
fargs[1] = jl_apply(fargs, 2);
522-
fargs[0] = jl_get_global_value(CC, jl_symbol("typeinf_code"));
522+
fargs[0] = jl_get_global_value(CC, jl_symbol("typeinf_code"), ct->world_age);
523523
fargs[2] = (jl_value_t*)mi;
524524
fargs[3] = jl_true;
525525
ci = (jl_code_info_t*)jl_apply(fargs, 4);

src/init.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) JL_NOTSAFEPOINT_ENTER
249249
if (jl_base_module) {
250250
size_t last_age = ct->world_age;
251251
ct->world_age = jl_get_world_counter();
252-
jl_value_t *f = jl_get_global_value(jl_base_module, jl_symbol("_atexit"));
252+
jl_value_t *f = jl_get_global_value(jl_base_module, jl_symbol("_atexit"), ct->world_age);
253253
if (f != NULL) {
254254
jl_value_t **fargs;
255255
JL_GC_PUSHARGS(fargs, 2);
@@ -357,7 +357,7 @@ JL_DLLEXPORT void jl_postoutput_hook(void)
357357
jl_task_t *ct = jl_get_current_task();
358358
size_t last_age = ct->world_age;
359359
ct->world_age = jl_get_world_counter();
360-
jl_value_t *f = jl_get_global_value(jl_base_module, jl_symbol("_postoutput"));
360+
jl_value_t *f = jl_get_global_value(jl_base_module, jl_symbol("_postoutput"), ct->world_age);
361361
if (f != NULL) {
362362
JL_TRY {
363363
JL_GC_PUSH1(&f);

src/interpreter.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,18 +162,18 @@ static jl_value_t *do_invoke(jl_value_t **args, size_t nargs, interpreter_state
162162
}
163163

164164
// get the global (throwing if null) in the current world
165-
jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e)
165+
jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e, size_t world)
166166
{
167-
jl_value_t *v = jl_get_global_value(m, e);
167+
jl_value_t *v = jl_get_global_value(m, e, world);
168168
if (v == NULL)
169169
jl_undefined_var_error(e, (jl_value_t*)m);
170170
return v;
171171
}
172172

173173
// get the global (throwing if null) in the current world, optimized
174-
jl_value_t *jl_eval_globalref(jl_globalref_t *g)
174+
jl_value_t *jl_eval_globalref(jl_globalref_t *g, size_t world)
175175
{
176-
jl_value_t *v = jl_get_globalref_value(g);
176+
jl_value_t *v = jl_get_globalref_value(g, world);
177177
if (v == NULL)
178178
jl_undefined_var_error(g->name, (jl_value_t*)g->mod);
179179
return v;
@@ -218,10 +218,10 @@ static jl_value_t *eval_value(jl_value_t *e, interpreter_state *s)
218218
return jl_quotenode_value(e);
219219
}
220220
if (jl_is_globalref(e)) {
221-
return jl_eval_globalref((jl_globalref_t*)e);
221+
return jl_eval_globalref((jl_globalref_t*)e, jl_current_task->world_age);
222222
}
223223
if (jl_is_symbol(e)) { // bare symbols appear in toplevel exprs not wrapped in `thunk`
224-
return jl_eval_global_var(s->module, (jl_sym_t*)e);
224+
return jl_eval_global_var(s->module, (jl_sym_t*)e, jl_current_task->world_age);
225225
}
226226
if (jl_is_pinode(e)) {
227227
jl_value_t *val = eval_value(jl_fieldref_noalloc(e, 0), s);

src/jl_uv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ static void jl_uv_call_close_callback(jl_value_t *val)
162162
JL_GC_PUSHARGS(args, 2); // val is "rooted" in the finalizer list only right now
163163
args[0] = jl_eval_global_var(
164164
jl_base_relative_to(((jl_datatype_t*)jl_typeof(val))->name->module),
165-
jl_symbol("_uv_hook_close")); // topmod(typeof(val))._uv_hook_close
165+
jl_symbol("_uv_hook_close"),
166+
jl_current_task->world_age); // topmod(typeof(val))._uv_hook_close
166167
args[1] = val;
167168
jl_apply(args, 2); // TODO: wrap in try-catch?
168169
JL_GC_POP();

src/jlapi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ static NOINLINE int true_main(int argc, char *argv[])
955955
ct->world_age = jl_get_world_counter();
956956

957957
jl_function_t *start_client = jl_base_module ?
958-
(jl_function_t*)jl_get_global_value(jl_base_module, jl_symbol("_start")) : NULL;
958+
(jl_function_t*)jl_get_global_value(jl_base_module, jl_symbol("_start"), ct->world_age) : NULL;
959959

960960
if (start_client) {
961961
int ret = 1;

src/jltypes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3286,6 +3286,7 @@ void jl_init_types(void) JL_GC_DISABLED
32863286
jl_perm_symsvec(3, "mod", "name", "binding"),
32873287
jl_svec(3, jl_module_type, jl_symbol_type, jl_binding_type),
32883288
jl_emptysvec, 0, 0, 3);
3289+
jl_globalref_type->name->mayinlinealloc = 0; // not at all worthwhile, since the only constructor returns a boxed object
32893290

32903291
jl_core_module = jl_new_module(jl_symbol("Core"), NULL);
32913292

src/julia.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,9 +2117,7 @@ JL_DLLEXPORT jl_value_t *jl_get_existing_strong_gf(jl_binding_t *b JL_PROPAGATES
21172117
JL_DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var, int allow_import);
21182118
JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var);
21192119
JL_DLLEXPORT int jl_globalref_is_const(jl_globalref_t *gr);
2120-
JL_DLLEXPORT jl_value_t *jl_get_globalref_value(jl_globalref_t *gr);
21212120
JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *var);
2122-
JL_DLLEXPORT jl_value_t *jl_get_global_value(jl_module_t *m, jl_sym_t *var);
21232121
JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT);
21242122
JL_DLLEXPORT void jl_set_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT);
21252123
void jl_set_initial_const(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT, int exported);

src/julia_internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,10 @@ STATIC_INLINE size_t module_usings_max(jl_module_t *m) JL_NOTSAFEPOINT {
901901

902902
JL_DLLEXPORT jl_sym_t *jl_module_name(jl_module_t *m) JL_NOTSAFEPOINT;
903903
void jl_add_scanned_method(jl_module_t *m, jl_method_t *meth);
904-
jl_value_t *jl_eval_global_var(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *e);
904+
jl_value_t *jl_eval_global_var(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *e, size_t world);
905+
JL_DLLEXPORT jl_value_t *jl_eval_globalref(jl_globalref_t *g, size_t world);
906+
jl_value_t *jl_get_globalref_value(jl_globalref_t *gr, size_t world);
907+
jl_value_t *jl_get_global_value(jl_module_t *m, jl_sym_t *var, size_t world);
905908
jl_value_t *jl_interpret_opaque_closure(jl_opaque_closure_t *clos, jl_value_t **args, size_t nargs);
906909
jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src);
907910
jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,

0 commit comments

Comments
 (0)