Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r915:ad1c9d106b1c
Date: 2014-03-01 22:31 +0100
http://bitbucket.org/pypy/stmgc/changeset/ad1c9d106b1c/

Log:    in-progress

diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -187,122 +187,84 @@
     }
 }
 
-static void mark_record_modified_objects(void)
+static inline void mark_record_trace(object_t **pobj)
+{
+    /* takes a normal pointer to a thread-local pointer to an object */
+    object_t *obj = *pobj;
+
+    if (obj == NULL || mark_visited_test_and_set(obj))
+        return;    /* already visited this object */
+
+    LIST_APPEND(mark_objects_to_trace, obj);
+}
+
+static void mark_from_object(object_t *obj, char *segment_base)
+{
+    if (obj == NULL || mark_visited_test_and_set(obj))
+        return;
+
+    assert(list_is_empty(mark_objects_to_trace));
+
+    while (1) {
+        struct object_s *realobj =
+            (struct object_s *)REAL_ADDRESS(segment_base, obj);
+        stmcb_trace(realobj, &mark_record_trace);
+
+        if (list_is_empty(mark_objects_to_trace))
+            break;
+
+        obj = (object_t *)list_pop_item(mark_objects_to_trace);
+    }
+}
+
+static void mark_visit_from_roots(void)
+{
+    stm_thread_local_t *tl = stm_all_thread_locals;
+    do {
+        /* If 'tl' is currently running, its 'associated_segment_num'
+           field is the segment number that contains the correct
+           version of its overflowed objects.  If not, then the
+           field is still some correct segment number, and it doesn't
+           matter which one we pick. */
+        char *segment_base = get_segment_base(tl->associated_segment_num);
+
+        object_t **current = tl->shadowstack;
+        object_t **base = tl->shadowstack_base;
+        while (current-- != base) {
+            assert(*current != (object_t *)-1);
+            mark_from_object(*current, segment_base);
+        }
+        mark_from_object(tl->thread_local_obj, segment_base);
+
+        tl = tl->next;
+    } while (tl != stm_all_thread_locals);
+
+    if (testing_prebuilt_objs != NULL) {
+        LIST_FOREACH_R(testing_prebuilt_objs, object_t * /*item*/,
+                       mark_from_object(item, get_segment_base(0)));
+    }
+}
+
+static void mark_visit_from_modified_objects(void)
 {
     /* The modified objects are the ones that may exist in two different
        versions: one in the segment that modified it, and another in
        all other segments. */
     long i;
     for (i = 0; i < NB_SEGMENTS; i++) {
-        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
         char *base1 = get_segment_base(i);   /* two different segments */
         char *base2 = get_segment_base(!i);
 
         LIST_FOREACH_R(
-            pseg->modified_old_objects,
+            get_priv_segment(i)->modified_old_objects,
             object_t * /*item*/,
             ({
-                assert(item != NULL);
-
-                uintptr_t lock_idx = mark_loc(item);
-                assert(write_locks[lock_idx] == pseg->write_lock_num);
-
-                write_locks[lock_idx] = WL_VISITED;
-                LIST_APPEND(mark_objects_to_trace, REAL_ADDRESS(base1, item));
-                LIST_APPEND(mark_objects_to_trace, REAL_ADDRESS(base2, item));
+                mark_from_object(item, base1);
+                mark_from_object(item, base2);
             }));
     }
 }
 
-static void reset_write_locks(void)
-{
-    /* the write_locks array, containing the visit marker during
-       major collection, is cleared in sweep_large_objects() for
-       large objects, but is not cleared for small objects.
-       Clear it now. */
-    object_t *loc2 = (object_t *)(uninitialized_page_stop  - stm_object_pages);
-    uintptr_t lock2_idx = mark_loc(loc2 - 1) + 1;
-
-#ifdef STM_TESTS
-    long _i;
-    for (_i=0; _i<lock2_idx; _i++) {
-        assert(write_locks[_i] == 0);
-        if (_i == 1000000) break;  /* ok, stop testing */
-    }
-#endif
-    memset(write_locks + lock2_idx, 0, sizeof(write_locks) - lock2_idx);
-
-    /* restore the write locks on the modified objects */
-    long i;
-    for (i = 0; i < NB_SEGMENTS; i++) {
-        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
-
-        LIST_FOREACH_R(
-            pseg->modified_old_objects,
-            object_t * /*item*/,
-            ({
-                uintptr_t lock_idx = mark_loc(item);
-                assert(write_locks[lock_idx] == 0);
-                write_locks[lock_idx] = pseg->write_lock_num;
-            }));
-    }
-}
-
-static inline void mark_record_trace(object_t **pobj)
-{
-    /* takes a normal pointer to a thread-local pointer to an object */
-    object_t *obj = *pobj;
-
-    if (obj == NULL)
-        return;
-
-    if (mark_visited_test_and_set(obj))
-        return;    /* already visited this object */
-
-    LIST_APPEND(mark_objects_to_trace, REAL_ADDRESS(stm_object_pages, obj));
-}
-
-static void mark_collect_roots(void)
-{
-    stm_thread_local_t *tl = stm_all_thread_locals;
-    do {
-        object_t **current = tl->shadowstack;
-        object_t **base = tl->shadowstack_base;
-        while (current-- != base) {
-            assert(*current != (object_t *)-1);
-            mark_record_trace(current);
-        }
-        mark_record_trace(&tl->thread_local_obj);
-
-        tl = tl->next;
-    } while (tl != stm_all_thread_locals);
-
-    if (testing_prebuilt_objs != NULL) {
-        LIST_FOREACH_R(testing_prebuilt_objs, object_t * /*item*/,
-                       mark_record_trace(&item));
-    }
-}
-
-static void mark_visit_all_objects(void)
-{
-    while (!list_is_empty(mark_objects_to_trace)) {
-        struct object_s *obj =
-            (struct object_s *)list_pop_item(mark_objects_to_trace);
-        stmcb_trace(obj, &mark_record_trace);
-    }
-}
-
-static inline bool largemalloc_keep_object_at(char *data)
-{
-    /* this is called by _stm_largemalloc_sweep() */
-    return mark_visited_test_and_clear((object_t *)(data - stm_object_pages));
-}
-
-static void sweep_large_objects(void)
-{
-    _stm_largemalloc_sweep();
-}
-
 static void clean_up_segment_lists(void)
 {
     long i;
@@ -340,6 +302,73 @@
     }
 }
 
+static inline bool largemalloc_keep_object_at(char *data)
+{
+    /* this is called by _stm_largemalloc_sweep() */
+    return mark_visited_test_and_clear((object_t *)(data - stm_object_pages));
+}
+
+static void sweep_large_objects(void)
+{
+    _stm_largemalloc_sweep();
+}
+
+static void clean_write_locks(void)
+{
+    /* the write_locks array, containing the visit marker during
+       major collection, is cleared in sweep_large_objects() for
+       large objects, but is not cleared for small objects.
+       Clear it now. */
+    object_t *loc2 = (object_t *)(uninitialized_page_stop  - stm_object_pages);
+    uintptr_t lock2_idx = mark_loc(loc2 - 1) + 1;
+
+#ifdef STM_TESTS
+    long _i;
+    for (_i=0; _i<lock2_idx; _i++) {
+        assert(write_locks[_i] == 0);
+        if (_i == 1000000) break;  /* ok, stop testing */
+    }
+#endif
+    memset(write_locks + lock2_idx, 0, sizeof(write_locks) - lock2_idx);
+}
+
+static void major_clear_write_locks(void)
+{
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
+
+        LIST_FOREACH_R(
+            pseg->modified_old_objects,
+            object_t * /*item*/,
+            ({
+                assert(item != NULL);
+
+                uintptr_t lock_idx = mark_loc(item);
+                assert(write_locks[lock_idx] == pseg->write_lock_num);
+                write_locks[lock_idx] = 0;
+            }));
+    }
+}
+
+static void major_set_write_locks(void)
+{
+    /* restore the write locks on the modified objects */
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
+
+        LIST_FOREACH_R(
+            pseg->modified_old_objects,
+            object_t * /*item*/,
+            ({
+                uintptr_t lock_idx = mark_loc(item);
+                assert(write_locks[lock_idx] == 0);
+                write_locks[lock_idx] = pseg->write_lock_num;
+            }));
+    }
+}
+
 static void major_collection_now_at_safe_point(void)
 {
     dprintf(("\n"));
@@ -352,11 +381,12 @@
     dprintf((" | used before collection: %ld\n",
              (long)pages_ctl.total_allocated));
 
+    major_clear_write_locks();
+
     /* marking */
     mark_objects_to_trace = list_create();
-    mark_record_modified_objects();
-    mark_collect_roots();
-    mark_visit_all_objects();
+    mark_visit_from_modified_objects();
+    mark_visit_from_roots();
     list_free(mark_objects_to_trace);
     mark_objects_to_trace = NULL;
 
@@ -369,7 +399,8 @@
     //sweep_uniform_pages();
     mutex_pages_unlock();
 
-    reset_write_locks();
+    clean_write_locks();
+    major_set_write_locks();
 
     dprintf((" | used after collection:  %ld\n",
              (long)pages_ctl.total_allocated));
diff --git a/c7/test/test_gcpage.py b/c7/test/test_gcpage.py
--- a/c7/test/test_gcpage.py
+++ b/c7/test/test_gcpage.py
@@ -177,6 +177,7 @@
         stm_major_collect()
         #
         self.switch(1)
+        x = self.pop_root()
         assert stm_get_char(x, size - 1) == 'E'
 
     def test_trace_correct_version_of_overflow_objects_2(self):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to