[pypy-commit] pypy gc-incminimark-pinning: (hopefully) finish work on stepwise useage of the nursery

groggi noreply at buildbot.pypy.org
Mon Jun 23 11:48:20 CEST 2014


Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning
Changeset: r72157:8306f5ed33e9
Date: 2014-06-23 11:45 +0200
http://bitbucket.org/pypy/pypy/changeset/8306f5ed33e9/

Log:	(hopefully) finish work on stepwise useage of the nursery

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
@@ -686,15 +686,23 @@
         else:
             self.minor_and_major_collection()
 
-    def move_nursery_top(self, totalsize):
-        size = self.nursery_cleanup
-        ll_assert(self.nursery_real_top - self.nursery_top >= size,
-            "nursery_cleanup not a divisor of nursery_size - initial_cleanup")
-        ll_assert(llmemory.raw_malloc_usage(totalsize) <= size,
-            "totalsize > nursery_cleanup")
+    def try_move_nursery_top(self, totalsize):
+        """Tries to move 'self.nursery_top' to accommodate
+        an object of 'totalsize'. Returns 'True' on success, otherwise
+        'False'. In case of failing (returned 'False') a minor collection
+        is needed."""
+
+        # in general we always move 'self.nursery_top' by 'self.nursery_cleanup'.
+        # However, because of the presence of pinned objects there are cases where
+        # the GC can't move by 'self.nursery_cleanup' without overflowing the arena.
+        # For such a case we use the space left in the nursery.
+        size = min(self.nursery_cleanup, self.nursery_real_top - self.nursery_top)
+        if llmemory.raw_malloc_usage(totalsize) > size:
+            return False
         llarena.arena_reset(self.nursery_top, size, 2)
         self.nursery_top += size
-    move_nursery_top._always_inline_ = True
+        return True
+    try_move_nursery_top._always_inline_ = True
 
     def collect_and_reserve(self, prev_result, totalsize):
         """To call when nursery_free overflows nursery_top.
@@ -728,10 +736,9 @@
             else:
                 #
                 # no barriers (i.e. pinned objects) after 'nursery_free'.
-                # if possible just enlarge the used part of the nursery.
-                # otherwise we are forced to clean up the nursery.
-                if self.nursery_top < self.nursery_real_top:
-                    self.move_nursery_top(totalsize)
+                # If possible just enlarge the used part of the nursery.
+                # Otherwise we are forced to clean up the nursery.
+                if self.try_move_nursery_top(totalsize):
                     return prev_result
                 #
                 self.minor_collection()
@@ -1623,13 +1630,16 @@
         # reset everything after the last pinned object till the end of the arena
         llarena.arena_reset(prev, self.nursery_real_top - prev, 0)
         #
-        # make sure we have some clean space to use after a minor collection
-        if self.nursery_real_top - prev >= self.nursery_cleanup:
+        # We assume that there are only a few pinned objects. Therefore, if there
+        # is 'self.nursery_cleanup' space between the nursery's start ('self.nursery')
+        # and the last pinned object ('prev'), we conclude that there is enough zeroed
+        # space inside the arena to use for new allocation. Otherwise we fill
+        # the nursery with zeros for 'self.nursery_cleanup' of space.
+        if prev - self.nursery >= self.nursery_cleanup:
+            nursery_barriers.append(prev)
+        else:
             llarena.arena_reset(prev, self.nursery_cleanup, 2)
             nursery_barriers.append(prev + self.nursery_cleanup)
-        else:
-            llarena.arena_reset(prev, self.nursery_real_top - prev, 2)
-            nursery_barriers.append(self.nursery_real_top)
         #
         self.nursery_barriers = nursery_barriers
         self.surviving_pinned_objects.delete()


More information about the pypy-commit mailing list