diff --git a/src/dump.c b/src/dump.c index 34e1b8c83c7ef..2aba78823df91 100644 --- a/src/dump.c +++ b/src/dump.c @@ -57,11 +57,6 @@ static arraylist_t flagref_list; // during deserialization later static arraylist_t reinit_list; -// list of any methtable objects that were deserialized in MODE_MODULE -// and need to be rehashed after assigning the uid fields to types -// (only used in MODE_MODULE and MODE_MODULE_POSTWORK) -static arraylist_t methtable_list; - // list of stuff that is being serialized // (only used by the incremental serializer in MODE_MODULE) static jl_array_t *serializer_worklist; @@ -708,6 +703,17 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) arraylist_push(&reinit_list, (void*)2); } } + if (mode == MODE_MODULE || mode == MODE_MODULE_POSTWORK) { + // TypeMapLevels need to be rehashed + if (jl_is_mtable(v)) { + arraylist_push(&reinit_list, (void*)pos); + arraylist_push(&reinit_list, (void*)3); + } + if (jl_is_method(v) && jl_typeof(((jl_method_t*)v)->tfunc.unknown) == (jl_value_t*)jl_typemap_level_type) { + arraylist_push(&reinit_list, (void*)pos); + arraylist_push(&reinit_list, (void*)4); + } + } if (mode == MODE_MODULE || mode == MODE_MODULE_POSTWORK) pos <<= 1; ptrhash_put(&backref_table, v, (char*)HT_NOTFOUND + pos + 1); @@ -896,15 +902,56 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) write_int32(s, t->size); } jl_serialize_value(s, t); - if ((mode == MODE_MODULE || mode == MODE_MODULE_POSTWORK) && t == jl_typename_type) { - if (module_in_worklist(((jl_typename_t*)v)->module)) { - write_uint8(s, 0); + if ((mode == MODE_MODULE || mode == MODE_MODULE_POSTWORK)) { + if (t == jl_typename_type) { + if (module_in_worklist(((jl_typename_t*)v)->module)) { + write_uint8(s, 0); + } + else { + write_uint8(s, 1); + jl_typename_t *tn = (jl_typename_t*)v; + jl_serialize_value(s, tn->module); + jl_serialize_value(s, tn->name); + return; + } } - else { - write_uint8(s, 1); - jl_typename_t *tn = (jl_typename_t*)v; - jl_serialize_value(s, tn->module); - jl_serialize_value(s, tn->name); + if (t == jl_typemap_level_type) { + // perform some compression on the typemap levels + // (which will need to be rehashed during deserialization anyhow) + jl_typemap_level_t *node = (jl_typemap_level_t*)v; + size_t i, l; + assert( // make sure this type has the expected ordering + offsetof(jl_typemap_level_t, arg1) == 0 * sizeof(jl_value_t*) && + offsetof(jl_typemap_level_t, targ) == 1 * sizeof(jl_value_t*) && + offsetof(jl_typemap_level_t, linear) == 2 * sizeof(jl_value_t*) && + offsetof(jl_typemap_level_t, key) == 3 * sizeof(jl_value_t*) && + sizeof(jl_typemap_level_t) == 4 * sizeof(jl_value_t*)); + if (node->arg1 != (void*)jl_nothing) { + jl_array_t *a = jl_alloc_cell_1d(0); + for (i = 0, l = jl_array_len(node->arg1); i < l; i++) { + jl_value_t *d = jl_cellref(node->arg1, i); + if (d != NULL && d != jl_nothing) + jl_cell_1d_push(a, d); + } + jl_serialize_value(s, a); + } + else { + jl_serialize_value(s, jl_nothing); + } + if (node->targ != (void*)jl_nothing) { + jl_array_t *a = jl_alloc_cell_1d(0); + for (i = 0, l = jl_array_len(node->targ); i < l; i++) { + jl_value_t *d = jl_cellref(node->targ, i); + if (d != NULL && d != jl_nothing) + jl_cell_1d_push(a, d); + } + jl_serialize_value(s, a); + } + else { + jl_serialize_value(s, jl_nothing); + } + jl_serialize_value(s, node->linear); + jl_serialize_value(s, node->key); return; } } @@ -1473,7 +1520,7 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t NWORDS(sizeof(jl_method_t))); if (usetable) arraylist_push(&backref_list, m); - m->tfunc = (union jl_typemap_t)jl_deserialize_value(s, (jl_value_t**)&m->tfunc); + m->tfunc.unknown = jl_deserialize_value(s, (jl_value_t**)&m->tfunc); jl_gc_wb(m, m->tfunc.unknown); m->name = (jl_sym_t*)jl_deserialize_value(s, NULL); jl_gc_wb(m, m->name); @@ -1670,8 +1717,6 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t } } if ((mode == MODE_MODULE || mode == MODE_MODULE_POSTWORK)) { - if (jl_is_mtable(v)) - arraylist_push(&methtable_list, v); // will resort this table, later if (dt == jl_typename_type) { jl_typename_t *tn = (jl_typename_t*)v; tn->uid = jl_assign_type_uid(); // make sure this has a new uid @@ -1825,6 +1870,7 @@ static void jl_finalize_serializer(ios_t *f) { write_int32(f, -1); } +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); static void jl_reinit_item(ios_t *f, jl_value_t *v, int how) { JL_TRY { switch (how) { @@ -1854,6 +1900,17 @@ static void jl_reinit_item(ios_t *f, jl_value_t *v, int how) { jl_gc_wb_binding(b, v); break; } + case 3: { // rehash MethodTable + jl_methtable_t *mt = (jl_methtable_t*)v; + jl_typemap_rehash(mt->defs, 0); + jl_typemap_rehash(mt->cache, (mt == jl_type_type->name->mt) ? 0 : 1); + break; + } + case 4: { // rehash tfunc + jl_method_t *m = (jl_method_t*)v; + jl_typemap_rehash(m->tfunc, 0); + break; + } default: assert(0); } @@ -2319,7 +2376,6 @@ static void jl_recache_types(void) } } -void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); static jl_array_t *_jl_restore_incremental(ios_t *f) { if (ios_eof(f)) { @@ -2338,7 +2394,6 @@ static jl_array_t *_jl_restore_incremental(ios_t *f) arraylist_new(&backref_list, 4000); arraylist_push(&backref_list, jl_main_module); arraylist_new(&flagref_list, 0); - arraylist_new(&methtable_list, 0); int en = jl_gc_enable(0); DUMP_MODES last_mode = mode; @@ -2356,18 +2411,9 @@ static jl_array_t *_jl_restore_incremental(ios_t *f) jl_deserialize_lambdas_from_mod(f); // hook up methods of external generic functions init_order = jl_finalize_deserializer(f); // done with f - // Resort the internal method tables - size_t i; - for (i = 0; i < methtable_list.len; i++) { - jl_methtable_t *mt = (jl_methtable_t*)methtable_list.items[i]; - int8_t offs = (mt == jl_type_type->name->mt) ? 0 : 1; - jl_typemap_rehash(mt->cache, offs); - } - mode = last_mode; jl_gc_enable(en); arraylist_free(&flagref_list); - arraylist_free(&methtable_list); arraylist_free(&backref_list); ios_close(f); JL_UNLOCK(dump); diff --git a/src/gf.c b/src/gf.c index f22ac590e7823..e9132f318c73e 100644 --- a/src/gf.c +++ b/src/gf.c @@ -126,7 +126,7 @@ static int sig_match_by_type_simple(jl_value_t **types, size_t n, jl_tupletype_t if (jl_is_type_type(a)) // decl is not Type, because it would be caught above a = jl_typeof(jl_tparam0(a)); if (!jl_types_equal(a, decl)) - return 0; + return 0; } } return 1; @@ -204,9 +204,11 @@ static inline union jl_typemap_t mtcache_hash_lookup(jl_array_t *a, jl_value_t *ty, int8_t tparam, int8_t offs) { uintptr_t uid = ((jl_datatype_t*)ty)->uid; + union jl_typemap_t ml; + ml.unknown = jl_nothing; if (!uid) - return (union jl_typemap_t)jl_nothing; - union jl_typemap_t ml = (union jl_typemap_t)jl_cellref(a, uid & (a->nrows-1)); + return ml; + ml.unknown = jl_cellref(a, uid & (a->nrows-1)); if (ml.unknown != NULL && ml.unknown != jl_nothing) { jl_value_t *t; if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { @@ -220,7 +222,8 @@ union jl_typemap_t mtcache_hash_lookup(jl_array_t *a, jl_value_t *ty, int8_t tpa if (t == ty) return ml; } - return (union jl_typemap_t)jl_nothing; + ml.unknown = jl_nothing; + return ml; } static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t tparam, int8_t offs) @@ -230,8 +233,9 @@ static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t tparam, i jl_array_t *n = jl_alloc_cell_1d(len*2); jl_value_t **nd = (jl_value_t**)n->data; size_t i; - for(i=0; i < len; i++) { - union jl_typemap_t ml = (union jl_typemap_t)d[i]; + for (i = 0; i < len; i++) { + union jl_typemap_t ml; + ml.unknown = d[i]; if (ml.unknown != NULL && ml.unknown != jl_nothing) { jl_value_t *t; if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { @@ -250,10 +254,24 @@ static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t tparam, i *pa = n; } +// Recursively rehash a TypeMap (for example, after deserialization) +void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs); +void jl_typemap_rehash_array(jl_array_t **pa, jl_value_t *parent, int8_t tparam, int8_t offs) { + size_t i, len = (*pa)->nrows; + for (i = 0; i < len; i++) { + union jl_typemap_t ml; + ml.unknown = jl_cellref(*pa, i); + assert(ml.unknown != NULL); + jl_typemap_rehash(ml, offs+1); + } + mtcache_rehash(pa, parent, tparam, offs); +} void jl_typemap_rehash(union jl_typemap_t ml, int8_t offs) { if (jl_typeof(ml.unknown) == (jl_value_t*)jl_typemap_level_type) { - mtcache_rehash(&ml.node->targ, ml.unknown, 1, offs); - mtcache_rehash(&ml.node->arg1, ml.unknown, 0, offs); + if (ml.node->targ != (void*)jl_nothing) + jl_typemap_rehash_array(&ml.node->targ, ml.unknown, 1, offs); + if (ml.node->arg1 != (void*)jl_nothing) + jl_typemap_rehash_array(&ml.node->arg1, ml.unknown, 0, offs); } }