From 27246c34829ef87adaafafa10e3f946ade7d0de8 Mon Sep 17 00:00:00 2001 From: mdehoon Date: Sun, 25 Jan 2026 00:20:14 +0900 Subject: [PATCH 1/2] Remove stray typedef in _tkinter.c (GH-142924) Co-authored-by: Michiel de Hoon --- Modules/_tkinter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index e6c0c1ff46ce52..1524d02d9e5a5e 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -235,7 +235,6 @@ static PyThread_type_lock tcl_lock = 0; #ifdef TCL_THREADS static Tcl_ThreadDataKey state_key; -typedef PyThreadState *ThreadSpecificData; #define tcl_tstate \ (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*))) #else From 979d92fefc0b6863c9783659f80d36cdfac90506 Mon Sep 17 00:00:00 2001 From: Yi Yang <1948638989@qq.com> Date: Sun, 25 Jan 2026 00:09:29 +0800 Subject: [PATCH 2/2] gh-144140: Optimize len for string constants in optimizer (GH-144142) --- Lib/test/test_capi/test_opt.py | 15 +++++++++++++++ Python/optimizer_bytecodes.c | 23 ++++++++++++++++++----- Python/optimizer_cases.c.h | 25 ++++++++++++++++++++----- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index ff3adb1d4542e0..0a02f29d978020 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2419,6 +2419,21 @@ def testfunc(n): self.assertNotIn("_GUARD_TOS_INT", uops) self.assertIn("_POP_TOP_NOP", uops) + def test_call_len_string(self): + def testfunc(n): + for _ in range(n): + _ = len("abc") + d = '' + _ = len(d) + _ = len(b"def") + _ = len(b"") + + _, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertNotIn("_CALL_LEN", uops) + self.assertEqual(count_ops(ex, "_SHUFFLE_3_LOAD_CONST_INLINE_BORROW"), 4) + def test_call_len_known_length_small_int(self): # Make sure that len(t) is optimized for a tuple of length 5. # See https://github.com/python/cpython/issues/139393. diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 38cd088d9fb030..9bc6075adc70cf 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1455,15 +1455,28 @@ dummy_func(void) { op(_CALL_LEN, (callable, null, arg -- res, a, c)) { res = sym_new_type(ctx, &PyLong_Type); - Py_ssize_t tuple_length = sym_tuple_length(arg); - if (tuple_length >= 0) { - PyObject *temp = PyLong_FromSsize_t(tuple_length); + Py_ssize_t length = sym_tuple_length(arg); + + // Not a tuple, check if it's a const string + if (length < 0 && sym_is_const(ctx, arg)) { + PyObject *const_val = sym_get_const(ctx, arg); + if (const_val != NULL) { + if (PyUnicode_CheckExact(const_val)) { + length = PyUnicode_GET_LENGTH(const_val); + } + else if (PyBytes_CheckExact(const_val)) { + length = PyBytes_GET_SIZE(const_val); + } + } + } + + if (length >= 0) { + PyObject *temp = PyLong_FromSsize_t(length); if (temp == NULL) { goto error; } if (_Py_IsImmortal(temp)) { - ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, - 0, (uintptr_t)temp); + ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); Py_DECREF(temp); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index e9405473fe2e0d..2cd1f833dc34f1 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3309,15 +3309,30 @@ arg = stack_pointer[-1]; callable = stack_pointer[-3]; res = sym_new_type(ctx, &PyLong_Type); - Py_ssize_t tuple_length = sym_tuple_length(arg); - if (tuple_length >= 0) { - PyObject *temp = PyLong_FromSsize_t(tuple_length); + Py_ssize_t length = sym_tuple_length(arg); + if (length < 0 && sym_is_const(ctx, arg)) { + PyObject *const_val = sym_get_const(ctx, arg); + if (const_val != NULL) { + if (PyUnicode_CheckExact(const_val)) { + length = PyUnicode_GET_LENGTH(const_val); + } + else if (PyBytes_CheckExact(const_val)) { + CHECK_STACK_BOUNDS(-2); + stack_pointer[-3] = res; + stack_pointer += -2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + length = PyBytes_GET_SIZE(const_val); + stack_pointer += 2; + } + } + } + if (length >= 0) { + PyObject *temp = PyLong_FromSsize_t(length); if (temp == NULL) { goto error; } if (_Py_IsImmortal(temp)) { - ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, - 0, (uintptr_t)temp); + ADD_OP(_SHUFFLE_3_LOAD_CONST_INLINE_BORROW, 0, (uintptr_t)temp); } res = sym_new_const(ctx, temp); CHECK_STACK_BOUNDS(-2);