Skip to content

Commit

Permalink
Exclude MethodInstances that don't link to worklist module
Browse files Browse the repository at this point in the history
This should prevent us from serializing too much code.
  • Loading branch information
timholy committed Feb 18, 2022
1 parent 3241c4c commit 48c91b3
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
42 changes: 40 additions & 2 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,47 @@ static int type_recursively_external(jl_datatype_t *dt) JL_NOTSAFEPOINT
return 1;
}

// When we infer external method instances, ensure they link back to the
// package. Otherwise they might be, e.g., for external macros
static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited)
{
void **bp = ptrhash_bp(visited, mi);
// HT_NOTFOUND: not yet analyzed
// HT_NOTFOUND + 1: doesn't link back
// HT_NOTFOUND + 2: does link back
if (*bp != HT_NOTFOUND)
return (char*)*bp - (char*)HT_NOTFOUND - 1;
*bp = (void*)((char*)HT_NOTFOUND + 1); // preliminarily mark as "not found"
jl_module_t *mod = mi->def.module;
if (jl_is_method(mod))
mod = ((jl_method_t*)mod)->module;
assert(jl_is_module(mod));
if (mi->precompiled || module_in_worklist(mod)) {
*bp = (void*)((char*)HT_NOTFOUND + 2); // found
return 1;
}
if (!mi->backedges) {
return 0;
}
size_t i, n = jl_array_len(mi->backedges);
for (i = 0; i < n; i++) {
jl_method_instance_t *be = (jl_method_instance_t*)jl_array_ptr_ref(mi->backedges, i);
if (has_backedge_to_worklist(be, visited)) {
*bp = (void*)((char*)HT_NOTFOUND + 2); // found
return 1;
}
}
return 0;
}

// given the list of MethodInstances that were inferred during the
// build, select those that are external and have at least one
// relocatable CodeInstance.
static size_t queue_external_mis(jl_array_t *list)
{
size_t i, n = 0;
htable_t visited;
htable_new(&visited, 0);
if (list) {
assert(jl_is_array(list));
size_t n0 = jl_array_len(list);
Expand All @@ -268,13 +303,16 @@ static size_t queue_external_mis(jl_array_t *list)
ci = ci->next;
}
if (relocatable && ptrhash_get(&external_mis, mi) == HT_NOTFOUND) {
ptrhash_put(&external_mis, mi, mi);
n++;
if (has_backedge_to_worklist(mi, &visited)) {
ptrhash_put(&external_mis, mi, mi);
n++;
}
}
}
}
}
}
htable_free(&visited);
return n;
}

Expand Down
2 changes: 2 additions & 0 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2248,6 +2248,7 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
if (mi == NULL)
return 0;
JL_GC_PROMISE_ROOTED(mi);
mi->precompiled = 1;
if (jl_generating_output()) {
jl_compile_now(mi);
// In addition to full compilation of the compilation-signature, if `types` is more specific (e.g. due to nospecialize),
Expand All @@ -2262,6 +2263,7 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
types2 = jl_type_intersection_env((jl_value_t*)types, (jl_value_t*)mi->def.method->sig, &tpenv2);
jl_method_instance_t *li2 = jl_specializations_get_linfo(mi->def.method, (jl_value_t*)types2, tpenv2);
JL_GC_POP();
li2->precompiled = 1;
if (jl_rettype_inferred(li2, world, world) == jl_nothing)
(void)jl_type_infer(li2, world, 1);
if (jl_typeinf_func && mi->def.method->primary_world <= tworld) {
Expand Down
8 changes: 5 additions & 3 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2466,23 +2466,25 @@ void jl_init_types(void) JL_GC_DISABLED
jl_method_instance_type =
jl_new_datatype(jl_symbol("MethodInstance"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(8,
jl_perm_symsvec(9,
"def",
"specTypes",
"sparam_vals",
"uninferred",
"backedges",
"callbacks",
"cache",
"inInference"),
jl_svec(8,
"inInference",
"precompiled"),
jl_svec(9,
jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type),
jl_any_type,
jl_simplevector_type,
jl_any_type,
jl_any_type,
jl_any_type,
jl_any_type,
jl_bool_type,
jl_bool_type),
jl_emptysvec,
0, 1, 3);
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ struct _jl_method_instance_t {
jl_array_t *callbacks; // list of callback functions to inform external caches about invalidations
_Atomic(struct _jl_code_instance_t*) cache;
uint8_t inInference; // flags to tell if inference is running on this object
uint8_t precompiled; // true if this instance was generated by an explicit `precompile(...)` call
};

// OpaqueClosure
Expand Down
1 change: 1 addition & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void)
li->callbacks = NULL;
jl_atomic_store_relaxed(&li->cache, NULL);
li->inInference = 0;
li->precompiled = 0;
return li;
}

Expand Down

0 comments on commit 48c91b3

Please sign in to comment.