Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-cycle
Changeset: r97591:f23e180d2dfc
Date: 2019-09-23 12:17 +0200
http://bitbucket.org/pypy/pypy/changeset/f23e180d2dfc/

Log:    Fixed bugs in rrc incmark Added test case and implemented missing
        check for new linked proxies

diff --git a/rpython/memory/gc/rrc/incmark.py b/rpython/memory/gc/rrc/incmark.py
--- a/rpython/memory/gc/rrc/incmark.py
+++ b/rpython/memory/gc/rrc/incmark.py
@@ -72,24 +72,35 @@
         #    set their cyclic refcount to > 0 to mark them as live
         consistent = True
         self.snapshot_consistent = True
-        # simply iterate the snapshot for objects in p_list, as linked objects 
might not be freed, except by the gc
+
+        # sync p_list_old (except gc-objects)
+        # simply iterate the snapshot for objects in p_list, as linked objects
+        # might not be freed, except by the gc
         free_p_list = self.gc.AddressStack()
         for i in range(0, self.total_objs):
             snapobj = self.snapshot_objs[i]
             if snapobj.pypy_link == 0:
-                break
+                break  # only look for objects in p_list
             pyobj = llmemory.cast_adr_to_ptr(snapobj.pyobj, self.PYOBJ_HDR_PTR)
             pygchdr = self.pyobj_as_gc(pyobj)
-            if (pygchdr <> lltype.nullptr(self.PYOBJ_GC_HDR) and
+            if (pygchdr != lltype.nullptr(self.PYOBJ_GC_HDR) and
                     pygchdr.c_gc_refs != self.RAWREFCOUNT_REFS_UNTRACKED):
-                break
+                break # only look for non-gc
             if snapobj.refcnt == 0:
+                # check consistency
                 consistent = pyobj.c_ob_refcnt == snapobj.refcnt_original
                 if not consistent:
                     break
                 # move to separate list
+                self.p_list_old.remove(snapobj.pyobj)
                 free_p_list.append(snapobj.pyobj)
 
+        # look if there is a (newly) linked non-gc proxy, where the non-rc obj
+        # is unmarked
+        self.p_list_old_consistent = True
+        self.p_list_old.foreach(self._check_consistency_p_list_old, None)
+        consistent &= self.p_list_old_consistent
+
         # sync gc objects
         pygchdr = self.pyobj_list.c_gc_next
         while pygchdr <> self.pyobj_list and consistent:
@@ -116,9 +127,14 @@
                     self._gc_list_add(self.pyobj_old_list, pygchdr)
             else:
                 # new object, keep alive
+                pygchdr.c_gc_refs = 1 << self.RAWREFCOUNT_REFS_SHIFT
                 pyobj = self.gc_as_pyobj(pygchdr)
-                pygchdr.c_gc_refs = 1 << self.RAWREFCOUNT_REFS_SHIFT
-                # TODO: also keep reachable objects alive (in case rc proxy -> 
non-rc -> non-rc proxy -> rc obj!!!)
+                if pyobj.c_ob_pypy_link != 0:
+                    addr = llmemory.cast_int_to_adr(pyobj.c_ob_pypy_link)
+                    if not (self.gc.header(addr).tid &
+                            (self.GCFLAG_VISITED | self.GCFLAG_NO_HEAP_PTRS)):
+                        consistent = False
+                        break
             pygchdr = next_old
 
         self._debug_check_consistency(print_label="end-check-consistency")
@@ -172,11 +188,19 @@
                         "refcnt original", snapobj.refcnt_original,
                         "link", snapobj.pypy_link)
 
+    def _check_consistency_p_list_old(self, pyobject, foo):
+        pyobj = llmemory.cast_adr_to_ptr(pyobject, self.PYOBJ_HDR_PTR)
+        pygchdr = self.pyobj_as_gc(pyobj)
+        if (pygchdr == lltype.nullptr(self.PYOBJ_GC_HDR) and
+                pyobj.c_ob_pypy_link != 0):
+            addr = llmemory.cast_int_to_adr(pyobj.c_ob_pypy_link)
+            if not (self.gc.header(addr).tid &
+                    (self.GCFLAG_VISITED | self.GCFLAG_NO_HEAP_PTRS)):
+                self.p_list_old_consistent = False
+
     def _free_p_list(self, pyobject, foo):
         from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
         from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
-        # unlink
-        self.p_list_old.remove(pyobject)
         pyobj = llmemory.cast_adr_to_ptr(pyobject, self.PYOBJ_HDR_PTR)
         refcnt = pyobj.c_ob_refcnt
         if refcnt >= REFCNT_FROM_PYPY_LIGHT:
diff --git a/rpython/memory/gc/test/dot/keep_cpython_inc_3.dot 
b/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
copy from rpython/memory/gc/test/dot/keep_cpython_inc_3.dot
copy to rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
--- a/rpython/memory/gc/test/dot/keep_cpython_inc_3.dot
+++ b/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
@@ -5,7 +5,7 @@
     "d" [type=B, alive=y];
     "e" [type=C, alive=y];
     "f" [type=C, alive=y, ext_refcnt=1, added=after_snap];
-    "g" [type=B, alive=y, added=linked_after_snap];
+    "g" [type=B, alive=y, added=linked_after_snap, gc=n];
     "a" -> "b" [removed=after_snap];
     "b" -> "c";
     "c" -> "d";
diff --git a/rpython/memory/gc/test/test_rawrefcount.py 
b/rpython/memory/gc/test/test_rawrefcount.py
--- a/rpython/memory/gc/test/test_rawrefcount.py
+++ b/rpython/memory/gc/test/test_rawrefcount.py
@@ -850,13 +850,15 @@
                         i += 1
                     for obj in add_linked_pyobj_after_snap:
                         r, raddr, check_alive = self._rawrefcount_pyobj(
-                            tracked=obj.info.tracked, tuple=obj.info.tuple)
+                            tracked=obj.info.tracked, tuple=obj.info.tuple,
+                            is_gc=obj.info.gc)
                         r.c_ob_refcnt += obj.info.ext_refcnt
                         obj.r = r
                         obj.raddr = raddr
-                        def double_check():
-                            obj.check_alive()
-                            check_alive()
+                        old_alive = obj.check_alive
+                        def double_check(ext_refcnt):
+                            old_alive()
+                            check_alive(ext_refcnt)
                         obj.check_alive = double_check
                         self.gc.rawrefcount_create_link_pypy(obj.pref, raddr)
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to