[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