[pypy-commit] pypy cpyext-gc-cycle: Fixed tests for non-gc proxies in incmark
stevie_92
pypy.commits at gmail.com
Sat Sep 21 10:43:27 EDT 2019
Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r97577:2606a6511ff0
Date: 2019-09-21 09:43 +0200
http://bitbucket.org/pypy/pypy/changeset/2606a6511ff0/
Log: Fixed tests for non-gc proxies in incmark
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
@@ -13,11 +13,6 @@
return True
if self.state == self.STATE_DEFAULT:
- # For all non-gc pyobjects which have a refcount > 0,
- # mark all reachable objects on the pypy side
- self.p_list_old.foreach(self._major_trace_nongc, False)
- # TODO: execute incrementally (own phase)
-
# Merge all objects whose finalizer have been executed to the
# pyobj_list (to reprocess them again in the snapshot). Finalizers
# can only be executed once, so termination will eventually happen.
@@ -72,10 +67,29 @@
# * move all dead objects still in pyob_list to pyobj_old_list
# * for all other objects (in snapshot and new),
# set their cyclic refcount to > 0 to mark them as live
- pygchdr = self.pyobj_list.c_gc_next
consistent = True
self.snapshot_consistent = True
- while pygchdr <> self.pyobj_list: # TODO: also sync p_list
+ # 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
+ 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
+ pygchdr.c_gc_refs != self.RAWREFCOUNT_REFS_UNTRACKED):
+ break
+ if snapobj.refcnt == 0:
+ consistent = pyobj.c_ob_refcnt == snapobj.refcnt_original
+ if not consistent:
+ break
+ # move to separate list
+ free_p_list.append(snapobj.pyobj)
+
+ # sync gc objects
+ pygchdr = self.pyobj_list.c_gc_next
+ while pygchdr <> self.pyobj_list and consistent:
next_old = pygchdr.c_gc_next
if pygchdr.c_gc_refs > 0: # object is in snapshot
snapobj = self.snapshot_objs[pygchdr.c_gc_refs - 1]
@@ -105,6 +119,8 @@
self._debug_check_consistency(print_label="end-check-consistency")
if not consistent: # keep all objects alive
+ while free_p_list.non_empty():
+ self.p_list_old.append(free_p_list.pop())
while pygchdr <> self.pyobj_list: # continue previous loop
pygchdr.c_gc_refs = 1
pygchdr = pygchdr.c_gc_next
@@ -114,6 +130,8 @@
pygchdr = pygchdr.c_gc_next
if not self._gc_list_is_empty(self.pyobj_old_list):
self._gc_list_merge(self.pyobj_old_list, self.pyobj_list)
+ else:
+ free_p_list.foreach(self._free_p_list, None)
self._debug_check_consistency(print_label="before-snap-discard")
@@ -140,6 +158,19 @@
self._debug_check_consistency(print_label="end-mark")
return True
+ 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:
+ refcnt -= REFCNT_FROM_PYPY_LIGHT
+ elif refcnt >= REFCNT_FROM_PYPY:
+ refcnt -= REFCNT_FROM_PYPY
+ pyobj.c_ob_refcnt = refcnt
+
def _collect_roots(self):
# Subtract all internal refcounts from the cyclic refcount
# of rawrefcounted objects
diff --git a/rpython/memory/gc/test/dot/keep_cross_nogc_1.dot b/rpython/memory/gc/test/dot/keep_nocycle_nogc_1.dot
copy from rpython/memory/gc/test/dot/keep_cross_nogc_1.dot
copy to rpython/memory/gc/test/dot/keep_nocycle_nogc_1.dot
--- a/rpython/memory/gc/test/dot/keep_cross_nogc_1.dot
+++ b/rpython/memory/gc/test/dot/keep_nocycle_nogc_1.dot
@@ -1,12 +1,7 @@
digraph G {
- "a" [type=P, alive=y];
- "b" [type=B, alive=y];
- "c" [type=C, alive=y];
- "d" [type=B, alive=y, gc=n];
- "e" [type=P, alive=y, rooted=y];
+ "a" [type=C, alive=y, ext_refcnt=1];
+ "b" [type=B, alive=y, gc=n];
+ "c" [type=P, alive=y];
"a" -> "b";
"b" -> "c";
- "c" -> "d";
- "d" -> "a";
- "e" -> "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
@@ -26,8 +26,8 @@
class TestRawRefCount(BaseDirectGCTest):
GCClass = IncMiniMark
- #RRCGCClass = RawRefCountIncMarkGC
- RRCGCClass = RawRefCountMarkGC
+ RRCGCClass = RawRefCountIncMarkGC
+ #RRCGCClass = RawRefCountMarkGC
def setup_method(self, method):
BaseDirectGCTest.setup_method(self, method)
@@ -773,24 +773,19 @@
for name in nodes:
n = nodes[name]
if n.info.alive:
+ print "Node", name, "should be alive."
if n.info.type == "P":
n.check_alive()
else:
n.check_alive(n.info.ext_refcnt)
+ print "Node", name, "is alive."
else:
+ print "Node", name, "should be dead."
if n.info.type == "P":
py.test.raises(RuntimeError, "n.p.x") # dead
else:
py.test.raises(RuntimeError, "n.r.c_ob_refcnt") # dead
-
- # check if all callbacks from weakrefs from cyclic garbage structures,
- # which should not be called because they could ressurrect dead
- # objects, have been cleared and no other callbacks were cleared; see:
- # https://github.com/python/cpython/blob/master/Modules/gc_weakref.txt
- for weakrefs in self.pyobj_weakrefs:
- for weakref in weakrefs:
- pass # TODO fix
- #assert weakref.callback_cleared == weakref.clear_callback
+ print "Node", name, "is dead."
# check if unreachable objects in cyclic structures with legacy
# finalizers and all otherwise unreachable objects reachable from them
More information about the pypy-commit
mailing list