From: Stefan Behnel Date: Mon, 26 May 2008 22:12:36 +0000 (+0200) Subject: invalidate the cache of all subtypes when updating a type's tp_dict (algorithm copied... X-Git-Tag: 0.9.8rc1~11^2~10^2~15^2 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=26ff13715e6bf92f32d89517a70cef5795a63380;p=cython.git invalidate the cache of all subtypes when updating a type's tp_dict (algorithm copied from typeobject.c in Py3) --- 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 +""" +]