aboutsummaryrefslogtreecommitdiff
path: root/py/objgenerator.c
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-05-15 13:37:06 +1000
committerDamien George <damien@micropython.org>2022-05-17 14:25:51 +1000
commit1762990579ff8ddc285e24492626fe40b6f2621d (patch)
tree180999f988cc79cebf1c56bfe9a978d4dbe3aaab /py/objgenerator.c
parent8e1db993cd6bca93c031619e05c465f05c48381c (diff)
py/bc: Provide separate code-state setup funcs for bytecode and native.
mpy-cross will now generate native code based on the size of mp_code_state_native_t, and the runtime will use this struct to calculate the offset of the .state field. This makes native code generation and execution (which rely on this struct) independent to the settings MICROPY_STACKLESS and MICROPY_PY_SYS_SETTRACE, both of which change the size of the mp_code_state_t struct. Fixes issue #5059. Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'py/objgenerator.c')
-rw-r--r--py/objgenerator.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/py/objgenerator.c b/py/objgenerator.c
index c1747a88b..12fd81a8b 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -65,7 +65,6 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
o->pend_exc = mp_const_none;
o->code_state.fun_bc = self_fun;
- o->code_state.ip = self_fun->bytecode;
o->code_state.n_state = n_state;
mp_setup_code_state(&o->code_state, n_args, n_kw, args);
return MP_OBJ_FROM_PTR(o);
@@ -87,6 +86,13 @@ const mp_obj_type_t mp_type_gen_wrap = {
#if MICROPY_EMIT_NATIVE
+// Based on mp_obj_gen_instance_t.
+typedef struct _mp_obj_gen_instance_native_t {
+ mp_obj_base_t base;
+ mp_obj_t pend_exc;
+ mp_code_state_native_t code_state;
+} mp_obj_gen_instance_native_t;
+
STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// The state for a native generating function is held in the same struct as a bytecode function
mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in);
@@ -106,14 +112,15 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k
MP_BC_PRELUDE_SIG_DECODE(ip);
// Allocate the generator object, with room for local stack (exception stack not needed).
- mp_obj_gen_instance_t *o = mp_obj_malloc_var(mp_obj_gen_instance_t, byte, n_state * sizeof(mp_obj_t), &mp_type_gen_instance);
+ mp_obj_gen_instance_native_t *o = mp_obj_malloc_var(mp_obj_gen_instance_native_t, byte, n_state * sizeof(mp_obj_t), &mp_type_gen_instance);
// Parse the input arguments and set up the code state
o->pend_exc = mp_const_none;
o->code_state.fun_bc = self_fun;
o->code_state.ip = prelude_ptr;
o->code_state.n_state = n_state;
- mp_setup_code_state(&o->code_state, n_args, n_kw, args);
+ o->code_state.sp = &o->code_state.state[0] - 1;
+ mp_setup_code_state_native(&o->code_state, n_args, n_kw, args);
// Indicate we are a native function, which doesn't use this variable
o->code_state.exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_SENTINEL;
@@ -171,7 +178,13 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
#endif
// If the generator is started, allow sending a value.
- if (self->code_state.sp == self->code_state.state - 1) {
+ void *state_start = self->code_state.state - 1;
+ #if MICROPY_EMIT_NATIVE
+ if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
+ state_start = ((mp_obj_gen_instance_native_t *)self)->code_state.state - 1;
+ }
+ #endif
+ if (self->code_state.sp == state_start) {
if (send_value != mp_const_none) {
mp_raise_TypeError(MP_ERROR_TEXT("can't send non-None value to a just-started generator"));
}
@@ -226,7 +239,14 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
case MP_VM_RETURN_EXCEPTION: {
self->code_state.ip = 0;
- *ret_val = self->code_state.state[0];
+ #if MICROPY_EMIT_NATIVE
+ if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) {
+ *ret_val = ((mp_obj_gen_instance_native_t *)self)->code_state.state[0];
+ } else
+ #endif
+ {
+ *ret_val = self->code_state.state[0];
+ }
// PEP479: if StopIteration is raised inside a generator it is replaced with RuntimeError
if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(*ret_val)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
*ret_val = mp_obj_new_exception_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("generator raised StopIteration"));