Author: Andrew Chambers <[email protected]>
Branch: incremental-gc
Changeset: r65988:199872039820
Date: 2013-08-07 19:57 +1200
http://bitbucket.org/pypy/pypy/changeset/199872039820/

Log:    making incminimark slightly more incremental. still called as non
        incremental.

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
@@ -1022,6 +1022,11 @@
         # the GCFLAG_VISITED should not be set between collections
         ll_assert(self.header(obj).tid & GCFLAG_VISITED == 0,
                   "unexpected GCFLAG_VISITED")
+        
+        # the GCFLAG_VISITED 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")
@@ -1651,23 +1656,37 @@
         if self.gc_state == STATE_SCANNING:
             self.objects_to_trace = self.AddressStack()
             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:
-            self.visit_all_objects()
             
-            if self.objects_with_finalizers.non_empty():
-                self.deal_with_objects_with_finalizers()
+            # XXX need a heuristic to tell how many objects to mark.
+            # Maybe based on previous mark time average
+            self.visit_all_objects_step(1)
             
-            self.objects_to_trace.delete()
-            #
-            # Weakref support: clear the weak pointers to dying objects
-            if self.old_objects_with_weakrefs.non_empty():
-                self.invalidate_old_weakrefs()
-            if self.old_objects_with_light_finalizers.non_empty():
-                self.deal_with_old_objects_with_finalizers()
-            
-            self.gc_state = STATE_SWEEPING
+            # 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(): 
+                
+                self.objects_to_trace.delete()
+                
+                if self.objects_with_finalizers.non_empty():
+                    self.deal_with_objects_with_finalizers()
+                #
+                # Weakref support: clear the weak pointers to dying objects
+                if self.old_objects_with_weakrefs.non_empty():
+                    self.invalidate_old_weakrefs()
+                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
+                
+                #SWEEPING not yet incrementalised
+                self.major_collection_step(reserving_size)
             #END MARKING
         elif self.gc_state == STATE_SWEEPING:
             #
@@ -1710,8 +1729,14 @@
                 self.max_heap_size_already_raised = True
                 raise MemoryError
             self.gc_state = STATE_FINALIZING
-            #END SWEEPING
+            # END SWEEPING
+            # FINALIZING not yet incrementalised
+            # but it seems safe to allow mutator to run after sweeping and
+            # before finalizers are called. This is because run_finalizers
+            # is a different list to objects_with_finalizers.
         elif self.gc_state == STATE_FINALIZING:
+            # XXX This is considered rare, 
+            # so should we make the calling incremental? or leave as is
             self.execute_finalizers()
             self.num_major_collects += 1
             self.gc_state = STATE_SCANNING
@@ -1746,6 +1771,9 @@
     def _reset_gcflag_visited(self, obj, ignored):
         self.header(obj).tid &= ~GCFLAG_VISITED
 
+    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   # survives
@@ -1822,7 +1850,15 @@
         while pending.non_empty():
             obj = pending.pop()
             self.visit(obj)
-
+    
+    def visit_all_objects_step(self,nobjects=1):
+        # Objects can be added to pending by visit_step
+        pending = self.objects_to_trace
+        while nobjects > 0 and pending.non_empty():
+            obj = pending.pop()
+            self.visit(obj)
+            nobjects -= 1
+    
     def visit(self, obj):
         #
         # 'obj' is a live object.  Check GCFLAG_VISITED to know if we
@@ -1840,6 +1876,8 @@
         #
         # It's the first time.  We set the flag.
         hdr.tid |= GCFLAG_VISITED
+        #visited objects are no longer grey
+        hdr.tid &= ~GCFLAG_GRAY
         if not self.has_gcptr(llop.extract_ushort(llgroup.HALFWORD, hdr.tid)):
             return
         #
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to