Skip to content

Commit

Permalink
Track method roots by precompile module (JuliaLang#43793)
Browse files Browse the repository at this point in the history
For roots of a method added during incremental compilation, track the
toplevel module build_id. This will ultimately allow such roots to be
"relocatable" in compressed IR, pending future changes in compression.
  • Loading branch information
timholy authored and LilithHafner committed Mar 8, 2022
1 parent b7c66d9 commit 2116f56
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7549,7 +7549,7 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
break;
}
if (j == jlen) // not found - add to array
jl_array_ptr_1d_push(m->roots, ival);
jl_add_method_root(m, jl_precompile_toplevel_module, ival);
}
}
ctx.roots = NULL;
Expand Down
7 changes: 7 additions & 0 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li
write_int8(s->s, m->constprop);
jl_serialize_value(s, (jl_value_t*)m->slot_syms);
jl_serialize_value(s, (jl_value_t*)m->roots);
jl_serialize_value(s, (jl_value_t*)m->root_blocks);
jl_serialize_value(s, (jl_value_t*)m->ccallable);
jl_serialize_value(s, (jl_value_t*)m->source);
jl_serialize_value(s, (jl_value_t*)m->unspecialized);
Expand Down Expand Up @@ -1573,6 +1574,9 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_
m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots);
if (m->roots)
jl_gc_wb(m, m->roots);
m->root_blocks = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->root_blocks);
if (m->root_blocks)
jl_gc_wb(m, m->root_blocks);
m->ccallable = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->ccallable);
if (m->ccallable) {
jl_gc_wb(m, m->ccallable);
Expand Down Expand Up @@ -2312,6 +2316,8 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
}
JL_GC_PUSH2(&mod_array, &udeps);
mod_array = jl_get_loaded_modules(); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
assert(jl_precompile_toplevel_module == NULL);
jl_precompile_toplevel_module = (jl_module_t*)jl_array_ptr_ref(worklist, jl_array_len(worklist)-1);

serializer_worklist = worklist;
write_header(&f);
Expand Down Expand Up @@ -2426,6 +2432,7 @@ JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist)
write_int32(&f, 0); // mark the end of the source text
ios_close(&f);
JL_GC_POP();
jl_precompile_toplevel_module = NULL;

return 0;
}
Expand Down
1 change: 1 addition & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,7 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
libsupport_init();
htable_new(&jl_current_modules, 0);
JL_MUTEX_INIT(&jl_modules_mutex);
jl_precompile_toplevel_module = NULL;
ios_set_io_wait_func = jl_set_io_wait;
jl_io_loop = uv_default_loop(); // this loop will internal events (spawning process etc.),
// best to call this first, since it also initializes libuv
Expand Down
2 changes: 1 addition & 1 deletion src/ircode.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static int literal_val_id(jl_ircode_state *s, jl_value_t *v) JL_GC_DISABLED
return i;
}
}
jl_array_ptr_1d_push(rs, v);
jl_add_method_root(s->method, jl_precompile_toplevel_module, v);
return jl_array_len(rs) - 1;
}

