Skip to content
Snippets Groups Projects
Commit 265500c5 authored by Damien George's avatar Damien George
Browse files

py/objnamedtuple: Simplify and remove use of alloca building namedtuple.

Prior to this patch there were 2 paths for creating the namedtuple, one for
when no keyword args were passed, and one when there were keyword args.
And alloca was used in the keyword-arg path to temporarily create the array
of elements for the namedtuple, which would then be copied to a
heap-allocated object (the namedtuple itself).

This patch simplifies the code by combining the no-keyword and keyword
paths, and removing the need for the alloca by constructing the namedtuple
on the heap before populating it.

Heap usage in unchanged, stack usage is reduced, use of alloca is removed,
and code size is not increased and is actually reduced by between 20-30
bytes for most ports.
parent 1942f0ce
No related branches found
No related tags found
No related merge requests found
...@@ -94,18 +94,15 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, ...@@ -94,18 +94,15 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
} }
} }
mp_obj_t *arg_objects; // Create a tuple and set the type to this namedtuple
if (n_args == num_fields) { mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, NULL));
arg_objects = (mp_obj_t*)args; tuple->base.type = type_in;
} else {
size_t alloc_size = sizeof(mp_obj_t) * num_fields;
arg_objects = alloca(alloc_size);
memset(arg_objects, 0, alloc_size);
for (size_t i = 0; i < n_args; i++) { // Copy the positional args into the first slots of the namedtuple
arg_objects[i] = args[i]; memcpy(&tuple->items[0], args, sizeof(mp_obj_t) * n_args);
}
// Fill in the remaining slots with the keyword args
memset(&tuple->items[n_args], 0, sizeof(mp_obj_t) * n_kw);
for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) { for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) {
qstr kw = mp_obj_str_get_qstr(args[i]); qstr kw = mp_obj_str_get_qstr(args[i]);
size_t id = namedtuple_find_field(type, kw); size_t id = namedtuple_find_field(type, kw);
...@@ -117,7 +114,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, ...@@ -117,7 +114,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
"unexpected keyword argument '%q'", kw)); "unexpected keyword argument '%q'", kw));
} }
} }
if (arg_objects[id] != MP_OBJ_NULL) { if (tuple->items[id] != MP_OBJ_NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_arg_error_terse_mismatch(); mp_arg_error_terse_mismatch();
} else { } else {
...@@ -125,12 +122,9 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, ...@@ -125,12 +122,9 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
"function got multiple values for argument '%q'", kw)); "function got multiple values for argument '%q'", kw));
} }
} }
arg_objects[id] = args[i + 1]; tuple->items[id] = args[i + 1];
}
} }
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, arg_objects));
tuple->base.type = type_in;
return MP_OBJ_FROM_PTR(tuple); return MP_OBJ_FROM_PTR(tuple);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment