[pypy-commit] stmgc c7-refactor: Unify overflow_objects_pointing_to_nursery and

arigo noreply at buildbot.pypy.org
Mon Feb 24 17:59:12 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r841:2286fb4f0127
Date: 2014-02-24 17:57 +0100
http://bitbucket.org/pypy/stmgc/changeset/2286fb4f0127/

Log:	Unify overflow_objects_pointing_to_nursery and
	old_objects_pointing_to_nursery: unless I'm wrong, we can merge the
	two lists.

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -18,10 +18,10 @@
     if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0) ==
             STM_PSEGMENT->overflow_number) {
 
-        dprintf_test(("write_slowpath %p -> ovf_obj\n", obj));
+        dprintf_test(("write_slowpath %p -> ovf obj_to_nurs\n", obj));
         obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
-        assert(STM_PSEGMENT->overflow_objects_pointing_to_nursery != NULL);
-        LIST_APPEND(STM_PSEGMENT->overflow_objects_pointing_to_nursery, obj);
+        assert(STM_PSEGMENT->objects_pointing_to_nursery != NULL);
+        LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
         return;
     }
 
@@ -32,7 +32,7 @@
     /* claim the write-lock for this object.  In case we're running the
        same transaction since a long while, the object can be already in
        'modified_old_objects' (but, because it had GCFLAG_WRITE_BARRIER,
-       not in 'old_objects_pointing_to_nursery').  We'll detect this case
+       not in 'objects_pointing_to_nursery').  We'll detect this case
        by finding that we already own the write-lock. */
     uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - WRITELOCK_START;
     uint8_t lock_num = STM_PSEGMENT->write_lock_num;
@@ -77,7 +77,7 @@
         }
     }
     else if (write_locks[lock_idx] == lock_num) {
-        OPT_ASSERT(STM_PSEGMENT->old_objects_pointing_to_nursery != NULL);
+        OPT_ASSERT(STM_PSEGMENT->objects_pointing_to_nursery != NULL);
 #ifdef STM_TESTS
         bool found = false;
         LIST_FOREACH_R(STM_PSEGMENT->modified_old_objects, object_t *,
@@ -97,11 +97,11 @@
     }
 
     /* A common case for write_locks[] that was either 0 or lock_num:
-       we need to add the object to 'old_objects_pointing_to_nursery'
+       we need to add the object to 'objects_pointing_to_nursery'
        if there is such a list. */
-    if (STM_PSEGMENT->old_objects_pointing_to_nursery != NULL) {
-        dprintf_test(("write_slowpath %p -> old_obj_pointing_to_nurs\n", obj));
-        LIST_APPEND(STM_PSEGMENT->old_objects_pointing_to_nursery, obj);
+    if (STM_PSEGMENT->objects_pointing_to_nursery != NULL) {
+        dprintf_test(("write_slowpath %p -> old obj_to_nurs\n", obj));
+        LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
     }
 
     /* add the write-barrier-already-called flag ONLY if we succeeded in
@@ -173,8 +173,7 @@
     }
 
     assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
-    assert(STM_PSEGMENT->old_objects_pointing_to_nursery == NULL);
-    assert(STM_PSEGMENT->overflow_objects_pointing_to_nursery == NULL);
+    assert(STM_PSEGMENT->objects_pointing_to_nursery == NULL);
     assert(STM_PSEGMENT->large_overflow_objects == NULL);
 
 #ifdef STM_TESTS
@@ -318,8 +317,7 @@
     STM_PSEGMENT->transaction_state = TS_NONE;
 
     /* reset these lists to NULL for the next transaction */
-    LIST_FREE(STM_PSEGMENT->old_objects_pointing_to_nursery);
-    LIST_FREE(STM_PSEGMENT->overflow_objects_pointing_to_nursery);
+    LIST_FREE(STM_PSEGMENT->objects_pointing_to_nursery);
     LIST_FREE(STM_PSEGMENT->large_overflow_objects);
 
     stm_thread_local_t *tl = STM_SEGMENT->running_thread;
@@ -332,6 +330,9 @@
     assert(!_has_mutex());
     assert(STM_PSEGMENT->safe_point == SP_RUNNING);
 
+    bool has_any_overflow_object =
+        (STM_PSEGMENT->objects_pointing_to_nursery != NULL);
+
     minor_collection(/*commit=*/ true);
 
     mutex_lock();
@@ -359,7 +360,7 @@
     push_modified_to_other_segments();
 
     /* update 'overflow_number' if needed */
-    if (STM_PSEGMENT->overflow_objects_pointing_to_nursery != NULL) {
+    if (has_any_overflow_object) {
         highest_overflow_number += GCFLAG_OVERFLOW_NUMBER_bit0;
         STM_PSEGMENT->overflow_number = highest_overflow_number;
     }
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -67,20 +67,15 @@
        that need to be copied to other segments upon commit. */
     struct list_s *modified_old_objects;
 
-    /* List of the modified old objects that may point to the nursery.
-       If the current transaction didn't span a minor collection so far,
-       this is NULL, understood as meaning implicitly "this is the same
-       as 'modified_old_objects'".  Otherwise, this list is a subset of
-       'modified_old_objects'. */
-    struct list_s *old_objects_pointing_to_nursery;
-
-    /* List of overflowed objects (from the same transaction but outside
-       the nursery) on which the write-barrier was triggered, so that
-       they likely contain a pointer to a nursery object.  This is used
-       by the GC: it's additional roots for the next minor collection.
-       This is NULL if the current transaction didn't span a minor
-       collection so far. */
-    struct list_s *overflow_objects_pointing_to_nursery;
+    /* List of out-of-nursery objects that may contain pointers to
+       nursery objects.  This is used to track the GC status: they
+       are all objects outside the nursery on which an stm_write()
+       occurred since the last minor collection.  If there was no
+       minor collection yet in the current transaction, this is NULL,
+       understood as meaning implicitly "this is the same as
+       'modified_old_objects'.  This list contains exactly the
+       objects without GCFLAG_WRITE_BARRIER. */
+    struct list_s *objects_pointing_to_nursery;
 
     /* List of all large, overflowed objects.  Only non-NULL after the
        current transaction spanned a minor collection. */
diff --git a/c7/stm/misc.c b/c7/stm/misc.c
--- a/c7/stm/misc.c
+++ b/c7/stm/misc.c
@@ -48,18 +48,11 @@
     return list_count(STM_PSEGMENT->modified_old_objects);
 }
 
-long _stm_count_old_objects_pointing_to_nursery(void)
+long _stm_count_objects_pointing_to_nursery(void)
 {
-    if (STM_PSEGMENT->old_objects_pointing_to_nursery == NULL)
+    if (STM_PSEGMENT->objects_pointing_to_nursery == NULL)
         return -1;
-    return list_count(STM_PSEGMENT->old_objects_pointing_to_nursery);
-}
-
-long _stm_count_overflow_objects_pointing_to_nursery(void)
-{
-    if (STM_PSEGMENT->overflow_objects_pointing_to_nursery == NULL)
-        return -1;
-    return list_count(STM_PSEGMENT->overflow_objects_pointing_to_nursery);
+    return list_count(STM_PSEGMENT->objects_pointing_to_nursery);
 }
 
 object_t *_stm_enum_modified_old_objects(long index)
@@ -68,15 +61,9 @@
         STM_PSEGMENT->modified_old_objects, index);
 }
 
-object_t *_stm_enum_old_objects_pointing_to_nursery(long index)
+object_t *_stm_enum_objects_pointing_to_nursery(long index)
 {
     return (object_t *)list_item(
-        STM_PSEGMENT->old_objects_pointing_to_nursery, index);
-}
-
-object_t *_stm_enum_overflow_objects_pointing_to_nursery(long index)
-{
-    return (object_t *)list_item(
-        STM_PSEGMENT->overflow_objects_pointing_to_nursery, index);
+        STM_PSEGMENT->objects_pointing_to_nursery, index);
 }
 #endif
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -113,7 +113,7 @@
     *pobj = nobj;
 
     /* Must trace the object later */
-    LIST_APPEND(STM_PSEGMENT->old_objects_pointing_to_nursery, nobj);
+    LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj);
 }
 
 static void collect_roots_in_nursery(void)
@@ -129,7 +129,7 @@
 
 static void collect_oldrefs_to_nursery(void)
 {
-    struct list_s *lst = STM_PSEGMENT->old_objects_pointing_to_nursery;
+    struct list_s *lst = STM_PSEGMENT->objects_pointing_to_nursery;
 
     while (!list_is_empty(lst)) {
         object_t *obj = (object_t *)list_pop_item(lst);
@@ -140,8 +140,8 @@
         obj->stm_flags |= GCFLAG_WRITE_BARRIER;
 
         /* Trace the 'obj' to replace pointers to nursery with pointers
-           outside the nursery, possibly forcing nursery objects out
-           and adding them to 'old_objects_pointing_to_nursery' as well. */
+           outside the nursery, possibly forcing nursery objects out and
+           adding them to 'objects_pointing_to_nursery' as well. */
         char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
         stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
     }
@@ -167,9 +167,9 @@
 
     /* We must move out of the nursery any object found within the
        nursery.  All objects touched are either from the current
-       transaction, or are from 'old_objects_pointing_to_young'.
-       In all cases, we should only read and change objects belonging
-       to the current segment.
+       transaction, or are from 'modified_old_objects'.  In all cases,
+       we should only read and change objects belonging to the current
+       segment.
 
        XXX improve: it might be possible to run this function in
        a safe-point but without the mutex, if we are careful
@@ -178,8 +178,15 @@
     dprintf(("minor_collection commit=%d\n", (int)commit));
 
     STM_PSEGMENT->minor_collect_will_commit_now = commit;
-    if (STM_PSEGMENT->old_objects_pointing_to_nursery == NULL)
-        STM_PSEGMENT->old_objects_pointing_to_nursery = list_create();
+
+    /* All the objects we move out of the nursery become "overflow"
+       objects.  We use the list 'objects_pointing_to_nursery'
+       to hold the ones we didn't trace so far. */
+    if (STM_PSEGMENT->objects_pointing_to_nursery == NULL)
+        STM_PSEGMENT->objects_pointing_to_nursery = list_create();
+
+    /* We need this to track the large overflow objects for a future
+       commit.  We don't need it if we're committing now. */
     if (!commit && STM_PSEGMENT->large_overflow_objects == NULL)
         STM_PSEGMENT->large_overflow_objects = list_create();
 
@@ -189,9 +196,7 @@
 
     reset_nursery();
 
-    assert(list_is_empty(STM_PSEGMENT->old_objects_pointing_to_nursery));
-    if (!commit && STM_PSEGMENT->overflow_objects_pointing_to_nursery == NULL)
-        STM_PSEGMENT->overflow_objects_pointing_to_nursery = list_create();
+    assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery));
 }
 
 void stm_collect(long level)
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -53,7 +53,7 @@
         pr->write_lock_num = i + 1;
         pr->pub.segment_num = i;
         pr->pub.segment_base = segment_base;
