avoid traversing/clearing exttype attributes with simple types during garbage collection
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 27 Jul 2013 05:52:50 +0000 (07:52 +0200)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 27 Jul 2013 05:52:50 +0000 (07:52 +0200)
Cython/Compiler/ModuleNode.py
Cython/Compiler/Symtab.py
tests/run/cyclic_gc.pyx

index fc78e94..6f2a114 100644 (file)
@@ -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 = ''
index 9c9059c..a1bc497 100644 (file)
@@ -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:
index ff26071..c4ada3b 100644 (file)
@@ -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