PyObject *
_PyType_GetMRO(PyTypeObject *self)
{
- PyObject *mro;
+#ifdef Py_GIL_DISABLED
+ PyObject *mro = _Py_atomic_load_ptr_relaxed(&self->tp_mro);
+ if (mro == NULL) {
+ return NULL;
+ }
+ if (_Py_TryIncref(&self->tp_mro, mro)) {
+ return mro;
+ }
+
BEGIN_TYPE_LOCK();
mro = lookup_tp_mro(self);
- Py_INCREF(mro);
+ Py_XINCREF(mro);
END_TYPE_LOCK()
return mro;
+#else
+ return Py_XNewRef(lookup_tp_mro(self));
+#endif
}
static inline void
}
static int
-is_subtype_unlocked(PyTypeObject *a, PyTypeObject *b);
+is_subtype_with_mro(PyObject *a_mro, PyTypeObject *a, PyTypeObject *b);
static void
type_mro_modified(PyTypeObject *type, PyObject *bases) {
PyObject *b = PyTuple_GET_ITEM(bases, i);
PyTypeObject *cls = _PyType_CAST(b);
- if (!is_subtype_unlocked(type, cls)) {
+ if (!is_subtype_with_mro(lookup_tp_mro(type), type, cls)) {
goto clear;
}
}
}
PyTypeObject *base = (PyTypeObject*)ob;
- if (is_subtype_unlocked(base, type) ||
+ if (is_subtype_with_mro(lookup_tp_mro(base), base, type) ||
/* In case of reentering here again through a custom mro()
the above check is not enough since it relies on
base->tp_mro which would gonna be updated inside
}
static int
-is_subtype_unlocked(PyTypeObject *a, PyTypeObject *b)
+is_subtype_with_mro(PyObject *a_mro, PyTypeObject *a, PyTypeObject *b)
{
- PyObject *mro;
-
- ASSERT_TYPE_LOCK_HELD();
- mro = lookup_tp_mro(a);
- if (mro != NULL) {
+ int res;
+ if (a_mro != NULL) {
/* Deal with multiple inheritance without recursion
by walking the MRO tuple */
Py_ssize_t i, n;
- assert(PyTuple_Check(mro));
- n = PyTuple_GET_SIZE(mro);
+ assert(PyTuple_Check(a_mro));
+ n = PyTuple_GET_SIZE(a_mro);
+ res = 0;
for (i = 0; i < n; i++) {
- if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
- return 1;
+ if (PyTuple_GET_ITEM(a_mro, i) == (PyObject *)b) {
+ res = 1;
+ break;
+ }
}
- return 0;
}
- else
+ else {
/* a is not completely initialized yet; follow tp_base */
- return type_is_subtype_base_chain(a, b);
+ res = type_is_subtype_base_chain(a, b);
+ }
+ return res;
}
int
PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
{
- int res;
- BEGIN_TYPE_LOCK();
- res = is_subtype_unlocked(a, b);
- END_TYPE_LOCK()
+#ifdef Py_GIL_DISABLED
+ PyObject *mro = _PyType_GetMRO(a);
+ int res = is_subtype_with_mro(mro, a, b);
+ Py_XDECREF(mro);
return res;
+#else
+ return is_subtype_with_mro(lookup_tp_mro(a), a, b);
+#endif
}
/* Routines to do a method lookup in the type without looking in the
}
PyTypeObject *base = (PyTypeObject*)obj;
- if (!is_subtype_unlocked(solid, solid_base(base))) {
+ if (!is_subtype_with_mro(lookup_tp_mro(solid), solid, solid_base(base))) {
PyErr_Format(
PyExc_TypeError,
"mro() returned base with unsuitable layout ('%.500s')",
#undef COPYVAL
/* Setup fast subclass flags */
- if (is_subtype_unlocked(base, (PyTypeObject*)PyExc_BaseException)) {
+ PyObject *mro = lookup_tp_mro(base);
+ if (is_subtype_with_mro(mro, base, (PyTypeObject*)PyExc_BaseException)) {
type->tp_flags |= Py_TPFLAGS_BASE_EXC_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyType_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyType_Type)) {
type->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyLong_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyLong_Type)) {
type->tp_flags |= Py_TPFLAGS_LONG_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyBytes_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyBytes_Type)) {
type->tp_flags |= Py_TPFLAGS_BYTES_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyUnicode_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyUnicode_Type)) {
type->tp_flags |= Py_TPFLAGS_UNICODE_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyTuple_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyTuple_Type)) {
type->tp_flags |= Py_TPFLAGS_TUPLE_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyList_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyList_Type)) {
type->tp_flags |= Py_TPFLAGS_LIST_SUBCLASS;
}
- else if (is_subtype_unlocked(base, &PyDict_Type)) {
+ else if (is_subtype_with_mro(mro, base, &PyDict_Type)) {
type->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
}
d = (PyWrapperDescrObject *)descr;
if ((specific == NULL || specific == d->d_wrapped) &&
d->d_base->wrapper == p->wrapper &&
- is_subtype_unlocked(type, PyDescr_TYPE(d)))
+ is_subtype_with_mro(lookup_tp_mro(type), type, PyDescr_TYPE(d)))
{
specific = d->d_wrapped;
}