Author: Remi Meier <[email protected]>
Branch: c8-card-marking
Changeset: r1674:11b04ac95b6c
Date: 2015-02-27 11:22 +0100
http://bitbucket.org/pypy/stmgc/changeset/11b04ac95b6c/

Log:    in-progress state that needs overflow objs to continue

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -610,9 +610,11 @@
            that the write_slowpath will not be called again until the
            next minor collection. */
         if (obj->stm_flags & GCFLAG_CARDS_SET) {
-            /* if we clear this flag, we also need to clear the cards */
+            /* if we clear this flag, we also need to clear the cards.
+               bk_slices are not needed as this is a new object */
+            /* XXX: add_missing_bk_slices_and_"clear"_cards */
             _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
-                                obj, CARD_CLEAR, false);
+                                obj, CARD_CLEAR, false, false);
         }
         obj->stm_flags &= ~(GCFLAG_WRITE_BARRIER | GCFLAG_CARDS_SET);
         LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj);
@@ -731,8 +733,12 @@
         if (obj->stm_flags & GCFLAG_CARDS_SET) {
             /* if we clear this flag, we have to tell sync_old_objs that
                everything needs to be synced */
+            /* if we clear this flag, we have to tell later write barriers
+               that we already did all backup slices: */
+            /* XXX: do_other_bk_slices_and_"clear"_cards */
             _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
-                                obj, CARD_MARKED_OLD, true); /* mark all */
+                                obj, STM_SEGMENT->transaction_read_version,
+                                true, false); /* mark all */
         }
 
         /* remove the WRITE_BARRIER flag and add WB_EXECUTED */
@@ -840,7 +846,8 @@
 #endif
         memset(readmarkers, 0, NB_READMARKER_PAGES * 4096UL);
     }
-    STM_SEGMENT->transaction_read_version = 1;
+    STM_SEGMENT->transaction_read_version = 2;
+    assert(STM_SEGMENT->transaction_read_version > _STM_CARD_MARKED);
 }
 
 static void reset_cards_from_modified_objects(void)
@@ -1308,8 +1315,27 @@
 }
 
 
