[pypy-commit] stmgc default: construct a list of unique objs again during major gc. it's still necessary because large objects get traced many many times otherwise, since they are split into multiple slices

Raemi noreply at buildbot.pypy.org
Thu Jan 22 16:26:43 CET 2015


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: 
Changeset: r1572:509da83c0d5d
Date: 2015-01-22 16:26 +0100
http://bitbucket.org/pypy/stmgc/changeset/509da83c0d5d/

Log:	construct a list of unique objs again during major gc. it's still
	necessary because large objects get traced many many times
	otherwise, since they are split into multiple slices

diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -307,29 +307,53 @@
        some of the pages) */
 
     long i;
+    struct list_s *uniques = list_create();
+
     for (i = 1; i < NB_SEGMENTS; i++) {
         char *base = get_segment_base(i);
+        OPT_ASSERT(list_is_empty(uniques));
 
+        /* the mod_old_objects list may contain maanny slices for
+           the same *huge* object. it seems worth to first construct
+           a list of unique objects. we use the VISITED flag for this
+           purpose as it is never set outside of seg0: */
         struct list_s *lst = get_priv_segment(i)->modified_old_objects;
+
         struct stm_undo_s *modified = (struct stm_undo_s *)lst->items;
         struct stm_undo_s *end = (struct stm_undo_s *)(lst->items + lst->count);
-
         for (; modified < end; modified++) {
             object_t *obj = modified->object;
-            /* All modified objs have all pages accessible for now.
-               This is because we create a backup of the whole obj
-               and thus make all pages accessible. */
-            assert_obj_accessible_in(i, obj);
+            struct object_s *dst = (struct object_s*)REAL_ADDRESS(base, obj);
 
-            assert(!is_new_object(obj)); /* should never be in that list */
+            if (!(dst->stm_flags & GCFLAG_VISITED)) {
+                LIST_APPEND(uniques, obj);
+                dst->stm_flags |= GCFLAG_VISITED;
+            }
+        }
 
-            if (!mark_visited_test_and_set(obj)) {
-                /* trace shared, committed version */
-                mark_and_trace(obj, stm_object_pages);
-            }
-            mark_and_trace(obj, base);   /* private, modified version */
-        }
+        LIST_FOREACH_R(uniques, object_t*,
+           ({
+               /* clear the VISITED flags again and actually visit them */
+               struct object_s *dst = (struct object_s*)REAL_ADDRESS(base, item);
+               dst->stm_flags &= ~GCFLAG_VISITED;
+
+               /* All modified objs have all pages accessible for now.
+                  This is because we create a backup of the whole obj
+                  and thus make all pages accessible. */
+               assert_obj_accessible_in(i, item);
+
+               assert(!is_new_object(item)); /* should never be in that list */
+
+               if (!mark_visited_test_and_set(item)) {
+                   /* trace shared, committed version */
+                   mark_and_trace(item, stm_object_pages);
+               }
+               mark_and_trace(item, base);   /* private, modified version */
+           }));
+
+        list_clear(uniques);
     }
+    LIST_FREE(uniques);
 }
 
 static void mark_visit_from_roots(void)


More information about the pypy-commit mailing list