diff options
author | Damien George <damien.p.george@gmail.com> | 2018-02-27 15:39:31 +1100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2018-02-27 15:39:31 +1100 |
commit | 22ade2f5c4ac88c90a013cbf4b81c8d795487f33 (patch) | |
tree | c764b91e008542db57a923ec502529201f72b188 /py | |
parent | c5fe610ba15468e1d92d7b6d5f5962f7595e3324 (diff) |
py/vm: Fix case of handling raised StopIteration within yield from.
This patch concerns the handling of an NLR-raised StopIteration, raised
during a call to mp_resume() which is handling the yield from opcode.
Previously, commit 6738c1dded8e436686f85008ec0a4fc47406ab7a introduced code
to handle this case, along with a test. It seems that it was lucky that
the test worked because the code did not correctly handle the stack pointer
(sp).
Furthermore, commit 79d996a57b351e0ef354eb1e2f644b194433cc73 improved the
way mp_resume() propagated certain exceptions: it changed raising an NLR
value to returning MP_VM_RETURN_EXCEPTION. This change meant that the
test introduced in gen_yield_from_ducktype.py was no longer hitting the
code introduced in 6738c1dded8e436686f85008ec0a4fc47406ab7a.
The patch here does two things:
1. Fixes the handling of sp in the VM for the case that yield from is
interrupted by a StopIteration raised via NLR.
2. Introduces a new test to check this handling of sp and re-covers the
code in the VM.
Diffstat (limited to 'py')
-rw-r--r-- | py/vm.c | 4 |
1 files changed, 3 insertions, 1 deletions
@@ -1162,6 +1162,7 @@ yield: mp_obj_t send_value = POP(); mp_obj_t t_exc = MP_OBJ_NULL; mp_obj_t ret_value; + code_state->sp = sp; // Save sp because it's needed if mp_resume raises StopIteration if (inject_exc != MP_OBJ_NULL) { t_exc = inject_exc; inject_exc = MP_OBJ_NULL; @@ -1361,7 +1362,8 @@ exception_handler: } else if (*code_state->ip == MP_BC_YIELD_FROM) { // StopIteration inside yield from call means return a value of // yield from, so inject exception's value as yield from's result - *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + // (Instead of stack pop then push we just replace exhausted gen with value) + *code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); code_state->ip++; // yield from is over, move to next instruction goto outer_dispatch_loop; // continue with dispatch loop } |