Skip to content

Commit 9a5bd48

Browse files
committed
gh-145685: Stop the world when updating MRO of existing types
We already have a stop-the-world pause elsewhere in this code path (type_set_bases) and this makes will make it easier to avoid contention on the TYPE_LOCK when looking up names in the MRO hierarchy. Also use deferred reference counting for non-immortal MROs.
1 parent 1564e23 commit 9a5bd48

File tree

1 file changed

+14
-11
lines changed

1 file changed

+14
-11
lines changed

Objects/typeobject.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,6 @@ clear_tp_bases(PyTypeObject *self, int final)
647647
static inline PyObject *
648648
lookup_tp_mro(PyTypeObject *self)
649649
{
650-
ASSERT_NEW_TYPE_OR_LOCKED(self);
651650
return self->tp_mro;
652651
}
653652

@@ -664,8 +663,19 @@ set_tp_mro(PyTypeObject *self, PyObject *mro, int initial)
664663
/* Other checks are done via set_tp_bases. */
665664
_Py_SetImmortal(mro);
666665
}
666+
else {
667+
PyUnstable_Object_EnableDeferredRefcount(mro);
668+
}
669+
}
670+
if (!initial) {
671+
type_lock_prevent_release();
672+
types_stop_world();
667673
}
668674
self->tp_mro = mro;
675+
if (!initial) {
676+
types_start_world();
677+
type_lock_allow_release();
678+
}
669679
}
670680

671681
static inline void
@@ -1728,18 +1738,11 @@ static PyObject *
17281738
type_get_mro(PyObject *tp, void *Py_UNUSED(closure))
17291739
{
17301740
PyTypeObject *type = PyTypeObject_CAST(tp);
1731-
PyObject *mro;
1732-
1733-
BEGIN_TYPE_LOCK();
1734-
mro = lookup_tp_mro(type);
1741+
PyObject *mro = lookup_tp_mro(type);
17351742
if (mro == NULL) {
1736-
mro = Py_None;
1737-
} else {
1738-
Py_INCREF(mro);
1743+
Py_RETURN_NONE;
17391744
}
1740-
1741-
END_TYPE_LOCK();
1742-
return mro;
1745+
return Py_NewRef(mro);
17431746
}
17441747

17451748
static PyTypeObject *find_best_base(PyObject *);

0 commit comments

Comments
 (0)