From: Kumar Aditya Date: Thu, 26 Mar 2026 09:06:55 +0000 (+0530) Subject: gh-146453: fix `_PyType_LookupByVersion` for types with fixed pre-defined version... X-Git-Tag: v3.15.0a8~174 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=495178ab058b35aa89b82099be80ad1ad01fa496;p=thirdparty%2FPython%2Fcpython.git gh-146453: fix `_PyType_LookupByVersion` for types with fixed pre-defined version tags (#146454) --- diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 9ebfa4f33f30..1456296a1339 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3017,6 +3017,20 @@ class TestUopsOptimization(unittest.TestCase): self.assertNotIn("_LOAD_ATTR_METHOD_NO_DICT", uops) self.assertNotIn("_LOAD_ATTR_METHOD_LAZY_DICT", uops) + def test_cached_attributes_fixed_version_tag(self): + def f(n): + c = 1 + x = 0 + for _ in range(n): + x += c.bit_length() + return x + + res, ex = self._run_with_optimizer(f, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + self.assertNotIn("_LOAD_ATTR_METHOD_NO_DICT", uops) + def test_store_fast_refcount_elimination(self): def foo(x): # Since x is known to be diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 7b4318e79fb2..66f6c3fb3c0a 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1349,6 +1349,35 @@ _PyType_LookupByVersion(unsigned int version) #ifdef Py_GIL_DISABLED return NULL; #else + switch (version) { + case _Py_TYPE_VERSION_INT: + return &PyLong_Type; + case _Py_TYPE_VERSION_FLOAT: + return &PyFloat_Type; + case _Py_TYPE_VERSION_LIST: + return &PyList_Type; + case _Py_TYPE_VERSION_TUPLE: + return &PyTuple_Type; + case _Py_TYPE_VERSION_STR: + return &PyUnicode_Type; + case _Py_TYPE_VERSION_SET: + return &PySet_Type; + case _Py_TYPE_VERSION_FROZEN_SET: + return &PyFrozenSet_Type; + case _Py_TYPE_VERSION_DICT: + return &PyDict_Type; + case _Py_TYPE_VERSION_BYTEARRAY: + return &PyByteArray_Type; + case _Py_TYPE_VERSION_BYTES: + return &PyBytes_Type; + case _Py_TYPE_VERSION_COMPLEX: + return &PyComplex_Type; + case _Py_TYPE_VERSION_FROZENDICT: + return &PyFrozenDict_Type; + default: + break; + } + PyInterpreterState *interp = _PyInterpreterState_GET(); PyTypeObject **slot = interp->types.type_version_cache