From 81026937e1d5eb39284a0efc65e12e1c8cfc183c Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 27 Jul 2013 07:52:50 +0200 Subject: [PATCH] avoid traversing/clearing exttype attributes with simple types during garbage collection --- Cython/Compiler/ModuleNode.py | 13 ++++--------- Cython/Compiler/Symtab.py | 6 ++++-- tests/run/cyclic_gc.pyx | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index fc78e94..6f2a114 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -1290,8 +1290,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): "static int %s(PyObject *o, visitproc v, void *a) {" % slot_func) - have_entries, (py_attrs, py_buffers, - memoryview_slices) = scope.get_refcounted_entries() + have_entries, (py_attrs, py_buffers, memoryview_slices) = ( + scope.get_refcounted_entries(include_gc_simple=False)) if base_type or py_attrs: code.putln("int e;") @@ -1354,13 +1354,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): if tp_slot.slot_code(scope) != slot_func: return # never used - py_attrs = [] - py_buffers = [] - for entry in scope.var_entries: - if entry.type.is_pyobject and entry.name != "__weakref__": - py_attrs.append(entry) - if entry.type == PyrexTypes.c_py_buffer_type: - py_buffers.append(entry) + have_entries, (py_attrs, py_buffers, memoryview_slices) = ( + scope.get_refcounted_entries(include_gc_simple=False)) if py_attrs or py_buffers or base_type: unused = '' diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 9c9059c..a1bc497 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -832,7 +832,8 @@ class Scope(object): def add_include_file(self, filename): self.outer_scope.add_include_file(filename) - def get_refcounted_entries(self, include_weakref=False): + def get_refcounted_entries(self, include_weakref=False, + include_gc_simple=True): py_attrs = [] py_buffers = [] memoryview_slices = [] @@ -840,7 +841,8 @@ class Scope(object): for entry in self.var_entries: if entry.type.is_pyobject: if include_weakref or entry.name != "__weakref__": - py_attrs.append(entry) + if include_gc_simple or not entry.type.is_gc_simple: + py_attrs.append(entry) elif entry.type == PyrexTypes.c_py_buffer_type: py_buffers.append(entry) elif entry.type.is_memoryviewslice: diff --git a/tests/run/cyclic_gc.pyx b/tests/run/cyclic_gc.pyx index ff26071..c4ada3b 100644 --- a/tests/run/cyclic_gc.pyx +++ b/tests/run/cyclic_gc.pyx @@ -79,12 +79,16 @@ cdef class ExtTypePyArgsWithGC: >>> obj = ExtTypePyArgsWithGC() >>> obj = ExtTypePyArgsWithGC() >>> obj = ExtTypePyArgsWithGC() + >>> obj.create_cycle() """ cdef bytes b cdef str s cdef unicode u cdef list l + def create_cycle(self): + self.l = [self] + @cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]') @cython.test_assert_path_exists('//CClassDefNode', @@ -98,4 +102,40 @@ cdef class ExtSubTypePyArgsWithGC(ExtTypePyArgsWithGC): >>> obj = ExtSubTypePyArgsWithGC() >>> obj = ExtSubTypePyArgsWithGC() >>> obj = ExtSubTypePyArgsWithGC() + >>> obj.create_cycle() + """ + + +@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]') +@cython.test_assert_path_exists('//CClassDefNode', + '//CClassDefNode[@scope]', + '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]') +cdef class ExtSubTypePlusPyArgsWithGC(ExtSubTypePyArgsWithGC): + """ + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj = ExtSubTypePlusPyArgsWithGC() + >>> obj.create_cycle() + """ + cdef bytes b2 + cdef unicode u2 + + +@cython.test_fail_if_path_exists('//CClassDefNode[@scope.has_cyclic_pyobject_attrs = False]') +@cython.test_assert_path_exists('//CClassDefNode', + '//CClassDefNode[@scope]', + '//CClassDefNode[@scope.has_cyclic_pyobject_attrs = True]') +cdef class ExtSubTypePlusGCPyArgsWithGC(ExtSubTypePlusPyArgsWithGC): + """ + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj = ExtSubTypePlusGCPyArgsWithGC() + >>> obj.create_cycle() """ + cdef tuple t -- 2.7.4