summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--py/vm.c61
1 files changed, 23 insertions, 38 deletions
diff --git a/py/vm.c b/py/vm.c
index b18a2b5e3..c629a61e2 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -48,14 +48,6 @@
// top element.
// Exception stack also grows up, top element is also pointed at.
-// Exception stack unwind reasons (WHY_* in CPython-speak)
-// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds
-// left to do encoded in the JUMP number
-typedef enum {
- UNWIND_RETURN = 1,
- UNWIND_JUMP,
-} mp_unwind_reason_t;
-
#define DECODE_UINT \
mp_uint_t unum = 0; \
do { \
@@ -613,29 +605,18 @@ dispatch_loop:
mp_call_method_n_kw(3, 0, sp);
SET_TOP(mp_const_none);
} else if (MP_OBJ_IS_SMALL_INT(TOP())) {
- mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP());
- if (cause_val == UNWIND_RETURN) {
- // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN)
- mp_obj_t ret_val = sp[-1];
- sp[-1] = mp_const_none;
- sp[0] = mp_const_none;
- sp[1] = mp_const_none;
- mp_call_method_n_kw(3, 0, sp - 3);
- sp[-3] = ret_val;
- sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN);
- } else {
- assert(cause_val == UNWIND_JUMP);
- // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP)
- mp_obj_t dest_ip = sp[-2];
- mp_obj_t num_exc = sp[-1];
- sp[-2] = mp_const_none;
- sp[-1] = mp_const_none;
- sp[0] = mp_const_none;
- mp_call_method_n_kw(3, 0, sp - 4);
- sp[-4] = dest_ip;
- sp[-3] = num_exc;
- sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP);
- }
+ // Getting here there are two distinct cases:
+ // - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1))
+ // - unwind jump, stack: (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc))
+ // For both cases we do exactly the same thing.
+ mp_obj_t data = sp[-1];
+ mp_obj_t cause = sp[0];
+ sp[-1] = mp_const_none;
+ sp[0] = mp_const_none;
+ sp[1] = mp_const_none;
+ mp_call_method_n_kw(3, 0, sp - 3);
+ sp[-3] = data;
+ sp[-2] = cause;
sp -= 2; // we removed (__exit__, ctx_mgr)
} else {
assert(mp_obj_is_exception_instance(TOP()));
@@ -680,10 +661,11 @@ unwind_jump:;
// of a "with" block contains the context manager info.
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
- // on a stack so it can return back to us when it is
+ // on the stack so it can return back to us when it is
// done (when WITH_CLEANUP or END_FINALLY reached).
- PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
- PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
+ // The sentinel is the number of exception handlers left to
+ // unwind, which is a non-negative integer.
+ PUSH(MP_OBJ_NEW_SMALL_INT(unum));
ip = exc_sp->handler; // get exception handler byte code address
exc_sp--; // pop exception handler
goto dispatch_loop; // run the exception handler
@@ -720,11 +702,14 @@ unwind_jump:;
} else if (MP_OBJ_IS_SMALL_INT(TOP())) {
// We finished "finally" coroutine and now dispatch back
// to our caller, based on TOS value
- mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP());
- if (reason == UNWIND_RETURN) {
+ mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP());
+ if (cause < 0) {
+ // A negative cause indicates unwind return
goto unwind_return;
} else {
- assert(reason == UNWIND_JUMP);
+ // Otherwise it's an unwind jump and we must push as a raw
+ // number the number of exception handlers to unwind
+ PUSH((mp_obj_t)cause);
goto unwind_jump;
}
} else {
@@ -1101,7 +1086,7 @@ unwind_return:
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is
// done (when WITH_CLEANUP or END_FINALLY reached).
- PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN));
+ PUSH(MP_OBJ_NEW_SMALL_INT(-1));
ip = exc_sp->handler;
exc_sp--;
goto dispatch_loop;