From 79d996a57b351e0ef354eb1e2f644b194433cc73 Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 15 Nov 2016 01:10:34 +0300 Subject: py/runtime: mp_resume: Handle exceptions in Python __next__(). This includes StopIteration and thus are important to make Python-coded iterables work with yield from/await. Exceptions in Python send() are still not handled and left for future consideration and optimization. --- py/runtime.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'py/runtime.c') diff --git a/py/runtime.c b/py/runtime.c index c25557464..4bab03b80 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1191,17 +1191,31 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th mp_obj_t dest[3]; // Reserve slot for send() arg + // Python instance iterator protocol if (send_value == mp_const_none) { mp_load_method_maybe(self_in, MP_QSTR___next__, dest); if (dest[0] != MP_OBJ_NULL) { - *ret_val = mp_call_method_n_kw(0, 0, dest); - return MP_VM_RETURN_YIELD; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + *ret_val = mp_call_method_n_kw(0, 0, dest); + nlr_pop(); + return MP_VM_RETURN_YIELD; + } else { + *ret_val = nlr.ret_val; + return MP_VM_RETURN_EXCEPTION; + } } } + // Either python instance generator protocol, or native object + // generator protocol. if (send_value != MP_OBJ_NULL) { mp_load_method(self_in, MP_QSTR_send, dest); dest[2] = send_value; + // TODO: This should have exception wrapping like __next__ case + // above. Not done right away to think how to optimize native + // generators better, see: + // https://github.com/micropython/micropython/issues/2628 *ret_val = mp_call_method_n_kw(1, 0, dest); return MP_VM_RETURN_YIELD; } -- cgit v1.2.3 From a0b2c6ad32230d679260eb2a545e5272234254ff Mon Sep 17 00:00:00 2001 From: Paul Sokolovsky Date: Tue, 15 Nov 2016 01:40:23 +0300 Subject: py/runtime: mp_resume: Fix exception handling for nanbox port. --- py/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'py/runtime.c') diff --git a/py/runtime.c b/py/runtime.c index 4bab03b80..0ecccbd87 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -1201,7 +1201,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th nlr_pop(); return MP_VM_RETURN_YIELD; } else { - *ret_val = nlr.ret_val; + *ret_val = MP_OBJ_FROM_PTR(nlr.ret_val); return MP_VM_RETURN_EXCEPTION; } } -- cgit v1.2.3 From e8f2db7da3f0e60901b09ee6eada99a9e875497f Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 14 Dec 2016 11:40:11 +1100 Subject: py/runtime: Zero out fs_user_mount array in mp_init. There's no need to force ports to copy-and-paste this initialisation code. If FSUSERMOUNT is enabled then this zeroing out must be done. --- esp8266/main.c | 3 --- py/runtime.c | 5 +++++ stmhal/main.c | 3 --- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'py/runtime.c') diff --git a/esp8266/main.c b/esp8266/main.c index 9883f9f96..6814248aa 100644 --- a/esp8266/main.c +++ b/esp8266/main.c @@ -52,9 +52,6 @@ STATIC void mp_reset(void) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_)); mp_obj_list_init(mp_sys_argv, 0); - #if MICROPY_VFS_FAT - memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount))); - #endif MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); MP_STATE_PORT(term_obj) = MP_OBJ_NULL; MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL; diff --git a/py/runtime.c b/py/runtime.c index 0ecccbd87..e7e35a081 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -91,6 +91,11 @@ void mp_init(void) { MP_STATE_VM(mp_module_builtins_override_dict) = NULL; #endif + #if MICROPY_FSUSERMOUNT + // zero out the pointers to the user-mounted devices + memset(MP_STATE_VM(fs_user_mount), 0, sizeof(MP_STATE_VM(fs_user_mount))); + #endif + #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif diff --git a/stmhal/main.c b/stmhal/main.c index b5d0916f3..78afe54ef 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -439,9 +439,6 @@ soft_reset: mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib)); mp_obj_list_init(mp_sys_argv, 0); - // zero out the pointers to the mounted devices - memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount))); - // Initialise low-level sub-systems. Here we need to very basic things like // zeroing out memory and resetting any of the sub-systems. Following this // we can run Python scripts (eg boot.py), but anything that is configurable -- cgit v1.2.3 From 7f1da0a03b1559080ca4d054bd38f104bde168e6 Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 15 Dec 2016 13:00:19 +1100 Subject: py: Add MICROPY_KBD_EXCEPTION config option to provide mp_kbd_exception. Defining and initialising mp_kbd_exception is boiler-plate code and so the core runtime can provide it, instead of each port needing to do it themselves. The exception object is placed in the VM state rather than on the heap. --- py/mpconfig.h | 5 +++++ py/mpstate.h | 5 +++++ py/runtime.c | 9 +++++++++ 3 files changed, 19 insertions(+) (limited to 'py/runtime.c') diff --git a/py/mpconfig.h b/py/mpconfig.h index ea90ec984..7a71ebd95 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -446,6 +446,11 @@ # endif #endif +// Whether to provide the mp_kbd_exception object +#ifndef MICROPY_KBD_EXCEPTION +#define MICROPY_KBD_EXCEPTION (0) +#endif + // Prefer to raise KeyboardInterrupt asynchronously (from signal or interrupt // handler) - if supported by a particular port. #ifndef MICROPY_ASYNC_KBD_INTR diff --git a/py/mpstate.h b/py/mpstate.h index 439ed6606..91fb68b3a 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -118,6 +118,11 @@ typedef struct _mp_state_vm_t { #endif #endif + #if MICROPY_KBD_EXCEPTION + // exception object of type KeyboardInterrupt + mp_obj_exception_t mp_kbd_exception; + #endif + // dictionary with loaded modules (may be exposed as sys.modules) mp_obj_dict_t mp_loaded_modules_dict; diff --git a/py/runtime.c b/py/runtime.c index e7e35a081..8b4420926 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -68,6 +68,15 @@ void mp_init(void) { mp_init_emergency_exception_buf(); #endif + #if MICROPY_KBD_EXCEPTION + // initialise the exception object for raising KeyboardInterrupt + MP_STATE_VM(mp_kbd_exception).base.type = &mp_type_KeyboardInterrupt; + MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0; + MP_STATE_VM(mp_kbd_exception).traceback_len = 0; + MP_STATE_VM(mp_kbd_exception).traceback_data = NULL; + MP_STATE_VM(mp_kbd_exception).args = mp_const_empty_tuple; + #endif + // call port specific initialization if any #ifdef MICROPY_PORT_INIT_FUNC MICROPY_PORT_INIT_FUNC; -- cgit v1.2.3