Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-cycle
Changeset: r96125:a3d95a9939f4
Date: 2019-02-22 11:27 +0100
http://bitbucket.org/pypy/pypy/changeset/a3d95a9939f4/

Log:    Added more tests for "modern" rawrefcount finalizers

diff --git a/rpython/memory/gc/test/dot/free_finalizer_nocycle.dot 
b/rpython/memory/gc/test/dot/free_finalizer_nocycle_1a.dot
rename from rpython/memory/gc/test/dot/free_finalizer_nocycle.dot
rename to rpython/memory/gc/test/dot/free_finalizer_nocycle_1a.dot
diff --git a/rpython/memory/gc/test/dot/free_finalizer_nocycle.dot 
b/rpython/memory/gc/test/dot/free_finalizer_nocycle_1b.dot
copy from rpython/memory/gc/test/dot/free_finalizer_nocycle.dot
copy to rpython/memory/gc/test/dot/free_finalizer_nocycle_1b.dot
--- a/rpython/memory/gc/test/dot/free_finalizer_nocycle.dot
+++ b/rpython/memory/gc/test/dot/free_finalizer_nocycle_1b.dot
@@ -1,7 +1,7 @@
 digraph G {
     "a" [type=P, alive=n];
     "b" [type=B, alive=n];
-    "c" [type=C, alive=n, finalizer=modern];
+    "c" [type=C, alive=n, finalizer=modern, delete="d"];
     "d" [type=C, alive=n];
     "e" [type=B, alive=n];
     "f" [type=P, alive=n];
diff --git a/rpython/memory/gc/test/dot/free_finalizer_nocycle.dot 
b/rpython/memory/gc/test/dot/free_finalizer_nocycle_1c.dot
copy from rpython/memory/gc/test/dot/free_finalizer_nocycle.dot
copy to rpython/memory/gc/test/dot/free_finalizer_nocycle_1c.dot
--- a/rpython/memory/gc/test/dot/free_finalizer_nocycle.dot
+++ b/rpython/memory/gc/test/dot/free_finalizer_nocycle_1c.dot
@@ -1,8 +1,8 @@
 digraph G {
     "a" [type=P, alive=n];
     "b" [type=B, alive=n];
-    "c" [type=C, alive=n, finalizer=modern];
-    "d" [type=C, alive=n];
+    "c" [type=C, alive=n, finalizer=modern, delete="d"];
+    "d" [type=C, alive=n, finalizer=modern, delete="e"];
     "e" [type=B, alive=n];
     "f" [type=P, alive=n];
     "a" -> "b";
diff --git a/rpython/memory/gc/test/dot/free_finalizer_simple.dot 
b/rpython/memory/gc/test/dot/free_finalizer_simple_1a.dot
rename from rpython/memory/gc/test/dot/free_finalizer_simple.dot
rename to rpython/memory/gc/test/dot/free_finalizer_simple_1a.dot
diff --git a/rpython/memory/gc/test/dot/free_finalizer_simple.dot 
b/rpython/memory/gc/test/dot/free_finalizer_simple_1b.dot
copy from rpython/memory/gc/test/dot/free_finalizer_simple.dot
copy to rpython/memory/gc/test/dot/free_finalizer_simple_1b.dot
--- a/rpython/memory/gc/test/dot/free_finalizer_simple.dot
+++ b/rpython/memory/gc/test/dot/free_finalizer_simple_1b.dot
@@ -1,7 +1,7 @@
 digraph G {
     "a" [type=P, alive=n];
     "b" [type=B, alive=n];
-    "c" [type=C, alive=n, finalizer=modern];
+    "c" [type=C, alive=n, finalizer=modern, delete="d"];
     "d" [type=C, alive=n];
     "e" [type=B, alive=n];
     "f" [type=P, alive=n];
diff --git a/rpython/memory/gc/test/dot/keep_finalizer_simple.dot 
b/rpython/memory/gc/test/dot/keep_finalizer_simple_1a.dot
rename from rpython/memory/gc/test/dot/keep_finalizer_simple.dot
rename to rpython/memory/gc/test/dot/keep_finalizer_simple_1a.dot
diff --git a/rpython/memory/gc/test/dot/keep_finalizer_simple.dot 
b/rpython/memory/gc/test/dot/keep_finalizer_simple_1b.dot
copy from rpython/memory/gc/test/dot/keep_finalizer_simple.dot
copy to rpython/memory/gc/test/dot/keep_finalizer_simple_1b.dot
--- a/rpython/memory/gc/test/dot/keep_finalizer_simple.dot
+++ b/rpython/memory/gc/test/dot/keep_finalizer_simple_1b.dot
@@ -1,7 +1,7 @@
 digraph G {
     "a" [type=P, alive=y];
     "b" [type=B, alive=y];
-    "c" [type=C, alive=y, finalizer=modern, resurrect="d"];
+    "c" [type=C, alive=y, finalizer=modern, resurrect="c"];
     "d" [type=C, alive=y];
     "e" [type=B, alive=y];
     "f" [type=P, alive=y];
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
@@ -31,7 +31,9 @@
         self.pyobjs = []
         self.pyobj_refs = []
         self.pyobj_finalizer = {}
+        self.pyobj_finalized = {}
         self.pyobj_resurrect = {}
+        self.pyobj_delete = {}
 
         def rawrefcount_tp_traverse(obj, callback, args):
             refs = self.pyobj_refs[self.pyobjs.index(obj)]
@@ -85,6 +87,10 @@
         refs = self.pyobj_resurrect[self.pyobjs.index(pyobj_source)] = []
         refs.append(pyobj_target)
 
+    def _rawrefcount_add_delete(self, pyobj_source, pyobj_target):
+        refs = self.pyobj_delete[self.pyobjs.index(pyobj_source)] = []
+        refs.append(pyobj_target)
+
     def _rawrefcount_pypyobj(self, intval, rooted=False, create_old=True):
         p1 = self.malloc(S)
         p1.x = intval
@@ -412,8 +418,6 @@
     @py.test.mark.parametrize("file", dot_files)
     def test_dots(self, file):
         from rpython.memory.gc.test.dot import pydot
-        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY
-        from rpython.rlib.rawrefcount import REFCNT_FROM_PYPY_LIGHT
 
         class Node:
             def __init__(self, info):
@@ -443,12 +447,14 @@
                 self.info = info
 
         class NodeInfo:
-            def __init__(self, type, alive, ext_refcnt, finalizer, resurrect):
+            def __init__(self, type, alive, ext_refcnt, finalizer, resurrect,
+                         delete):
                 self.type = type
                 self.alive = alive
                 self.ext_refcnt = ext_refcnt
                 self.finalizer = finalizer
                 self.resurrect = resurrect
+                self.delete = delete
 
         path = os.path.join(self.dot_dir, file)
         g = pydot.graph_from_dot_file(path)[0]
@@ -468,7 +474,9 @@
             if finalizer <> None:
                 finalizers = True
             resurrect = attr['resurrect'] if 'resurrect' in attr else None
-            info = NodeInfo(type, alive, ext_refcnt, finalizer, resurrect)
+            delete = attr['delete'] if 'delete' in attr else None
+            info = NodeInfo(type, alive, ext_refcnt, finalizer, resurrect,
+                            delete)
             if type == "C":
                 r, raddr, check_alive = self._rawrefcount_pyobj()
                 r.c_ob_refcnt += ext_refcnt
@@ -509,10 +517,15 @@
             if hasattr(n, "r"):
                 index = self.pyobjs.index(n.r)
                 resurrect = n.info.resurrect
-                if n.info.finalizer == "modern" and resurrect is not None:
+                delete = n.info.delete
+                if n.info.finalizer == "modern":
                     self.pyobj_finalizer[index] = RAWREFCOUNT_FINALIZER_MODERN
-                    self._rawrefcount_add_resurrect(n.r, nodes[resurrect].r)
-                    nodes[resurrect].info.ext_refcnt += 1
+                    if resurrect is not None:
+                        self._rawrefcount_add_resurrect(n.r,
+                                                        nodes[resurrect].r)
+                        nodes[resurrect].info.ext_refcnt += 1
+                    if delete is not None:
+                        self._rawrefcount_add_delete(n.r, nodes[delete].r)
                 else:
                     self.pyobj_finalizer[index] = RAWREFCOUNT_FINALIZER_NONE
 
@@ -534,18 +547,32 @@
 
         def cleanup():
             # do cleanup after collection (clear all dead pyobjects)
+            def finalize_modern(pyobj):
+                index = self.pyobjs.index(pyobj)
+                if not self.pyobj_finalizer.has_key(index) or \
+                    self.pyobj_finalizer[index] != \
+                        RAWREFCOUNT_FINALIZER_MODERN:
+                    return
+                if self.pyobj_finalized.has_key(index):
+                    return
+                self.pyobj_finalized[index] = True
+                if self.pyobj_resurrect.has_key(index):
+                    resurrect = self.pyobj_resurrect[index]
+                    for r in resurrect:
+                        r.c_ob_refcnt += 1
+                if self.pyobj_delete.has_key(index):
+                    delete = self.pyobj_delete[index]
+                    for r in delete:
+                        self.pyobj_refs[index].remove(r)
+                        decref(r, None)
+
             def decref_children(pyobj):
                 self.gc.rrc_tp_traverse(pyobj, decref, None)
 
             def decref(pyobj, ignore):
                 pyobj.c_ob_refcnt -= 1
                 if pyobj.c_ob_refcnt == 0:
-                    if self.pyobj_resurrect.has_key(self.pyobjs.index(pyobj)):
-                        resurrect = self.pyobj_resurrect[
-                            self.pyobjs.index(pyobj)]
-                        for r in resurrect:
-                            r.c_ob_refcnt += 1
-                            resurrect.remove(r)
+                    finalize_modern(pyobj)
                 if pyobj.c_ob_refcnt == 0:
                     gchdr = self.gc.rrc_pyobj_as_gc(pyobj)
                     next = gchdr.c_gc_next
@@ -567,12 +594,9 @@
             while next <> llmemory.NULL:
                 pyobj = llmemory.cast_adr_to_ptr(next,
                                                  self.gc.PYOBJ_HDR_PTR)
-                if self.pyobj_resurrect.has_key(self.pyobjs.index(pyobj)):
-                    resurrect = self.pyobj_resurrect[self.pyobjs.index(pyobj)]
-                    for r in resurrect:
-                        r.c_ob_refcnt += 1
-                        # TODO: improve test, use flag in gc_refs instead
-                        resurrect.remove(r)
+                pyobj.c_ob_refcnt += 1
+                finalize_modern(pyobj)
+                decref(pyobj, None)
                 next = self.gc.rawrefcount_next_cyclic_isolate()
 
             next_dead = self.gc.rawrefcount_cyclic_garbage_head()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to