summaryrefslogtreecommitdiffstatshomepage
path: root/py/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/vm.c')
-rw-r--r--py/vm.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/py/vm.c b/py/vm.c
index 1afd8363d1..7f4efeea0f 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -82,7 +82,7 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args,
mp_exc_stack exc_stack[4];
mp_exc_stack *exc_sp = &exc_stack[0] - 1;
// execute the byte code
- mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp);
+ mp_vm_return_kind_t vm_return_kind = mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp, exc_stack, &exc_sp, MP_OBJ_NULL);
switch (vm_return_kind) {
case MP_VM_RETURN_NORMAL:
@@ -107,8 +107,8 @@ mp_vm_return_kind_t mp_execute_byte_code(const byte *code, const mp_obj_t *args,
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out,
mp_obj_t *fastn, mp_obj_t **sp_in_out,
- mp_exc_stack *exc_stack,
- mp_exc_stack **exc_sp_in_out) {
+ mp_exc_stack *exc_stack, mp_exc_stack **exc_sp_in_out,
+ volatile mp_obj_t inject_exc) {
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
const byte *ip = *ip_in_out;
@@ -118,13 +118,21 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
mp_obj_t obj1, obj2;
nlr_buf_t nlr;
- volatile machine_uint_t currently_in_except_block = 0; // 0 or 1, to detect nested exceptions
- mp_exc_stack *volatile exc_sp = *exc_sp_in_out; // stack grows up, exc_sp points to top of stack
+ volatile machine_uint_t currently_in_except_block = (int)*exc_sp_in_out & 1; // 0 or 1, to detect nested exceptions
+ mp_exc_stack *volatile exc_sp = (void*)((int)*exc_sp_in_out & ~1); // stack grows up, exc_sp points to top of stack
const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
// outer exception handling loop
for (;;) {
if (nlr_push(&nlr) == 0) {
+ // If we have exception to inject, now that we finish setting up
+ // execution context, raise it. This works as if RAISE_VARARGS
+ // bytecode was executed.
+ if (inject_exc != MP_OBJ_NULL) {
+ mp_obj_t t = inject_exc;
+ inject_exc = MP_OBJ_NULL;
+ nlr_jump(rt_make_raise_obj(t));
+ }
// loop to execute byte code
for (;;) {
dispatch_loop:
@@ -599,7 +607,7 @@ unwind_return:
nlr_pop();
*ip_in_out = ip;
*sp_in_out = sp;
- *exc_sp_in_out = exc_sp;
+ *exc_sp_in_out = (void*)((int)exc_sp | currently_in_except_block);
return MP_VM_RETURN_YIELD;
case MP_BC_IMPORT_NAME: