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

py/objboundmeth: Allocate arg state on stack if heap alloc fails.

If the heap is locked, or memory allocation fails, then calling a bound
method will still succeed by allocating the argument state on the stack.

The new code also allocates less stack than before if less than 4
arguments are passed.  It's also a tiny bit smaller in code size.

This was done as part of the ESA project.
parent bb293e6b
No related branches found
No related tags found
No related merge requests found
......@@ -52,22 +52,25 @@ STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, size_t n_args, size_t n_kw, co
// need to insert self->self before all other args and then call self->meth
mp_uint_t n_total = n_args + 2 * n_kw;
if (n_total <= 4) {
// use stack to allocate temporary args array
mp_obj_t args2[5];
args2[0] = self->self;
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
return mp_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
} else {
// use heap to allocate temporary args array
mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_total);
size_t n_total = n_args + 2 * n_kw;
mp_obj_t *args2 = NULL;
mp_obj_t *free_args2 = NULL;
if (n_total > 4) {
// try to use heap to allocate temporary args array
args2 = m_new_maybe(mp_obj_t, 1 + n_total);
free_args2 = args2;
}
if (args2 == NULL) {
// (fallback to) use stack to allocate temporary args array
args2 = alloca(sizeof(mp_obj_t) * (1 + n_total));
}
args2[0] = self->self;
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
mp_obj_t res = mp_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
m_del(mp_obj_t, args2, 1 + n_total);
return res;
if (free_args2 != NULL) {
m_del(mp_obj_t, free_args2, 1 + n_total);
}
return res;
}
#if MICROPY_PY_FUNCTION_ATTRS
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment