[pypy-commit] stmgc default: in-progress. still a bug left

arigo noreply at buildbot.pypy.org
Sat Mar 1 20:04:16 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r913:e7ae3f43dde8
Date: 2014-03-01 20:03 +0100
http://bitbucket.org/pypy/stmgc/changeset/e7ae3f43dde8/

Log:	in-progress. still a bug left

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -236,6 +236,7 @@
 
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     ssize_t obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+    assert(obj_size >= 16);
     uintptr_t start = (uintptr_t)obj;
     uintptr_t end = start + obj_size;
     uintptr_t first_page = start / 4096UL;
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -95,6 +95,8 @@
     return addr;
 }
 
+static struct list_s *testing_prebuilt_objs = NULL;
+
 object_t *_stm_allocate_old(ssize_t size_rounded_up)
 {
     /* only for tests */
@@ -103,6 +105,11 @@
 
     object_t *o = (object_t *)(p - stm_object_pages);
     o->stm_flags = STM_FLAGS_PREBUILT;
+
+    if (testing_prebuilt_objs == NULL)
+        testing_prebuilt_objs = list_create();
+    LIST_APPEND(testing_prebuilt_objs, o);
+
     return o;
 }
 
@@ -147,6 +154,13 @@
     return lock_idx;
 }
 
+static inline bool mark_visited_test(object_t *obj)
+{
+    uintptr_t lock_idx = mark_loc(obj);
+    assert(write_locks[lock_idx] == 0 || write_locks[lock_idx] == WL_VISITED);
+    return write_locks[lock_idx] != 0;
+}
+
 static inline bool mark_visited_test_and_set(object_t *obj)
 {
     uintptr_t lock_idx = mark_loc(obj);
@@ -228,6 +242,7 @@
             object_t * /*item*/,
             ({
                 uintptr_t lock_idx = mark_loc(item);
+                assert(write_locks[lock_idx] == 0);
                 write_locks[lock_idx] = pseg->write_lock_num;
             }));
     }
@@ -261,6 +276,9 @@
 
         tl = tl->next;
     } while (tl != stm_all_thread_locals);
+
+    LIST_FOREACH_R(testing_prebuilt_objs, object_t * /*item*/,
+                   mark_record_trace(&item));
 }
 
 static void mark_visit_all_objects(void)
@@ -283,6 +301,43 @@
     _stm_largemalloc_sweep();
 }
 
+static void clean_up_segment_lists(void)
+{
+    long i;
+    for (i = 0; i < NB_SEGMENTS; i++) {
+        struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
+        struct list_s *lst;
+
+        /* 'objects_pointing_to_nursery' should be empty, but isn't
+           necessarily because it also lists objects that have been
+           written to but don't actually point to the nursery.  Clear
+           it up and set GCFLAG_WRITE_BARRIER again on the objects. */
+        lst = pseg->objects_pointing_to_nursery;
+        if (lst != NULL) {
+            LIST_FOREACH_R(lst, uintptr_t /*item*/,
+                ({
+                    struct object_s *realobj = (struct object_s *)
+                        REAL_ADDRESS(pseg->pub.segment_base, item);
+                    assert(!(realobj->stm_flags & GCFLAG_WRITE_BARRIER));
+                    realobj->stm_flags |= GCFLAG_WRITE_BARRIER;
+                }));
+            list_clear(lst);
+        }
+
+        /* Remove from 'large_overflow_objects' all objects that die */
+        lst = pseg->large_overflow_objects;
+        if (lst != NULL) {
+            uintptr_t n = list_count(lst);
+            while (n > 0) {
+                object_t *obj = (object_t *)list_item(lst, --n);
+                if (!mark_visited_test(obj)) {
+                    list_set_item(lst, n, list_pop_item(lst));
+                }
+            }
+        }
+    }
+}
+
 static void major_collection_now_at_safe_point(void)
 {
     dprintf(("\n"));
@@ -303,6 +358,9 @@
     list_free(mark_objects_to_trace);
     mark_objects_to_trace = NULL;
 
+    /* cleanup */
+    clean_up_segment_lists();
+
     /* sweeping */
     mutex_pages_lock();
     sweep_large_objects();
diff --git a/c7/stm/largemalloc.c b/c7/stm/largemalloc.c
--- a/c7/stm/largemalloc.c
+++ b/c7/stm/largemalloc.c
@@ -251,6 +251,12 @@
     assert((chunk->size & (sizeof(char *) - 1)) == 0);
     assert(chunk->prev_size != THIS_CHUNK_FREE);
 
+#ifndef NDEBUG
+    assert(chunk->size >= sizeof(dlist_t));
+    assert(chunk->size <= (((char *)last_chunk) - (char *)data));
+    memset(data, 0xDD, chunk->size);
+#endif
+
     /* try to merge with the following chunk in memory */
     size_t msize = chunk->size + CHUNK_HEADER_SIZE;
     mchunk_t *mscan = chunk_at_offset(chunk, msize);
diff --git a/c7/stm/list.h b/c7/stm/list.h
--- a/c7/stm/list.h
+++ b/c7/stm/list.h
@@ -58,6 +58,12 @@
     return lst->items[index];
 }
 
+static inline void list_set_item(struct list_s *lst, uintptr_t index,
+                                 uintptr_t newitem)
+{
+    lst->items[index] = newitem;
+}
+
 #define LIST_FOREACH_R(lst, TYPE, CODE)         \
     do {                                        \
         struct list_s *_lst = (lst);            \
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -217,7 +217,7 @@
         return myobj->type_id - 42;
     }
     else {
-        int nrefs = myobj->type_id - 421420;
+        uint64_t nrefs = myobj->type_id - 421420;
         assert(nrefs < 10000);     /* artificial limit, to check for garbage */
         if (nrefs == 0)   /* weakrefs */
             nrefs = 1;
diff --git a/c7/test/test_largemalloc.py b/c7/test/test_largemalloc.py
--- a/c7/test/test_largemalloc.py
+++ b/c7/test/test_largemalloc.py
@@ -136,11 +136,15 @@
         from_before = set()
 
         r = random.Random(1000)
-        for j in range(50):
+        for j in range(500):
             sizes = [random.choice(range(104, 500, 8)) for i in range(20)]
             all = [lib._stm_large_malloc(size) for size in sizes]
             print all
 
+            for i in range(len(all)):
+                all[i][50] = chr(65 + i)
+            all_orig = all[:]
+
             keep_me = set()
             for i in range(len(all)):
                 if r.random() < 0.5:
@@ -152,10 +156,16 @@
 
             seen_for = set()
             lib._stm_largemalloc_sweep()
+            if errors:
+                raise errors[0]
             assert seen_for == set([i for i in range(len(all))
                                       if all[i] is not None])
             lib._stm_large_dump()
+
             from_before = [all[i] for i in keep_me]
 
-            if errors:
-                raise errors[0]
+            for i in range(len(all)):
+                if i in keep_me:
+                    assert all[i][50] == chr(65 + i)
+                else:
+                    assert all_orig[i][50] == '\xDD'
diff --git a/c7/test/test_random.py b/c7/test/test_random.py
--- a/c7/test/test_random.py
+++ b/c7/test/test_random.py
@@ -384,6 +384,12 @@
     thread_state.pop_roots(ex)
     thread_state.reload_roots(ex)
 
+def op_major_collect(ex, global_state, thread_state):
+    thread_state.push_roots(ex)
+    ex.do('stm_major_collect()')
+    thread_state.pop_roots(ex)
+    thread_state.reload_roots(ex)
+
 
 def op_forget_root(ex, global_state, thread_state):
     r = thread_state.forget_random_root()
@@ -566,6 +572,7 @@
             op_assert_size,
             op_assert_modified,
             op_minor_collect,
+            op_major_collect,
         ]
         for _ in range(200):
             # make sure we are in a transaction:


More information about the pypy-commit mailing list