Expand Down
2 changes: 2 additions & 0 deletions src/jl_exported_data.inc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
XX(jl_array_type) \
XX(jl_array_typename) \
XX(jl_array_uint8_type) \
XX(jl_array_uint64_type) \
XX(jl_atomicerror_type) \
XX(jl_base_module) \
XX(jl_bool_type) \
Expand Down Expand Up @@ -84,6 +85,7 @@
XX(jl_pinode_type) \
XX(jl_pointer_type) \
XX(jl_pointer_typename) \
XX(jl_precompile_toplevel_module) \
XX(jl_quotenode_type) \
XX(jl_readonlymemory_exception) \
XX(jl_ref_type) \
Expand Down
7 changes: 5 additions & 2 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_array_symbol_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_symbol_type, jl_box_long(1));
jl_array_uint8_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint8_type, jl_box_long(1));
jl_array_int32_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_int32_type, jl_box_long(1));
jl_array_uint64_type = jl_apply_type2((jl_value_t*)jl_array_type, (jl_value_t*)jl_uint64_type, jl_box_long(1));
jl_an_empty_vec_any = (jl_value_t*)jl_alloc_vec_any(0); // used internally
jl_atomic_store_relaxed(&jl_nonfunction_mt->leafcache, (jl_array_t*)jl_an_empty_vec_any);
jl_atomic_store_relaxed(&jl_type_type_mt->leafcache, (jl_array_t*)jl_an_empty_vec_any);
Expand Down Expand Up @@ -2392,7 +2393,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_method_type =
jl_new_datatype(jl_symbol("Method"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(26,
jl_perm_symsvec(27,
"name",
"module",
"file",
Expand All @@ -2408,6 +2409,7 @@ void jl_init_types(void) JL_GC_DISABLED
"unspecialized", // !const
"generator", // !const
"roots", // !const
"root_blocks", // !const
"ccallable", // !const
"invokes", // !const
"recursion_relation", // !const
Expand All @@ -2419,7 +2421,7 @@ void jl_init_types(void) JL_GC_DISABLED
"pure",
"is_for_opaque_closure",
"constprop"),
jl_svec(26,
jl_svec(27,
jl_symbol_type,
jl_module_type,
jl_symbol_type,
Expand All @@ -2435,6 +2437,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_any_type, // jl_method_instance_type
jl_any_type,
jl_array_any_type,
jl_array_uint64_type,
jl_simplevector_type,
jl_any_type,
jl_any_type,
Expand Down
4 changes: 4 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ typedef struct _jl_method_t {
_Atomic(struct _jl_method_instance_t*) unspecialized; // unspecialized executable method instance, or null
jl_value_t *generator; // executable code-generating function if available
jl_array_t *roots; // pointers in generated code (shared to reduce memory), or null
// Identify roots by module-of-origin. We only track the module for roots added during incremental compilation.
// May be NULL if no external roots have been added, otherwise it's a Vector{UInt64}
jl_array_t *root_blocks; // RLE (build_id, offset) pairs (even/odd indexing)
jl_svec_t *ccallable; // svec(rettype, sig) if a ccallable entry point is requested for this

// cache of specializations of this method for invoke(), i.e.
Expand Down Expand Up @@ -708,6 +711,7 @@ extern JL_DLLIMPORT jl_value_t *jl_array_uint8_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_value_t *jl_array_any_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_value_t *jl_array_symbol_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_value_t *jl_array_int32_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_value_t *jl_array_uint64_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_expr_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_globalref_type JL_GLOBALLY_ROOTED;
extern JL_DLLIMPORT jl_datatype_t *jl_linenumbernode_type JL_GLOBALLY_ROOTED;
Expand Down
3 changes: 3 additions & 0 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,8 @@ JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void);
void jl_resolve_globals_in_ir(jl_array_t *stmts, jl_module_t *m, jl_svec_t *sparam_vals,
int binding_effects);

JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root);

int jl_valid_type_param(jl_value_t *v);

JL_DLLEXPORT jl_value_t *jl_apply_2va(jl_value_t *f, jl_value_t **args, uint32_t nargs);
Expand Down Expand Up @@ -647,6 +649,7 @@ jl_binding_t *jl_get_module_binding(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t
JL_DLLEXPORT void jl_binding_deprecation_warning(jl_module_t *m, jl_binding_t *b);
extern jl_array_t *jl_module_init_order JL_GLOBALLY_ROOTED;
extern htable_t jl_current_modules JL_GLOBALLY_ROOTED;
extern JL_DLLEXPORT jl_module_t *jl_precompile_toplevel_module JL_GLOBALLY_ROOTED;
int jl_compile_extern_c(void *llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt);

jl_opaque_closure_t *jl_new_opaque_closure(jl_tupletype_t *argt, jl_value_t *isva, jl_value_t *rt_lb,
Expand Down
48 changes: 48 additions & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module)
m->sig = NULL;
m->slot_syms = NULL;
m->roots = NULL;
m->root_blocks = NULL;
m->ccallable = NULL;
m->module = module;
m->external_mt = NULL;
Expand Down Expand Up @@ -987,6 +988,53 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata,
return m;
}

// root blocks

static uint64_t current_root_id(jl_array_t *root_blocks)
{
if (!root_blocks)
return 0;
assert(jl_is_array(root_blocks));
size_t nx2 = jl_array_len(root_blocks);
if (nx2 == 0)
return 0;
uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
return blocks[nx2-2];
}

static void add_root_block(jl_array_t *root_blocks, uint64_t modid, size_t len)
{
assert(jl_is_array(root_blocks));
jl_array_grow_end(root_blocks, 2);
uint64_t *blocks = (uint64_t*)jl_array_data(root_blocks);
int nx2 = jl_array_len(root_blocks);
blocks[nx2-2] = modid;
blocks[nx2-1] = len;
}

JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root)
{
JL_GC_PUSH2(&m, &root);
uint64_t modid = 0;
if (mod) {
assert(jl_is_module(mod));
modid = mod->build_id;
}
assert(jl_is_method(m));
if (!m->roots) {
m->roots = jl_alloc_vec_any(0);
jl_gc_wb(m, m->roots);
}
if (!m->root_blocks && modid != 0) {
m->root_blocks = jl_alloc_array_1d(jl_array_uint64_type, 0);
jl_gc_wb(m, m->root_blocks);
}
if (current_root_id(m->root_blocks) != modid)
add_root_block(m->root_blocks, modid, jl_array_len(m->roots));
jl_array_ptr_1d_push(m->roots, root);
JL_GC_POP();
}

#ifdef __cplusplus
}
#endif
3 changes: 2 additions & 1 deletion src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extern "C" {
// TODO: put WeakRefs on the weak_refs list during deserialization
// TODO: handle finalizers

#define NUM_TAGS 151
#define NUM_TAGS 152

// 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.
Expand Down Expand Up @@ -106,6 +106,7 @@ jl_value_t **const*const get_tags(void) {
INSERT_TAG(jl_array_symbol_type);
INSERT_TAG(jl_array_uint8_type);
INSERT_TAG(jl_array_int32_type);
INSERT_TAG(jl_array_uint64_type);
INSERT_TAG(jl_int32_type);
INSERT_TAG(jl_int64_type);
INSERT_TAG(jl_bool_type);
Expand Down
10 changes: 10 additions & 0 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ JL_DLLEXPORT const char *jl_filename = "none"; // need to update jl_critical_err
htable_t jl_current_modules;
jl_mutex_t jl_modules_mutex;

// During incremental compilation, the following gets set
JL_DLLEXPORT jl_module_t *jl_precompile_toplevel_module; // the toplevel module currently being defined

JL_DLLEXPORT void jl_add_standard_imports(jl_module_t *m)
{
jl_module_t *base_module = jl_base_relative_to(m);
Expand Down Expand Up @@ -138,11 +141,16 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex
ptrhash_put(&jl_current_modules, (void*)newm, (void*)((uintptr_t)HT_NOTFOUND + 1));
JL_UNLOCK(&jl_modules_mutex);

jl_module_t *old_toplevel_module = jl_precompile_toplevel_module;

// copy parent environment info into submodule
newm->uuid = parent_module->uuid;
if (jl_is__toplevel__mod(parent_module)) {
newm->parent = newm;
jl_register_root_module(newm);
if (jl_options.incremental) {
jl_precompile_toplevel_module = newm;
}
}
else {
newm->parent = parent_module;
Expand Down Expand Up @@ -261,6 +269,8 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex
}
}

jl_precompile_toplevel_module = old_toplevel_module;

JL_GC_POP();
return (jl_value_t*)newm;
}
Expand Down
Loading

0 comments on commit 2116f56

Please sign in to comment.