[pypy-commit] pypy gc-incminimark-pinning: implemented shadow handling, passing all three available tests.

groggi noreply at buildbot.pypy.org
Mon Jun 2 17:24:13 CEST 2014


Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning
Changeset: r71831:cb3c392ce68b
Date: 2014-05-20 13:38 +0200
http://bitbucket.org/pypy/pypy/changeset/cb3c392ce68b/

Log:	implemented shadow handling, passing all three available tests.

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
@@ -723,8 +723,6 @@
                 # move search area to the next free memory block in the
                 # nursery.
                 self.nursery_free = self.nursery_top + pinned_obj_size
-                # XXX should be, but check if the new area
-                # (nursery_free to nursery_top) was reset (arena_reset()). (groggi)
                 self.nursery_top = self.nursery_barriers.popleft()
                 # XXX should we progress a step in the major collection?
                 # in original version this is always done if we call this
@@ -1490,6 +1488,14 @@
                 self.old_objects_with_cards_set.append(dest_addr)
                 dest_hdr.tid |= GCFLAG_CARDS_SET
 
+    def record_pinned_object_with_shadow(self, obj, new_shadow_object_dict):
+        # checks if the pinned object has a shadow and if so add it to the
+        # dict of shadows.
+        obj = obj + self.gcheaderbuilder.size_gc_header
+        shadow = self.nursery_objects_shadows.get(obj)
+        if shadow != NULL:
+            new_shadow_object_dict.setitem(obj, shadow)
+
     # ----------
     # Nursery collection
 
@@ -1499,6 +1505,22 @@
         #
         debug_start("gc-minor")
         #
+        # All nursery barriers right now are invalid from this point on.  They
+        # are evaluated anew as part of a minor collection.
+        self.nursery_barriers.delete()
+        #
+        # Keeps track of surviving pinned objects. See also `_trace_drag_out()`
+        # where this stack is filled.
+        self.surviving_pinned_objects = self.AddressStack()
+        #
+        # The following counter keeps track of the amount of alive and pinned
+        # objects inside the nursery.  The counter is reset, as we have to
+        # check which pinned objects are actually still alive. Pinning an
+        # object does not prevent the removal of an object, if it's not used
+        # anymore.
+        # XXX is this true? does it make sense? (groggi)
+        self.pinned_objects_in_nursery = 0
+        #
         # Before everything else, remove from 'old_objects_pointing_to_young'
         # the young arrays.
         if self.young_rawmalloced_objects:
@@ -1513,18 +1535,6 @@
             self.old_objects_pointing_to_young.foreach(
                 self._add_to_more_objects_to_trace, None)
         #
-        # Keeps track of surviving pinned objects. See also `_trace_drag_out()`
-        # where this stack is filled.
-        self.surviving_pinned_objects = self.AddressStack()
-        #
-        # The following counter keeps track of the amount of alive and pinned
-        # objects inside the nursery.  The counter is reset, as we have to
-        # check which pinned objects are actually still alive. Pinning an
-        # object does not prevent the removal of an object, if it's not used
-        # anymore.
-        # XXX is this true? does it make sense? (groggi)
-        self.pinned_objects_in_nursery = 0
-        #
         # 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.
@@ -1563,11 +1573,20 @@
         if self.young_objects_with_light_finalizers.non_empty():
             self.deal_with_young_objects_with_finalizers()
         #
-        # Clear this mapping.
-        # XXX gc-minimark-pinning contains some additional code
-        # in regard to pinned object. TODO (groggi)
+        # Clear this mapping.  Without pinned objects we just clear the dict
+        # as all objects in the nursery are dragged out of the nursery and, if
+        # needed, into their shadow.  However, if we have pinned objects we have
+        # to check if those pinned object have a shadow and keep a dictionary
+        # filled with shadow information for them as they stay in the nursery.
         if self.nursery_objects_shadows.length() > 0:
-            self.nursery_objects_shadows.clear()
+            if self.surviving_pinned_objects.non_empty():
+                new_shadows = self.AddressDict()
+                self.surviving_pinned_objects.foreach(
+                    self.record_pinned_object_with_shadow, new_shadows)
+                self.nursery_objects_shadows.delete()
+                self.nursery_objects_shadows = new_shadows
+            else:
+                self.nursery_objects_shadows.clear()
         #
         # Walk the list of young raw-malloced objects, and either free
         # them or make them old.
@@ -1607,27 +1626,20 @@
                 (size_gc_header + self.get_size(obj))
         #
         # clear the rest of the arena
+        # XXX resetting just to self.nursery_top may be enough? (groggi)
         llarena.arena_reset(prev, self.nursery_real_top - prev, 2)
         #                         ^^^ calculate the size of the last continuous
         #                             arena block.
         #
+        debug_print("last: resetting arena from %s for size: %s" %
+            (prev, self.nursery_real_top - prev))
         self.surviving_pinned_objects.delete()
-        self.nursery_barriers.delete()
         self.nursery_barriers = nursery_barriers
         # XXX gc-minimark-pinning does a debug_rotate_nursery() here (groggi)
         self.nursery_free = self.nursery
-        self.nursery_barriers.append(self.nursery + self.nursery_size)
+        self.nursery_barriers.append(self.nursery_real_top)
         self.nursery_top = self.nursery_barriers.popleft()
 
-# All live nursery objects are out, and the rest dies.  Fill
-# the nursery up to the cleanup point with zeros
-#        llarena.arena_reset(self.nursery, self.nursery_size, 0)
-#        llarena.arena_reset(self.nursery, self.initial_cleanup, 2)
-#        self.debug_rotate_nursery()
-#        self.nursery_free = self.nursery
-#        self.nursery_top = self.nursery + self.initial_cleanup
-#        self.nursery_real_top = self.nursery + self.nursery_size
-        #
         debug_print("minor collect, total memory used:",
                     self.get_total_memory_used())
         debug_print("number of pinned objects:",
@@ -1804,7 +1816,6 @@
             newhdr = self._malloc_out_of_nursery(totalsize)
             #
         elif self.is_forwarded(obj):
-            # XXX check if GCFLAG_PINNED is relevant for this case (groggi)
             #
             # 'obj' was already forwarded.  Change the original reference
             # to point to its forwarding address, and we're done.


More information about the pypy-commit mailing list