Prevent repetitive recursive scanning of dicts when making them long-lived

This commit is contained in:
Dan Halbert 2018-07-19 15:19:21 -04:00
parent 85a5276f36
commit be1d882a8b
2 changed files with 14 additions and 2 deletions

View File

@ -91,6 +91,13 @@ mp_obj_dict_t *make_dict_long_lived(mp_obj_dict_t *dict, uint8_t max_depth) {
if (dict == NULL || max_depth == 0) {
return dict;
}
// Don't recurse unnecessarily. Return immediately if we've already seen this dict.
if (dict->map.scanning) {
return dict;
}
// Mark that we're processing this dict.
dict->map.scanning = 1;
// Update all of the references first so that we reduce the chance of references to the old
// copies.
dict->map.table = gc_make_long_lived(dict->map.table);
@ -100,7 +107,10 @@ mp_obj_dict_t *make_dict_long_lived(mp_obj_dict_t *dict, uint8_t max_depth) {
dict->map.table[i].value = make_obj_long_lived(value, max_depth - 1);
}
}
return gc_make_long_lived(dict);
dict = gc_make_long_lived(dict);
// Done recursing through this dict.
dict->map.scanning = 0;
return dict;
}
mp_obj_str_t *make_str_long_lived(mp_obj_str_t *str) {

View File

@ -359,7 +359,9 @@ typedef struct _mp_map_t {
size_t all_keys_are_qstrs : 1;
size_t is_fixed : 1; // a fixed array that can't be modified; must also be ordered
size_t is_ordered : 1; // an ordered array
size_t used : (8 * sizeof(size_t) - 3);
size_t scanning : 1; // true if we're in the middle of scanning linked dictionaries,
// e.g., make_dict_long_lived()
size_t used : (8 * sizeof(size_t) - 4);
size_t alloc;
mp_map_elem_t *table;
} mp_map_t;