Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r67425:bd065e8a99b7
Date: 2013-10-16 16:09 +0200
http://bitbucket.org/pypy/pypy/changeset/bd065e8a99b7/

Log:    Tweak tweak tweak: try to ensure termination of 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
@@ -1040,10 +1040,13 @@
                       "raw_malloc_might_sweep must be empty outside SWEEPING")
 
             if self.gc_state == STATE_MARKING:
-                self._debug_objects_to_trace_dict = \
+                self._debug_objects_to_trace_dict1 = \
                                             self.objects_to_trace.stack2dict()
+                self._debug_objects_to_trace_dict2 = \
+                                       self.more_objects_to_trace.stack2dict()
                 MovingGCBase.debug_check_consistency(self)
-                self._debug_objects_to_trace_dict.delete()
+                self._debug_objects_to_trace_dict2.delete()
+                self._debug_objects_to_trace_dict1.delete()
             else:
                 MovingGCBase.debug_check_consistency(self)
 
@@ -1084,7 +1087,8 @@
         obj = root.address[0]
         if self.header(obj).tid & GCFLAG_VISITED != 0:
             pass    # black -> black
-        elif self._debug_objects_to_trace_dict.contains(obj):
+        elif (self._debug_objects_to_trace_dict1.contains(obj) or
+              self._debug_objects_to_trace_dict2.contains(obj)):
             pass    # black -> gray
         elif self.header(obj).tid & GCFLAG_NO_HEAP_PTRS != 0:
             pass    # black -> white-but-prebuilt-so-dont-care
@@ -1522,7 +1526,7 @@
                 # fully traced very soon.
                 if self.gc_state == STATE_MARKING:
                     self.header(obj).tid &= ~GCFLAG_VISITED
-                    self.objects_to_trace.append(obj)
+                    self.more_objects_to_trace.append(obj)
 
 
     def collect_oldrefs_to_nursery(self):
@@ -1556,7 +1560,7 @@
             # makes sure that we see otherwise-white objects.
             if state_is_marking:
                 self.header(obj).tid &= ~GCFLAG_VISITED
-                self.objects_to_trace.append(obj)
+                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
@@ -1586,7 +1590,7 @@
             obj = root.address[0]
             if not self.is_in_nursery(obj):
                 if not self.header(obj).tid & GCFLAG_VISITED:
-                    self.objects_to_trace.append(obj)
+                    self.more_objects_to_trace.append(obj)
         #
         self._trace_drag_out(root, None)
 
@@ -1669,7 +1673,7 @@
             # but in the STATE_MARKING phase we still need this bit...
             if self.gc_state == STATE_MARKING:
                 self.header(newobj).tid &= ~GCFLAG_VISITED
-                self.objects_to_trace.append(newobj)
+                self.more_objects_to_trace.append(newobj)
 
     _trace_drag_out._always_inline_ = True
 
@@ -1791,25 +1795,48 @@
             self.objects_to_trace = self.AddressStack()
             self.collect_roots()
             self.gc_state = STATE_MARKING
+            self.more_objects_to_trace = self.AddressStack()
             #END SCANNING
         elif self.gc_state == STATE_MARKING:
             debug_print("number of objects to mark",
-                        self.objects_to_trace.length())
+                        self.objects_to_trace.length(),
+                        "plus",
+                        self.more_objects_to_trace.length())
             estimate = self.gc_increment_step
             estimate_from_nursery = self.nursery_surviving_size * 2
             if estimate_from_nursery > estimate:
                 estimate = estimate_from_nursery
-            self.visit_all_objects_step(intmask(estimate))
+            estimate = intmask(estimate)
+            remaining = self.visit_all_objects_step(estimate)
+            #
+            if remaining >= estimate // 2:
+                if self.more_objects_to_trace.non_empty():
+                    # We consumed less than 1/2 of our step's time, and
+                    # there are more objects added during the marking steps
+                    # of this major collection.  Visit them all now.
+                    # The idea is to ensure termination at the cost of some
+                    # incrementality, in theory.
+                    swap = self.objects_to_trace
+                    self.objects_to_trace = self.more_objects_to_trace
+                    self.more_objects_to_trace = swap
+                    self.visit_all_objects()
 
             # XXX A simplifying assumption that should be checked,
             # finalizers/weak references are rare and short which means that
             # they do not need a seperate state and do not need to be
             # made incremental.
-            if not self.objects_to_trace.non_empty():
+            if (not self.objects_to_trace.non_empty() and
+                not self.more_objects_to_trace.non_empty()):
+                #
                 if self.objects_with_finalizers.non_empty():
                     self.deal_with_objects_with_finalizers()
 
+                ll_assert(not self.objects_to_trace.non_empty(),
+                          "objects_to_trace should be empty")
+                ll_assert(not self.more_objects_to_trace.non_empty(),
+                          "more_objects_to_trace should be empty")
                 self.objects_to_trace.delete()
+                self.more_objects_to_trace.delete()
 
                 #
                 # Weakref support: clear the weak pointers to dying objects
@@ -1933,8 +1960,9 @@
     def start_free_rawmalloc_objects(self):
         ll_assert(not self.raw_malloc_might_sweep.non_empty(),
                   "raw_malloc_might_sweep must be empty")
-        (self.raw_malloc_might_sweep, self.old_rawmalloced_objects) = (
-            self.old_rawmalloced_objects, self.raw_malloc_might_sweep)
+        swap = self.raw_malloc_might_sweep
+        self.raw_malloc_might_sweep = self.old_rawmalloced_objects
+        self.old_rawmalloced_objects = swap
 
     # Returns true when finished processing objects
     def free_unvisited_rawmalloc_objects_step(self, nobjects):
@@ -1981,14 +2009,18 @@
         self.objects_to_trace.append(root.address[0])
 
     def visit_all_objects(self):
-        self.visit_all_objects_step(sys.maxint)
+        while self.objects_to_trace.non_empty():
+            self.visit_all_objects_step(sys.maxint)
 
     def visit_all_objects_step(self, size_to_track):
         # Objects can be added to pending by visit
         pending = self.objects_to_trace
-        while size_to_track > 0 and pending.non_empty():
+        while pending.non_empty():
             obj = pending.pop()
-            size_to_track = self.visit(obj)
+            size_to_track -= self.visit(obj)
+            if size_to_track < 0:
+                return 0
+        return size_to_track
 
     def visit(self, obj):
         #
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to