py: Convert all uses of alloca() to use new scoped allocation API.

This commit is contained in:
Damien George 2017-11-26 23:37:19 +11:00
parent 02d830c035
commit 1e5a33df41
6 changed files with 41 additions and 6 deletions

View File

@ -318,7 +318,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
} }
uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len);
char *new_mod = alloca(new_mod_l); char *new_mod = mp_local_alloc(new_mod_l);
memcpy(new_mod, this_name, p - this_name); memcpy(new_mod, this_name, p - this_name);
if (mod_len != 0) { if (mod_len != 0) {
new_mod[p - this_name] = '.'; new_mod[p - this_name] = '.';
@ -326,9 +326,10 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
} }
qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l); qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
mp_local_free(new_mod);
DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
module_name = MP_OBJ_NEW_QSTR(new_mod_q); module_name = MP_OBJ_NEW_QSTR(new_mod_q);
mod_str = new_mod; mod_str = qstr_str(new_mod_q);
mod_len = new_mod_l; mod_len = new_mod_l;
} }

View File

@ -1050,7 +1050,7 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])); len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
} }
char *q_ptr = alloca(len); char *q_ptr = mp_local_alloc(len);
char *str_dest = q_ptr; char *str_dest = q_ptr;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (i > 0) { if (i > 0) {
@ -1062,6 +1062,7 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
str_dest += str_src_len; str_dest += str_src_len;
} }
qstr q_full = qstr_from_strn(q_ptr, len); qstr q_full = qstr_from_strn(q_ptr, len);
mp_local_free(q_ptr);
EMIT_ARG(import_name, q_full); EMIT_ARG(import_name, q_full);
if (is_as) { if (is_as) {
for (int i = 1; i < n; i++) { for (int i = 1; i < n; i++) {

View File

@ -51,6 +51,9 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s
// need to insert self before all other args and then call meth // need to insert self before all other args and then call meth
size_t n_total = n_args + 2 * n_kw; size_t n_total = n_args + 2 * n_kw;
mp_obj_t *args2 = NULL; mp_obj_t *args2 = NULL;
#if MICROPY_ENABLE_PYSTACK
args2 = mp_pystack_alloc(sizeof(mp_obj_t) * (1 + n_total));
#else
mp_obj_t *free_args2 = NULL; mp_obj_t *free_args2 = NULL;
if (n_total > 4) { if (n_total > 4) {
// try to use heap to allocate temporary args array // try to use heap to allocate temporary args array
@ -61,12 +64,17 @@ mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, s
// (fallback to) use stack to allocate temporary args array // (fallback to) use stack to allocate temporary args array
args2 = alloca(sizeof(mp_obj_t) * (1 + n_total)); args2 = alloca(sizeof(mp_obj_t) * (1 + n_total));
} }
#endif
args2[0] = self; args2[0] = self;
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t)); memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2); mp_obj_t res = mp_call_function_n_kw(meth, n_args + 1, n_kw, args2);
#if MICROPY_ENABLE_PYSTACK
mp_pystack_free(args2);
#else
if (free_args2 != NULL) { if (free_args2 != NULL) {
m_del(mp_obj_t, free_args2, 1 + n_total); m_del(mp_obj_t, free_args2, 1 + n_total);
} }
#endif
return res; return res;
} }

View File

