From 9bd6851383489731cfccdbee167f4a9ea49c5db8 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Thu, 15 Jun 2023 23:16:50 -0400 Subject: [PATCH 1/9] MethodInstance roots --- base/stacktraces.jl | 13 +++- src/ircode.c | 158 ++++++++++++++++++++++++++++++++++++++++++- src/jltypes.c | 14 ++-- src/julia.h | 6 ++ src/julia_internal.h | 3 + src/method.c | 56 ++++++++++++++- src/serialize.h | 5 +- src/staticdata.c | 3 + 8 files changed, 249 insertions(+), 9 deletions(-) diff --git a/base/stacktraces.jl b/base/stacktraces.jl index 523ca827897d5..f4e6932bb5389 100644 --- a/base/stacktraces.jl +++ b/base/stacktraces.jl @@ -105,11 +105,15 @@ function get_inlinetable(mi::MethodInstance) end get_method_instance_roots(::Any) = nothing -function get_method_instance_roots(mi::Union{Method, MethodInstance}) +function get_method_instance_roots(mi::Method) m = mi isa MethodInstance ? mi.def : mi m isa Method && isdefined(m, :roots) || return nothing return filter(x -> x isa MethodInstance, m.roots) end +function get_method_instance_roots(mi::MethodInstance) + isdefined(mi, :roots) || return nothing + return mi.roots +end function lookup_inline_frame_info(func::Symbol, file::Symbol, linenum::Int, inlinetable::Vector{Core.LineInfoNode}) #REPL frames and some base files lack this prefix while others have it; should fix? @@ -204,6 +208,13 @@ Base.@constprop :none function lookup(pointer::Ptr{Cvoid}) linfo = lookup_inline_frame_info(func, file, linenum, inlinetable) elseif miroots !== nothing linfo = lookup_inline_frame_info(func, file, miroots) + if linfo === nothing + # fallback to method roots + methodroots = get_method_instance_roots(parent_linfo.def) + if methodroots !== nothing + linfo = lookup_inline_frame_info(func, file, methodroots) + end + end end linfo = linfo === nothing ? parentmodule(res[i + 1]) : linfo # e.g. `macro expansion` end diff --git a/src/ircode.c b/src/ircode.c index bc5cc61e7f892..853ff16b05f23 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -25,6 +25,7 @@ typedef struct { ios_t *s; // method we're compressing for jl_method_t *method; + jl_method_instance_t *method_instance; jl_ptls_t ptls; uint8_t relocatability; } jl_ircode_state; @@ -67,6 +68,12 @@ static void tagged_root(rle_reference *rr, jl_ircode_state *s, int i) s->relocatability = 0; } +static void tagged_root_method_instance(rle_reference *rr, jl_ircode_state *s, int i) +{ + if (!get_root_reference_method_instance(rr, s->method_instance, i)) + s->relocatability = 0; +} + static void literal_val_id(rle_reference *rr, jl_ircode_state *s, jl_value_t *v) JL_GC_DISABLED { jl_array_t *rs = s->method->roots; @@ -87,6 +94,19 @@ static void literal_val_id(rle_reference *rr, jl_ircode_state *s, jl_value_t *v) return tagged_root(rr, s, jl_array_len(rs) - 1); } +static void literal_val_id_method_instance(rle_reference *rr, jl_ircode_state *s, jl_value_t *v) JL_GC_DISABLED +{ + assert(jl_is_method_instance(v)); + jl_array_t *rs = s->method_instance->roots; + int i, l = jl_array_len(rs); + for (i = 0; i < l; i++) { + if (jl_egal(jl_array_ptr_ref(rs, i), v)) + return tagged_root_method_instance(rr, s, i); + } + jl_add_method_instance_root(s->method_instance, jl_precompile_toplevel_module, v); + return tagged_root_method_instance(rr, s, jl_array_len(rs) - 1); +} + static void jl_encode_int32(jl_ircode_state *s, int32_t x) { if (x >= INT16_MIN && x <= INT16_MAX) { @@ -121,6 +141,53 @@ static void jl_encode_as_indexed_root(jl_ircode_state *s, jl_value_t *v) } } +static void jl_encode_as_indexed_root_method_instance(jl_ircode_state *s, jl_value_t *v) +{ + // store the def name as fallback if method instance root table is not available + + assert(jl_is_method_instance(v)); + rle_reference rr; + rle_reference rr_def; + + literal_val_id_method_instance(&rr, s, v); + + jl_value_t *def = ((jl_method_instance_t*)v)->def.value; + jl_sym_t *name = NULL; + if (jl_is_method(def)) + name = ((jl_method_t*)def)->name; + else if (jl_is_module(def)) + name = ((jl_module_t*)def)->name; + assert(name); + literal_val_id(&rr_def, s, (jl_value_t*)name); + int id = rr.index; + int id_def = rr_def.index; + assert(id >= 0); + assert(id_def >= 0); + if (rr.key) { + write_uint8(s->s, TAG_RELOC_METHODINSTANCEROOT); + write_uint64(s->s, rr.key); + write_uint64(s->s, rr_def.key); + } + if (id <= UINT8_MAX) { + write_uint8(s->s, TAG_METHODINSTANCEROOT); + write_uint8(s->s, id); + } + else { + assert(id <= UINT32_MAX); + write_uint8(s->s, TAG_LONG_METHODINSTANCEROOT); + write_uint32(s->s, id); + } + if (id_def <= UINT8_MAX) { + write_uint8(s->s, TAG_METHODROOT); + write_uint8(s->s, id_def); + } + else { + assert(id_def <= UINT32_MAX); + write_uint8(s->s, TAG_LONG_METHODROOT); + write_uint32(s->s, id_def); + } +} + static void jl_encode_value_(jl_ircode_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED { size_t i; @@ -323,8 +390,15 @@ static void jl_encode_value_(jl_ircode_state *s, jl_value_t *v, int as_literal) } else if (jl_typetagis(v, jl_lineinfonode_type)) { write_uint8(s->s, TAG_LINEINFO); - for (i = 0; i < jl_datatype_nfields(jl_lineinfonode_type); i++) - jl_encode_value(s, jl_get_nth_field(v, i)); + for (i = 0; i < jl_datatype_nfields(jl_lineinfonode_type); i++) { + jl_value_t *vi = jl_get_nth_field(v, i); + if (i == 1 && jl_is_method_instance(vi)) { + jl_encode_as_indexed_root_method_instance(s, vi); + } + else { + jl_encode_value(s, vi); + } + } } else if (((jl_datatype_t*)jl_typeof(v))->instance == v) { write_uint8(s->s, TAG_SINGLETON); @@ -663,6 +737,65 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED return lookup_root(s->method, 0, read_uint8(s->s)); case TAG_LONG_METHODROOT: return lookup_root(s->method, 0, read_uint32(s->s)); + case TAG_RELOC_METHODINSTANCEROOT: + key = read_uint64(s->s); + uint64_t key_def = read_uint64(s->s); + tag = read_uint8(s->s); + assert(tag == TAG_METHODINSTANCEROOT || tag == TAG_LONG_METHODINSTANCEROOT); + index = -1; + if (tag == TAG_METHODINSTANCEROOT) + index = read_uint8(s->s); + else if (tag == TAG_LONG_METHODINSTANCEROOT) + index = read_uint32(s->s); + assert(index >= 0); + int index_def = -1; + tag = read_uint8(s->s); + assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); + if (tag == TAG_METHODROOT) + index_def = read_uint8(s->s); + else if (tag == TAG_LONG_METHODROOT) + index_def = read_uint32(s->s); + assert(index_def >= 0); + if (s->method_instance != NULL) { + return lookup_root_method_instance(s->method_instance, key, index); + } + else { + return lookup_root(s->method, key_def, index_def); + } + case TAG_METHODINSTANCEROOT: + index = read_uint8(s->s); + assert(index >= 0); + tag = read_uint8(s->s); + assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); + index_def = -1; + if (tag == TAG_METHODROOT) + index_def = read_uint8(s->s); + else if (tag == TAG_LONG_METHODROOT) + index_def = read_uint32(s->s); + assert(index_def >= 0); + if (s->method_instance != NULL) { + return lookup_root_method_instance(s->method_instance, 0, index); + } + else { + return lookup_root(s->method, 0, index_def); + } + case TAG_LONG_METHODINSTANCEROOT: + index = read_uint32(s->s); + assert(index >= 0); + tag = read_uint8(s->s); + assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); + index_def = -1; + if (tag == TAG_METHODROOT) + index_def = read_uint8(s->s); + else if (tag == TAG_LONG_METHODROOT) + index_def = read_uint32(s->s); + assert(index_def >= 0); + if (s->method_instance != NULL) { + return lookup_root_method_instance(s->method_instance, 0, index); + } + else { + return lookup_root(s->method, 0, index_def); + } case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC: return jl_decode_value_svec(s, tag); case TAG_COMMONSYM: @@ -770,6 +903,10 @@ JL_DLLEXPORT jl_string_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code) JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); assert(jl_is_code_info(code)); + jl_method_instance_t *mi = NULL; + if (jl_is_method_instance(code->parent)) { + mi = code->parent; + } ios_t dest; ios_mem(&dest, 0); int en = jl_gc_enable(0); // Might GC @@ -779,9 +916,17 @@ JL_DLLEXPORT jl_string_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code) m->roots = jl_alloc_vec_any(0); jl_gc_wb(m, m->roots); } + if (jl_is_method_instance(code->parent)) { + jl_method_instance_t *mi = code->parent; + if (mi->roots == NULL) { + mi->roots = jl_alloc_vec_any(0); + jl_gc_wb(mi, mi->roots); + } + } jl_ircode_state s = { &dest, m, + mi, jl_current_task->ptls, 1 }; @@ -849,6 +994,9 @@ JL_DLLEXPORT jl_string_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code) if (jl_array_len(m->roots) == 0) { m->roots = NULL; } + if (mi != NULL && jl_array_len(mi->roots) == 0) { + mi->roots = NULL; + } JL_GC_PUSH1(&v); jl_gc_enable(en); JL_UNLOCK(&m->writelock); // Might GC @@ -865,6 +1013,11 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); assert(jl_is_string(data)); + assert(jl_is_code_instance(metadata)); + jl_method_instance_t *mi = NULL; + if (metadata != NULL && jl_is_method_instance(metadata->def)) { + mi = metadata->def; + } size_t i; ios_t src; ios_mem(&src, 0); @@ -874,6 +1027,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t jl_ircode_state s = { &src, m, + mi, jl_current_task->ptls, 1 }; diff --git a/src/jltypes.c b/src/jltypes.c index 444923f600569..bd3b39ee326ab 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3078,7 +3078,7 @@ 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(10, + jl_perm_symsvec(13, "def", "specTypes", "sparam_vals", @@ -3088,8 +3088,11 @@ void jl_init_types(void) JL_GC_DISABLED "cache", "inInference", "cache_with_orig", - "precompiled"), - jl_svec(10, + "precompiled", + "roots", // !const + "root_blocks", // !const + "nroots_sysimg"), + jl_svec(13, jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), jl_any_type, jl_simplevector_type, @@ -3099,7 +3102,10 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_bool_type, jl_bool_type, - jl_bool_type), + jl_bool_type, + jl_array_any_type, + jl_array_uint64_type, + jl_int32_type), jl_emptysvec, 0, 1, 3); // These fields should be constant, but Serialization wants to mutate them in initialization diff --git a/src/julia.h b/src/julia.h index 694a8d81b06e9..a9cb405f48f53 100644 --- a/src/julia.h +++ b/src/julia.h @@ -394,6 +394,12 @@ struct _jl_method_instance_t { uint8_t inInference; // flags to tell if inference is running on this object uint8_t cache_with_orig; // !cache_with_specTypes _Atomic(uint8_t) precompiled; // true if this instance was generated by an explicit `precompile(...)` call + + 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.lo, offset) pairs (even/odd indexing) + int32_t nroots_sysimg; // # of roots stored in the system image }; // OpaqueClosure diff --git a/src/julia_internal.h b/src/julia_internal.h index 87a35b80516c2..c4c7551fc72c1 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -640,9 +640,12 @@ int set_next_edge(jl_array_t *list, int i, jl_value_t *invokesig, jl_method_inst void push_edge(jl_array_t *list, jl_value_t *invokesig, jl_method_instance_t *caller); JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root); +JL_DLLEXPORT void jl_add_method_instance_root(jl_method_instance_t *m, jl_module_t *mod, jl_value_t* root); void jl_append_method_roots(jl_method_t *m, uint64_t modid, jl_array_t* roots); int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i) JL_NOTSAFEPOINT; +int get_root_reference_method_instance(rle_reference *rr, jl_method_instance_t *m, size_t i) JL_NOTSAFEPOINT; jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index) JL_NOTSAFEPOINT; +jl_value_t *lookup_root_method_instance(jl_method_instance_t *m, uint64_t key, int index) JL_NOTSAFEPOINT; int nroots_with_key(jl_method_t *m, uint64_t key) JL_NOTSAFEPOINT; int jl_valid_type_param(jl_value_t *v); diff --git a/src/method.c b/src/method.c index 06a05361a927d..d13307d95fe07 100644 --- a/src/method.c +++ b/src/method.c @@ -454,6 +454,9 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) mi->inInference = 0; mi->cache_with_orig = 0; jl_atomic_store_relaxed(&mi->precompiled, 0); + mi->roots = NULL; + mi->root_blocks = NULL; + mi->nroots_sysimg = 0; return mi; } @@ -1195,6 +1198,18 @@ static void prepare_method_for_roots(jl_method_t *m, uint64_t modid) } } +static void prepare_method_instance_for_roots(jl_method_instance_t *m, uint64_t modid) +{ + 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); + } +} + // Add a single root with owner `mod` to a method JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_t* root) { @@ -1204,7 +1219,6 @@ JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_ assert(jl_is_module(mod)); modid = mod->build_id.lo; } - assert(jl_is_method(m)); prepare_method_for_roots(m, modid); if (current_root_id(m->root_blocks) != modid) add_root_block(m->root_blocks, modid, jl_array_len(m->roots)); @@ -1212,6 +1226,22 @@ JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_ JL_GC_POP(); } +// Add a single root with owner `mod` to a method instance +JL_DLLEXPORT void jl_add_method_instance_root(jl_method_instance_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.lo; + } + prepare_method_instance_for_roots(m, modid); + 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(); +} + // Add a list of roots with key `modid` to a method void jl_append_method_roots(jl_method_t *m, uint64_t modid, jl_array_t* roots) { @@ -1239,6 +1269,19 @@ int get_root_reference(rle_reference *rr, jl_method_t *m, size_t i) return i < m->nroots_sysimg; } +int get_root_reference_method_instance(rle_reference *rr, jl_method_instance_t *m, size_t i) +{ + if (!m->root_blocks) { + rr->key = 0; + rr->index = i; + return i < m->nroots_sysimg; + } + rle_index_to_reference(rr, i, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0); + if (rr->key) + return 1; + return i < m->nroots_sysimg; +} + // get a root, given its key and index relative to the key // this is the relocatable way to get a root from m->roots jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index) @@ -1252,6 +1295,17 @@ jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index) return jl_array_ptr_ref(m->roots, i); } +jl_value_t *lookup_root_method_instance(jl_method_instance_t *m, uint64_t key, int index) +{ + if (!m->root_blocks) { + assert(key == 0); + return jl_array_ptr_ref(m->roots, index); + } + rle_reference rr = {key, index}; + size_t i = rle_reference_to_index(&rr, (uint64_t*)jl_array_data(m->root_blocks), jl_array_len(m->root_blocks), 0); + return jl_array_ptr_ref(m->roots, i); +} + // Count the number of roots added by module with id `key` int nroots_with_key(jl_method_t *m, uint64_t key) { diff --git a/src/serialize.h b/src/serialize.h index afcdcc31d66c4..a9ab5a6a3870c 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -64,8 +64,11 @@ extern "C" { #define TAG_ARGUMENT 56 #define TAG_RELOC_METHODROOT 57 #define TAG_BINDING 58 +#define TAG_METHODINSTANCEROOT 59 +#define TAG_LONG_METHODINSTANCEROOT 60 +#define TAG_RELOC_METHODINSTANCEROOT 61 -#define LAST_TAG 58 +#define LAST_TAG 61 #define write_uint8(s, n) ios_putc((n), (s)) #define read_uint8(s) ((uint8_t)ios_getc((s))) diff --git a/src/staticdata.c b/src/staticdata.c index df080bc68c88f..e246363c642fb 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1465,6 +1465,9 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED assert(f == s->s); jl_method_instance_t *newmi = (jl_method_instance_t*)&f->buf[reloc_offset]; jl_atomic_store_relaxed(&newmi->precompiled, 0); + if (!(s->incremental)) { + newmi->nroots_sysimg = newmi->roots ? jl_array_len(newmi->roots) : 0; + } } else if (jl_is_code_instance(v)) { assert(f == s->s); From efda907db011b9c902715c469ec31b4f396e02b1 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 01:37:48 -0400 Subject: [PATCH 2/9] Fixed! --- src/ircode.c | 114 ++++++++++++++++--------------------------- src/julia_internal.h | 1 + src/method.c | 17 +++++++ src/serialize.h | 6 +-- src/staticdata.c | 3 +- 5 files changed, 64 insertions(+), 77 deletions(-) diff --git a/src/ircode.c b/src/ircode.c index 853ff16b05f23..080d5fad8b3a5 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -141,51 +141,44 @@ static void jl_encode_as_indexed_root(jl_ircode_state *s, jl_value_t *v) } } +// Encode a method instance for storing with its method instance, as well as the method name +// as a method root as a fallback for when the method instance is not available. Intended +// mainly for storage of method instances associated with linetable entries. static void jl_encode_as_indexed_root_method_instance(jl_ircode_state *s, jl_value_t *v) { - // store the def name as fallback if method instance root table is not available - assert(jl_is_method_instance(v)); + rle_reference rr; - rle_reference rr_def; literal_val_id_method_instance(&rr, s, v); - - jl_value_t *def = ((jl_method_instance_t*)v)->def.value; - jl_sym_t *name = NULL; - if (jl_is_method(def)) - name = ((jl_method_t*)def)->name; - else if (jl_is_module(def)) - name = ((jl_module_t*)def)->name; - assert(name); - literal_val_id(&rr_def, s, (jl_value_t*)name); + int id = rr.index; - int id_def = rr_def.index; assert(id >= 0); - assert(id_def >= 0); if (rr.key) { - write_uint8(s->s, TAG_RELOC_METHODINSTANCEROOT); + write_uint8(s->s, TAG_RELOC_METHODINSTROOT); write_uint64(s->s, rr.key); - write_uint64(s->s, rr_def.key); } if (id <= UINT8_MAX) { - write_uint8(s->s, TAG_METHODINSTANCEROOT); + write_uint8(s->s, TAG_METHODINSTROOT); write_uint8(s->s, id); } else { assert(id <= UINT32_MAX); - write_uint8(s->s, TAG_LONG_METHODINSTANCEROOT); + write_uint8(s->s, TAG_LONG_METHODINSTROOT); write_uint32(s->s, id); } - if (id_def <= UINT8_MAX) { - write_uint8(s->s, TAG_METHODROOT); - write_uint8(s->s, id_def); + + jl_method_instance_t *mi = (jl_method_instance_t*)v; + jl_value_t* name = NULL; + if (jl_is_module(mi->def.value)) { + name = (jl_value_t*)mi->def.module->name; } - else { - assert(id_def <= UINT32_MAX); - write_uint8(s->s, TAG_LONG_METHODROOT); - write_uint32(s->s, id_def); + else if (jl_is_method(mi->def.value)) { + name = (jl_value_t*)mi->def.method->name; } + assert(name != NULL); + + jl_encode_as_indexed_root(s, name); } static void jl_encode_value_(jl_ircode_state *s, jl_value_t *v, int as_literal) JL_GC_DISABLED @@ -737,65 +730,40 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED return lookup_root(s->method, 0, read_uint8(s->s)); case TAG_LONG_METHODROOT: return lookup_root(s->method, 0, read_uint32(s->s)); - case TAG_RELOC_METHODINSTANCEROOT: + case TAG_RELOC_METHODINSTROOT: key = read_uint64(s->s); - uint64_t key_def = read_uint64(s->s); tag = read_uint8(s->s); - assert(tag == TAG_METHODINSTANCEROOT || tag == TAG_LONG_METHODINSTANCEROOT); + assert(tag == TAG_METHODINSTROOT || tag == TAG_LONG_METHODINSTROOT); index = -1; - if (tag == TAG_METHODINSTANCEROOT) + if (tag == TAG_METHODINSTROOT) index = read_uint8(s->s); - else if (tag == TAG_LONG_METHODINSTANCEROOT) + else if (tag == TAG_LONG_METHODINSTROOT) index = read_uint32(s->s); assert(index >= 0); - int index_def = -1; - tag = read_uint8(s->s); - assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); - if (tag == TAG_METHODROOT) - index_def = read_uint8(s->s); - else if (tag == TAG_LONG_METHODROOT) - index_def = read_uint32(s->s); - assert(index_def >= 0); - if (s->method_instance != NULL) { + jl_value_t *name = jl_decode_value(s); + assert(jl_is_symbol(name)); + if (s->method_instance != NULL) return lookup_root_method_instance(s->method_instance, key, index); - } - else { - return lookup_root(s->method, key_def, index_def); - } - case TAG_METHODINSTANCEROOT: + else + return name; + case TAG_METHODINSTROOT: index = read_uint8(s->s); assert(index >= 0); - tag = read_uint8(s->s); - assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); - index_def = -1; - if (tag == TAG_METHODROOT) - index_def = read_uint8(s->s); - else if (tag == TAG_LONG_METHODROOT) - index_def = read_uint32(s->s); - assert(index_def >= 0); - if (s->method_instance != NULL) { - return lookup_root_method_instance(s->method_instance, 0, index); - } - else { - return lookup_root(s->method, 0, index_def); - } - case TAG_LONG_METHODINSTANCEROOT: + name = jl_decode_value(s); + assert(jl_is_symbol(name)); + if (s->method_instance != NULL) + return lookup_root_method_instance(s->method_instance, key, index); + else + return name; + case TAG_LONG_METHODINSTROOT: index = read_uint32(s->s); assert(index >= 0); - tag = read_uint8(s->s); - assert(tag == TAG_METHODROOT || tag == TAG_LONG_METHODROOT); - index_def = -1; - if (tag == TAG_METHODROOT) - index_def = read_uint8(s->s); - else if (tag == TAG_LONG_METHODROOT) - index_def = read_uint32(s->s); - assert(index_def >= 0); - if (s->method_instance != NULL) { - return lookup_root_method_instance(s->method_instance, 0, index); - } - else { - return lookup_root(s->method, 0, index_def); - } + name = jl_decode_value(s); + assert(jl_is_symbol(name)); + if (s->method_instance != NULL) + return lookup_root_method_instance(s->method_instance, key, index); + else + return name; case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC: return jl_decode_value_svec(s, tag); case TAG_COMMONSYM: diff --git a/src/julia_internal.h b/src/julia_internal.h index c4c7551fc72c1..ea402a02607f0 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -647,6 +647,7 @@ int get_root_reference_method_instance(rle_reference *rr, jl_method_instance_t * jl_value_t *lookup_root(jl_method_t *m, uint64_t key, int index) JL_NOTSAFEPOINT; jl_value_t *lookup_root_method_instance(jl_method_instance_t *m, uint64_t key, int index) JL_NOTSAFEPOINT; int nroots_with_key(jl_method_t *m, uint64_t key) JL_NOTSAFEPOINT; +int nroots_with_key_method_instance(jl_method_instance_t *m, uint64_t key) JL_NOTSAFEPOINT; int jl_valid_type_param(jl_value_t *v); diff --git a/src/method.c b/src/method.c index d13307d95fe07..c66b89b3867e8 100644 --- a/src/method.c +++ b/src/method.c @@ -1324,6 +1324,23 @@ int nroots_with_key(jl_method_t *m, uint64_t key) return nwithkey; } +int nroots_with_key_method_instance(jl_method_instance_t *m, uint64_t key) +{ + size_t nroots = 0; + if (m->roots) + nroots = jl_array_len(m->roots); + if (!m->root_blocks) + return key == 0 ? nroots : 0; + uint64_t *rletable = (uint64_t*)jl_array_data(m->root_blocks); + size_t j, nblocks2 = jl_array_len(m->root_blocks); + int nwithkey = 0; + for (j = 0; j < nblocks2; j+=2) { + if (rletable[j] == key) + nwithkey += (j+3 < nblocks2 ? rletable[j+3] : nroots) - rletable[j+1]; + } + return nwithkey; +} + #ifdef __cplusplus } #endif diff --git a/src/serialize.h b/src/serialize.h index a9ab5a6a3870c..51bb3b081d1d9 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -64,9 +64,9 @@ extern "C" { #define TAG_ARGUMENT 56 #define TAG_RELOC_METHODROOT 57 #define TAG_BINDING 58 -#define TAG_METHODINSTANCEROOT 59 -#define TAG_LONG_METHODINSTANCEROOT 60 -#define TAG_RELOC_METHODINSTANCEROOT 61 +#define TAG_METHODINSTROOT 59 +#define TAG_LONG_METHODINSTROOT 60 +#define TAG_RELOC_METHODINSTROOT 61 #define LAST_TAG 61 diff --git a/src/staticdata.c b/src/staticdata.c index e246363c642fb..5b78d5f9aeca8 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1463,10 +1463,11 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED } else if (jl_is_method_instance(v)) { assert(f == s->s); + jl_method_instance_t *mi = (jl_method_instance_t*)v; jl_method_instance_t *newmi = (jl_method_instance_t*)&f->buf[reloc_offset]; jl_atomic_store_relaxed(&newmi->precompiled, 0); if (!(s->incremental)) { - newmi->nroots_sysimg = newmi->roots ? jl_array_len(newmi->roots) : 0; + newmi->nroots_sysimg = mi->roots ? jl_array_len(mi->roots) : 0; } } else if (jl_is_code_instance(v)) { From 90bb55d3fef39291879ac79a7c2e0501340652fa Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 02:18:23 -0400 Subject: [PATCH 3/9] Restore asserts --- src/method.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/method.c b/src/method.c index c66b89b3867e8..cf3572b25e50c 100644 --- a/src/method.c +++ b/src/method.c @@ -1219,6 +1219,7 @@ JL_DLLEXPORT void jl_add_method_root(jl_method_t *m, jl_module_t *mod, jl_value_ assert(jl_is_module(mod)); modid = mod->build_id.lo; } + assert(jl_is_method(m)); prepare_method_for_roots(m, modid); if (current_root_id(m->root_blocks) != modid) add_root_block(m->root_blocks, modid, jl_array_len(m->roots)); @@ -1235,6 +1236,7 @@ JL_DLLEXPORT void jl_add_method_instance_root(jl_method_instance_t *m, jl_module assert(jl_is_module(mod)); modid = mod->build_id.lo; } + assert(jl_is_method_instance(m)); prepare_method_instance_for_roots(m, modid); if (current_root_id(m->root_blocks) != modid) add_root_block(m->root_blocks, modid, jl_array_len(m->roots)); From cc766ccf1c2fbddac2e39864641a89bcfe9cdf85 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 11:04:04 -0400 Subject: [PATCH 4/9] Remove bad arg --- src/ircode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ircode.c b/src/ircode.c index 080d5fad8b3a5..a4d1211b3b0ba 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -752,7 +752,7 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED name = jl_decode_value(s); assert(jl_is_symbol(name)); if (s->method_instance != NULL) - return lookup_root_method_instance(s->method_instance, key, index); + return lookup_root_method_instance(s->method_instance, 0, index); else return name; case TAG_LONG_METHODINSTROOT: @@ -761,7 +761,7 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED name = jl_decode_value(s); assert(jl_is_symbol(name)); if (s->method_instance != NULL) - return lookup_root_method_instance(s->method_instance, key, index); + return lookup_root_method_instance(s->method_instance, 0, index); else return name; case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC: From 6434a845d02c098cf5bc492d8654facc535ba669 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 11:04:20 -0400 Subject: [PATCH 5/9] Add CI to uncompress for inlining --- base/compiler/ssair/inlining.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 17df27bd5f637..0260859fa43cb 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -981,7 +981,7 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any}, end function retrieve_ir_for_inlining(mi::MethodInstance, src::String) - src = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), mi.def, C_NULL, src)::CodeInfo + src = ccall(:jl_uncompress_ir, Any, (Any, Any, Any), mi.def, mi.cache, src)::CodeInfo return inflate_ir!(src, mi) end retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo) = inflate_ir(src, mi) From 293f6a4408c74302ecfb3ff72cd64882b99f3e1f Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 11:27:57 -0400 Subject: [PATCH 6/9] Moved last common symbols from 8-bit encoding to extended array --- src/common_symbols1.inc | 3 --- src/common_symbols2.inc | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common_symbols1.inc b/src/common_symbols1.inc index 547d5d0eabede..8daf16f252c0d 100644 --- a/src/common_symbols1.inc +++ b/src/common_symbols1.inc @@ -93,6 +93,3 @@ jl_symbol("promote"), jl_symbol("unsigned"), jl_symbol("is_top_bit_set"), jl_symbol("structdiff"), -jl_symbol("undef"), -jl_symbol("sizeof"), -jl_symbol("String"), diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index b5a334172dd76..dba471a38bc0c 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -1,3 +1,6 @@ +jl_symbol("undef"), +jl_symbol("sizeof"), +jl_symbol("String"), jl_symbol("namedtuple.jl"), jl_symbol("pop"), jl_symbol("inbounds"), From 196e836a045be17c7d49eee114c9a38450f63f65 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 12:23:42 -0400 Subject: [PATCH 7/9] Adjust gen_sysimg_symtab.jl --- src/gen_sysimg_symtab.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gen_sysimg_symtab.jl b/src/gen_sysimg_symtab.jl index 8f03cc1560767..2fccc8c125f23 100644 --- a/src/gen_sysimg_symtab.jl +++ b/src/gen_sysimg_symtab.jl @@ -69,5 +69,5 @@ function outputline(io, name) println(io, "jl_symbol(\"", name, "\"),") end -open(f->foreach(l->outputline(f,l), take(syms, 100)), "common_symbols1.inc", "w") -open(f->foreach(l->outputline(f,l), take(drop(syms, 100), 254)), "common_symbols2.inc", "w") +open(f->foreach(l->outputline(f,l), take(syms, 97)), "common_symbols1.inc", "w") +open(f->foreach(l->outputline(f,l), take(drop(syms, 97), 254)), "common_symbols2.inc", "w") From 272f90e9f379a185e1c88c087f66292cc5285f8b Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 12:45:31 -0400 Subject: [PATCH 8/9] Remove end symbols from extended list --- src/common_symbols2.inc | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/common_symbols2.inc b/src/common_symbols2.inc index dba471a38bc0c..b3147a017c4b0 100644 --- a/src/common_symbols2.inc +++ b/src/common_symbols2.inc @@ -252,6 +252,3 @@ jl_symbol("filemode"), jl_symbol("ComplexF64"), jl_symbol("SparseMatrixCSC"), jl_symbol("view"), -jl_symbol("GitError"), -jl_symbol("zeros"), -jl_symbol("InexactError"), From c4ebff3c29af9531ff0138bc2e32c76580b36bca Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Sat, 17 Jun 2023 12:49:55 -0400 Subject: [PATCH 9/9] Allow null metadata arg --- src/ircode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ircode.c b/src/ircode.c index a4d1211b3b0ba..04d00f9c18c9d 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -981,7 +981,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); assert(jl_is_string(data)); - assert(jl_is_code_instance(metadata)); + assert(metadata == NULL || jl_is_code_instance(metadata)); jl_method_instance_t *mi = NULL; if (metadata != NULL && jl_is_method_instance(metadata->def)) { mi = metadata->def;