Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r67761:e2cc638553ad
Date: 2013-10-31 09:18 +0100
http://bitbucket.org/pypy/pypy/changeset/e2cc638553ad/

Log:    Tweak 'more_objects_to_trace' to avoid recording *all* surviving
        young objects during the marking phase.

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
@@ -1390,6 +1390,15 @@
         if self.young_rawmalloced_objects:
             self.remove_young_arrays_from_old_objects_pointing_to_young()
         #
+        # A special step in the STATE_MARKING phase.
+        if self.gc_state == STATE_MARKING:
+            # Copy the 'old_objects_pointing_to_young' list so far to
+            # 'more_objects_to_trace'.  Turn black objects back to gray.
+            # This is because these are precisely the old objects that
+            # have been modified and need rescanning.
+            self.old_objects_pointing_to_young.foreach(
+                self._add_to_more_objects_to_trace, None)
+        #
         # First, find the roots that point to young objects.  All nursery
         # objects found are copied out of the nursery, and the occasional
         # young raw-malloced object is flagged with GCFLAG_VISITED_RMY.
@@ -1459,10 +1468,14 @@
         # then the write_barrier must have ensured that the prebuilt
         # GcStruct is in the list self.old_objects_pointing_to_young.
         debug_start("gc-minor-walkroots")
+        if self.gc_state == STATE_MARKING:
+            callback = IncrementalMiniMarkGC._trace_drag_out1_marking_phase
+        else:
+            callback = IncrementalMiniMarkGC._trace_drag_out1
         self.root_walker.walk_roots(
-            IncrementalMiniMarkGC._trace_drag_out1,  # stack roots
-            IncrementalMiniMarkGC._trace_drag_out1,  # static in prebuilt 
non-gc
-            None)                         # static in prebuilt gc
+            callback,     # stack roots
+            callback,     # static in prebuilt non-gc
+            None)         # static in prebuilt gc
         debug_stop("gc-minor-walkroots")
 
     def collect_cardrefs_to_nursery(self):
@@ -1522,21 +1535,14 @@
                     interval_start = next_byte_start
                 #
                 # If we're incrementally marking right now, sorry, we also
-                # need to add the object to 'objects_to_trace' and have it
-                # fully traced very soon.
+                # need to add the object to 'more_objects_to_trace' and have
+                # it fully traced once at the end of the current marking phase.
                 if self.gc_state == STATE_MARKING:
                     self.header(obj).tid &= ~GCFLAG_VISITED
                     self.more_objects_to_trace.append(obj)
 
 
     def collect_oldrefs_to_nursery(self):
-        if self.gc_state == STATE_MARKING:
-            self._collect_oldrefs_to_nursery(True)
-        else:
-            self._collect_oldrefs_to_nursery(False)
-
-    @specialize.arg(1)
-    def _collect_oldrefs_to_nursery(self, state_is_marking):
         # Follow the old_objects_pointing_to_young list and move the
         # young objects they point to out of the nursery.
         oldlist = self.old_objects_pointing_to_young
@@ -1553,15 +1559,6 @@
             # have this flag set after a nursery collection.
             self.header(obj).tid |= GCFLAG_TRACK_YOUNG_PTRS
             #
-            # If the incremental major collection is currently at
-            # STATE_MARKING, then we must add to 'objects_to_trace' all
-            # objects that go through 'old_objects_pointing_to_young'.
-            # This basically turns black objects gray again, but also
-            # makes sure that we see otherwise-white objects.
-            if state_is_marking:
-                self.header(obj).tid &= ~GCFLAG_VISITED
-                self.more_objects_to_trace.append(obj)
-            #
             # Trace the 'obj' to replace pointers to nursery with pointers
             # outside the nursery, possibly forcing nursery objects out
             # and adding them to 'old_objects_pointing_to_young' as well.
@@ -1584,15 +1581,21 @@
 
 
     def _trace_drag_out1(self, root):
-        # In the MARKING state, we must also record this old object,
-        # if it is not VISITED yet.
-        if self.gc_state == STATE_MARKING:
-            obj = root.address[0]
-            if not self.is_in_nursery(obj):
-                if not self.header(obj).tid & GCFLAG_VISITED:
-                    self.more_objects_to_trace.append(obj)
+        self._trace_drag_out(root, None)
+
+    def _trace_drag_out1_marking_phase(self, root):
+        self._trace_drag_out(root, None)
         #
-        self._trace_drag_out(root, None)
+        # We are in the MARKING state: we must also record this object
+        # if it was young.  Don't bother with old objects in general,
+        # as they are anyway added to 'more_objects_to_trace' if they
+        # are modified (see _add_to_more_objects_to_trace).  But we do
+        # need to record the not-visited-yet (white) old objects.  So
+        # as a conservative approximation, we need to add the object to
+        # the list if and only if it doesn't have GCFLAG_VISITED yet.
+        obj = root.address[0]
+        if not self.header(obj).tid & GCFLAG_VISITED:
+            self.more_objects_to_trace.append(obj)
 
     def _trace_drag_out(self, root, ignored):
         obj = root.address[0]
@@ -1668,12 +1671,6 @@
         if self.has_gcptr(typeid):
             # we only have to do it if we have any gcptrs
             self.old_objects_pointing_to_young.append(newobj)
-        else:
-            # we don't need to add this to 'old_objects_pointing_to_young',
-            # but in the STATE_MARKING phase we still need this bit...
-            if self.gc_state == STATE_MARKING:
-                self.header(newobj).tid &= ~GCFLAG_VISITED
-                self.more_objects_to_trace.append(newobj)
 
     _trace_drag_out._always_inline_ = True
 
@@ -1756,6 +1753,10 @@
             old.append(new.pop())
         new.delete()
 
+    def _add_to_more_objects_to_trace(self, obj, ignored):
+        self.header(obj).tid &= ~GCFLAG_VISITED
+        self.more_objects_to_trace.append(obj)
+
     def minor_and_major_collection(self):
         # First, finish the current major gc, if there is one in progress.
         # This is a no-op if the gc_state is already STATE_SCANNING.
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to