diff options
author | Irit Katriel <1055913+iritkatriel@users.noreply.github.com> | 2021-12-17 14:46:22 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-17 14:46:22 (GMT) |
commit | 396b58345f81d4c8c5a52546d2288e666a1b9b8b (patch) | |
tree | 89140d0930da874df676cfac27d2e85e746a5fc1 /Python | |
parent | 62a0a2a25dbe3ba6f2973a37a3022d982fdc163c (diff) | |
download | cpython-396b58345f81d4c8c5a52546d2288e666a1b9b8b.zip cpython-396b58345f81d4c8c5a52546d2288e666a1b9b8b.tar.gz cpython-396b58345f81d4c8c5a52546d2288e666a1b9b8b.tar.bz2 |
bpo-45711: Remove type and traceback from exc_info (GH-30122)
* Do not PUSH/POP traceback or type to the stack as part of exc_info
* Remove exc_traceback and exc_type from _PyErr_StackItem
* Add to what's new, because this change breaks things like Cython
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 212 | ||||
-rw-r--r-- | Python/compile.c | 156 | ||||
-rw-r--r-- | Python/errors.c | 18 | ||||
-rw-r--r-- | Python/pystate.c | 2 |
4 files changed, 119 insertions, 269 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 87d6a22..bac57cc 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1094,29 +1094,11 @@ fail: static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); static PyObject *do_reraise_star(PyObject *excs, PyObject *orig); static int exception_group_match( - PyObject *exc_type, PyObject* exc_value, PyObject *match_type, + PyObject* exc_value, PyObject *match_type, PyObject **match, PyObject **rest); static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); -#ifdef Py_DEBUG -static void -_assert_exception_type_is_redundant(PyObject* type, PyObject* val) -{ - if (type == NULL || type == Py_None) { - assert(val == type); - } - else { - assert(PyExceptionInstance_Check(val)); - assert(PyExceptionInstance_Class(val) == type); - } -} - -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) _assert_exception_type_is_redundant(t, v) -#else -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) -#endif - PyObject * PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) { @@ -2737,25 +2719,15 @@ check_eval_breaker: } TARGET(POP_EXCEPT) { - PyObject *type, *value, *traceback; - _PyErr_StackItem *exc_info; - exc_info = tstate->exc_info; - type = exc_info->exc_type; - value = exc_info->exc_value; - traceback = exc_info->exc_traceback; - - exc_info->exc_type = POP(); + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *value = exc_info->exc_value; exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); - Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); DISPATCH(); } TARGET(POP_EXCEPT_AND_RERAISE) { - PyObject *lasti = PEEK(4); + PyObject *lasti = PEEK(2); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2764,31 +2736,24 @@ check_eval_breaker: _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); goto error; } - PyObject *type, *value, *traceback; - _PyErr_StackItem *exc_info; - type = POP(); - value = POP(); - traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + PyObject *value = POP(); + assert(value); + assert(PyExceptionInstance_Check(value)); + PyObject *type = Py_NewRef(PyExceptionInstance_Class(value)); + PyObject *traceback = PyException_GetTraceback(value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); - exc_info = tstate->exc_info; - type = exc_info->exc_type; + + _PyErr_StackItem *exc_info = tstate->exc_info; value = exc_info->exc_value; - traceback = exc_info->exc_traceback; - exc_info->exc_type = POP(); exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); - Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); goto exception_unwind; } TARGET(RERAISE) { if (oparg) { - PyObject *lasti = PEEK(oparg+3); + PyObject *lasti = PEEK(oparg + 1); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2799,11 +2764,10 @@ check_eval_breaker: goto error; } } - PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); + assert(val && PyExceptionInstance_Check(val)); + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); + PyObject *tb = PyException_GetTraceback(val); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -2823,35 +2787,21 @@ check_eval_breaker: PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero()); PUSH(lasti_unused); - if (!Py_IsNone(val)) { - PyObject *tb = PyException_GetTraceback(val); - PUSH(tb ? tb : Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_TYPE(val))); - } - else { - // nothing to reraise - PUSH(Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_None)); - } + PUSH(val); DISPATCH(); } TARGET(END_ASYNC_FOR) { - PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); - if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { - Py_DECREF(exc); + assert(val && PyExceptionInstance_Check(val)); + if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) { Py_DECREF(val); - Py_DECREF(tb); Py_DECREF(POP()); DISPATCH(); } else { + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); + PyObject *tb = PyException_GetTraceback(val); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -3971,16 +3921,15 @@ check_eval_breaker: TARGET(JUMP_IF_NOT_EG_MATCH) { PyObject *match_type = POP(); - PyObject *exc_type = TOP(); - PyObject *exc_value = SECOND(); if (check_except_star_type_valid(tstate, match_type) < 0) { Py_DECREF(match_type); goto error; } + PyObject *exc_value = TOP(); PyObject *match = NULL, *rest = NULL; - int res = exception_group_match(exc_type, exc_value, - match_type, &match, &rest); + int res = exception_group_match(exc_value, match_type, + &match, &rest); Py_DECREF(match_type); if (res < 0) { goto error; @@ -4001,46 +3950,21 @@ check_eval_breaker: else { /* Total or partial match - update the stack from - * [tb, val, exc] + * [val] * to - * [tb, rest, exc, tb, match, exc] + * [rest, match] * (rest can be Py_None) */ + PyObject *exc = TOP(); - PyObject *type = TOP(); - PyObject *val = SECOND(); - PyObject *tb = THIRD(); - - if (!Py_IsNone(rest)) { - /* tb remains the same */ - SET_TOP(Py_NewRef(Py_TYPE(rest))); - SET_SECOND(Py_NewRef(rest)); - SET_THIRD(Py_NewRef(tb)); - } - else { - SET_TOP(Py_NewRef(Py_None)); - SET_SECOND(Py_NewRef(Py_None)); - SET_THIRD(Py_NewRef(Py_None)); - } - /* Push match */ + SET_TOP(rest); + PUSH(match); - PUSH(Py_NewRef(tb)); - PUSH(Py_NewRef(match)); - PUSH(Py_NewRef(Py_TYPE(match))); + PyErr_SetExcInfo(NULL, Py_NewRef(match), NULL); - // set exc_info to the current match - PyErr_SetExcInfo( - Py_NewRef(Py_TYPE(match)), - Py_NewRef(match), - Py_NewRef(tb)); - - Py_DECREF(tb); - Py_DECREF(val); - Py_DECREF(type); + Py_DECREF(exc); - Py_DECREF(match); - Py_DECREF(rest); } DISPATCH(); @@ -4048,8 +3972,7 @@ check_eval_breaker: TARGET(JUMP_IF_NOT_EXC_MATCH) { PyObject *right = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND()); - PyObject *left = SECOND(); + PyObject *left = TOP(); assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { Py_DECREF(right); @@ -4465,26 +4388,24 @@ check_eval_breaker: } TARGET(WITH_EXCEPT_START) { - /* At the top of the stack are 8 values: - - (TOP, SECOND, THIRD) = exc_info() - - (FOURTH, FIFTH, SIXTH) = previous exception - - SEVENTH: lasti of exception in exc_info() - - EIGHTH: the context.__exit__ bound method - We call EIGHTH(TOP, SECOND, THIRD). - Then we push again the TOP exception and the __exit__ - return value. + /* At the top of the stack are 4 values: + - TOP = exc_info() + - SECOND = previous exception + - THIRD: lasti of exception in exc_info() + - FOURTH: the context.__exit__ bound method + We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). + Then we push the __exit__ return value. */ PyObject *exit_func; PyObject *exc, *val, *tb, *res; - exc = TOP(); - val = SECOND(); - tb = THIRD(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(!Py_IsNone(exc)); - assert(!PyLong_Check(exc)); - assert(PyLong_Check(PEEK(7))); - exit_func = PEEK(8); + val = TOP(); + assert(val && PyExceptionInstance_Check(val)); + exc = PyExceptionInstance_Class(val); + tb = PyException_GetTraceback(val); + Py_XDECREF(tb); + assert(PyLong_Check(PEEK(3))); + exit_func = PEEK(4); PyObject *stack[4] = {NULL, exc, val, tb}; res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); @@ -4496,40 +4417,22 @@ check_eval_breaker: } TARGET(PUSH_EXC_INFO) { - PyObject *type = TOP(); - PyObject *value = SECOND(); - PyObject *tb = THIRD(); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + PyObject *value = TOP(); + _PyErr_StackItem *exc_info = tstate->exc_info; - SET_THIRD(exc_info->exc_traceback); if (exc_info->exc_value != NULL) { - SET_SECOND(exc_info->exc_value); - } - else { - Py_INCREF(Py_None); - SET_SECOND(Py_None); - } - if (exc_info->exc_type != NULL) { - SET_TOP(exc_info->exc_type); + SET_TOP(exc_info->exc_value); } else { Py_INCREF(Py_None); SET_TOP(Py_None); } - Py_INCREF(tb); - PUSH(tb); - exc_info->exc_traceback = tb; Py_INCREF(value); PUSH(value); assert(PyExceptionInstance_Check(value)); exc_info->exc_value = value; - Py_INCREF(type); - PUSH(type); - assert(PyExceptionClass_Check(type)); - exc_info->exc_type = type; - DISPATCH(); } @@ -5518,14 +5421,9 @@ exception_unwind: PyException_SetTraceback(val, tb); else PyException_SetTraceback(val, Py_None); - if (tb == NULL) { - tb = Py_None; - Py_INCREF(Py_None); - } - PUSH(tb); + Py_XDECREF(tb); + Py_XDECREF(exc); PUSH(val); - PUSH(exc); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); JUMPTO(handler); /* Resume normal execution */ frame->f_state = FRAME_EXECUTING; @@ -6375,19 +6273,17 @@ raise_error: */ static int -exception_group_match(PyObject *exc_type, PyObject* exc_value, - PyObject *match_type, PyObject **match, PyObject **rest) +exception_group_match(PyObject* exc_value, PyObject *match_type, + PyObject **match, PyObject **rest) { - if (Py_IsNone(exc_type)) { - assert(Py_IsNone(exc_value)); + if (Py_IsNone(exc_value)) { *match = Py_NewRef(Py_None); *rest = Py_NewRef(Py_None); return 0; } - assert(PyExceptionClass_Check(exc_type)); assert(PyExceptionInstance_Check(exc_value)); - if (PyErr_GivenExceptionMatches(exc_type, match_type)) { + if (PyErr_GivenExceptionMatches(exc_value, match_type)) { /* Full match of exc itself */ bool is_eg = _PyBaseExceptionGroup_Check(exc_value); if (is_eg) { diff --git a/Python/compile.c b/Python/compile.c index 6179ad9..8e90b1a 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1048,9 +1048,9 @@ stack_effect(int opcode, int oparg, int jump) case POP_BLOCK: return 0; case POP_EXCEPT: - return -3; + return -1; case POP_EXCEPT_AND_RERAISE: - return -7; + return -3; case STORE_NAME: return -1; @@ -1095,7 +1095,7 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_IF_NOT_EXC_MATCH: return -1; case JUMP_IF_NOT_EG_MATCH: - return jump > 0 ? -1 : 2; + return jump > 0 ? -1 : 0; case IMPORT_NAME: return -1; case IMPORT_FROM: @@ -1120,25 +1120,25 @@ stack_effect(int opcode, int oparg, int jump) /* Exception handling pseudo-instructions */ case SETUP_FINALLY: /* 0 in the normal flow. - * Restore the stack position and push 3 values before jumping to + * Restore the stack position and push 1 value before jumping to * the handler if an exception be raised. */ - return jump ? 3 : 0; + return jump ? 1 : 0; case SETUP_CLEANUP: /* As SETUP_FINALLY, but pushes lasti as well */ - return jump ? 4 : 0; + return jump ? 2 : 0; case SETUP_WITH: /* 0 in the normal flow. * Restore the stack position to the position before the result - * of __(a)enter__ and push 4 values before jumping to the handler + * of __(a)enter__ and push 2 values before jumping to the handler * if an exception be raised. */ - return jump ? -1 + 4 : 0; + return jump ? 1 : 0; case PREP_RERAISE_STAR: - return 2; + return 0; case RERAISE: - return -3; + return -1; case PUSH_EXC_INFO: - return 3; + return 1; case WITH_EXCEPT_START: return 1; @@ -1199,7 +1199,7 @@ stack_effect(int opcode, int oparg, int jump) case GET_YIELD_FROM_ITER: return 0; case END_ASYNC_FOR: - return -4; + return -2; case FORMAT_VALUE: /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ @@ -1888,13 +1888,11 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, case FINALLY_END: if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -1927,7 +1925,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP(c, POP_BLOCK); } if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -3310,18 +3308,16 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) [] POP_BLOCK [] JUMP_FORWARD L0 - [tb, val, exc] L1: <evaluate E1> ) - [tb, val, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 - [tb, val, exc] POP - [tb, val] <assign to V1> (or POP if no V1) - [tb] POP + [exc] L1: <evaluate E1> ) + [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [exc] <assign to V1> (or POP if no V1) [] <code for S1> JUMP_FORWARD L0 - [tb, val, exc] L2: <evaluate E2> + [exc] L2: <evaluate E2> .............................etc....................... - [tb, val, exc] Ln+1: RERAISE # re-raise exception + [exc] Ln+1: RERAISE # re-raise exception [] L0: <next statement> @@ -3372,7 +3368,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); if (handler->v.ExceptHandler.name) { basicblock *cleanup_end, *cleanup_body; @@ -3383,7 +3378,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) } compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); /* try: @@ -3434,8 +3428,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (!cleanup_body) return 0; - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ compiler_use_next_block(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) return 0; @@ -3467,52 +3460,42 @@ compiler_try_except(struct compiler *c, stmt_ty s) at the right; 'tb' is trace-back info, 'val' the exception instance, and 'typ' the exception's type.) - Value stack Label Instruction Argument - [] SETUP_FINALLY L1 - [] <code for S> - [] POP_BLOCK - [] JUMP_FORWARD L0 + Value stack Label Instruction Argument + [] SETUP_FINALLY L1 + [] <code for S> + [] POP_BLOCK + [] JUMP_FORWARD L0 - [tb, val, typ] L1: DUP_TOP_TWO ) save a copy of the - [tb, val, typ, orig, typ] POP_TOP ) original raised exception - [tb, val, typ, orig] ROT_FOUR ) - [orig, tb, val, typ] BUILD_LIST ) list for raised/reraised - [orig, tb, val, typ, res] ROT_FOUR ) exceptions ("result") + [exc] L1: DUP_TOP ) save copy of the original exception + [orig, exc] BUILD_LIST ) list for raised/reraised excs ("result") + [orig, exc, res] ROT_TWO - [orig, res, tb, val, typ] <evaluate E1> ) - [orig, res, tb, val, typ, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [orig, res, exc] <evaluate E1> + [orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2 - [orig, res, tb, rest, typ, tb, match, typ] POP - [orig, res, tb, rest, typ, tb, match] <assign to V1> (or POP if no V1) - [orig, res, tb, rest, typ, tb] POP + [orig, res, rest, match] <assign to V1> (or POP if no V1) - [orig, res, tb, rest, typ] SETUP_FINALLY R1 - [orig, res, tb, rest, typ] <code for S1> - [orig, res, tb, rest, typ] JUMP_FORWARD L2 + [orig, res, rest] SETUP_FINALLY R1 + [orig, res, rest] <code for S1> + [orig, res, rest] JUMP_FORWARD L2 - [orig, res, tb, rest, typ, i, tb, v, t] R1: POP ) exception raised in except* body - [orig, res, tb, rest, typ, i, tb, v] LIST_APPEND 6 ) add it to res - [orig, res, tb, rest, typ, i, tb] POP - [orig, res, tb, rest, typ, i] POP + [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res + [orig, res, rest, i] POP - [orig, res, tb, rest, typ] L2: <evaluate E2> + [orig, res, rest] L2: <evaluate E2> .............................etc....................... - [orig, res, tb, rest, typ] Ln+1: POP ) add unhandled exception - [orig, res, tb, rest] LIST_APPEND 2 ) to res (could be None) - [orig, res, tb] POP + [orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None) - [orig, res] PREP_RERAISE_STAR - [i, tb, val, typ] POP_JUMP_IF_TRUE RER - [i, tb, val, typ] POP - [i, tb, val] POP - [i, tb] POP - [i] POP - [] JUMP_FORWARD L0 + [orig, res] PREP_RERAISE_STAR + [i, exc] POP_JUMP_IF_TRUE RER + [i, exc] POP + [i] POP + [] JUMP_FORWARD L0 - [i, tb, val, typ] RER: POP_EXCEPT_AND_RERAISE + [i, exc] RER: POP_EXCEPT_AND_RERAISE - [] L0: <next statement> + [] L0: <next statement> */ static int compiler_try_star_except(struct compiler *c, stmt_ty s) @@ -3573,30 +3556,25 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == 0) { /* Push the original EG into the stack */ /* - [tb, val, exc] DUP_TOP_TWO - [tb, val, exc, val, exc] POP_TOP - [tb, val, exc, val] ROT_FOUR - [val, tb, val, exc] + [exc] DUP_TOP + [orig, exc] */ - ADDOP(c, DUP_TOP_TWO); - ADDOP(c, POP_TOP); - ADDOP(c, ROT_FOUR); + ADDOP(c, DUP_TOP); /* create empty list for exceptions raised/reraise in the except* blocks */ /* - [val, tb, val, exc] BUILD_LIST - [val, tb, val, exc, []] ROT_FOUR - [val, [], tb, val, exc] + [orig, exc] BUILD_LIST + [orig, exc, []] ROT_TWO + [orig, [], exc] */ ADDOP_I(c, BUILD_LIST, 0); - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } if (handler->v.ExceptHandler.type) { VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); // exc_type basicblock *cleanup_end = compiler_new_block(c); if (cleanup_end == NULL) { @@ -3611,9 +3589,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) compiler_nameop(c, handler->v.ExceptHandler.name, Store); } else { - ADDOP(c, POP_TOP); // val + ADDOP(c, POP_TOP); // exc } - ADDOP(c, POP_TOP); // tb /* try: @@ -3657,9 +3634,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) } /* add exception raised to the res list */ - ADDOP(c, POP_TOP); // type - ADDOP_I(c, LIST_APPEND, 6); // exc - ADDOP(c, POP_TOP); // tb + ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP(c, POP_TOP); // lasti ADDOP_JUMP(c, JUMP_ABSOLUTE, except); @@ -3667,9 +3642,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ - ADDOP(c, POP_TOP); - ADDOP_I(c, LIST_APPEND, 2); - ADDOP(c, POP_TOP); + ADDOP_I(c, LIST_APPEND, 1); ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); } } @@ -3690,8 +3663,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* Nothing to reraise - pop it */ ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP_FORWARD, end); @@ -5449,13 +5420,11 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { return 0; ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit); NEXT_BLOCK(c); - ADDOP_I(c, RERAISE, 4); + ADDOP_I(c, RERAISE, 2); compiler_use_next_block(c, cleanup); ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, exit); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP(c, POP_TOP); @@ -5587,7 +5556,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) E: WITH_EXCEPT_START (calls EXPR.__exit__) POP_JUMP_IF_TRUE T: RERAISE - T: POP_TOP * 3 (remove exception from stack) + T: POP_TOP (remove exception from stack) POP_EXCEPT POP_TOP EXIT: @@ -7368,7 +7337,10 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas int size = end-start; assert(end > start); int target = handler->b_offset; - int depth = handler->b_preserve_lasti ? handler->b_startdepth-4 : handler->b_startdepth-3; + int depth = handler->b_startdepth - 1; + if (handler->b_preserve_lasti) { + depth -= 1; + } assert(depth >= 0); int depth_lasti = (depth<<1) | handler->b_preserve_lasti; assemble_emit_exception_table_item(a, start, (1<<7)); diff --git a/Python/errors.c b/Python/errors.c index 5be15e5..6c5fe41 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -84,11 +84,8 @@ _PyErr_GetTopmostException(PyThreadState *tstate) while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { - assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); exc_info = exc_info->previous_item; } - assert(exc_info->previous_item == NULL || - (exc_info->exc_type != NULL && exc_info->exc_type != Py_None)); return exc_info; } @@ -524,27 +521,17 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { - PyObject *oldtype, *oldvalue, *oldtraceback; PyThreadState *tstate = _PyThreadState_GET(); - oldtype = tstate->exc_info->exc_type; - oldvalue = tstate->exc_info->exc_value; - oldtraceback = tstate->exc_info->exc_traceback; - + PyObject *oldvalue = tstate->exc_info->exc_value; - tstate->exc_info->exc_type = get_exc_type(value); - Py_XINCREF(tstate->exc_info->exc_type); tstate->exc_info->exc_value = value; - tstate->exc_info->exc_traceback = get_exc_traceback(value); - Py_XINCREF(tstate->exc_info->exc_traceback); /* These args are no longer used, but we still need to steal a ref */ Py_XDECREF(type); Py_XDECREF(traceback); - Py_XDECREF(oldtype); Py_XDECREF(oldvalue); - Py_XDECREF(oldtraceback); } @@ -629,9 +616,6 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) exc_info_given = 1; } - assert( (exc_info->exc_type == NULL || exc_info->exc_type == Py_None) == - (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) ); - if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) { return; } diff --git a/Python/pystate.c b/Python/pystate.c index 463b248..0301ce6 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1028,9 +1028,7 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->curexc_value); Py_CLEAR(tstate->curexc_traceback); - Py_CLEAR(tstate->exc_state.exc_type); Py_CLEAR(tstate->exc_state.exc_value); - Py_CLEAR(tstate->exc_state.exc_traceback); /* The stack of exception states should contain just this thread. */ if (verbose && tstate->exc_info != &tstate->exc_state) { |