|
48 | 48 | // top element. |
49 | 49 | // Exception stack also grows up, top element is also pointed at. |
50 | 50 |
|
51 | | -// Exception stack unwind reasons (WHY_* in CPython-speak) |
52 | | -// TODO perhaps compress this to RETURN=0, JUMP>0, with number of unwinds |
53 | | -// left to do encoded in the JUMP number |
54 | | -typedef enum { |
55 | | - UNWIND_RETURN = 1, |
56 | | - UNWIND_JUMP, |
57 | | -} mp_unwind_reason_t; |
58 | | - |
59 | 51 | #define DECODE_UINT \ |
60 | 52 | mp_uint_t unum = 0; \ |
61 | 53 | do { \ |
@@ -613,29 +605,18 @@ run_code_state: ; |
613 | 605 | mp_call_method_n_kw(3, 0, sp); |
614 | 606 | SET_TOP(mp_const_none); |
615 | 607 | } else if (MP_OBJ_IS_SMALL_INT(TOP())) { |
616 | | - mp_int_t cause_val = MP_OBJ_SMALL_INT_VALUE(TOP()); |
617 | | - if (cause_val == UNWIND_RETURN) { |
618 | | - // stack: (..., __exit__, ctx_mgr, ret_val, UNWIND_RETURN) |
619 | | - mp_obj_t ret_val = sp[-1]; |
620 | | - sp[-1] = mp_const_none; |
621 | | - sp[0] = mp_const_none; |
622 | | - sp[1] = mp_const_none; |
623 | | - mp_call_method_n_kw(3, 0, sp - 3); |
624 | | - sp[-3] = ret_val; |
625 | | - sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN); |
626 | | - } else { |
627 | | - assert(cause_val == UNWIND_JUMP); |
628 | | - // stack: (..., __exit__, ctx_mgr, dest_ip, num_exc, UNWIND_JUMP) |
629 | | - mp_obj_t dest_ip = sp[-2]; |
630 | | - mp_obj_t num_exc = sp[-1]; |
631 | | - sp[-2] = mp_const_none; |
632 | | - sp[-1] = mp_const_none; |
633 | | - sp[0] = mp_const_none; |
634 | | - mp_call_method_n_kw(3, 0, sp - 4); |
635 | | - sp[-4] = dest_ip; |
636 | | - sp[-3] = num_exc; |
637 | | - sp[-2] = MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP); |
638 | | - } |
| 608 | + // Getting here there are two distinct cases: |
| 609 | + // - unwind return, stack: (..., __exit__, ctx_mgr, ret_val, SMALL_INT(-1)) |
| 610 | + // - unwind jump, stack: (..., __exit__, ctx_mgr, dest_ip, SMALL_INT(num_exc)) |
| 611 | + // For both cases we do exactly the same thing. |
| 612 | + mp_obj_t data = sp[-1]; |
| 613 | + mp_obj_t cause = sp[0]; |
| 614 | + sp[-1] = mp_const_none; |
| 615 | + sp[0] = mp_const_none; |
| 616 | + sp[1] = mp_const_none; |
| 617 | + mp_call_method_n_kw(3, 0, sp - 3); |
| 618 | + sp[-3] = data; |
| 619 | + sp[-2] = cause; |
639 | 620 | sp -= 2; // we removed (__exit__, ctx_mgr) |
640 | 621 | } else { |
641 | 622 | assert(mp_obj_is_exception_instance(TOP())); |
@@ -680,10 +661,11 @@ unwind_jump:; |
680 | 661 | // of a "with" block contains the context manager info. |
681 | 662 | // We're going to run "finally" code as a coroutine |
682 | 663 | // (not calling it recursively). Set up a sentinel |
683 | | - // on a stack so it can return back to us when it is |
| 664 | + // on the stack so it can return back to us when it is |
684 | 665 | // done (when WITH_CLEANUP or END_FINALLY reached). |
685 | | - PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind |
686 | | - PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel |
| 666 | + // The sentinel is the number of exception handlers left to |
| 667 | + // unwind, which is a non-negative integer. |
| 668 | + PUSH(MP_OBJ_NEW_SMALL_INT(unum)); |
687 | 669 | ip = exc_sp->handler; // get exception handler byte code address |
688 | 670 | exc_sp--; // pop exception handler |
689 | 671 | goto dispatch_loop; // run the exception handler |
@@ -720,11 +702,14 @@ unwind_jump:; |
720 | 702 | } else if (MP_OBJ_IS_SMALL_INT(TOP())) { |
721 | 703 | // We finished "finally" coroutine and now dispatch back |
722 | 704 | // to our caller, based on TOS value |
723 | | - mp_unwind_reason_t reason = MP_OBJ_SMALL_INT_VALUE(POP()); |
724 | | - if (reason == UNWIND_RETURN) { |
| 705 | + mp_int_t cause = MP_OBJ_SMALL_INT_VALUE(POP()); |
| 706 | + if (cause < 0) { |
| 707 | + // A negative cause indicates unwind return |
725 | 708 | goto unwind_return; |
726 | 709 | } else { |
727 | | - assert(reason == UNWIND_JUMP); |
| 710 | + // Otherwise it's an unwind jump and we must push as a raw |
| 711 | + // number the number of exception handlers to unwind |
| 712 | + PUSH((mp_obj_t)cause); |
728 | 713 | goto unwind_jump; |
729 | 714 | } |
730 | 715 | } else { |
@@ -1101,7 +1086,7 @@ unwind_jump:; |
1101 | 1086 | // (not calling it recursively). Set up a sentinel |
1102 | 1087 | // on a stack so it can return back to us when it is |
1103 | 1088 | // done (when WITH_CLEANUP or END_FINALLY reached). |
1104 | | - PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_RETURN)); |
| 1089 | + PUSH(MP_OBJ_NEW_SMALL_INT(-1)); |
1105 | 1090 | ip = exc_sp->handler; |
1106 | 1091 | exc_sp--; |
1107 | 1092 | goto dispatch_loop; |
|
0 commit comments