From f3039b8f5f256273b850a2d4a3397e05124b4826 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Fri, 18 Sep 2020 16:32:48 -0400 Subject: [PATCH] restore type cache pruning in sysimage saving --- src/dump.c | 12 ------- src/jltypes.c | 9 +++--- src/staticdata.c | 81 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/dump.c b/src/dump.c index d6a96ac3a7f01..4206f1a3d7d26 100644 --- a/src/dump.c +++ b/src/dump.c @@ -78,7 +78,6 @@ static jl_value_t *jl_idtable_type = NULL; static jl_typename_t *jl_idtable_typename = NULL; static jl_value_t *jl_bigint_type = NULL; static int gmp_limb_size = 0; -static arraylist_t builtin_typenames; static void write_uint64(ios_t *s, uint64_t i) JL_NOTSAFEPOINT { @@ -2677,17 +2676,6 @@ void jl_init_serializer(void) i += 1; } assert(i <= 256); - - arraylist_new(&builtin_typenames, 0); - arraylist_push(&builtin_typenames, jl_array_typename); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_ref_type->body)->name); - arraylist_push(&builtin_typenames, jl_pointer_typename); - arraylist_push(&builtin_typenames, jl_type_typename); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_abstractarray_type))->name); - arraylist_push(&builtin_typenames, ((jl_datatype_t*)jl_unwrap_unionall((jl_value_t*)jl_densearray_type))->name); - arraylist_push(&builtin_typenames, jl_tuple_typename); - arraylist_push(&builtin_typenames, jl_vararg_typename); - arraylist_push(&builtin_typenames, jl_namedtuple_typename); } #ifdef __cplusplus diff --git a/src/jltypes.c b/src/jltypes.c index b7a58a3610027..94eef9c50d9ce 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -633,7 +633,7 @@ static jl_datatype_t *lookup_type_set(jl_svec_t *cache, jl_value_t **key, size_t jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]); if (val == NULL) return NULL; - if (val->hash == hv && typekey_eq(val, key, n)) + if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekey_eq(val, key, n)) return val; index = (index + 1) & (sz - 1); iter++; @@ -656,7 +656,7 @@ static jl_datatype_t *lookup_type_setvalue(jl_svec_t *cache, jl_value_t *key1, j jl_datatype_t *val = jl_atomic_load_relaxed(&tab[index]); if (val == NULL) return NULL; - if (val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf)) + if ((jl_value_t*)val != jl_nothing && val->hash == hv && typekeyvalue_eq(val, key1, key, n, leaf)) return val; index = (index + 1) & (sz - 1); iter++; @@ -744,7 +744,8 @@ static int cache_insert_type_set_(jl_svec_t *a, jl_datatype_t *val, uint_t hv) orig = index; size_t maxprobe = max_probe(sz); do { - if (tab[index] == NULL) { + jl_value_t *tab_i = (jl_value_t*)tab[index]; + if (tab_i == NULL || tab_i == jl_nothing) { jl_atomic_store_release(&tab[index], val); jl_gc_wb(a, val); return 1; @@ -794,7 +795,7 @@ static jl_svec_t *cache_rehash_set(jl_svec_t *a, size_t newsz) JL_GC_PUSH1(&newa); for (i = 0; i < sz; i += 1) { jl_datatype_t *val = ol[i]; - if (val != NULL) { + if (val != NULL && (jl_value_t*)val != jl_nothing) { uint_t hv = val->hash; if (!cache_insert_type_set_(newa, val, hv)) { break; diff --git a/src/staticdata.c b/src/staticdata.c index 9726b676a529e..ddc5f2f9dc335 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -99,7 +99,6 @@ static arraylist_t deser_sym; static htable_t backref_table; static int backref_table_numel; static arraylist_t layout_table; -static arraylist_t builtin_typenames; // list of (size_t pos, (void *f)(jl_value_t*)) entries // for the serializer to mark values in need of rework by function f @@ -259,8 +258,8 @@ static uintptr_t jl_fptr_id(void *fptr) return *(uintptr_t*)pbp; } -#define jl_serialize_value(s, v) jl_serialize_value_(s,(jl_value_t*)(v)) -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v); +#define jl_serialize_value(s, v) jl_serialize_value_(s,(jl_value_t*)(v),1) +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int recursive); static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m) @@ -287,7 +286,7 @@ static void jl_serialize_module(jl_serializer_state *s, jl_module_t *m) #define NBOX_C 1024 -static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) +static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int recursive) { // ignore items that are given a special representation if (v == NULL || jl_is_symbol(v)) { @@ -331,6 +330,8 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) // skip it } else if (jl_is_svec(v)) { + if (!recursive) + return; size_t i, l = jl_svec_len(v); jl_value_t **data = jl_svec_data(v); for (i = 0; i < l; i++) { @@ -366,6 +367,17 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v) else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); } + else if (jl_is_typename(v)) { + jl_typename_t *tn = (jl_typename_t*)v; + jl_serialize_value(s, tn->name); + jl_serialize_value(s, tn->module); + jl_serialize_value(s, tn->names); + jl_serialize_value(s, tn->wrapper); + jl_serialize_value_(s, (jl_value_t*)tn->cache, 0); + jl_serialize_value_(s, (jl_value_t*)tn->linearcache, 0); + jl_serialize_value(s, tn->mt); + jl_serialize_value(s, tn->partial); + } else if (t->layout->nfields > 0) { char *data = (char*)jl_data_ptr(v); size_t i, np = t->layout->npointers; @@ -1235,7 +1247,7 @@ static void jl_finalize_serializer(jl_serializer_state *s, arraylist_t *list) } -static void jl_reinit_item(jl_value_t *v, int how) +static void jl_reinit_item(jl_value_t *v, int how) JL_GC_DISABLED { switch (how) { case 1: { // rehash IdDict @@ -1280,7 +1292,7 @@ static void jl_reinit_item(jl_value_t *v, int how) } -static void jl_finalize_deserializer(jl_serializer_state *s) +static void jl_finalize_deserializer(jl_serializer_state *s) JL_GC_DISABLED { // run reinitialization functions uintptr_t base = (uintptr_t)&s->s->buf[0]; @@ -1298,21 +1310,40 @@ static void jl_finalize_deserializer(jl_serializer_state *s) // --- helper functions --- // remove cached types not referenced in the stream -static void jl_prune_type_cache(jl_svec_t *cache) +static int keep_type_cache_entry(jl_value_t *ti) +{ + if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND || jl_get_llvm_gv(native_functions, ti) != 0) + return 1; + if (jl_is_datatype(ti)) { + jl_value_t *singleton = ((jl_datatype_t*)ti)->instance; + if (singleton && (ptrhash_get(&backref_table, singleton) != HT_NOTFOUND || + jl_get_llvm_gv(native_functions, singleton) != 0)) + return 1; + } + return 0; +} + +static void jl_prune_type_cache_hash(jl_svec_t *cache) +{ + size_t l = jl_svec_len(cache), i; + for (i = 0; i < l; i++) { + jl_value_t *ti = jl_svecref(cache, i); + if (ti == NULL || ti == jl_nothing) + continue; + if (!keep_type_cache_entry(ti)) + jl_svecset(cache, i, jl_nothing); + } +} + +static void jl_prune_type_cache_linear(jl_svec_t *cache) { size_t l = jl_svec_len(cache), ins = 0, i; for (i = 0; i < l; i++) { jl_value_t *ti = jl_svecref(cache, i); if (ti == NULL) break; - if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND || jl_get_llvm_gv(native_functions, ti) != 0) + if (keep_type_cache_entry(ti)) jl_svecset(cache, ins++, ti); - else if (jl_is_datatype(ti)) { - jl_value_t *singleton = ((jl_datatype_t*)ti)->instance; - if (singleton && (ptrhash_get(&backref_table, singleton) != HT_NOTFOUND || - jl_get_llvm_gv(native_functions, singleton) != 0)) - jl_svecset(cache, ins++, ti); - } } if (i > ins) { memset(&jl_svec_data(cache)[ins], 0, (i - ins) * sizeof(jl_value_t*)); @@ -1325,7 +1356,7 @@ static void jl_prune_type_cache(jl_svec_t *cache) static void jl_init_serializer2(int); static void jl_cleanup_serializer2(void); -static void jl_save_system_image_to_stream(ios_t *f) +static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED { jl_gc_collect(JL_GC_FULL); jl_gc_collect(JL_GC_INCREMENTAL); // sweep finalizers @@ -1376,15 +1407,13 @@ static void jl_save_system_image_to_stream(ios_t *f) jl_value_t *tag = *tags[i]; jl_serialize_value(&s, tag); } - for (i = 0; i < builtin_typenames.len; i++) { - jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; - jl_prune_type_cache(tn->cache); - jl_prune_type_cache(tn->linearcache); - } - for (i = 0; i < builtin_typenames.len; i++) { - jl_typename_t *tn = (jl_typename_t*)builtin_typenames.items[i]; - jl_serialize_value(&s, tn->cache); - jl_serialize_value(&s, tn->linearcache); + // prune unused entries from built-in type caches + for (i = 0; i < backref_table.size; i += 2) { + jl_typename_t *tn = (jl_typename_t*)backref_table.table[i]; + if (tn == HT_NOTFOUND || !jl_is_typename(tn)) + continue; + jl_prune_type_cache_hash(tn->cache); + jl_prune_type_cache_linear(tn->linearcache); } } @@ -1509,7 +1538,7 @@ JL_DLLEXPORT void jl_set_sysimg_so(void *handle) sysimg_fptrs = jl_init_processor_sysimg(handle); } -static void jl_restore_system_image_from_stream(ios_t *f) +static void jl_restore_system_image_from_stream(ios_t *f) JL_GC_DISABLED { JL_TIMING(SYSIMG_LOAD); int en = jl_gc_enable(0); @@ -1686,7 +1715,6 @@ static void jl_init_serializer2(int for_serialize) htable_new(&symbol_table, 0); htable_new(&fptr_to_id, sizeof(id_to_fptrs) / sizeof(*id_to_fptrs)); htable_new(&backref_table, 0); - arraylist_new(&builtin_typenames, 0); uintptr_t i; for (i = 0; id_to_fptrs[i] != NULL; i++) { ptrhash_put(&fptr_to_id, (void*)(uintptr_t)id_to_fptrs[i], (void*)(i + 2)); @@ -1704,7 +1732,6 @@ static void jl_cleanup_serializer2(void) htable_reset(&fptr_to_id, 0); htable_reset(&backref_table, 0); arraylist_free(&deser_sym); - arraylist_free(&builtin_typenames); } #ifdef __cplusplus