@@ -373,12 +373,23 @@ lookup_tp_mro(PyTypeObject *self)
373
373
PyObject *
374
374
_PyType_GetMRO (PyTypeObject * self )
375
375
{
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
+
377
385
BEGIN_TYPE_LOCK ();
378
386
mro = lookup_tp_mro (self );
379
- Py_INCREF (mro );
387
+ Py_XINCREF (mro );
380
388
END_TYPE_LOCK ()
381
389
return mro ;
390
+ #else
391
+ return Py_XNewRef (lookup_tp_mro (self ));
392
+ #endif
382
393
}
383
394
384
395
static inline void
@@ -911,7 +922,7 @@ PyType_Modified(PyTypeObject *type)
911
922
}
912
923
913
924
static int
914
- is_subtype_unlocked ( PyTypeObject * a , PyTypeObject * b );
925
+ is_subtype_with_mro ( PyObject * a_mro , PyTypeObject * a , PyTypeObject * b );
915
926
916
927
static void
917
928
type_mro_modified (PyTypeObject * type , PyObject * bases ) {
@@ -957,7 +968,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
957
968
PyObject * b = PyTuple_GET_ITEM (bases , i );
958
969
PyTypeObject * cls = _PyType_CAST (b );
959
970
960
- if (!is_subtype_unlocked ( type , cls )) {
971
+ if (!is_subtype_with_mro ( lookup_tp_mro ( type ), type , cls )) {
961
972
goto clear ;
962
973
}
963
974
}
@@ -1431,7 +1442,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
1431
1442
}
1432
1443
PyTypeObject * base = (PyTypeObject * )ob ;
1433
1444
1434
- if (is_subtype_unlocked ( base , type ) ||
1445
+ if (is_subtype_with_mro ( lookup_tp_mro ( base ), base , type ) ||
1435
1446
/* In case of reentering here again through a custom mro()
1436
1447
the above check is not enough since it relies on
1437
1448
base->tp_mro which would gonna be updated inside
@@ -2292,37 +2303,41 @@ type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
2292
2303
}
2293
2304
2294
2305
static int
2295
- is_subtype_unlocked ( PyTypeObject * a , PyTypeObject * b )
2306
+ is_subtype_with_mro ( PyObject * a_mro , PyTypeObject * a , PyTypeObject * b )
2296
2307
{
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 ) {
2302
2310
/* Deal with multiple inheritance without recursion
2303
2311
by walking the MRO tuple */
2304
2312
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 ;
2307
2316
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
+ }
2310
2321
}
2311
- return 0 ;
2312
2322
}
2313
- else
2323
+ else {
2314
2324
/* 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 ;
2316
2328
}
2317
2329
2318
2330
int
2319
2331
PyType_IsSubtype (PyTypeObject * a , PyTypeObject * b )
2320
2332
{
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 );
2325
2337
return res ;
2338
+ #else
2339
+ return is_subtype_with_mro (lookup_tp_mro (a ), a , b );
2340
+ #endif
2326
2341
}
2327
2342
2328
2343
/* Routines to do a method lookup in the type without looking in the
@@ -2815,7 +2830,7 @@ mro_check(PyTypeObject *type, PyObject *mro)
2815
2830
}
2816
2831
PyTypeObject * base = (PyTypeObject * )obj ;
2817
2832
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 ))) {
2819
2834
PyErr_Format (
2820
2835
PyExc_TypeError ,
2821
2836
"mro() returned base with unsuitable layout ('%.500s')" ,
@@ -7071,28 +7086,29 @@ inherit_special(PyTypeObject *type, PyTypeObject *base)
7071
7086
#undef COPYVAL
7072
7087
7073
7088
/* 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 )) {
7075
7091
type -> tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS ;
7076
7092
}
7077
- else if (is_subtype_unlocked ( base , & PyType_Type )) {
7093
+ else if (is_subtype_with_mro ( mro , base , & PyType_Type )) {
7078
7094
type -> tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS ;
7079
7095
}
7080
- else if (is_subtype_unlocked ( base , & PyLong_Type )) {
7096
+ else if (is_subtype_with_mro ( mro , base , & PyLong_Type )) {
7081
7097
type -> tp_flags |= Py_TPFLAGS_LONG_SUBCLASS ;
7082
7098
}
7083
- else if (is_subtype_unlocked ( base , & PyBytes_Type )) {
7099
+ else if (is_subtype_with_mro ( mro , base , & PyBytes_Type )) {
7084
7100
type -> tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS ;
7085
7101
}
7086
- else if (is_subtype_unlocked ( base , & PyUnicode_Type )) {
7102
+ else if (is_subtype_with_mro ( mro , base , & PyUnicode_Type )) {
7087
7103
type -> tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS ;
7088
7104
}
7089
- else if (is_subtype_unlocked ( base , & PyTuple_Type )) {
7105
+ else if (is_subtype_with_mro ( mro , base , & PyTuple_Type )) {
7090
7106
type -> tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS ;
7091
7107
}
7092
- else if (is_subtype_unlocked ( base , & PyList_Type )) {
7108
+ else if (is_subtype_with_mro ( mro , base , & PyList_Type )) {
7093
7109
type -> tp_flags |= Py_TPFLAGS_LIST_SUBCLASS ;
7094
7110
}
7095
- else if (is_subtype_unlocked ( base , & PyDict_Type )) {
7111
+ else if (is_subtype_with_mro ( mro , base , & PyDict_Type )) {
7096
7112
type -> tp_flags |= Py_TPFLAGS_DICT_SUBCLASS ;
7097
7113
}
7098
7114
@@ -10193,7 +10209,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p)
10193
10209
d = (PyWrapperDescrObject * )descr ;
10194
10210
if ((specific == NULL || specific == d -> d_wrapped ) &&
10195
10211
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 )))
10197
10213
{
10198
10214
specific = d -> d_wrapped ;
10199
10215
}
0 commit comments