[pypy-commit] stmgc c8-card-marking: progress

Raemi noreply at buildbot.pypy.org
Thu Feb 26 21:46:49 CET 2015


Author: Remi Meier <remi.meier at gmail.com>
Branch: c8-card-marking
Changeset: r1672:023ed269165f
Date: 2015-02-26 21:22 +0100
http://bitbucket.org/pypy/stmgc/changeset/023ed269165f/

Log:	progress

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -445,6 +445,7 @@
 }
 
 
+static void reset_cards_from_modified_objects(void);
 static void reset_wb_executed_flags(void);
 static void readd_wb_executed_flags(void);
 static void check_all_write_barrier_flags(char *segbase, struct list_s *list);
@@ -527,6 +528,8 @@
         STM_PSEGMENT->transaction_state = TS_NONE;
         STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
 
+        reset_cards_from_modified_objects();
+
         list_clear(STM_PSEGMENT->modified_old_objects);
         STM_PSEGMENT->last_commit_log_entry = new;
         release_modification_lock(STM_SEGMENT->segment_num);
@@ -553,6 +556,8 @@
         check_all_write_barrier_flags(STM_SEGMENT->segment_base,
                                       STM_PSEGMENT->modified_old_objects);
 
+        reset_cards_from_modified_objects();
+
         /* compare with _validate_and_attach: */
         STM_PSEGMENT->transaction_state = TS_NONE;
         STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
@@ -576,10 +581,13 @@
 }
 
 
-static bool obj_should_use_cards(object_t *obj)
+static bool obj_should_use_cards(char *seg_base, object_t *obj)
 {
+    if (is_small_uniform(obj))
+        return false;
+
     struct object_s *realobj = (struct object_s *)
-        REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+        REAL_ADDRESS(seg_base, obj);
     long supports = stmcb_obj_supports_cards(realobj);
     if (!supports)
         return false;
@@ -750,7 +758,7 @@
 {
     /* the PyPy JIT calls this function directly if it finds that an
        array doesn't have the GCFLAG_CARDS_SET */
-    bool mark_card = obj_should_use_cards(obj);
+    bool mark_card = obj_should_use_cards(STM_SEGMENT->segment_base, obj);
     write_slowpath_common(obj, mark_card);
     return mark_card;
 }
@@ -835,6 +843,20 @@
     STM_SEGMENT->transaction_read_version = 1;
 }
 
+static void reset_cards_from_modified_objects(void)
+{
+    struct list_s *list = STM_PSEGMENT->modified_old_objects;
+    struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
+    struct stm_undo_s *end = (struct stm_undo_s *)(list->items + list->count);
+
+    for (; undo < end; undo++) {
+        object_t *obj = undo->object;
+        if (obj_should_use_cards(STM_SEGMENT->segment_base, obj))
+            _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+                                obj, CARD_CLEAR, false);
+    }
+}
+
 static void reset_wb_executed_flags(void)
 {
     dprintf(("reset_wb_executed_flags()\n"));
@@ -984,9 +1006,9 @@
     LIST_FOREACH_R(STM_PSEGMENT->new_objects, object_t *,
         ({
             assert(item->stm_flags & GCFLAG_WB_EXECUTED);
-            _cards_cleared_in_object(pseg, item); /* check for C8 */
-
             item->stm_flags &= ~GCFLAG_WB_EXECUTED;
+            if (obj_should_use_cards(pseg->pub.segment_base, item))
+                _reset_object_cards(pseg, item, CARD_CLEAR, false);
             synchronize_object_enqueue(item, true);
         }));
     synchronize_objects_flush();
@@ -1020,7 +1042,6 @@
     bool was_inev = STM_PSEGMENT->transaction_state == TS_INEVITABLE;
     _validate_and_add_to_commit_log();
 
-
     /* XXX do we still need a s_mutex_lock() section here? */
     s_mutex_lock();
 
@@ -1081,7 +1102,7 @@
                undo->backup,
                SLICE_SIZE(undo->slice));
 
-        if (obj_should_use_cards(obj))
+        if (obj_should_use_cards(pseg->pub.segment_base, obj))
             _reset_object_cards(pseg, obj, CARD_CLEAR, false);
         /* XXXXXXXXX: only reset cards of slice!! ^^^^^^^ */
 
@@ -1124,14 +1145,8 @@
     /* some new objects may have cards when aborting, clear them too */
     LIST_FOREACH_R(pseg->new_objects, object_t * /*item*/,
         {
-            struct object_s *realobj = (struct object_s *)
-                REAL_ADDRESS(pseg->pub.segment_base, item);
-
-            if (realobj->stm_flags & GCFLAG_CARDS_SET) {
-                /* CARDS_SET is enough since other HAS_CARDS objs
-                   are already cleared */
+            if (obj_should_use_cards(pseg->pub.segment_base, item))
                 _reset_object_cards(pseg, item, CARD_CLEAR, false);
-            }
         });
 
     acquire_modification_lock(segment_num);
@@ -1318,7 +1333,7 @@
 static void _card_wise_synchronize_object_now(object_t *obj, ssize_t obj_size)
 {
     assert(obj_size >= 32);
-    assert(obj_should_use_cards(obj));
+    assert(obj_should_use_cards(STM_SEGMENT->segment_base, obj));
     assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
 
     uintptr_t offset_itemsize[2];
@@ -1434,7 +1449,7 @@
         OPT_ASSERT(obj_size <= GC_LAST_SMALL_SIZE);
         _synchronize_fragment((stm_char *)obj, obj_size);
         return;
-    } else if (ignore_cards || !obj_should_use_cards(obj)) {
+    } 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);
diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -111,6 +111,15 @@
 }
 
 
+uint8_t _stm_get_card_value(object_t *obj, long idx)
+{
+    struct stm_read_marker_s *cards = get_read_marker(STM_SEGMENT->segment_base,
+                                                      (uintptr_t)obj);
+    return cards[get_index_to_card_index(idx)].rm;
+}
+
+
+
 static struct stm_commit_log_entry_s *_last_cl_entry;
 static long _last_cl_entry_index;
 void _stm_start_enum_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
@@ -250,8 +250,6 @@
     uintptr_t card_index = 1;
     uintptr_t last_card_index = get_index_to_card_index(size - 1); /* max valid index */
 
-    assert(cards->rm == STM_SEGMENT->transaction_read_version); /* stm_read() */
-
     /* XXX: merge ranges */
     while (card_index <= last_card_index) {
         if (cards[card_index].rm == CARD_MARKED) {
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -94,6 +94,7 @@
 char *_stm_real_address(object_t *o);
 #ifdef STM_TESTS
 #include <stdbool.h>
+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);
 bool _stm_was_written_card(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
@@ -11,6 +11,7 @@
 #define _STM_GCFLAG_WRITE_BARRIER ...
 #define _STM_FAST_ALLOC ...
 #define _STM_CARD_SIZE ...
+#define _STM_CARD_MARKED ...
 
 typedef struct {
 ...;
@@ -46,6 +47,8 @@
 
 /*void stm_write_card(); use _checked_stm_write_card() instead */
 
+uint8_t _stm_get_card_value(object_t *obj, long idx);
+
 void stm_setup(void);
 void stm_teardown(void);
 void stm_register_thread_local(stm_thread_local_t *tl);
@@ -396,6 +399,10 @@
 NB_SEGMENTS = lib.STM_NB_SEGMENTS
 FAST_ALLOC = lib._STM_FAST_ALLOC
 CARD_SIZE = lib._STM_CARD_SIZE # 16b at least
+CARD_CLEAR = 0
+CARD_MARKED = lib._STM_CARD_MARKED
+CARD_MARKED_OLD = CARD_MARKED + 1
+
 
 class Conflict(Exception):
     pass
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
@@ -2,6 +2,8 @@
 import py
 
 
+get_card_value = lib._stm_get_card_value
+
 class TestBasic(BaseTest):
 
     def _collect(self, kind):
@@ -221,3 +223,24 @@
         assert stm_get_char(o, 1000+CARD_SIZE*12) == 'e'
 
         self.commit_transaction()
+
+
+    def test_clear_cards(self):
+        o = stm_allocate_old(1000+20*CARD_SIZE)
+
+        self.start_transaction()
+        assert get_card_value(o, 1000) == CARD_CLEAR
+        stm_set_char(o, 'a', 1000, True)
+        assert get_card_value(o, 1000) == CARD_MARKED
+        assert o in old_objects_with_cards_set()
+
+        stm_minor_collect()
+        assert get_card_value(o, 1000) == CARD_MARKED_OLD
+        self.commit_transaction()
+
+        self.start_transaction()
+        assert get_card_value(o, 1000) == CARD_CLEAR
+        stm_set_char(o, 'b', 1000, True)
+        assert get_card_value(o, 1000) == CARD_MARKED
+        assert o in old_objects_with_cards_set()
+        self.commit_transaction()
diff --git a/c8/test/test_random.py b/c8/test/test_random.py
--- a/c8/test/test_random.py
+++ b/c8/test/test_random.py
@@ -428,7 +428,7 @@
     r = thread_state.get_random_root()
     trs = thread_state.transaction_state
     is_ref = global_state.has_ref_type(r)
-    try_cards = global_state.rnd.randrange(1, 100) > 5 and False
+    try_cards = global_state.rnd.randrange(1, 100) > 5 # and False
     #
     # decide on a value to write
     if is_ref:


More information about the pypy-commit mailing list