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

Reply via email to