[pypy-commit] pypy cpyext-gc-cycle: Fixed issue in gc if rawrefcount is disabled

stevie_92 pypy.commits at gmail.com
Sat Mar 2 08:46:28 EST 2019


Author: Stefan Beyer <home at sbeyer.at>
Branch: cpyext-gc-cycle
Changeset: r96200:85b1a76a7d3a
Date: 2019-03-02 14:45 +0100
http://bitbucket.org/pypy/pypy/changeset/85b1a76a7d3a/

Log:	Fixed issue in gc if rawrefcount is disabled Refactored rrc code to
	make it easier to read

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -2719,7 +2719,8 @@
         # to also set TRACK_YOUNG_PTRS here, for the write barrier.
         hdr.tid |= GCFLAG_VISITED | GCFLAG_TRACK_YOUNG_PTRS
 
-        if self.rrc_state == self.RAWREFCOUNT_STATE_MARKING:
+        if self.rrc_enabled and \
+                self.rrc_state == self.RAWREFCOUNT_STATE_MARKING:
             hdr.tid |= GCFLAG_GARBAGE
 
         if self.has_gcptr(llop.extract_ushort(llgroup.HALFWORD, hdr.tid)):
@@ -3381,53 +3382,24 @@
     _rrc_free._always_inline_ = True
 
     def rrc_major_collection_trace(self):
+        # Only trace and mark rawrefcounted object if we are not doing
+        # something special, like building gc.garbage.
         if self.rrc_state == self.RAWREFCOUNT_STATE_DEFAULT:
+            # check objects with finalizers from last collection cycle
             if not self._rrc_gc_list_is_empty(self.rrc_pyobj_old_list):
-                # Check, if the cyclic isolate from the last collection cycle
-                # is reachable from outside, after the finalizers have been
-                # executed.
-                self._rrc_collect_rawrefcount_roots(self.rrc_pyobj_old_list)
-                found_alive = False
-                gchdr = self.rrc_pyobj_old_list.c_gc_next
-                while gchdr <> self.rrc_pyobj_old_list:
-                    if (gchdr.c_gc_refs >> self.RAWREFCOUNT_REFS_SHIFT) > 0:
-                        found_alive = True
-                        break
-                    gchdr = gchdr.c_gc_next
-                if found_alive:
-                    self._rrc_gc_list_merge(self.rrc_pyobj_old_list,
-                                            self.rrc_pyobj_list)
-                else:
-                    self._rrc_gc_list_merge(self.rrc_pyobj_old_list,
-                                            self.rrc_pyobj_garbage_list)
-
+                self._rrc_check_finalizer()
+            # collect all rawrefcounted roots
             self._rrc_collect_rawrefcount_roots(self.rrc_pyobj_list)
+            # mark all objects reachable from rawrefcounted roots
             self._rrc_mark_rawrefcount()
-
-            # handle legacy finalizers
-            self.rrc_state = self.RAWREFCOUNT_STATE_MARKING
-            # TODO: move all pyobjs to sublist of pyobj_list and reset cyclic refcount
-            # TODO: mark all pypy-objects with special flag and mark them visited
-            self.rrc_state = self.RAWREFCOUNT_STATE_DEFAULT
-
-            # now handle modern finalizers
-            found_finalizer = False
-            gchdr = self.rrc_pyobj_old_list.c_gc_next
-            while gchdr <> self.rrc_pyobj_old_list:
-                if self.rrc_finalizer_type(gchdr) == \
-                        self.RAWREFCOUNT_FINALIZER_MODERN:
-                    found_finalizer = True
-                gchdr = gchdr.c_gc_next
-            if found_finalizer:
-                self._rrc_gc_list_move(self.rrc_pyobj_old_list,
-                                       self.rrc_pyobj_isolate_list)
-
-            use_cylicrefcnt = not found_finalizer
+            self._rrc_mark_garbage() # handle legacy finalizers
+            use_cylicrc = not self._rrc_find_finalizer() # modern finalizers
         else:
-            use_cylicrefcnt = False
-
-        self.rrc_p_list_old.foreach(self._rrc_major_trace, use_cylicrefcnt)
-        self.rrc_o_list_old.foreach(self._rrc_major_trace, use_cylicrefcnt)
+            use_cylicrc = False # don't sweep any objects in cyclic isolates
+
+        # now mark all pypy objects at the border, depending on the results
+        self.rrc_p_list_old.foreach(self._rrc_major_trace, use_cylicrc)
+        self.rrc_o_list_old.foreach(self._rrc_major_trace, use_cylicrc)
 
         # TODO: handle weakrefs for unreachable objects and create
         # TODO: a list of callbacks, which has to be called after the
@@ -3581,6 +3553,44 @@
         # now all rawrefcounted objects, which are alive, have a cyclic
         # refcount > 0 or are marked
 
+    def _rrc_mark_garbage(self):
+        self.rrc_state = self.RAWREFCOUNT_STATE_MARKING
+        # TODO: move all pyobjs to sublist of pyobj_list and reset cyclic refcount
+        # TODO: mark all pypy-objects with special flag and mark them visited
+        self.rrc_state = self.RAWREFCOUNT_STATE_DEFAULT
+
+    def _rrc_check_finalizer(self):
+        # Check, if the cyclic isolate from the last collection cycle
+        # is reachable from outside, after the finalizers have been
+        # executed.
+        self._rrc_collect_rawrefcount_roots(self.rrc_pyobj_old_list)
+        found_alive = False
+        gchdr = self.rrc_pyobj_old_list.c_gc_next
+        while gchdr <> self.rrc_pyobj_old_list:
+            if (gchdr.c_gc_refs >> self.RAWREFCOUNT_REFS_SHIFT) > 0:
+                found_alive = True
+                break
+            gchdr = gchdr.c_gc_next
+        if found_alive:
+            self._rrc_gc_list_merge(self.rrc_pyobj_old_list,
+                                    self.rrc_pyobj_list)
+        else:
+            self._rrc_gc_list_merge(self.rrc_pyobj_old_list,
+                                    self.rrc_pyobj_garbage_list)
+
+    def _rrc_find_finalizer(self):
+        found_finalizer = False
+        gchdr = self.rrc_pyobj_old_list.c_gc_next
+        while gchdr <> self.rrc_pyobj_old_list:
+            if self.rrc_finalizer_type(gchdr) == \
+                    self.RAWREFCOUNT_FINALIZER_MODERN:
+                found_finalizer = True
+            gchdr = gchdr.c_gc_next
+        if found_finalizer:
+            self._rrc_gc_list_move(self.rrc_pyobj_old_list,
+                                   self.rrc_pyobj_isolate_list)
+        return found_finalizer
+
     def _rrc_visit(pyobj, self_ptr):
         from rpython.rtyper.annlowlevel import cast_adr_to_nongc_instance
         #


More information about the pypy-commit mailing list