[pypy-commit] stmgc card-marking: test & fix for major gc

Raemi noreply at buildbot.pypy.org
Tue May 20 17:05:27 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: card-marking
Changeset: r1222:b7879ec94205
Date: 2014-05-20 17:06 +0200
http://bitbucket.org/pypy/stmgc/changeset/b7879ec94205/

Log:	test & fix for major gc

diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -231,7 +231,9 @@
     return (byte_offset >> 5) + 1;
 }
 static inline uintptr_t get_write_lock_idx(uintptr_t obj) {
-    return (obj >> 4) - WRITELOCK_START;
+    uintptr_t res = (obj >> 4) - WRITELOCK_START;
+    assert(res < sizeof(write_locks));
+    return res;
 }
 
 static inline char *get_segment_base(long segment_num) {
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -166,7 +166,7 @@
 
 static inline uintptr_t mark_loc(object_t *obj)
 {
-    uintptr_t lock_idx = (((uintptr_t)obj) >> 4) - WRITELOCK_START;
+    uintptr_t lock_idx = get_write_lock_idx((uintptr_t)obj);
     assert(lock_idx < sizeof(write_locks));
     return lock_idx;
 }
@@ -450,7 +450,7 @@
            written to but don't actually point to the nursery.  Clear
            it up and set GCFLAG_WRITE_BARRIER again on the objects.
            This is the case for transactions where
-               MINOR_NOTHING_TO_DO() == false
+               MINOR_NOTHING_TO_DO() == true
            but they still did write-barriers on objects
         */
         lst = pseg->objects_pointing_to_nursery;
@@ -463,6 +463,16 @@
                     realobj->stm_flags |= GCFLAG_WRITE_BARRIER;
                 }));
             list_clear(lst);
+
+            lst = pseg->old_objects_with_cards;
+            LIST_FOREACH_R(lst, object_t* /*item*/,
+                ({
+                    struct object_s *realobj = (struct object_s *)
+                        REAL_ADDRESS(pseg->pub.segment_base, item);
+                    OPT_ASSERT(realobj->stm_flags & GCFLAG_CARDS_SET);
+                    _reset_object_cards(&pseg->pub, item);
+                }));
+            list_clear(lst);
         }
 
         /* Remove from 'large_overflow_objects' all objects that die */
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -183,10 +183,14 @@
     minor_trace_if_young(&tl->thread_local_obj);
 }
 
-static void _reset_cards(object_t *obj)
+static void _reset_object_cards(struct stm_segment_info_s *seg, object_t *obj)
 {
-    char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
-    size_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+#pragma push_macro("STM_PSEGMENT")
+#pragma push_macro("STM_SEGMENT")
+#undef STM_PSEGMENT
+#undef STM_SEGMENT
+    struct object_s *realobj = (struct object_s *)REAL_ADDRESS(seg->segment_base, obj);
+    size_t size = stmcb_size_rounded_up(realobj);
 
     uintptr_t first_card_index = get_write_lock_idx((uintptr_t)obj);
     uintptr_t card_index = 1;
@@ -197,7 +201,10 @@
         card_index++;
     }
 
-    obj->stm_flags &= ~GCFLAG_CARDS_SET;
+    realobj->stm_flags &= ~GCFLAG_CARDS_SET;
+    dprintf(("reset cards on %p\n", obj));
+#pragma pop_macro("STM_SEGMENT")
+#pragma pop_macro("STM_PSEGMENT")
 }
 
 static __thread object_t *_card_base_obj;
@@ -229,7 +236,8 @@
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     stmcb_trace((struct object_s *)realobj, &minor_trace_if_young_cards);
 
-    _reset_cards(obj);
+    _reset_object_cards(
+        get_segment(STM_SEGMENT->segment_num), obj);
 }
 
 
