Skip to content

Commit 08def6b

Browse files
authored
Merge pull request adafruit#1052 from dhalbert/speed-up-dict-long-lived
Prevent repetitive recursive scanning of dicts when making them long-…
2 parents 85a5276 + be1d882 commit 08def6b

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

py/gc_long_lived.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ mp_obj_dict_t *make_dict_long_lived(mp_obj_dict_t *dict, uint8_t max_depth) {
9191
if (dict == NULL || max_depth == 0) {
9292
return dict;
9393
}
94+
// Don't recurse unnecessarily. Return immediately if we've already seen this dict.
95+
if (dict->map.scanning) {
96+
return dict;
97+
}
98+
// Mark that we're processing this dict.
99+
dict->map.scanning = 1;
100+
94101
// Update all of the references first so that we reduce the chance of references to the old
95102
// copies.
96103
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) {
100107
dict->map.table[i].value = make_obj_long_lived(value, max_depth - 1);
101108
}
102109
}
103-
return gc_make_long_lived(dict);
110+
dict = gc_make_long_lived(dict);
111+
// Done recursing through this dict.
112+
dict->map.scanning = 0;
113+
return dict;
104114
}
105115

106116
mp_obj_str_t *make_str_long_lived(mp_obj_str_t *str) {

py/obj.h

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

0 commit comments

Comments
 (0)