[pypy-commit] pypy incremental-gc: more in-progress

arigo noreply at buildbot.pypy.org
Fri Oct 11 17:16:09 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: incremental-gc
Changeset: r67320:656c62aad308
Date: 2013-10-11 17:15 +0200
http://bitbucket.org/pypy/pypy/changeset/656c62aad308/

Log:	more in-progress

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
@@ -1020,42 +1020,29 @@
              (self.card_page_shift + 3)))
 
     def debug_check_consistency(self):
+        if self.DEBUG:
+            ll_assert(not self.young_rawmalloced_objects,
+                      "young raw-malloced objects in a major collection")
+            ll_assert(not self.young_objects_with_weakrefs.non_empty(),
+                      "young objects with weakrefs in a major collection")
 
-        if self.DEBUG:
+            if self.raw_malloc_might_sweep.non_empty():
+                ll_assert(self.gc_state == STATE_SWEEPING,
+                      "raw_malloc_might_sweep must be empty outside SWEEPING")
 
-            # somewhat of a hack
-            # some states require custom prep and cleanup
-            # before calling the check_object functions
-            already_checked = False
-
-            if self.gc_state == STATE_SCANNING:
-                # We are just starting a scan. Same as a non incremental here.
-                ll_assert(not self.young_rawmalloced_objects,
-                          "young raw-malloced objects in a major collection")
-                ll_assert(not self.young_objects_with_weakrefs.non_empty(),
-                          "young objects with weakrefs in a major collection")
-            elif self.gc_state == STATE_MARKING:
+            if self.gc_state == STATE_MARKING:
                 self._debug_objects_to_trace_dict = \
                                             self.objects_to_trace.stack2dict()
                 MovingGCBase.debug_check_consistency(self)
                 self._debug_objects_to_trace_dict.delete()
-                already_checked = True
-            elif self.gc_state == STATE_SWEEPING:
-                pass
-            elif self.gc_state == STATE_FINALIZING:
-                pass
             else:
-                ll_assert(False,"uknown gc_state value")
-
-            if not already_checked:
                 MovingGCBase.debug_check_consistency(self)
 
-
     def debug_check_object(self, obj):
-
-        ll_assert((self.header(obj).tid & GCFLAG_GRAY != 0
-                    and self.header(obj).tid & GCFLAG_VISITED != 0) == False,
-                    "object gray and visited at the same time." )
+        # We are after a minor collection, and possibly after a major
+        # collection step.  No object should be in the nursery
+        ll_assert(not self.is_in_nursery(obj),
+                  "object in nursery after collection")
 
         if self.gc_state == STATE_SCANNING:
             self._debug_check_object_scanning(obj)
@@ -1066,60 +1053,39 @@
         elif self.gc_state == STATE_FINALIZING:
             self._debug_check_object_finalizing(obj)
         else:
-            ll_assert(False,"uknown gc_state value")
+            ll_assert(False, "unknown gc_state value")
 
     def _debug_check_object_marking(self, obj):
         if self.header(obj).tid & GCFLAG_VISITED != 0:
-            # Visited, should NEVER point to a white object.
-            self.trace(obj,self._debug_check_not_white,None)
+            # A black object.  Should NEVER point to a white object.
+            self.trace(obj, self._debug_check_not_white, None)
             # During marking, all visited (black) objects should always have
             # the GCFLAG_TRACK_YOUNG_PTRS flag set, for the write barrier to
-            # trigger
-            ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
-                      "black object without GCFLAG_TRACK_YOUNG_PTRS")
-
-        if self.header(obj).tid & GCFLAG_GRAY != 0:
-            ll_assert(self._debug_objects_to_trace_dict.contains(obj),
-                        "gray object not in pending trace list.")
-        else:
-            #if not gray and not black
-            if self.header(obj).tid & GCFLAG_VISITED == 0:
-                if self.header(obj).tid & GCFLAG_NO_HEAP_PTRS == 0:
-                    ll_assert(not self._debug_objects_to_trace_dict.contains(obj),
-                        "white object in pending trace list.")
+            # trigger --- at least if they contain any gc ptr
+            typeid = self.get_type_id(obj)
+            if self.has_gcptr(typeid):
+                ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
+                          "black object without GCFLAG_TRACK_YOUNG_PTRS")
 
     def _debug_check_not_white(self, root, ignored):
         obj = root.address[0]
-        ll_assert(self.header(obj).tid & (GCFLAG_GRAY | GCFLAG_VISITED) != 0,
-                  "visited object points to unprocessed (white) object." )
+        if self.header(obj).tid & GCFLAG_VISITED != 0:
+            pass    # black -> black
+        elif self._debug_objects_to_trace_dict.contains(obj):
+            pass    # black -> gray
+        else:
+            ll_assert(False, "black -> white pointer found")
 
     def _debug_check_object_sweeping(self, obj):
-        pass
+        # We see only reachable objects here.  They all start as VISITED
+        # but this flag is progressively removed in the sweeping phase.
 
