From 3679a47eb064850406f473bc435c36d95017c16e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 29 Mar 2022 12:11:42 -0500 Subject: [PATCH] py/runtime: Do not overallocate when len is known. This fixes overallocating an extra mp_obj_t when the length of *args and **args is known. Previously we were allocating 1 mp_obj_t for each n_args and n_kw plus the length of each *arg and **arg (if they are known). Since n_args includes *args and n_kw includes **args, this was allocating an extra mp_obj_t in addition to the length of these args when unpacked. To fix this, we just subtract 1 from the length to account for the 1 already implicitly allocated by n_args and n_kw. Signed-off-by: David Lechner --- py/runtime.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/py/runtime.c b/py/runtime.c index 90722ee18a..95990197d0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -715,27 +715,29 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ uint args2_len = 0; // Try to get a hint for unpacked * args length - uint list_len = 0; + int list_len = 0; if (star_args != 0) { for (uint i = 0; i < n_args; i++) { if (star_args & (1 << i)) { mp_obj_t len = mp_obj_len_maybe(args[i]); if (len != MP_OBJ_NULL) { - list_len += mp_obj_get_int(len); + // -1 accounts for 1 of n_args occupied by this arg + list_len += mp_obj_get_int(len) - 1; } } } } // Try to get a hint for the size of the kw_dict - uint kw_dict_len = 0; + int kw_dict_len = 0; for (uint i = 0; i < n_kw; i++) { mp_obj_t key = args[n_args + i * 2]; mp_obj_t value = args[n_args + i * 2 + 1]; if (key == MP_OBJ_NULL && value != MP_OBJ_NULL && mp_obj_is_type(value, &mp_type_dict)) { - kw_dict_len += mp_obj_dict_len(value); + // -1 accounts for 1 of n_kw occupied by this arg + kw_dict_len += mp_obj_dict_len(value) - 1; } }