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

py: Fallback to stack alloca for Python-stack if heap alloc fails.

If heap allocation for the Python-stack of a function fails then we may
as well allocate the Python-stack on the C stack.  This will allow to
run more code without using the heap.
parent 371f4ba6
No related branches found
No related tags found
No related merge requests found
...@@ -147,7 +147,7 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) { ...@@ -147,7 +147,7 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
// With this macro you can tune the maximum number of function state bytes // With this macro you can tune the maximum number of function state bytes
// that will be allocated on the stack. Any function that needs more // that will be allocated on the stack. Any function that needs more
// than this will use the heap. // than this will try to use the heap, with fallback to stack allocation.
#define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t)) #define VM_MAX_STATE_ON_STACK (11 * sizeof(mp_uint_t))
// Set this to enable a simple stack overflow check. // Set this to enable a simple stack overflow check.
...@@ -220,11 +220,13 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, ...@@ -220,11 +220,13 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
// allocate state for locals and stack // allocate state for locals and stack
mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state *code_state; mp_code_state *code_state = NULL;
if (state_size > VM_MAX_STATE_ON_STACK) { if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var(mp_code_state, byte, state_size); code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size);
} else { }
if (code_state == NULL) {
code_state = alloca(sizeof(mp_code_state) + state_size); code_state = alloca(sizeof(mp_code_state) + state_size);
state_size = 0; // indicate that we allocated using alloca
} }
code_state->n_state = n_state; code_state->n_state = n_state;
...@@ -285,7 +287,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, ...@@ -285,7 +287,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
} }
// free the state if it was allocated on the heap // free the state if it was allocated on the heap
if (state_size > VM_MAX_STATE_ON_STACK) { if (state_size != 0) {
m_del_var(mp_code_state, byte, state_size, code_state); m_del_var(mp_code_state, byte, state_size, code_state);
} }
......
...@@ -2,23 +2,31 @@ ...@@ -2,23 +2,31 @@
import gc import gc
def f(a): def f1(a):
print(a) print(a)
def g(a, b=2): def f2(a, b=2):
print(a, b) print(a, b)
def f3(a, b, c, d):
x1 = x2 = a
x3 = x4 = b
x5 = x6 = c
x7 = x8 = d
print(x1, x3, x5, x7, x2 + x4 + x6 + x8)
global_var = 1 global_var = 1
def h(): def test():
global global_var global global_var
global_var = 2 # set an existing global variable global_var = 2 # set an existing global variable
for i in range(2): # for loop for i in range(2): # for loop
f(i) # function call f1(i) # function call
f(i * 2 + 1) # binary operation with small ints f1(i * 2 + 1) # binary operation with small ints
f(a=i) # keyword arguments f1(a=i) # keyword arguments
g(i) # default arg (second one) f2(i) # default arg (second one)
g(i, i) # 2 args f2(i, i) # 2 args
f3(1, 2, 3, 4) # function with lots of local state
# call h with heap allocation disabled and all memory used up # call h with heap allocation disabled and all memory used up
gc.disable() gc.disable()
...@@ -27,5 +35,5 @@ try: ...@@ -27,5 +35,5 @@ try:
'a'.lower # allocates 1 cell for boundmeth 'a'.lower # allocates 1 cell for boundmeth
except MemoryError: except MemoryError:
pass pass
h() test()
gc.enable() gc.enable()
...@@ -8,3 +8,4 @@ ...@@ -8,3 +8,4 @@
1 1
1 2 1 2
1 1 1 1
1 2 3 4 10
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment