8000 Make PyType_IsSubType not acquire lock · python/cpython@ccd1d9d · GitHub
[go: up one dir, main page]

Skip to content

Commit ccd1d9d

Browse files
committed
Make PyType_IsSubType not acquire lock
1 parent 61e54bf commit ccd1d9d

File tree

1 file changed

+48
-32
lines changed

1 file changed

+48
-32
lines changed

Objects/typeobject.c

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,23 @@ lookup_tp_mro(PyTypeObject *self)
373373
PyObject *
374374
_PyType_GetMRO(PyTypeObject *self)
375375
{
376-
PyObject *mro;
376+
#ifdef Py_GIL_DISABLED
377+
PyObject *mro = _Py_atomic_load_ptr_relaxed(&self->tp_mro);
378+
if (mro == NULL) {
379+
return NULL;
380+
}
381+
if (_Py_TryIncref(&self->tp_mro, mro)) {
382+
return mro;
383+
}
384+
377385
BEGIN_TYPE_LOCK();
378386
mro = lookup_tp_mro(self);
379-
Py_INCREF(mro);
387+
Py_XINCREF(mro);
380388
END_TYPE_LOCK()
381389
return mro;
390+
#else
391+
return Py_XNewRef(lookup_tp_mro(self));
392+
#endif
382393
}
383394

384395
static inline void
@@ -911,7 +922,7 @@ PyType_Modified(PyTypeObject *type)
911922
}
912923

913924
static int
914-
is_subtype_unlocked(PyTypeObject *a, PyTypeObject *b);
925+
is_subtype_with_mro(PyObject *a_mro, PyTypeObject *a, PyTypeObject *b);
915926

916927
static void
917928
type_mro_modified(PyTypeObject *type, PyObject *bases) {
@@ -957,7 +968,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
957968
PyObject *b = PyTuple_GET_ITEM(bases, i);
958969
PyTypeObject *cls = _PyType_CAST(b);
959970

960-
if (!is_subtype_unlocked(type, cls)) {
971+
if (!is_subtype_with_mro(lookup_tp_mro(type), type, cls)) {
961972
goto clear;
962973
}
963974
}
@@ -1431,7 +1442,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
14311442
}
14321443
PyTypeObject *base = (PyTypeObject*)ob;
14331444

1434-
if (is_subtype_unlocked(base, type) ||
1445+
if (is_subtype_with_mro(lookup_tp_mro(base), base, type) ||
14351446
/* In case of reentering here again through a custom mro()
14361447
the above check is not enough since it relies on
14371448
base->tp_mro which would gonna be updated inside
@@ -2292,37 +2303,41 @@ type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
22922303
}
22932304

22942305
static int
2295-
is_subtype_unlocked(PyTypeObject *a, PyTypeObject *b)
2306+
is_subtype_with_mro(PyObject *a_mro, PyTypeObject *a, PyTypeObject *b)
22962307
{
2297-
PyObject *mro;
2298-
2299-
ASSERT_TYPE_LOCK_HELD();
2300-
mro = lookup_tp_mro(a);
2301-
if (mro != NULL) {
2308+
int res;
2309+
if (a_mro != NULL) {
23022310
/* Deal with multiple inheritance without recursion
23032311
by walking the MRO tuple */
23042312
Py_ssize_t i, n;
2305-
assert(PyTuple_Check(mro));
2306-
n = PyTuple_GET_SIZE(mro);
2313+
assert(PyTuple_Check(a_mro));
2314+
n = PyTuple_GET_SIZE(a_mro);
2315+
res = 0;
23072316
for (i = 0; i < n; i++) {
2308-
if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
2309-
return 1;
2317+
if (PyTuple_GET_ITEM(a_mro, i) == (PyObject *)b) {
2318+
res = 1;
2319+
break;
2320+
}
23102321
}
2311-
return 0;
23122322
}
2313-
else
2323+
else {
23142324
/* a is not completely initialized yet; follow tp_base */
2315-
return type_is_subtype_base_chain(a, b);
2325+
res = type_is_subtype_base_chain(a, b);
2326+
}
2327+
return res;
23162328
}
23172329

23182330
int
23192331
PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
23202332
{
2321-
int res;
2322-
BEGIN_TYPE_LOCK();
2323-
res = is_subtype_unlocked(a, b);
2324-
END_TYPE_LOCK()
2333+
#ifdef Py_GIL_DISABLED
2334+
PyObject *mro = _PyType_GetMRO(a);
2335+
int res = is_subtype_with_mro(mro, a, b);
2336+
Py_XDECREF(mro);
23252337
return res;
2338+
#else
2339+
return is_subtype_with_mro(lookup_tp_mro(a), a, b);
2340+
#endif
23262341
}
23272342

23282343
/* Routines to do a method lookup in the type without looking in the
@@ -2815,7 +2830,7 @@ mro_check(PyTypeObject *type, PyObject *mro)
28152830
}
28162831
PyTypeObject *base = (PyTypeObject*)obj;
28172832

2818-
if (!i A3E2 s_subtype_unlocked(solid, solid_base(base))) {
2833+
if (!is_subtype_with_mro(lookup_tp_mro(solid), solid, solid_base(base))) {
28192834
PyErr_Format(
28202835
PyExc_TypeError,
28212836
"mro() returned base with unsuitable layout ('%.500s')",
@@ -7071,28 +7086,29 @@ inherit_special(PyTypeObject *type, PyTypeObject *base)
70717086
#undef COPYVAL
70727087

70737088
/* Setup fast subclass flags */
7074-
if (is_subtype_unlocked(base, (PyTypeObject*)PyExc_BaseException)) {
7089+
PyObject *mro = lookup_tp_mro(base);
7090+
if (is_subtype_with_mro(mro, base, (PyTypeObject*)PyExc_BaseException)) {
70757091
type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS;
70767092
}
7077-
else if (is_subtype_unlocked(base, &PyType_Type)) {
7093+
else if (is_subtype_with_mro(mro, base, &PyType_Type)) {
70787094
type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
70797095
}
7080-
else if (is_subtype_unlocked(base, &PyLong_Type)) {
7096+
else if (is_subtype_with_mro(mro, base, &PyLong_Type)) {
70817097
type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
70827098
}
7083-
else if (is_subtype_unlocked(base, &PyBytes_Type)) {
7099+
else if (is_subtype_with_mro(mro, base, &PyBytes_Type)) {
70847100
type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS;
70857101
}
7086-
else if (is_subtype_unlocked(base, &PyUnicode_Type)) {
7102+
else if (is_subtype_with_mro(mro, base, &PyUnicode_Type)) {
70877103
type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS;
70887104
}
7089-
else if (is_subtype_unlocked(base, &PyTuple_Type)) {
7105+
else if (is_subtype_with_mro(mro, base, &PyTuple_Type)) {
70907106
type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
70917107
}
7092-
else if (is_subtype_unlocked(base, &PyList_Type)) {
7108+
else if (is_subtype_with_mro(mro, base, &PyList_Type)) {
70937109
type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
70947110
}
7095-
else if (is_subtype_unlocked(base, &PyDict_Type)) {
7111+
else if (is_subtype_with_mro(mro, base, &PyDict_Type)) {
70967112
type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
70977113
}
70987114

@@ -10193,7 +10209,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p)
1019310209
d = (PyWrapperDescrObject *)descr;
1019410210
if ((specific == NULL || specific == d->d_wrapped) &&
1019510211
d->d_base->wrapper == p->wrapper &&
10196-
is_subtype_unlocked(type, PyDescr_TYPE(d)))
10212+
is_subtype_with_mro(lookup_tp_mro(type), type, PyDescr_TYPE(d)))
1019710213
{
1019810214
specific = d->d_wrapped;
1019910215
}

0 commit comments

Comments
 (0)
0