diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2019-05-26 15:14:23 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-26 15:14:23 -0700 |
commit | bfd0b7720196b9ff647cc33dafbd31a04496402c (patch) | |
tree | 27624afe606c757cdcee2f074226031b85e1b8a7 /Objects | |
parent | f3d909428c7c61ea32e8fbb9c8b48344e7904a53 (diff) | |
download | cpython-git-bfd0b7720196b9ff647cc33dafbd31a04496402c.tar.gz |
[3.7] bpo-28866: No type cache for types with specialized mro, invalidation is hard. (GH-13157) (GH-13589)
* 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.
(cherry picked from commit 180dc1b0f4a57c3f66351568ae8488fa8576d7f0)
Co-authored-by: Julien Palard <julien@palard.fr>
https://bugs.python.org/issue28866
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 8adae49a7f..9dba45ac6f 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -77,6 +77,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 '('. @@ -281,17 +284,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); @@ -302,14 +323,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 |