Skip to content

Commit c3a7df1

Browse files
committed
[3.14] gh-145566: Skip stop-the-world when reassigning __class__ on newly created objects (gh-145567)
(cherry picked from commit 1d091a3) Co-authored-by: Sam Gross <colesbury@gmail.com>
1 parent 7b9508f commit c3a7df1

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
In the free threading build, skip the stop-the-world pause when reassigning
2+
``__class__`` on a newly created object.

Objects/typeobject.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7120,7 +7120,11 @@ object_set_class_world_stopped(PyObject *self, PyTypeObject *newto)
71207120

71217121
assert(_PyObject_GetManagedDict(self) == dict);
71227122

7123-
if (_PyDict_DetachFromObject(dict, self) < 0) {
7123+
int err;
7124+
Py_BEGIN_CRITICAL_SECTION(dict);
7125+
err = _PyDict_DetachFromObject(dict, self);
7126+
Py_END_CRITICAL_SECTION();
7127+
if (err < 0) {
71247128
return -1;
71257129
}
71267130

@@ -7160,14 +7164,19 @@ object_set_class(PyObject *self, PyObject *value, void *closure)
71607164
return -1;
71617165
}
71627166

7167+
int unique = _PyObject_IsUniquelyReferenced(self);
71637168
#ifdef Py_GIL_DISABLED
71647169
PyInterpreterState *interp = _PyInterpreterState_GET();
7165-
_PyEval_StopTheWorld(interp);
7170+
if (!unique) {
7171+
_PyEval_StopTheWorld(interp);
7172+
}
71667173
#endif
71677174
PyTypeObject *oldto = Py_TYPE(self);
71687175
int res = object_set_class_world_stopped(self, newto);
71697176
#ifdef Py_GIL_DISABLED
7170-
_PyEval_StartTheWorld(interp);
7177+
if (!unique) {
7178+
_PyEval_StartTheWorld(interp);
7179+
}
71717180
#endif
71727181
if (res == 0) {
71737182
if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) {

0 commit comments

Comments
 (0)