From c3a7df1ecb7118993cc3350bd46e338eafe3cd0d Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 6 Mar 2026 12:01:06 -0500 Subject: [PATCH 1/2] [3.14] gh-145566: Skip stop-the-world when reassigning `__class__` on newly created objects (gh-145567) (cherry picked from commit 1d091a336e60b703a7d7ae4124f652eabe144f4e) Co-authored-by: Sam Gross --- ...26-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst | 2 ++ Objects/typeobject.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst new file mode 100644 index 00000000000000..723b81ddc5f897 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst @@ -0,0 +1,2 @@ +In the free threading build, skip the stop-the-world pause when reassigning +``__class__`` on a newly created object. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 03d5cfa4ca5249..8e0dde905d23b9 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -7120,7 +7120,11 @@ object_set_class_world_stopped(PyObject *self, PyTypeObject *newto) assert(_PyObject_GetManagedDict(self) == dict); - if (_PyDict_DetachFromObject(dict, self) < 0) { + int err; + Py_BEGIN_CRITICAL_SECTION(dict); + err = _PyDict_DetachFromObject(dict, self); + Py_END_CRITICAL_SECTION(); + if (err < 0) { return -1; } @@ -7160,14 +7164,19 @@ object_set_class(PyObject *self, PyObject *value, void *closure) return -1; } + int unique = _PyObject_IsUniquelyReferenced(self); #ifdef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); - _PyEval_StopTheWorld(interp); + if (!unique) { + _PyEval_StopTheWorld(interp); + } #endif PyTypeObject *oldto = Py_TYPE(self); int res = object_set_class_world_stopped(self, newto); #ifdef Py_GIL_DISABLED - _PyEval_StartTheWorld(interp); + if (!unique) { + _PyEval_StartTheWorld(interp); + } #endif if (res == 0) { if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) { From a8dfdbcead7f08f99afb3d719c88403bc0812b05 Mon Sep 17 00:00:00 2001 From: Sam Gross Date: Fri, 6 Mar 2026 13:06:48 -0500 Subject: [PATCH 2/2] Fix unused variable warning --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8e0dde905d23b9..76886a18036854 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -7164,9 +7164,9 @@ object_set_class(PyObject *self, PyObject *value, void *closure) return -1; } - int unique = _PyObject_IsUniquelyReferenced(self); #ifdef Py_GIL_DISABLED PyInterpreterState *interp = _PyInterpreterState_GET(); + int unique = _PyObject_IsUniquelyReferenced(self); if (!unique) { _PyEval_StopTheWorld(interp); }