Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-cycle
Changeset: r98591:e8295913b0ef
Date: 2020-01-29 19:58 +0100
http://bitbucket.org/pypy/pypy/changeset/e8295913b0ef/
Log: Added rrc gc tests to improve code coverage
diff --git a/rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
b/rpython/memory/gc/test/dot/free_cpython_weakref_simple_4.dot
copy from rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
copy to rpython/memory/gc/test/dot/free_cpython_weakref_simple_4.dot
--- a/rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
+++ b/rpython/memory/gc/test/dot/free_cpython_weakref_simple_4.dot
@@ -1,7 +1,8 @@
digraph G {
"a" [type=C, alive=n];
"b" [type=C, alive=n];
+ "c" [type=C, alive=n];
"a" -> "b";
- "b" -> "a";
+ "b" -> "c";
"a" -> "b" [weakref=y, callback=y, clear_callback=y];
}
diff --git a/rpython/memory/gc/test/dot/free_finalizer_simple_1a.dot
b/rpython/memory/gc/test/dot/free_finalizer_simple_2.dot
copy from rpython/memory/gc/test/dot/free_finalizer_simple_1a.dot
copy to rpython/memory/gc/test/dot/free_finalizer_simple_2.dot
--- a/rpython/memory/gc/test/dot/free_finalizer_simple_1a.dot
+++ b/rpython/memory/gc/test/dot/free_finalizer_simple_2.dot
@@ -1,10 +1,10 @@
digraph G {
- "a" [type=P, alive=n];
- "b" [type=B, alive=n];
+ "a" [type=C, alive=n];
+ "b" [type=C, alive=n];
"c" [type=C, alive=n, finalizer=modern];
"d" [type=C, alive=n];
- "e" [type=B, alive=n];
- "f" [type=P, alive=n];
+ "e" [type=C, alive=n];
+ "f" [type=C, alive=n];
"a" -> "b";
"b" -> "c";
"c" -> "d";
diff --git a/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
b/rpython/memory/gc/test/dot/keep_cpython_inc_5.dot
copy from rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
copy to rpython/memory/gc/test/dot/keep_cpython_inc_5.dot
--- a/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
+++ b/rpython/memory/gc/test/dot/keep_cpython_inc_5.dot
@@ -1,15 +1,10 @@
digraph G {
"a" [type=B, alive=y, ext_refcnt=1];
- "b" [type=P, alive=n];
- "c" [type=P, alive=y];
- "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, gc=n];
- "a" -> "b" [removed=after_snap];
+ "b" [type=P, alive=y];
+ "c" [type=B, alive=y, added=linked_after_snap];
+ "d" [type=C, alive=y];
+ "a" -> "b";
"b" -> "c";
- "c" -> "d";
- "d" -> "e";
- "f" -> "g" [added=after_snap];
- "g" -> "c" [added=after_snap];
+ "c" -> "d" [added=after_snap];
+ "d" -> "a";
}
diff --git a/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
b/rpython/memory/gc/test/dot/keep_cpython_inc_6.dot
copy from rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
copy to rpython/memory/gc/test/dot/keep_cpython_inc_6.dot
--- a/rpython/memory/gc/test/dot/keep_cpython_inc_3b.dot
+++ b/rpython/memory/gc/test/dot/keep_cpython_inc_6.dot
@@ -1,15 +1,10 @@
digraph G {
- "a" [type=B, alive=y, ext_refcnt=1];
- "b" [type=P, alive=n];
- "c" [type=P, alive=y];
- "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, gc=n];
- "a" -> "b" [removed=after_snap];
+ "a" [type=C, alive=y, ext_refcnt=1];
+ "b" [type=C, alive=y];
+ "c" [type=C, alive=y, removed=after_snap];
+ "d" [type=C, alive=n];
+ "a" -> "b";
"b" -> "c";
- "c" -> "d";
- "d" -> "e";
- "f" -> "g" [added=after_snap];
- "g" -> "c" [added=after_snap];
+ "c" -> "d" [removed=after_snap];
+ "d" -> "a";
}
diff --git a/rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
b/rpython/memory/gc/test/dot/keep_cpython_weakref_simple_1.dot
copy from rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
copy to rpython/memory/gc/test/dot/keep_cpython_weakref_simple_1.dot
--- a/rpython/memory/gc/test/dot/free_cpython_weakref_simple_1.dot
+++ b/rpython/memory/gc/test/dot/keep_cpython_weakref_simple_1.dot
@@ -1,7 +1,10 @@
digraph G {
- "a" [type=C, alive=n];
- "b" [type=C, alive=n];
+ "a" [type=C, alive=y, ext_refcnt=1];
+ "b" [type=C, alive=y];
+ "c" [type=C, alive=n];
+ "d" [type=C, alive=n];
"a" -> "b";
- "b" -> "a";
- "a" -> "b" [weakref=y, callback=y, clear_callback=y];
+ "c" -> "d";
+ "d" -> "c";
+ "b" -> "c" [weakref=y, callback=y, clear_callback=n];
}
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
@@ -25,18 +25,57 @@
('prev', lltype.Ptr(S)),
('next', lltype.Ptr(S))))
-
class TestRawRefCount(BaseDirectGCTest):
GCClass = IncMiniMark
RRCGCClass = RawRefCountIncMarkGC
#RRCGCClass = RawRefCountMarkGC
+ # do cleanup after collection (clear all dead pyobjects)
+ def finalize_modern(self, 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)
+ self.decref(r, None)
+
+ def decref_children(self, pyobj):
+ self.gc.rrc_gc.tp_traverse(pyobj, self.decref, None)
+
+ def decref(self, pyobj, ignore):
+ pyobj.c_ob_refcnt -= 1
+ if pyobj.c_ob_refcnt == 0:
+ self.finalize_modern(pyobj)
+ if pyobj.c_ob_refcnt == 0:
+ gchdr = self.gc.rrc_gc.pyobj_as_gc(pyobj)
+ if gchdr != lltype.nullptr(PYOBJ_GC_HDR) and \
+ gchdr.c_gc_refs != RAWREFCOUNT_REFS_UNTRACKED:
+ next = gchdr.c_gc_next
+ next.c_gc_prev = gchdr.c_gc_prev
+ gchdr.c_gc_prev.c_gc_next = next
+ self.decref_children(pyobj)
+ self.pyobjs[self.pyobjs.index(pyobj)] = \
+ lltype.nullptr(PYOBJ_HDR_PTR.TO)
+ lltype.free(pyobj, flavor='raw')
+
def setup_method(self, method):
BaseDirectGCTest.setup_method(self, method)
self.trigger = []
self.gcobjs = []
self.pyobjs = []
+ self.pyobjs_removed_count = []
self.pyobj_refs = []
self.pyobj_weakrefs = []
self.pyobj_finalizer = {}
@@ -123,6 +162,14 @@
refs.append(pyobj_to)
pyobj_to.c_ob_refcnt += 1
+ def _rawrefcount_removeref(self, pyobj_from, pyobj_to):
+ refs = self.pyobj_refs[self.pyobjs.index(pyobj_from)]
+ refs.remove(pyobj_to)
+ self.decref(pyobj_to, None)
+
+ def _get_removed_count(self, pyobj):
+ return self.pyobjs_removed_count[self.pyobjs.index(pyobj)]
+
def _rawrefcount_addweakref(self, pyobj_from, weakref):
refs = self.pyobj_weakrefs[self.pyobjs.index(pyobj_from)]
refs.append(weakref)
@@ -169,6 +216,7 @@
self.tupletypes.append(tuple_type)
self.pyobjs.append(r1)
+ self.pyobjs_removed_count.append(0)
self.is_pygc.append(is_gc)
self.pyobj_refs.append([])
self.pyobj_weakrefs.append([])
@@ -220,6 +268,7 @@
self.tupletypes.append(tuple_type)
self.pyobjs.append(r1)
+ self.pyobjs_removed_count.append(0)
self.is_pygc.append(is_gc)
self.pyobj_refs.append([])
self.pyobj_weakrefs.append([])
@@ -729,44 +778,12 @@
garbage_pypy = []
garbage_pyobj = []
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_gc.tp_traverse(pyobj, decref, None)
def decref(pyobj, ignore):
- pyobj.c_ob_refcnt -= 1
- if pyobj.c_ob_refcnt == 0:
- finalize_modern(pyobj)
- if pyobj.c_ob_refcnt == 0:
- gchdr = self.gc.rrc_gc.pyobj_as_gc(pyobj)
- if gchdr != lltype.nullptr(PYOBJ_GC_HDR) and \
- gchdr.c_gc_refs != RAWREFCOUNT_REFS_UNTRACKED:
- next = gchdr.c_gc_next
- next.c_gc_prev = gchdr.c_gc_prev
- gchdr.c_gc_prev.c_gc_next = next
- decref_children(pyobj)
- self.pyobjs[self.pyobjs.index(pyobj)] = \
- lltype.nullptr(PYOBJ_HDR_PTR.TO)
- lltype.free(pyobj, flavor='raw')
+ self.decref(pyobj, ignore)
+
+ def finalize_modern(pyobj):
+ self.finalize_modern(pyobj)
next_dead = self.gc.rawrefcount_next_dead()
while next_dead <> llmemory.NULL:
@@ -901,8 +918,11 @@
remove[2].p.prev = remove[2].p
else:
assert False, "not yet supported"
- else:
- assert False, "not yet supported"
+ elif remove[0] == "C":
+ source = remove[1]
+ dest = remove[2]
+ self._rawrefcount_removeref(source.r, dest.r)
+
after_snap = True
self.gc.rrc_gc.invoke_callback()
@@ -925,7 +945,8 @@
if n.info.type == "P":
n.check_alive()
else:
- n.check_alive(n.info.ext_refcnt)
+ removed_refs = self._get_removed_count(n.r)
+ n.check_alive(n.info.ext_refcnt - removed_refs)
print "Node", name, "is alive."
else:
print "Node", name, "should be dead."
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit