Author: Stefan Beyer <[email protected]>
Branch: cpyext-gc-cycle
Changeset: r97392:4afcd17db69f
Date: 2019-09-07 10:53 +0200
http://bitbucket.org/pypy/pypy/changeset/4afcd17db69f/
Log: Reverted handling of modern fin for rrc mark to improve termination
Added TODOs for rrc mark and incmark for modern finalizers
diff --git a/rpython/memory/gc/rrc/base.py b/rpython/memory/gc/rrc/base.py
--- a/rpython/memory/gc/rrc/base.py
+++ b/rpython/memory/gc/rrc/base.py
@@ -543,6 +543,36 @@
self.gc.trace(obj, self._collect_ref_rec, None)
return True
+ def _check_finalizer(self):
+ # Check, if the cyclic isolate from the last collection cycle
+ # is reachable from outside, after the finalizers have been
+ # executed (and if all finalizers have been executed). Return
+ # True if some objects are reachable and thus have been resurrected.
+
+ # check if the list has been fully processed since the last cycle
+ # (for safety)
+ found_alive = not self._gc_list_is_empty(self.pyobj_isolate_list)
+
+ # check if all finalizers have actually been called (for safety)
+ if not found_alive:
+ found_alive = self._find_finalizer()
+
+ # check if there are any objects with a reference count > 0
+ if not found_alive:
+ gchdr = self.pyobj_old_list.c_gc_next
+ while gchdr <> self.pyobj_old_list:
+ if True: # TODO: check refcount or marked (see _collect_roots)
+ found_alive = True
+ break
+ gchdr = gchdr.c_gc_next
+
+ if found_alive:
+ self._gc_list_merge(self.pyobj_old_list, self.pyobj_list)
+ return True
+ else:
+ self._gc_list_merge(self.pyobj_old_list, self.pyobj_dead_list)
+ return False
+
def _find_finalizer(self):
gchdr = self.pyobj_old_list.c_gc_next
while gchdr <> self.pyobj_old_list:
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,6 +13,11 @@
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.
@@ -20,11 +25,13 @@
# this cycle.
if not self._gc_list_is_empty(self.pyobj_old_list):
self._gc_list_merge(self.pyobj_old_list, self.pyobj_list)
+ # TODO: take snapshot of pyobj_old_list and perform _collect_roots
+ # incrementally (own phase)
# Untrack all tuples with only non-gc rrc objects and
# promote all other tuples to the pyobj_list
self._untrack_tuples()
- # TODO: execute incrementally? (before snapshot!)
+ # TODO: execute incrementally? (before snapshot!, own phase)
# Now take a snapshot
self._take_snapshot(self.pyobj_list)
@@ -33,11 +40,6 @@
self._collect_roots()
# TODO: execute incrementally (own phase, save index)
- # 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
-
self._debug_check_consistency(print_label="roots-marked")
self.state = self.STATE_MARKING
return False
diff --git a/rpython/memory/gc/rrc/mark.py b/rpython/memory/gc/rrc/mark.py
--- a/rpython/memory/gc/rrc/mark.py
+++ b/rpython/memory/gc/rrc/mark.py
@@ -20,18 +20,25 @@
# Only trace and mark rawrefcounted object if we are not doing
# something special, like building gc.garbage.
if self.state == self.STATE_MARKING and self.cycle_enabled:
- # 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.
- # Objects which have not been resurrected should be freed during
- # this cycle.
+
+ # check if objects with finalizers from last collection cycle
+ # have been resurrected
+ dead_list_empty = True
if not self._gc_list_is_empty(self.pyobj_old_list):
- self._gc_list_merge(self.pyobj_old_list, self.pyobj_list)
+ dead_list_empty = self._check_finalizer()
# collect all rawrefcounted roots
self._collect_roots()
self._debug_check_consistency(print_label="roots-marked")
+ if not dead_list_empty:
+ # set all refcounts to zero for objects in dead list
+ # (might have been incremented) by fix_refcnt
+ gchdr = self.pyobj_dead_list.c_gc_next
+ while gchdr <> self.pyobj_dead_list:
+ gchdr.c_gc_refs = 0
+ gchdr = gchdr.c_gc_next
+
# mark all objects reachable from rawrefcounted roots
self._mark_rawrefcount()
self._debug_check_consistency(print_label="before-fin")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit