diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index c75992761d1334f..e3453a8756fdf14 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -470,7 +470,7 @@ def foo(a: int, b: str) -> str: %4d LOAD_GLOBAL 0 (Exception) CHECK_EXC_MATCH - POP_JUMP_IF_FALSE 24 (to L9) + POP_JUMP_IF_FALSE 22 (to L9) L4: NOT_TAKEN L5: STORE_FAST 0 (e) @@ -478,16 +478,14 @@ def foo(a: int, b: str) -> str: LOAD_ATTR 2 (__traceback__) STORE_FAST 1 (tb) L7: POP_EXCEPT - LOAD_COMMON_CONSTANT 7 (None) + PUSH_NULL STORE_FAST 0 (e) - DELETE_FAST 0 (e) %4d LOAD_FAST 1 (tb) RETURN_VALUE - -- L8: LOAD_COMMON_CONSTANT 7 (None) + -- L8: PUSH_NULL STORE_FAST 0 (e) - DELETE_FAST 0 (e) RERAISE 1 %4d L9: RERAISE 0 diff --git a/Lib/test/test_monitoring.py b/Lib/test/test_monitoring.py index 5c2d69934b02ea6..b4cef37f22eb606 100644 --- a/Lib/test/test_monitoring.py +++ b/Lib/test/test_monitoring.py @@ -1955,8 +1955,8 @@ def func(): ('branch', 'func', 4, 4), ('line', 'func', 5), ('line', 'meth', 1), - ('jump', 'func', 5, '[offset=122]'), - ('branch', 'func', '[offset=126]', '[offset=132]'), + ('jump', 'func', 5, '[offset=118]'), + ('branch', 'func', '[offset=122]', '[offset=128]'), ('line', 'get_events', 11)]) self.check_events(func, recorders = FLOW_AND_LINE_RECORDERS, expected = [ @@ -1970,8 +1970,8 @@ def func(): ('line', 'func', 5), ('line', 'meth', 1), ('return', 'meth', None), - ('jump', 'func', 5, '[offset=122]'), - ('branch', 'func', '[offset=126]', '[offset=132]'), + ('jump', 'func', 5, '[offset=118]'), + ('branch', 'func', '[offset=122]', '[offset=128]'), ('return', 'func', None), ('line', 'get_events', 11)]) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-18-54-06.gh-issue-145749.o1IQ5P.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-18-54-06.gh-issue-145749.o1IQ5P.rst new file mode 100644 index 000000000000000..eab4b459ddef25c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-15-18-54-06.gh-issue-145749.o1IQ5P.rst @@ -0,0 +1 @@ +Named exception blocks are now faster as they no longer use a ``DELETE_FAST`` instruction. diff --git a/Python/codegen.c b/Python/codegen.c index fa8c4ce88956557..7056145642617b4 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -2331,6 +2331,46 @@ codegen_continue(compiler *c, location loc) return SUCCESS; } +static int +codegen_clear_exception_name(compiler *c, identifier name) +{ + PyObject *mangled = _PyCompile_MaybeMangle(c, name); + if (mangled == NULL) { + return ERROR; + } + + int scope = _PyST_GetScope(SYMTABLE_ENTRY(c), mangled); + if (scope == -1) { + Py_DECREF(mangled); + return ERROR; + } + + _PyCompile_optype optype; + Py_ssize_t arg = 0; + if (_PyCompile_ResolveNameop( + c, mangled, scope, &optype, &arg) < 0) { + Py_DECREF(mangled); + return ERROR; + } + + if (optype == COMPILE_OP_FAST) { + ADDOP(c, NO_LOCATION, PUSH_NULL); + ADDOP_N(c, NO_LOCATION, STORE_FAST_MAYBE_NULL, mangled, varnames); + Py_DECREF(mangled); + return SUCCESS; + } + + Py_DECREF(mangled); + + ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); + RETURN_IF_ERROR( + codegen_nameop(c, NO_LOCATION, name, Store)); + RETURN_IF_ERROR( + codegen_nameop(c, NO_LOCATION, name, Del)); + + return SUCCESS; +} + /* Code generated for "try: finally: " is as follows: @@ -2574,22 +2614,14 @@ codegen_try_except(compiler *c, stmt_ty s) ADDOP(c, NO_LOCATION, POP_BLOCK); ADDOP(c, NO_LOCATION, POP_BLOCK); ADDOP(c, NO_LOCATION, POP_EXCEPT); - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store)); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); + codegen_clear_exception_name(c, handler->v.ExceptHandler.name); ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, end); /* except: */ USE_LABEL(c, cleanup_end); /* name = None; del name; # artificial */ - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store)); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); + codegen_clear_exception_name(c, handler->v.ExceptHandler.name); ADDOP_I(c, NO_LOCATION, RERAISE, 1); } @@ -2771,11 +2803,7 @@ codegen_try_star_except(compiler *c, stmt_ty s) /* name = None; del name; # artificial */ ADDOP(c, NO_LOCATION, POP_BLOCK); if (handler->v.ExceptHandler.name) { - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store)); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); + codegen_clear_exception_name(c, handler->v.ExceptHandler.name); } ADDOP_JUMP(c, NO_LOCATION, JUMP_NO_INTERRUPT, except); @@ -2784,11 +2812,7 @@ codegen_try_star_except(compiler *c, stmt_ty s) /* name = None; del name; # artificial */ if (handler->v.ExceptHandler.name) { - ADDOP_LOAD_CONST(c, NO_LOCATION, Py_None); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Store)); - RETURN_IF_ERROR( - codegen_nameop(c, NO_LOCATION, handler->v.ExceptHandler.name, Del)); + codegen_clear_exception_name(c, handler->v.ExceptHandler.name); } /* add exception raised to the res list */