From 26ff13715e6bf92f32d89517a70cef5795a63380 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 27 May 2008 00:12:36 +0200 Subject: [PATCH] invalidate the cache of all subtypes when updating a type's tp_dict (algorithm copied from typeobject.c in Py3) --- Cython/Compiler/ExprNodes.py | 45 ++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 6372ea77..f6b59cdf 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -847,6 +847,8 @@ class NameNode(AtomicExprNode): env.control_flow.set_state(self.pos, (self.name, 'source'), 'assignment') if self.entry.is_declared_generic: self.result_ctype = py_object_type + if self.entry.is_pyglobal and self.entry.is_member: + env.use_utility_code(type_cache_invalidation_code) def analyse_types(self, env): self.entry = env.lookup(self.name) @@ -990,11 +992,8 @@ class NameNode(AtomicExprNode): self.interned_cname, rhs.py_result())) # in Py2.6+, we need to invalidate the method cache - typeptr_cname = entry.scope.parent_type.typeptr_cname - code.putln("#if PY_VERSION_HEX >= 0x02060000") - code.putln("(%s)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;" % - typeptr_cname) - code.putln("#endif") + code.putln("__Pyx_TypeModified((PyTypeObject*)%s);" % + entry.scope.parent_type.typeptr_cname) else: code.put_error_if_neg(self.pos, 'PyObject_SetAttr(%s, %s, %s)' % ( @@ -4102,3 +4101,39 @@ static INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) { } ""","" ] + +#------------------------------------------------------------------------------------ + +type_cache_invalidation_code = [ +""" +#if PY_VERSION_HEX >= 0x02060000 +static void __Pyx_TypeModified(PyTypeObject* type); /*proto*/ +#else + #define __Pyx_TypeModified(t) +#endif +""",""" +#if PY_VERSION_HEX >= 0x02060000 +/* copied from typeobject.c in Python 3.0a5 */ +static void __Pyx_TypeModified(PyTypeObject* type) { + PyObject *raw, *ref; + Py_ssize_t i, n; + + if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) + return; + + raw = type->tp_subclasses; + if (raw != NULL) { + n = PyList_GET_SIZE(raw); + for (i = 0; i < n; i++) { + ref = PyList_GET_ITEM(raw, i); + ref = PyWeakref_GET_OBJECT(ref); + if (ref != Py_None) { + __Pyx_TypeModified((PyTypeObject *)ref); + } + } + } + type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; +} +#endif +""" +] -- 2.26.2