@@ -249,7 +257,8 @@
 
         obj->stm_flags |= GCFLAG_WRITE_BARRIER;
         if (obj->stm_flags & GCFLAG_CARDS_SET) {
-            _reset_cards(obj);
+            _reset_object_cards(
+                get_segment(STM_SEGMENT->segment_num), obj);
         }
     } if (obj->stm_flags & GCFLAG_CARDS_SET) {
         _trace_card_object(obj);
@@ -366,7 +375,7 @@
 
     if (pseg->old_objects_with_cards) {
         LIST_FOREACH_R(pseg->old_objects_with_cards, object_t * /*item*/,
-                       _reset_cards(item));
+                       _reset_object_cards(&pseg->pub, item));
     }
 
     return nursery_used;
diff --git a/c7/stm/nursery.h b/c7/stm/nursery.h
--- a/c7/stm/nursery.h
+++ b/c7/stm/nursery.h
@@ -6,6 +6,7 @@
 
 static uint32_t highest_overflow_number;
 
+static void _reset_object_cards(struct stm_segment_info_s *seg, object_t *obj);
 static void minor_collection(bool commit);
 static void check_nursery_at_transaction_start(void);
 static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg);
diff --git a/c7/test/test_card_marking.py b/c7/test/test_card_marking.py
--- a/c7/test/test_card_marking.py
+++ b/c7/test/test_card_marking.py
@@ -1,8 +1,21 @@
 from support import *
 import py
 
+
 class TestBasic(BaseTest):
 
+    def _collect(self, kind):
+        if kind == 0:
+            stm_minor_collect()
+        elif kind == 1:
+            stm_major_collect()
+        elif kind == 2:
+            self.switch(1)
+            self.start_transaction()
+            stm_major_collect()
+            self.abort_transaction()
+            self.switch(0)
+
     def test_simple(self):
         o = stm_allocate_old(1024, True)
         self.start_transaction()
@@ -10,7 +23,6 @@
         stm_write(o)
         self.commit_transaction()
 
-
     def test_simple2(self):
         o = stm_allocate_old(1024, True)
         self.start_transaction()
@@ -19,13 +31,20 @@
         assert stm_was_written_card(o)
         self.commit_transaction()
 
-    def test_overflow(self):
+    @py.test.mark.parametrize("k", range(3))
+    def test_overflow(self, k):
         self.start_transaction()
         o = stm_allocate(1024, True)
+
         self.push_root(o)
-        stm_minor_collect()
+        self._collect(k)
         o = self.pop_root()
+
         stm_write_card(o, 5)
+
+        assert o in old_objects_with_cards()
+        assert o not in modified_old_objects() # overflow object
+        assert o not in objects_pointing_to_nursery()
         # don't remove GCFLAG_WB
         assert not stm_was_written(o)
         stm_write(o)
@@ -80,7 +99,7 @@
         e = stm_allocate(64)
         stm_set_ref(o, 199, p, True)
         stm_set_ref(o, 1, d, False)
-        lib._set_ptr(o, 100, e)
+        lib._set_ptr(o, 100, e) # no barrier
 
         self.push_root(o)
         stm_minor_collect()
@@ -144,3 +163,26 @@
 
         assert not is_in_nursery(stm_get_ref(o, 1))
         assert is_in_nursery(stm_get_ref(o, 199)) # not traced
+
+    @py.test.mark.parametrize("k", range(3))
+    def test_major_gc(self, k):
+        o = stm_allocate_old_refs(200, True)
+        self.start_transaction()
+        p = stm_allocate(64)
+        stm_set_ref(o, 0, p, True)
+
+        self.push_root(o)
+        stm_major_collect()
+        o = self.pop_root()
+
+        stm_set_ref(o, 1, ffi.NULL, True)
+        p = stm_get_ref(o, 0)
+        assert stm_was_written_card(o)
+
+        self.push_root(o)
+        self._collect(k)
+        o = self.pop_root()
+
+        assert not stm_was_written_card(o)
+        assert stm_get_ref(o, 0) == p
+        self.commit_transaction()


More information about the pypy-commit mailing list