@ -225,6 +225,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args
DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size); DECODE_CODESTATE_SIZE(self->bytecode, n_state, state_size);
mp_code_state_t *code_state; mp_code_state_t *code_state;
#if MICROPY_ENABLE_PYSTACK
code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size);
#else
// If we use m_new_obj_var(), then on no memory, MemoryError will be // If we use m_new_obj_var(), then on no memory, MemoryError will be
// raised. But this is not correct exception for a function call, // raised. But this is not correct exception for a function call,
// RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(), // RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(),
@ -234,6 +237,7 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args
if (!code_state) { if (!code_state) {
return NULL; return NULL;
} }
#endif
INIT_CODESTATE(code_state, self, n_args, n_kw, args); INIT_CODESTATE(code_state, self, n_args, n_kw, args);
@ -260,6 +264,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
// allocate state for locals and stack // allocate state for locals and stack
mp_code_state_t *code_state = NULL; mp_code_state_t *code_state = NULL;
#if MICROPY_ENABLE_PYSTACK
code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size);
#else
if (state_size > VM_MAX_STATE_ON_STACK) { if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
} }
@ -267,6 +274,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
code_state = alloca(sizeof(mp_code_state_t) + state_size); code_state = alloca(sizeof(mp_code_state_t) + state_size);
state_size = 0; // indicate that we allocated using alloca state_size = 0; // indicate that we allocated using alloca
} }
#endif
INIT_CODESTATE(code_state, self, n_args, n_kw, args); INIT_CODESTATE(code_state, self, n_args, n_kw, args);
@ -312,10 +320,14 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
result = code_state->state[n_state - 1]; result = code_state->state[n_state - 1];
} }
#if MICROPY_ENABLE_PYSTACK
mp_pystack_free(code_state);
#else
// free the state if it was allocated on the heap // free the state if it was allocated on the heap
if (state_size != 0) { if (state_size != 0) {
m_del_var(mp_code_state_t, byte, state_size, code_state); m_del_var(mp_code_state_t, byte, state_size, code_state);
} }
#endif
if (vm_return_kind == MP_VM_RETURN_NORMAL) { if (vm_return_kind == MP_VM_RETURN_NORMAL) {
return result; return result;

View File

@ -1348,11 +1348,12 @@ import_error:
const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len); const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
const uint dot_name_len = pkg_name_len + 1 + qstr_len(name); const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
char *dot_name = alloca(dot_name_len); char *dot_name = mp_local_alloc(dot_name_len);
memcpy(dot_name, pkg_name, pkg_name_len); memcpy(dot_name, pkg_name, pkg_name_len);
dot_name[pkg_name_len] = '.'; dot_name[pkg_name_len] = '.';
memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name)); memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len); qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);
mp_local_free(dot_name);
mp_obj_t args[5]; mp_obj_t args[5];
args[0] = MP_OBJ_NEW_QSTR(dot_name_q); args[0] = MP_OBJ_NEW_QSTR(dot_name_q);

16
py/vm.c
View File

@ -1108,7 +1108,13 @@ unwind_return:
if (code_state->prev != NULL) { if (code_state->prev != NULL) {
mp_obj_t res = *sp; mp_obj_t res = *sp;
mp_globals_set(code_state->old_globals); mp_globals_set(code_state->old_globals);
code_state = code_state->prev; mp_code_state_t *new_code_state = code_state->prev;
#if MICROPY_ENABLE_PYSTACK
// The sizeof in the following statement does not include the size of the variable
// part of the struct. This arg is anyway not used if pystack is enabled.
mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
#endif
code_state = new_code_state;
*code_state->sp = res; *code_state->sp = res;
goto run_code_state; goto run_code_state;
} }
@ -1450,7 +1456,13 @@ unwind_loop:
#if MICROPY_STACKLESS #if MICROPY_STACKLESS
} else if (code_state->prev != NULL) { } else if (code_state->prev != NULL) {
mp_globals_set(code_state->old_globals); mp_globals_set(code_state->old_globals);
code_state = code_state->prev; mp_code_state_t *new_code_state = code_state->prev;
#if MICROPY_ENABLE_PYSTACK
// The sizeof in the following statement does not include the size of the variable
// part of the struct. This arg is anyway not used if pystack is enabled.
mp_nonlocal_free(code_state, sizeof(mp_code_state_t));
#endif
code_state = new_code_state;
size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode); size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
fastn = &code_state->state[n_state - 1]; fastn = &code_state->state[n_state - 1];
exc_stack = (mp_exc_stack_t*)(code_state->state + n_state); exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);