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