Author: Remi Meier <[email protected]>
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)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to