vm: Support strict stackless mode, with proper exception reporting.
I.e. in this mode, C stack will never be used to call a Python function, but if there's no free heap for a call, it will be reported as RuntimeError (as expected), not MemoryError.
This commit is contained in:
parent
f0a8f21190
commit
7f1c98177b
@ -125,11 +125,19 @@
|
|||||||
#define MICROPY_QSTR_BYTES_IN_LEN (1)
|
#define MICROPY_QSTR_BYTES_IN_LEN (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Avoid using C stack when making Python function calls.
|
// Avoid using C stack when making Python function calls. C stack still
|
||||||
|
// may be used if there's no free heap.
|
||||||
#ifndef MICROPY_STACKLESS
|
#ifndef MICROPY_STACKLESS
|
||||||
#define MICROPY_STACKLESS (0)
|
#define MICROPY_STACKLESS (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Never use C stack when making Python function calls. This may break
|
||||||
|
// testsuite as will subtly change which exception is thrown in case
|
||||||
|
// of too deep recursion and other similar cases.
|
||||||
|
#ifndef MICROPY_STACKLESS_STRICT
|
||||||
|
#define MICROPY_STACKLESS_STRICT (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Micro Python emitters */
|
/* Micro Python emitters */
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ void mp_import_all(mp_obj_t module);
|
|||||||
|
|
||||||
// Raise NotImplementedError with given message
|
// Raise NotImplementedError with given message
|
||||||
NORETURN void mp_not_implemented(const char *msg);
|
NORETURN void mp_not_implemented(const char *msg);
|
||||||
|
NORETURN void mp_exc_recursion_depth(void);
|
||||||
|
|
||||||
// helper functions for native/viper code
|
// helper functions for native/viper code
|
||||||
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
|
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/nlr.h"
|
#include "py/nlr.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
#include "py/stackctrl.h"
|
#include "py/stackctrl.h"
|
||||||
|
|
||||||
void mp_stack_ctrl_init(void) {
|
void mp_stack_ctrl_init(void) {
|
||||||
@ -46,10 +47,14 @@ void mp_stack_set_limit(mp_uint_t limit) {
|
|||||||
MP_STATE_VM(stack_limit) = limit;
|
MP_STATE_VM(stack_limit) = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mp_exc_recursion_depth(void) {
|
||||||
|
nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
|
||||||
|
MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
|
||||||
|
}
|
||||||
|
|
||||||
void mp_stack_check(void) {
|
void mp_stack_check(void) {
|
||||||
if (mp_stack_usage() >= MP_STATE_VM(stack_limit)) {
|
if (mp_stack_usage() >= MP_STATE_VM(stack_limit)) {
|
||||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
|
mp_exc_recursion_depth();
|
||||||
MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
21
py/vm.c
21
py/vm.c
@ -880,6 +880,12 @@ unwind_jump:;
|
|||||||
nlr_pop();
|
nlr_pop();
|
||||||
goto run_code_state;
|
goto run_code_state;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_STACKLESS_STRICT
|
||||||
|
else {
|
||||||
|
deep_recursion_error:
|
||||||
|
mp_exc_recursion_depth();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
|
SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
|
||||||
@ -912,6 +918,11 @@ unwind_jump:;
|
|||||||
nlr_pop();
|
nlr_pop();
|
||||||
goto run_code_state;
|
goto run_code_state;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_STACKLESS_STRICT
|
||||||
|
else {
|
||||||
|
goto deep_recursion_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
|
SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
|
||||||
@ -941,6 +952,11 @@ unwind_jump:;
|
|||||||
nlr_pop();
|
nlr_pop();
|
||||||
goto run_code_state;
|
goto run_code_state;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_STACKLESS_STRICT
|
||||||
|
else {
|
||||||
|
goto deep_recursion_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
|
SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
|
||||||
@ -973,6 +989,11 @@ unwind_jump:;
|
|||||||
nlr_pop();
|
nlr_pop();
|
||||||
goto run_code_state;
|
goto run_code_state;
|
||||||
}
|
}
|
||||||
|
#if MICROPY_STACKLESS_STRICT
|
||||||
|
else {
|
||||||
|
goto deep_recursion_error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
|
SET_TOP(mp_call_method_n_kw_var(true, unum, sp));
|
||||||
|
Loading…
Reference in New Issue
Block a user