@@ -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
}
@@ -1442,7 +1453,7 @@ type_set_bases_unlocked(PyTypeObject *type, PyObject *new_bases, void *context)
1442
1453
}
1443
1454
PyTypeObject * base = (PyTypeObject * )ob ;
1444
1455
1445
- if (is_subtype_unlocked ( base , type ) ||
1456
+ if (is_subtype_with_mro ( lookup_tp_mro ( base ), base , type ) ||
1446
1457
/* In case of reentering here again through a custom mro()
1447
1458
the above check is not enough since it relies on
1448
1459
base->tp_mro which would gonna be updated inside
@@ -2303,37 +2314,41 @@ type_is_subtype_base_chain(PyTypeObject *a, PyTypeObject *b)
2303
2314
}
2304
2315
2305
2316
static int
2306
- is_subtype_unlocked ( PyTypeObject * a , PyTypeObject * b )
2317
+ is_subtype_with_mro ( PyObject * a_mro , PyTypeObject * a , PyTypeObject * b )
2307
2318
{
2308
- PyObject * mro ;
2309
-
2310
- ASSERT_TYPE_LOCK_HELD ();
2311
- mro = lookup_tp_mro (a );
2312
- if (mro != NULL ) {
2319
+ int res ;
2320
+ if (a_mro != NULL ) {
2313
2321
/* Deal with multiple inheritance without recursion
2314
2322
by walking the MRO tuple */
2315
2323
Py_ssize_t i , n ;
2316
- assert (PyTuple_Check (mro ));
2317
- n = PyTuple_GET_SIZE (mro );
2324
+ assert (PyTuple_Check (a_mro ));
2325
+ n = PyTuple_GET_SIZE (a_mro );
2326
+ res = 0 ;
2318
2327
for (i = 0 ; i < n ; i ++ ) {
2319
- if (PyTuple_GET_ITEM (mro , i ) == (PyObject * )b )
2320
- return 1 ;
2328
+ if (PyTuple_GET_ITEM (a_mro , i ) == (PyObject * )b ) {
2329
+ res = 1 ;
2330
+ break ;
2331
+ }
2321
2332
}
2322
- return 0 ;
2323
2333
}
2324
- else
2334
+ else {
2325
2335
/* a is not completely initialized yet; follow tp_base */
2326
- return type_is_subtype_base_chain (a , b );
2336
+ res = type_is_subtype_base_chain (a , b );
2337
+ }
2338
+ return res ;
2327
2339
}
2328
2340
2329
2341
int
2330
2342
PyType_IsSubtype (PyTypeObject * a , PyTypeObject * b )
2331
2343
{
2332
- int res ;
2333
- BEGIN_TYPE_LOCK ( );
2334
- res = is_subtype_unlocked ( a , b );
2335
- END_TYPE_LOCK ()
2344
+ #ifdef Py_GIL_DISABLED
2345
+ PyObject * mro = _PyType_GetMRO ( a );
2346
+ int res = is_subtype_with_mro ( mro , a , b );
2347
+ Py_XDECREF ( mro );
2336
2348
return res ;
2349
+ #else
2350
+ return is_subtype_with_mro (lookup_tp_mro (a ), a , b );
2351
+ #endif
2337
2352
}
2338
2353
2339
2354
/* Routines to do a method lookup in the type without looking in the
@@ -2826,7 +2841,7 @@ mro_check(PyTypeObject *type, PyObject *mro)
2826
2841
}
2827
2842
PyTypeObject * base = (PyTypeObject * )obj ;
2828
2843
2829
- if (!is_subtype_unlocked ( solid , solid_base (base ))) {
2844
+ if (!is_subtype_with_mro ( lookup_tp_mro ( solid ), solid , solid_base (base ))) {
2830
2845
PyErr_Format (
2831
2846
PyExc_TypeError ,
2832
2847
"mro() returned base with unsuitable layout ('%.500s')" ,
@@ -7082,28 +7097,29 @@ inherit_special(PyTypeObject *type, PyTypeObject *base)
7082
7097
#undef COPYVAL
7083
7098
7084
7099
/* Setup fast subclass flags */
7085
- if (is_subtype_unlocked (base , (PyTypeObject * )PyExc_BaseException )) {
7100
+ PyObject * mro = lookup_tp_mro (base );
7101
+ if (is_subtype_with_mro (mro , base , (PyTypeObject * )PyExc_BaseException )) {
7086
7102
type -> tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS ;
7087
7103
}
7088
- else if (is_subtype_unlocked ( base , & PyType_Type )) {
7104
+ else if (is_subtype_with_mro ( mro , base , & PyType_Type )) {
7089
7105
type -> tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS ;
7090
7106
}
7091
- else if (is_subtype_unlocked ( base , & PyLong_Type )) {
7107
+ else if (is_subtype_with_mro ( mro , base , & PyLong_Type )) {
7092
7108
type -> tp_flags |= Py_TPFLAGS_LONG_SUBCLASS ;
7093
7109
}
7094
- else if (is_subtype_unlocked ( base , & PyBytes_Type )) {
7110
+ else if (is_subtype_with_mro ( mro , base , & PyBytes_Type )) {
7095
7111
type -> tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS ;
7096
7112
}
7097
- else if (is_subtype_unlocked ( base , & PyUnicode_Type )) {
7113
+ else if (is_subtype_with_mro ( mro , base , & PyUnicode_Type )) {
7098
7114
type -> tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS ;
7099
7115
}
7100
- else if (is_subtype_unlocked ( base , & PyTuple_Type )) {
7116
+ else if (is_subtype_with_mro ( mro , base , & PyTuple_Type )) {
7101
7117
type -> tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS ;
7102
7118
}
7103
- else if (is_subtype_unlocked ( base , & PyList_Type )) {
7119
+ else if (is_subtype_with_mro ( mro , base , & PyList_Type )) {
7104
7120
type -> tp_flags |= Py_TPFLAGS_LIST_SUBCLASS ;
7105
7121
}
7106
- else if (is_subtype_unlocked ( base , & PyDict_Type )) {
7122
+ else if (is_subtype_with_mro ( mro , base , & PyDict_Type )) {
7107
7123
type -> tp_flags |= Py_TPFLAGS_DICT_SUBCLASS ;
7108
7124
}
7109
7125
@@ -10204,7 +10220,7 @@ update_one_slot(PyTypeObject *type, pytype_slotdef *p)
10204
10220
d = (PyWrapperDescrObject * )descr ;
10205
10221
if ((specific == NULL || specific == d -> d_wrapped ) &&
10206
10222
d -> d_base -> wrapper == p -> wrapper &&
10207
- is_subtype_unlocked ( type , PyDescr_TYPE (d )))
10223
+ is_subtype_with_mro ( lookup_tp_mro ( type ), type , PyDescr_TYPE (d )))
10208
10224
{
10209
10225
specific = d -> d_wrapped ;
10210
10226
}
0 commit comments