Skip to content

Commit

Permalink
fix rehashing logic for incremental serializer
Browse files Browse the repository at this point in the history
plus pack the TypeMapLevel tables when serializing them to maybe save a
bit of space
  • Loading branch information
vtjnash committed Apr 15, 2016
1 parent 99dbe07 commit f4f1ee5
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 35 deletions.
100 changes: 73 additions & 27 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
Expand All @@ -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);
Expand Down
34 changes: 26 additions & 8 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
Expand All @@ -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) {
Expand All @@ -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);
}
}

Expand Down

0 comments on commit f4f1ee5

Please sign in to comment.