diff options
author | Julien Palard <julien@palard.fr> | 2019-05-26 14:25:47 (GMT) |
---|---|---|
committer | Mark Shannon <mark@hotpy.org> | 2019-05-26 14:25:47 (GMT) |
commit | 180dc1b0f4a57c3f66351568ae8488fa8576d7f0 (patch) | |
tree | 63d3b62daf6e75634c5df968afa541b3fd1c04fb /Objects | |
parent | 135c6a56e55d2f4f8718b3b9f03ce3c692b15f0f (diff) | |
download | cpython-180dc1b0f4a57c3f66351568ae8488fa8576d7f0.zip cpython-180dc1b0f4a57c3f66351568ae8488fa8576d7f0.tar.gz cpython-180dc1b0f4a57c3f66351568ae8488fa8576d7f0.tar.bz2 |
bpo-28866: No type cache for types with specialized mro, invalidation is hard. (#13157)
* No type cache for types with specialized mro, invalidation is hard.
* FIX: Don't disable method cache custom types that do not implement mro().
* fixing implem.
* Avoid storing error flags, also decref.
* news entry
* Clear as soon as we're getting an error.
* FIX: Reference leak.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 339f728..fc809d3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -78,6 +78,9 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static void clear_slotdefs(void); +static PyObject * +lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound); + /* * finds the beginning of the docstring's introspection signature. * if present, returns a pointer pointing to the first '('. @@ -287,17 +290,35 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type has a custom MRO that includes a type which is not officially - super type. + super type, or if the type implements its own mro() method. Called from mro_internal, which will subsequently be called on each subclass when their mro is recursively updated. */ Py_ssize_t i, n; - int clear = 0; + int custom = (Py_TYPE(type) != &PyType_Type); + int unbound; + PyObject *mro_meth = NULL; + PyObject *type_mro_meth = NULL; if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG)) return; + if (custom) { + _Py_IDENTIFIER(mro); + mro_meth = lookup_maybe_method( + (PyObject *)type, &PyId_mro, &unbound); + if (mro_meth == NULL) + goto clear; + type_mro_meth = lookup_maybe_method( + (PyObject *)&PyType_Type, &PyId_mro, &unbound); + if (type_mro_meth == NULL) + goto clear; + if (mro_meth != type_mro_meth) + goto clear; + Py_XDECREF(mro_meth); + Py_XDECREF(type_mro_meth); + } n = PyTuple_GET_SIZE(bases); for (i = 0; i < n; i++) { PyObject *b = PyTuple_GET_ITEM(bases, i); @@ -308,14 +329,15 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) { if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) || !PyType_IsSubtype(type, cls)) { - clear = 1; - break; + goto clear; } } - - if (clear) - type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG| - Py_TPFLAGS_VALID_VERSION_TAG); + return; + clear: + Py_XDECREF(mro_meth); + Py_XDECREF(type_mro_meth); + type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG| + Py_TPFLAGS_VALID_VERSION_TAG); } static int |