-static void _page_wise_synchronize_object_now(object_t *obj, ssize_t obj_size)
+
+static void synchronize_object_enqueue(object_t *obj)
 {
+    assert(!_is_young(obj));
+    assert(STM_PSEGMENT->privatization_lock);
+    assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
+    assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
+
+    ssize_t obj_size = stmcb_size_rounded_up(
+        (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
+    OPT_ASSERT(obj_size >= 16);
+
+    if (LIKELY(is_small_uniform(obj))) {
+        assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
+        OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
+        _synchronize_fragment((stm_char *)obj, obj_size);
+        return;
+    }
+
+    /* else, a more complicated case for large objects, to copy
+       around data only within the needed pages */
     uintptr_t start = (uintptr_t)obj;
     uintptr_t end = start + obj_size;
 
@@ -1330,135 +1356,6 @@
     } while (start != end);
 }
 
-static void _card_wise_synchronize_object_now(object_t *obj, ssize_t obj_size)
-{
-    assert(obj_size >= 32);
-    assert(obj_should_use_cards(STM_SEGMENT->segment_base, obj));
-    assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
-
-    uintptr_t offset_itemsize[2];
-    struct object_s *realobj = (struct object_s 
*)REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
-    stmcb_get_card_base_itemsize(realobj, offset_itemsize);
-    size_t real_idx_count = (obj_size - offset_itemsize[0]) / 
offset_itemsize[1];
-
-    struct stm_read_marker_s *cards = 
get_read_marker(STM_SEGMENT->segment_base, (uintptr_t)obj);
-    uintptr_t card_index = 1;
-    uintptr_t last_card_index = get_index_to_card_index(real_idx_count - 1); 
/* max valid index */
-    assert(cards->rm == STM_SEGMENT->transaction_read_version); /* stm_read() 
*/
-
-    /* simple heuristic to check if probably the whole object is
-       marked anyway so we should do page-wise synchronize */
-    if (cards[1].rm == CARD_MARKED_OLD
-        && cards[last_card_index].rm == CARD_MARKED_OLD
-        && cards[(last_card_index >> 1) + 1].rm == CARD_MARKED_OLD) {
-
-        dprintf(("card_wise_sync assumes %p,size:%lu is fully marked\n", obj, 
obj_size));
-        _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
-                            obj, CARD_CLEAR, false);
-        _page_wise_synchronize_object_now(obj, obj_size);
-        return;
-    }
-
-    dprintf(("card_wise_sync syncs %p,size:%lu card-wise\n", obj, obj_size));
-
-    /* Combine multiple marked cards and do a memcpy for them. We don't
-       try yet to use page_copy() or otherwise take into account privatization
-       of pages (except _has_private_page_in_range) */
-    bool all_cards_were_cleared = true;
-
-    uintptr_t start_card_index = -1;
-    while (card_index <= last_card_index) {
-        uint8_t card_value = cards[card_index].rm;
-
-        if (card_value == CARD_MARKED_OLD) {
-            cards[card_index].rm = CARD_CLEAR;
-
-            if (start_card_index == -1) {   /* first marked card */
-                start_card_index = card_index;
-                /* start = (uintptr_t)obj + stmcb_index_to_byte_offset( */
-                /*     realobj, get_card_index_to_index(card_index)); */
-                if (all_cards_were_cleared) {
-                    all_cards_were_cleared = false;
-                }
-            }
-        }
-        else {
-            OPT_ASSERT(card_value == CARD_CLEAR);
-        }
-
-        if (start_card_index != -1                    /* something to copy */
-            && (card_value != CARD_MARKED_OLD         /* found non-marked card 
*/
-                || card_index == last_card_index)) {  /* this is the last card 
*/
-            /* do the copying: */
-            uintptr_t start, copy_size;
-            uintptr_t next_card_offset;
-            uintptr_t start_card_offset;
-            uintptr_t next_card_index = card_index;
-
-            if (card_value == CARD_MARKED_OLD) {
-                /* card_index is the last card of the object, but we need
-                   to go one further to get the right offset */
-                next_card_index++;
-            }
-
-            start_card_offset = offset_itemsize[0] +
-                get_card_index_to_index(start_card_index) * offset_itemsize[1];
-
-            next_card_offset = offset_itemsize[0] +
-                get_card_index_to_index(next_card_index) * offset_itemsize[1];
-
-            if (next_card_offset > obj_size)
-                next_card_offset = obj_size;
-
-            start = (uintptr_t)obj + start_card_offset;
-            copy_size = next_card_offset - start_card_offset;
-            OPT_ASSERT(copy_size > 0);
-
-            /* push to seg0 and enqueue for synchronization */
-            _synchronize_fragment((stm_char *)start, copy_size);
-
-            start_card_index = -1;
-        }
-
-        card_index++;
-    }
-
-    if (all_cards_were_cleared) {
-        /* well, seems like we never called stm_write_card() on it, so actually
-           we need to fall back to synchronize the whole object */
-        _page_wise_synchronize_object_now(obj, obj_size);
-        return;
-    }
-
-}
-
-
-static void synchronize_object_enqueue(object_t *obj, bool ignore_cards)
-{
-    assert(!_is_young(obj));
-    assert(STM_PSEGMENT->privatization_lock);
-    assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
-    assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED));
-
-    ssize_t obj_size = stmcb_size_rounded_up(
-        (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
-    OPT_ASSERT(obj_size >= 16);
-
-    if (LIKELY(is_small_uniform(obj))) {
-        assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
-        OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
-        _synchronize_fragment((stm_char *)obj, obj_size);
-        return;
-    } else if (ignore_cards || 
!obj_should_use_cards(STM_SEGMENT->segment_base, obj)) {
-        /* else, a more complicated case for large objects, to copy
-           around data only within the needed pages */
-        _page_wise_synchronize_object_now(obj, obj_size);
-    } else {
-        /* ... or even only cards that need to be updated */
-        _card_wise_synchronize_object_now(obj, obj_size);
-    }
-}
-
 static void synchronize_objects_flush(void)
 {
     long j = STM_PSEGMENT->sq_len;
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -50,7 +50,7 @@
 enum /* card values in read markers */ {
     CARD_CLEAR = 0,                 /* card not used at all */
     CARD_MARKED = _STM_CARD_MARKED, /* card marked for tracing in the next gc 
*/
-    CARD_MARKED_OLD = _STM_CARD_MARKED+1,
+    /* CARD_MARKED_OLD = STM_PSEGMENT->transaction_read_version, */
     /* card was marked before, but cleared in a GC */
 };
 
@@ -246,7 +246,7 @@
 static stm_thread_local_t *abort_with_mutex_no_longjmp(void);
 static void abort_data_structures_from_segment_num(int segment_num);
 
-static void synchronize_object_enqueue(object_t *obj, bool ignore_cards);
+static void synchronize_object_enqueue(object_t *obj);
 static void synchronize_objects_flush(void);
 
 static void _signal_handler(int sig, siginfo_t *siginfo, void *context);
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -518,8 +518,9 @@
 
                 /* mark marked cards as old if it survives */
                 uint8_t mark_value = mark_visited_test(item) ?
-                    CARD_MARKED_OLD : CARD_CLEAR;
-                _reset_object_cards(pseg, item, mark_value, false);
+                    pseg->pub.transaction_read_version : CARD_CLEAR;
+                _reset_object_cards(pseg, item, mark_value, false,
+                                    mark_value == CARD_CLEAR);
             }));
         list_clear(lst);
 
@@ -531,7 +532,7 @@
             object_t *obj = (object_t *)list_item(lst, n);
             if (!mark_visited_test(obj)) {
                 if (obj_should_use_cards(pseg->pub.segment_base, obj))
-                    _reset_object_cards(pseg, obj, CARD_CLEAR, false);
+                    _reset_object_cards(pseg, obj, CARD_CLEAR, false, true);
                 list_set_item(lst, n, list_pop_item(lst));
             }
         }
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -118,6 +118,11 @@
     return cards[get_index_to_card_index(idx)].rm;
 }
 
+uint8_t _stm_get_transaction_read_version()
+{
+    return STM_SEGMENT->transaction_read_version;
+}
+
 
 
 static struct stm_commit_log_entry_s *_last_cl_entry;
diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c
--- a/c8/stm/nursery.c
+++ b/c8/stm/nursery.c
@@ -159,7 +159,8 @@
     uintptr_t last_card_index = get_index_to_card_index(size - 1); /* max 
valid index */
 
     while (card_index <= last_card_index) {
-        assert(cards[card_index].rm == CARD_CLEAR);
+        assert(cards[card_index].rm == CARD_CLEAR
+               || cards[card_index].rm < pseg->pub.transaction_read_version);
         card_index++;
     }
 
@@ -191,7 +192,7 @@
 
 static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
                                 object_t *obj, uint8_t mark_value,
-                                bool mark_all)
+                                bool mark_all, bool really_clear)
 {
 #pragma push_macro("STM_PSEGMENT")
 #pragma push_macro("STM_SEGMENT")
@@ -205,8 +206,12 @@
     stmcb_get_card_base_itemsize(realobj, offset_itemsize);
     size = (size - offset_itemsize[0]) / offset_itemsize[1];
 
+    /* really_clear only used for freed new objs in minor collections, as
+       they need to clear cards even if they are set to 
transaction_read_version */
+    assert(IMPLY(really_clear, mark_value == CARD_CLEAR && !mark_all));
     assert(IMPLY(mark_value == CARD_CLEAR, !mark_all)); /* not necessary */
-    assert(IMPLY(mark_all, mark_value == CARD_MARKED_OLD)); /* set *all* to 
OLD */
+    assert(IMPLY(mark_all,
+                 mark_value == pseg->pub.transaction_read_version)); /* set 
*all* to OLD */
 
     struct stm_read_marker_s *cards = get_read_marker(pseg->pub.segment_base, 
(uintptr_t)obj);
     uintptr_t card_index = 1;
@@ -216,7 +221,8 @@
                 obj, size, mark_value, mark_all));
        dprintf(("obj has %lu cards\n", last_card_index));*/
     while (card_index <= last_card_index) {
-        if (mark_all || cards[card_index].rm != CARD_CLEAR) {
+        if (mark_all || cards[card_index].rm == CARD_MARKED
+            || (really_clear && cards[card_index].rm != CARD_CLEAR)) {
             /* dprintf(("mark card %lu,wl:%lu of %p with %d\n", */
             /*          card_index, card_lock_idx, obj, mark_value)); */
             cards[card_index].rm = mark_value;
@@ -238,7 +244,6 @@
     assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
 
     dprintf(("_trace_card_object(%p)\n", obj));
-    uint8_t mark_value = CARD_MARKED_OLD;
 
     struct object_s *realobj = (struct object_s 
*)REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     size_t size = stmcb_size_rounded_up(realobj);
@@ -254,7 +259,7 @@
     while (card_index <= last_card_index) {
         if (cards[card_index].rm == CARD_MARKED) {
             /* clear or set to old: */
-            cards[card_index].rm = mark_value;
+            cards[card_index].rm = STM_SEGMENT->transaction_read_version;
 
             uintptr_t start = get_card_index_to_index(card_index);
             uintptr_t stop = get_card_index_to_index(card_index + 1);
@@ -340,7 +345,7 @@
             struct stm_priv_segment_info_s *pseg = 
get_priv_segment(STM_SEGMENT->segment_num);
             if (pseg->minor_collect_will_commit_now) {
                 acquire_privatization_lock(pseg->pub.segment_num);
-                synchronize_object_enqueue(obj, true); /* ignore cards! */
+                synchronize_object_enqueue(obj);
                 release_privatization_lock(pseg->pub.segment_num);
             } else {
                 LIST_APPEND(pseg->new_objects, obj);
diff --git a/c8/stm/nursery.h b/c8/stm/nursery.h
--- a/c8/stm/nursery.h
+++ b/c8/stm/nursery.h
@@ -5,7 +5,7 @@
 static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg, 
object_t *obj);
 static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
                                 object_t *obj, uint8_t mark_value,
-                                bool mark_all);
+                                bool mark_all, bool really_clear);
 
 static void minor_collection(bool commit);
 static void check_nursery_at_transaction_start(void);
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -77,7 +77,7 @@
 #define _STM_NSE_SIGNAL_ABORT             1
 #define _STM_NSE_SIGNAL_MAX               2
 
-#define _STM_CARD_MARKED 1
+#define _STM_CARD_MARKED 1      /* should always be 1... */
 #define _STM_GCFLAG_CARDS_SET          0x8
 #define _STM_CARD_SIZE                 32     /* must be >= 32 */
 #define _STM_MIN_CARD_COUNT            17
@@ -94,6 +94,7 @@
 char *_stm_real_address(object_t *o);
 #ifdef STM_TESTS
 #include <stdbool.h>
+uint8_t _stm_get_transaction_read_version();
 uint8_t _stm_get_card_value(object_t *obj, long idx);
 bool _stm_was_read(object_t *obj);
 bool _stm_was_written(object_t *obj);
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -48,6 +48,7 @@
 /*void stm_write_card(); use _checked_stm_write_card() instead */
 
 uint8_t _stm_get_card_value(object_t *obj, long idx);
+uint8_t _stm_get_transaction_read_version();
 
 void stm_setup(void);
 void stm_teardown(void);
@@ -401,7 +402,7 @@
 CARD_SIZE = lib._STM_CARD_SIZE # 16b at least
 CARD_CLEAR = 0
 CARD_MARKED = lib._STM_CARD_MARKED
-CARD_MARKED_OLD = CARD_MARKED + 1
+CARD_MARKED_OLD = lib._stm_get_transaction_read_version
 
 
 class Conflict(Exception):
diff --git a/c8/test/test_card_marking.py b/c8/test/test_card_marking.py
--- a/c8/test/test_card_marking.py
+++ b/c8/test/test_card_marking.py
@@ -235,7 +235,7 @@
         assert o in old_objects_with_cards_set()
 
         stm_minor_collect()
-        assert get_card_value(o, 1000) == CARD_MARKED_OLD
+        assert get_card_value(o, 1000) == CARD_MARKED_OLD()
         self.commit_transaction()
 
         self.start_transaction()
@@ -288,3 +288,43 @@
         assert o not in old_objects_with_cards_set()
 
         self.commit_transaction()
+
+    def test_clear_cards4(self):
+        self.start_transaction()
+        o = stm_allocate(1000+20*CARD_SIZE)
+        p = stm_allocate(1000+20*CARD_SIZE)
+        assert get_card_value(o, 1000) == CARD_CLEAR
+        assert get_card_value(p, 1000) == CARD_CLEAR
+
+        self.push_root(o)
+        self.push_root(p)
+        stm_minor_collect()
+        p = self.pop_root()
+        o = self.pop_root()
+
+        assert get_card_value(o, 1000) == CARD_CLEAR
+        assert get_card_value(p, 1000) == CARD_CLEAR
+        stm_set_char(o, 'b', 1000, True)
+        stm_set_char(p, 'b', 1000, True)
+        assert get_card_value(o, 1000) == CARD_MARKED
+        assert get_card_value(p, 1000) == CARD_MARKED
+
+        self.push_root(o)
+        stm_minor_collect()
+        o = self.pop_root()
+
+        assert get_card_value(o, 1000) == CARD_MARKED_OLD()
+        assert get_card_value(p, 1000) == CARD_CLEAR
+
+        self.push_root(o)
+        self.commit_transaction()
+
+        self.start_transaction()
+        o = self.pop_root()
+
+        assert get_card_value(o, 1000) != CARD_CLEAR
+        assert get_card_value(o, 1000) < CARD_MARKED_OLD()
+        stm_set_char(o, 'b', 1000, True)
+        assert get_card_value(o, 1000) == CARD_MARKED
+
+        self.commit_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to