-    def _debug_check_object_finalizing(self,obj):
-        pass
-
-    def _debug_check_object_scanning(self, obj):
-        # This check is called before scanning starts.
-        # scanning is done in a single step.
-
-        # after a minor or major collection, no object should be in the nursery
-        ll_assert(not self.is_in_nursery(obj),
-                  "object in nursery after collection")
-        # similarily, all objects should have this flag, except if they
+        # All objects should have this flag, except if they
         # don't have any GC pointer
         typeid = self.get_type_id(obj)
         if self.has_gcptr(typeid):
             ll_assert(self.header(obj).tid & GCFLAG_TRACK_YOUNG_PTRS != 0,
                       "missing GCFLAG_TRACK_YOUNG_PTRS")
-        # the GCFLAG_VISITED should not be set between collections
-        ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
-                  "unexpected GCFLAG_VISITED")
-
-        # the GCFLAG_GRAY should never be set at the start of a collection
-        ll_assert(self.header(obj).tid & GCFLAG_GRAY == 0,
-          "unexpected GCFLAG_GRAY")
-
         # the GCFLAG_FINALIZATION_ORDERING should not be set between coll.
         ll_assert(self.header(obj).tid & GCFLAG_FINALIZATION_ORDERING == 0,
                   "unexpected GCFLAG_FINALIZATION_ORDERING")
@@ -1149,6 +1115,22 @@
                           "the card marker bits are not cleared")
                 i -= 1
 
+    def _debug_check_object_finalizing(self, obj):
+        # Same invariants as STATE_SCANNING.
+        self._debug_check_object_scanning(obj)
+
+    def _debug_check_object_scanning(self, obj):
+        # This check is called before scanning starts.
+        # Scanning is done in a single step.
+        # the GCFLAG_VISITED should not be set between collections
+        ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
+                  "unexpected GCFLAG_VISITED")
+
+        # All other invariants from the sweeping phase should still be
+        # satisfied.
+        self._debug_check_object_sweeping(obj)
+
+
     # ----------
     # Write barrier
 
@@ -1767,10 +1749,7 @@
         # to smaller increments using stacks for resuming
         if self.gc_state == STATE_SCANNING:
             self.objects_to_trace = self.AddressStack()
-            # XXX do it in one step
             self.collect_roots()
-            #set all found roots to gray before entering marking state
-            self.objects_to_trace.foreach(self._set_gcflag_gray, None)
             self.gc_state = STATE_MARKING
             #END SCANNING
         elif self.gc_state == STATE_MARKING:
@@ -1797,10 +1776,9 @@
                 if self.old_objects_with_light_finalizers.non_empty():
                     self.deal_with_old_objects_with_finalizers()
                 #objects_to_trace processed fully, can move on to sweeping
-                self.gc_state = STATE_SWEEPING
-                #prepare for the next state
                 self.ac.mass_free_prepare()
                 self.start_free_rawmalloc_objects()
+                self.gc_state = STATE_SWEEPING
             #END MARKING
         elif self.gc_state == STATE_SWEEPING:
             #
@@ -1883,9 +1861,6 @@
     def _reset_gcflag_visited(self, obj, ignored):
         self.header(obj).tid &= ~(GCFLAG_VISITED|GCFLAG_GRAY)
 
-    def _set_gcflag_gray(self, obj, ignored):
-        self.header(obj).tid |= GCFLAG_GRAY
-
     def free_rawmalloced_object_if_unvisited(self, obj):
         if self.header(obj).tid & GCFLAG_VISITED:
             self.header(obj).tid &= ~(GCFLAG_VISITED|GCFLAG_GRAY)   # survives
@@ -1962,19 +1937,13 @@
         self.objects_to_trace.append(root.address[0])
 
     def visit_all_objects(self):
-        pending = self.objects_to_trace
-        while pending.non_empty():
-            obj = pending.pop()
-            self.visit(obj)
+        self.visit_all_objects_step(sys.maxint)
 
     def visit_all_objects_step(self, nobjects):
         # Objects can be added to pending by visit
         pending = self.objects_to_trace
         while nobjects > 0 and pending.non_empty():
             obj = pending.pop()
-            ll_assert(self.header(obj).tid &
-                        (GCFLAG_GRAY|GCFLAG_VISITED|GCFLAG_NO_HEAP_PTRS) != 0,
-                        "non gray or black object being traced")
             self.visit(obj)
             nobjects -= 1
 
@@ -1990,15 +1959,13 @@
         # and the GCFLAG_VISITED will be reset at the end of the
         # collection.
         hdr = self.header(obj)
-        # visited objects are no longer grey
-        hdr.tid &= ~GCFLAG_GRAY
         if hdr.tid & (GCFLAG_VISITED | GCFLAG_NO_HEAP_PTRS):
             return
         #
-        # It's the first time.  We set the flag.
+        # It's the first time.  We set the flag VISITED.  The trick is
+        # to also set TRACK_YOUNG_PTRS here, for the write barrier.
         hdr.tid |= GCFLAG_VISITED | GCFLAG_TRACK_YOUNG_PTRS
 
-
         if not self.has_gcptr(llop.extract_ushort(llgroup.HALFWORD, hdr.tid)):
             return
         #


More information about the pypy-commit mailing list