-        pr->overflow_objects_pointing_to_nursery = NULL;
+        pr->objects_pointing_to_nursery = NULL;
         pr->large_overflow_objects = NULL;
         pr->modified_old_objects = list_create();
         pr->overflow_number = GCFLAG_OVERFLOW_NUMBER_bit0 * (i + 1);
@@ -85,9 +85,8 @@
     long i;
     for (i = 0; i < NB_SEGMENTS; i++) {
         struct stm_priv_segment_info_s *pr = get_priv_segment(i);
-        assert(pr->overflow_objects_pointing_to_nursery == NULL);
+        assert(pr->objects_pointing_to_nursery == NULL);
         assert(pr->large_overflow_objects == NULL);
-        assert(pr->old_objects_pointing_to_nursery == NULL);
         list_free(pr->modified_old_objects);
     }
 
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -82,11 +82,9 @@
 void _stm_stop_safe_point(void);
 void _stm_set_nursery_free_count(uint64_t free_count);
 long _stm_count_modified_old_objects(void);
-long _stm_count_old_objects_pointing_to_nursery(void);
-long _stm_count_overflow_objects_pointing_to_nursery(void);
+long _stm_count_objects_pointing_to_nursery(void);
 object_t *_stm_enum_modified_old_objects(long index);
-object_t *_stm_enum_old_objects_pointing_to_nursery(long index);
-object_t *_stm_enum_overflow_objects_pointing_to_nursery(long index);
+object_t *_stm_enum_objects_pointing_to_nursery(long index);
 #endif
 
 #define _STM_GCFLAG_WRITE_BARRIER      0x01
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -77,11 +77,9 @@
 ssize_t stmcb_size_rounded_up(struct object_s *obj);
 
 long _stm_count_modified_old_objects(void);
-long _stm_count_old_objects_pointing_to_nursery(void);
-long _stm_count_overflow_objects_pointing_to_nursery(void);
+long _stm_count_objects_pointing_to_nursery(void);
 object_t *_stm_enum_modified_old_objects(long index);
-object_t *_stm_enum_old_objects_pointing_to_nursery(long index);
-object_t *_stm_enum_overflow_objects_pointing_to_nursery(long index);
+object_t *_stm_enum_objects_pointing_to_nursery(long index);
 
 void stm_collect(long level);
 """)
@@ -367,17 +365,11 @@
         return None
     return map(lib._stm_enum_modified_old_objects, range(count))
 
-def old_objects_pointing_to_nursery():
-    count = lib._stm_count_old_objects_pointing_to_nursery()
+def objects_pointing_to_nursery():
+    count = lib._stm_count_objects_pointing_to_nursery()
     if count < 0:
         return None
-    return map(lib._stm_enum_old_objects_pointing_to_nursery, range(count))
-
-def overflow_objects_pointing_to_nursery():
-    count = lib._stm_count_overflow_objects_pointing_to_nursery()
-    if count < 0:
-        return None
-    return map(lib._stm_enum_overflow_objects_pointing_to_nursery,range(count))
+    return map(lib._stm_enum_objects_pointing_to_nursery, range(count))
 
 
 SHADOWSTACK_LENGTH = 1000
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -51,8 +51,7 @@
         stm_write(lp1)
         assert stm_was_written(lp1)
         assert modified_old_objects() == []             # object not old
-        assert old_objects_pointing_to_nursery() == None    # short transac.
-        assert overflow_objects_pointing_to_nursery() == None # short transac.
+        assert objects_pointing_to_nursery() == None    # short transaction
         self.commit_transaction()
 
     def test_allocate_old(self):
@@ -89,7 +88,7 @@
         assert modified_old_objects() == []
         stm_write(lp1)
         assert modified_old_objects() == [lp1]
-        assert old_objects_pointing_to_nursery() == None
+        assert objects_pointing_to_nursery() == None
         assert stm_get_char(lp1) == 'a'
         stm_set_char(lp1, 'b')
         #


More information about the pypy-commit mailing list