summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2015-03-28 01:14:45 +0200
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2015-04-03 00:26:47 +0300
commit7f1c98177bb27a45886fd7e42aa72bef9b1e4a0f (patch)
tree915706975a238a9944cdc45f4bd944bd201580bd /py
parentf0a8f2119066943553ba2dc1f27a402ad5ef0a7b (diff)
downloadmicropython-7f1c98177bb27a45886fd7e42aa72bef9b1e4a0f.tar.gz
micropython-7f1c98177bb27a45886fd7e42aa72bef9b1e4a0f.zip
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.
Diffstat (limited to 'py')
-rw-r--r--py/mpconfig.h10
-rw-r--r--py/runtime.h1
-rw-r--r--py/stackctrl.c9
-rw-r--r--py/vm.c21
4 files changed, 38 insertions, 3 deletions
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 94e2737de0..d561f80790 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -125,11 +125,19 @@
#define MICROPY_QSTR_BYTES_IN_LEN (1)
#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
#define MICROPY_STACKLESS (0)
#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 */
diff --git a/py/runtime.h b/py/runtime.h
index 8666ce1075..a36f1b1bd7 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -130,6 +130,7 @@ void mp_import_all(mp_obj_t module);
// Raise NotImplementedError with given message
NORETURN void mp_not_implemented(const char *msg);
+NORETURN void mp_exc_recursion_depth(void);
// helper functions for native/viper code
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
diff --git a/py/stackctrl.c b/py/stackctrl.c
index 7d7bbc1be1..4c51653727 100644
--- a/py/stackctrl.c
+++ b/py/stackctrl.c
@@ -27,6 +27,7 @@
#include "py/mpstate.h"
#include "py/nlr.h"
#include "py/obj.h"
+#include "py/runtime.h"
#include "py/stackctrl.h"
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;
}
+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) {
if (mp_stack_usage() >= MP_STATE_VM(stack_limit)) {
- nlr_raise(mp_obj_new_exception_arg1(&mp_type_RuntimeError,
- MP_OBJ_NEW_QSTR(MP_QSTR_maximum_space_recursion_space_depth_space_exceeded)));
+ mp_exc_recursion_depth();
}
}
diff --git a/py/vm.c b/py/vm.c
index 291e707c1f..dc4f9c2739 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -880,6 +880,12 @@ unwind_jump:;
nlr_pop();
goto run_code_state;
}
+ #if MICROPY_STACKLESS_STRICT
+ else {
+ deep_recursion_error:
+ mp_exc_recursion_depth();
+ }
+ #endif
}
#endif
SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
@@ -912,6 +918,11 @@ unwind_jump:;
nlr_pop();
goto run_code_state;
}
+ #if MICROPY_STACKLESS_STRICT
+ else {
+ goto deep_recursion_error;
+ }
+ #endif
}
#endif
SET_TOP(mp_call_method_n_kw_var(false, unum, sp));
@@ -941,6 +952,11 @@ unwind_jump:;
nlr_pop();
goto run_code_state;
}
+ #if MICROPY_STACKLESS_STRICT
+ else {
+ goto deep_recursion_error;
+ }
+ #endif
}
#endif
SET_TOP(mp_call_method_n_kw(unum & 0xff, (unum >> 8) & 0xff, sp));
@@ -973,6 +989,11 @@ unwind_jump:;
nlr_pop();
goto run_code_state;
}
+ #if MICROPY_STACKLESS_STRICT
+ else {
+ goto deep_recursion_error;
+ }
+ #endif
}
#endif
SET_TOP(mp_call_method_n_kw_var(true, unum, sp));