summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott@tannewt.org>2018-07-23 18:17:08 -0700
committerGitHub <noreply@github.com>2018-07-23 18:17:08 -0700
commit08def6b51ecb9853ccbe21fc6feecbb18cc3e387 (patch)
treef40d5269a71138367f49f70fcdf39adeccb204a9
parent85a5276f36fb8b1be981d3155e4f0ef0c4cf72df (diff)
parentbe1d882a8b5d2878c9b4402ae641abf9a88cd682 (diff)
Merge pull request #1052 from dhalbert/speed-up-dict-long-lived
Prevent repetitive recursive scanning of dicts when making them long-…
-rw-r--r--py/gc_long_lived.c12
-rw-r--r--py/obj.h4
2 files changed, 14 insertions, 2 deletions
diff --git a/py/gc_long_lived.c b/py/gc_long_lived.c
index d34fde5d9..dd5f0e8fd 100644
--- a/py/gc_long_lived.c
+++ b/py/gc_long_lived.c
@@ -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) {
diff --git a/py/obj.h b/py/obj.h
index d086d3c14..8e95983f0 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -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;