]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-145566: Skip stop-the-world when reassigning `__class__` on newly created objects...
authorSam Gross <colesbury@gmail.com>
Fri, 6 Mar 2026 17:01:06 +0000 (12:01 -0500)
committerGitHub <noreply@github.com>
Fri, 6 Mar 2026 17:01:06 +0000 (12:01 -0500)
Misc/NEWS.d/next/Core_and_Builtins/2026-03-05-19-10-56.gh-issue-145566.H4RupyYN.rst [new file with mode: 0644]
Objects/typeobject.c

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 (file)
index 0000000..723b81d
--- /dev/null
@@ -0,0 +1,2 @@
+In the free threading build, skip the stop-the-world pause when reassigning
+``__class__`` on a newly created object.
index 1fdd3cbdaaa6391b024570d0989174d9f62de526..27ec8bb40a929ff521db4ae6b15935b83bc89c7f 100644 (file)
@@ -7568,7 +7568,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;
             }
 
@@ -7608,10 +7612,15 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
         return -1;
     }
 
-    types_stop_world();
+    int unique = _PyObject_IsUniquelyReferenced(self);
+    if (!unique) {
+        types_stop_world();
+    }
     PyTypeObject *oldto = Py_TYPE(self);
     int res = object_set_class_world_stopped(self, newto);
-    types_start_world();
+    if (!unique) {
+        types_start_world();
+    }
     if (res == 0) {
         if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {
             Py_DECREF(oldto);