From: Antoine Pitrou Date: Wed, 20 Dec 2017 14:58:21 +0000 (+0100) Subject: bpo-32379: Faster MRO computation for single inheritance (#4932) X-Git-Tag: v3.7.0a4~85 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1f1a34c3145781628e10534440017b3b43211a60;p=thirdparty%2FPython%2Fcpython.git bpo-32379: Faster MRO computation for single inheritance (#4932) * bpo-32379: Faster MRO computation for single inheritance --- diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index ced25f3fc442..d24d005ccfaa 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1783,6 +1783,12 @@ order (MRO) for bases """ def f(self): return "C" class D(B, C): pass + self.assertEqual(A.mro(), [A, object]) + self.assertEqual(A.__mro__, (A, object)) + self.assertEqual(B.mro(), [B, A, object]) + self.assertEqual(B.__mro__, (B, A, object)) + self.assertEqual(C.mro(), [C, A, object]) + self.assertEqual(C.__mro__, (C, A, object)) self.assertEqual(D.mro(), [D, B, C, A, object]) self.assertEqual(D.__mro__, (D, B, C, A, object)) self.assertEqual(D().f(), "C") diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst new file mode 100644 index 000000000000..1050c61b9ec5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst @@ -0,0 +1 @@ +Make MRO computation faster when a class inherits from a single base. diff --git a/Objects/typeobject.c b/Objects/typeobject.c index aa907018859e..849c6dc19294 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1761,6 +1761,36 @@ mro_implementation(PyTypeObject *type) return NULL; } + bases = type->tp_bases; + n = PyTuple_GET_SIZE(bases); + if (n == 1) { + /* Fast path: if there is a single base, constructing the MRO + * is trivial. + */ + PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0); + Py_ssize_t k; + + if (base->tp_mro == NULL) { + PyErr_Format(PyExc_TypeError, + "Cannot extend an incomplete type '%.100s'", + base->tp_name); + return NULL; + } + k = PyTuple_GET_SIZE(base->tp_mro); + result = PyTuple_New(k + 1); + if (result == NULL) { + return NULL; + } + Py_INCREF(type); + PyTuple_SET_ITEM(result, 0, (PyObject *) type); + for (i = 0; i < k; i++) { + PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); + Py_INCREF(cls); + PyTuple_SET_ITEM(result, i + 1, cls); + } + return result; + } + /* Find a superclass linearization that honors the constraints of the explicit lists of bases and the constraints implied by each base class. @@ -1770,9 +1800,6 @@ mro_implementation(PyTypeObject *type) to_merge is the declared list of bases. */ - bases = type->tp_bases; - n = PyTuple_GET_SIZE(bases); - to_merge = PyList_New(n+1); if (to_merge == NULL) return NULL; @@ -1830,7 +1857,12 @@ static PyObject * type_mro_impl(PyTypeObject *self) /*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/ { - return mro_implementation(self); + PyObject *seq; + seq = mro_implementation(self); + if (seq != NULL && !PyList_Check(seq)) { + Py_SETREF(seq, PySequence_List(seq)); + } + return seq; } static int