Author: Remi Meier <[email protected]>
Branch: card-marking
Changeset: r1225:4ccf9352f725
Date: 2014-05-21 18:33 +0200
http://bitbucket.org/pypy/stmgc/changeset/4ccf9352f725/

Log:    horrible conversion to 3-state cards (cards get reset too often and
        it's generally messy)

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -43,7 +43,18 @@
 static void _stm_mark_card(object_t *obj, uintptr_t card_index)
 {
     assert(card_index > 0);
-    dprintf(("mark %p card %lu\n", obj, card_index));
+
+    assert(obj->stm_flags & GCFLAG_HAS_CARDS);
+    assert(!(obj->stm_flags & GCFLAG_SMALL_UNIFORM)); /* not supported/tested 
*/
+#ifndef NDEBUG
+    struct object_s *realobj = (struct object_s *)
+        REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+    size_t size = stmcb_size_rounded_up(realobj);
+    assert(size >= 32);
+    /* we need at least one lock in addition to the STM-reserved object 
write-lock */
+#endif
+
+    dprintf(("mark %p card %lu with %d\n", obj, card_index, CARD_MARKED));
 
     if (!(obj->stm_flags & GCFLAG_CARDS_SET)) {
         /* not yet in the list */
@@ -60,19 +71,18 @@
        We already own the object here or it is an overflow obj. */
     uintptr_t card_lock_idx = get_write_lock_idx((uintptr_t)obj) + card_index;
 
-    assert(write_locks[card_lock_idx] == 0
-           || write_locks[card_lock_idx] == STM_PSEGMENT->write_lock_num);
+    assert(write_locks[get_write_lock_idx((uintptr_t)obj)] == 0 /* overflow 
obj */
+           || write_locks[get_write_lock_idx((uintptr_t)obj)] == 
STM_PSEGMENT->write_lock_num);
     assert(get_write_lock_idx((uintptr_t)obj) != card_lock_idx);
 
-    if (!write_locks[card_lock_idx])
-        write_locks[card_lock_idx] = STM_PSEGMENT->write_lock_num;
+    if (write_locks[card_lock_idx] != CARD_MARKED)
+        write_locks[card_lock_idx] = CARD_MARKED;
 }
 
 static bool _stm_write_slowpath_overflow_objs(object_t *obj, uintptr_t 
card_index)
 {
     /* is this an object from the same transaction, outside the nursery? */
-    if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0)
-        == STM_PSEGMENT->overflow_number) {
+    if (IS_OVERFLOW_OBJ(STM_PSEGMENT, obj)) {
 
         assert(STM_PSEGMENT->objects_pointing_to_nursery != NULL);
         dprintf_test(("write_slowpath %p -> ovf obj_to_nurs\n", obj));
@@ -542,6 +552,7 @@
     STM_PSEGMENT->marker_inev[1] = 0;
 
     /* reset these lists to NULL for the next transaction */
+    
_verify_cards_cleared_in_all_lists(get_priv_segment(STM_SEGMENT->segment_num));
     LIST_FREE(STM_PSEGMENT->objects_pointing_to_nursery);
     LIST_FREE(STM_PSEGMENT->old_objects_with_cards);
     LIST_FREE(STM_PSEGMENT->large_overflow_objects);
@@ -681,6 +692,10 @@
 
 static void abort_data_structures_from_segment_num(int segment_num)
 {
+#pragma push_macro("STM_PSEGMENT")
+#pragma push_macro("STM_SEGMENT")
+#undef STM_PSEGMENT
+#undef STM_SEGMENT
     /* This function clears the content of the given segment undergoing
        an abort.  It is called from abort_with_mutex(), but also sometimes
        from other threads that figure out that this segment should abort.
@@ -725,6 +740,8 @@
     LIST_FREE(pseg->old_objects_with_cards);
     LIST_FREE(pseg->large_overflow_objects);
     list_clear(pseg->young_weakrefs);
+#pragma pop_macro("STM_SEGMENT")
+#pragma pop_macro("STM_PSEGMENT")
 }
 
 static void abort_with_mutex(void)
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -223,9 +223,19 @@
 
 static uint8_t write_locks[WRITELOCK_END - WRITELOCK_START];
 
+enum /* card values for write_locks */ {
+    CARD_CLEAR = 0,             /* card not used at all */
+    CARD_MARKED = 100,            /* card marked for tracing in the next gc */
+    CARD_MARKED_OLD = 101,        /* card was marked before, but cleared
+                                     in a GC */
+};
+
 
 #define REAL_ADDRESS(segment_base, src)   ((segment_base) + (uintptr_t)(src))
 
+#define IS_OVERFLOW_OBJ(pseg, obj) ((obj->stm_flags & 
-GCFLAG_OVERFLOW_NUMBER_bit0) \
+                                    == pseg->overflow_number)
+
 static inline uintptr_t get_card_index(uintptr_t byte_offset) {
     assert(_STM_CARD_SIZE == 32);
     return (byte_offset >> 5) + 1;
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -440,6 +440,11 @@
 
 static void clean_up_segment_lists(void)
 {
+#pragma push_macro("STM_PSEGMENT")
+#pragma push_macro("STM_SEGMENT")
+#undef STM_PSEGMENT
+#undef STM_SEGMENT
+
     long i;
     for (i = 1; i <= NB_SEGMENTS; i++) {
         struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
@@ -455,15 +460,28 @@
         */
         lst = pseg->objects_pointing_to_nursery;
         if (lst != NULL) {
-            LIST_FOREACH_R(lst, uintptr_t /*item*/,
+            LIST_FOREACH_R(lst, object_t* /*item*/,
                 ({
                     struct object_s *realobj = (struct object_s *)
-                        REAL_ADDRESS(pseg->pub.segment_base, item);
+                        REAL_ADDRESS(pseg->pub.segment_base, (uintptr_t)item);
 
                     assert(!(realobj->stm_flags & GCFLAG_WRITE_BARRIER));
                     OPT_ASSERT(!(realobj->stm_flags & GCFLAG_CARDS_SET));
 
                     realobj->stm_flags |= GCFLAG_WRITE_BARRIER;
+                    /* XXX: this will be necessary when only synchronising 
cards */
+
+                    if (realobj->stm_flags & GCFLAG_HAS_CARDS) {
+                        /* We called a normal WB on these objs. If we wrote
+                           a value to some place in them, we need to
+                           synchronise the whole object on commit */
+                        if (IS_OVERFLOW_OBJ(pseg, realobj)) {
+                            /* we do not need the old cards for overflow 
objects */
+                            _reset_object_cards(pseg, item, CARD_CLEAR, false);
+                        } else {
+                            _reset_object_cards(pseg, item, CARD_MARKED_OLD, 
true); /* mark all */
+                        }
+                    }
                 }));
             list_clear(lst);
 
@@ -473,19 +491,19 @@
                     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);
+                    OPT_ASSERT(realobj->stm_flags & GCFLAG_WRITE_BARRIER);
+
+                    /* XXX: this will be necessary when only synchronising 
cards */
+                    uint8_t mark_value = IS_OVERFLOW_OBJ(pseg, realobj) ?
+                        CARD_CLEAR : CARD_MARKED_OLD;
+                    _reset_object_cards(pseg, item, mark_value, false);
                 }));
             list_clear(lst);
+
         } else {
-            LIST_FOREACH_R(pseg->modified_old_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) {
-                       _reset_object_cards(&pseg->pub, item);
-                   }
-               });
+            /* if here MINOR_NOTHING_TO_DO() was true before, it's like
+               we "didn't do a collection" at all. So nothing to do on
+               modified_old_objs. */
         }
 
         /* Remove from 'large_overflow_objects' all objects that die */
@@ -500,6 +518,8 @@
             }
         }
     }
+#pragma pop_macro("STM_SEGMENT")
+#pragma pop_macro("STM_PSEGMENT")
 }
 
 static inline bool largemalloc_keep_object_at(char *data)
@@ -513,6 +533,17 @@
     _stm_largemalloc_sweep();
 }
 
+static void assert_cleared_locks(size_t n)
+{
+#ifndef NDEBUG
+    size_t i;
+    uint8_t *s = write_locks;
+    for (i = 0; i < n; i++)
+        assert(s[i] == CARD_CLEAR || s[i] == CARD_MARKED
+               || s[i] == CARD_MARKED_OLD);
+#endif
+}
+
 static void clean_write_locks(void)
 {
     /* the write_locks array, containing the visit marker during
@@ -522,7 +553,7 @@
     object_t *loc2 = (object_t *)(uninitialized_page_stop - stm_object_pages);
     uintptr_t lock2_idx = mark_loc(loc2 - 1) + 1;
 
-    assert_memset_zero(write_locks, lock2_idx);
+    assert_cleared_locks(lock2_idx);
     memset(write_locks + lock2_idx, 0, sizeof(write_locks) - lock2_idx);
 }
 
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -183,30 +183,96 @@
     minor_trace_if_young(&tl->thread_local_obj);
 }
 
-static void _reset_object_cards(struct stm_segment_info_s *seg, object_t *obj)
+static void _cards_cleared_in_object(struct stm_priv_segment_info_s *pseg, 
object_t *obj)
+{
+#ifndef NDEBUG
+    struct object_s *realobj = (struct object_s 
*)REAL_ADDRESS(pseg->pub.segment_base, obj);
+    size_t size = stmcb_size_rounded_up(realobj);
+
+    if (!(realobj->stm_flags & GCFLAG_HAS_CARDS))
+        return;
+
+    uintptr_t first_card_index = get_write_lock_idx((uintptr_t)obj);
+    uintptr_t card_index = 1;
+    uintptr_t last_card_index = get_card_index(size - 1);
+
+    OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS_MAX
+               || write_locks[first_card_index] == 255); /* see gcpage.c */
+    while (card_index <= last_card_index) {
+        uintptr_t card_lock_idx = first_card_index + card_index;
+        assert(write_locks[card_lock_idx] == CARD_CLEAR);
+        card_index++;
+    }
+
+    assert(!(realobj->stm_flags & GCFLAG_CARDS_SET));
+#endif
+}
+
+static void _verify_cards_cleared_in_all_lists(struct stm_priv_segment_info_s 
*pseg)
+{
+#ifndef NDEBUG
+    LIST_FOREACH_R(
+        pseg->modified_old_objects, object_t * /*item*/,
+        _cards_cleared_in_object(pseg, item));
+
+    if (pseg->large_overflow_objects) {
+        LIST_FOREACH_R(
+            pseg->large_overflow_objects, object_t * /*item*/,
+            _cards_cleared_in_object(pseg, item));
+    }
+    if (pseg->objects_pointing_to_nursery) {
+        LIST_FOREACH_R(
+            pseg->objects_pointing_to_nursery, object_t * /*item*/,
+            _cards_cleared_in_object(pseg, item));
+    }
+    if (pseg->old_objects_with_cards) {
+        LIST_FOREACH_R(
+            pseg->old_objects_with_cards, object_t * /*item*/,
+            _cards_cleared_in_object(pseg, item));
+    }
+#endif
+}
+
+static void _reset_object_cards(struct stm_priv_segment_info_s *pseg,
+                                object_t *obj, uint8_t mark_value,
+                                bool mark_all)
 {
 #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);
+    struct object_s *realobj = (struct object_s 
*)REAL_ADDRESS(pseg->pub.segment_base, obj);
     size_t size = stmcb_size_rounded_up(realobj);
 
+    OPT_ASSERT(size >= 32);
+    assert(realobj->stm_flags & GCFLAG_HAS_CARDS);
+    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(IS_OVERFLOW_OBJ(pseg, realobj),
+                 mark_value == CARD_CLEAR)); /* overflows are always CLEARed */
+
     uintptr_t first_card_index = get_write_lock_idx((uintptr_t)obj);
     uintptr_t card_index = 1;
     uintptr_t last_card_index = get_card_index(size - 1);
 
+    dprintf(("mark cards of %p, size %lu with %d\n", obj, size, mark_value));
+
+    OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS
+               || write_locks[first_card_index] == 255); /* see gcpage.c */
     while (card_index <= last_card_index) {
-        #ifndef NDEBUG
-        if (write_locks[first_card_index + card_index])
-            dprintf(("cleared card %lu on %p\n", card_index, obj));
-        #endif
-        write_locks[first_card_index + card_index] = 0;
+        uintptr_t card_lock_idx = first_card_index + card_index;
+
+        if (mark_all || write_locks[card_lock_idx] != CARD_CLEAR) {
+            /* dprintf(("mark card %lu,wl:%lu of %p with %d\n", */
+            /*          card_index, card_lock_idx, obj, mark_value)); */
+            write_locks[card_lock_idx] = mark_value;
+        }
         card_index++;
     }
+    OPT_ASSERT(write_locks[first_card_index] <= NB_SEGMENTS
+               || write_locks[first_card_index] == 255); /* see gcpage.c */
 
     realobj->stm_flags &= ~GCFLAG_CARDS_SET;
-    dprintf(("reset cards on %p\n", obj));
 #pragma pop_macro("STM_SEGMENT")
 #pragma pop_macro("STM_PSEGMENT")
 }
@@ -218,11 +284,10 @@
        also gives the obj-base */
     assert(_card_base_obj);
     uintptr_t base_lock_idx = get_write_lock_idx((uintptr_t)_card_base_obj);
-    uintptr_t card_lock_idx = base_lock_idx;
-    card_lock_idx += get_card_index(
+    uintptr_t card_lock_idx = base_lock_idx + get_card_index(
         (uintptr_t)((char*)pobj - STM_SEGMENT->segment_base) - 
(uintptr_t)_card_base_obj);
 
-    if (write_locks[card_lock_idx]) {
+    if (write_locks[card_lock_idx] == CARD_MARKED) {
         dprintf(("minor_trace_if_young_cards: trace %p\n", *pobj));
         minor_trace_if_young(pobj);
     }
@@ -234,13 +299,17 @@
     _card_base_obj = obj;
     assert(!_is_in_nursery(obj));
     assert(obj->stm_flags & GCFLAG_CARDS_SET);
+    assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
 
     dprintf(("_trace_card_object(%p)\n", obj));
 
     char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
     stmcb_trace((struct object_s *)realobj, &minor_trace_if_young_cards);
 
-    _reset_object_cards(get_segment(STM_SEGMENT->segment_num), obj);
+    bool obj_is_overflow = IS_OVERFLOW_OBJ(STM_PSEGMENT, obj);
+    uint8_t mark_value = obj_is_overflow ? CARD_CLEAR : CARD_MARKED_OLD;
+    _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+                        obj, mark_value, false); /* mark marked */
 }
 
 
@@ -259,8 +328,15 @@
         stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
 
         obj->stm_flags |= GCFLAG_WRITE_BARRIER;
-        if (obj->stm_flags & GCFLAG_CARDS_SET) {
-            _reset_object_cards(get_segment(STM_SEGMENT->segment_num), obj);
+        if (obj->stm_flags & GCFLAG_HAS_CARDS) {
+            if (IS_OVERFLOW_OBJ(STM_PSEGMENT, obj)) {
+                /* we do not need the old cards for overflow objects */
+                _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+                                    obj, CARD_CLEAR, false);
+            } else {
+                _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
+                                    obj, CARD_MARKED_OLD, true); /* mark all */
+            }
         }
     } if (obj->stm_flags & GCFLAG_CARDS_SET) {
         _trace_card_object(obj);
@@ -298,13 +374,18 @@
                WRITE_BARRIER flag and traced into it to fix its
                content); or add the object to 'large_overflow_objects'.
             */
+            struct stm_priv_segment_info_s *pseg = 
get_priv_segment(STM_SEGMENT->segment_num);
             if (STM_PSEGMENT->minor_collect_will_commit_now) {
                 acquire_privatization_lock();
                 synchronize_object_now(obj);
                 release_privatization_lock();
+                if (obj->stm_flags & GCFLAG_HAS_CARDS) {
+                    _reset_object_cards(pseg, obj, CARD_CLEAR, false); /* was 
young */
+                }
             } else {
                 LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj);
             }
+            _cards_cleared_in_object(pseg, obj);
         }
 
         /* the list could have moved while appending */
@@ -368,7 +449,15 @@
         wlog_t *item;
 
         TREE_LOOP_FORWARD(*pseg->young_outside_nursery, item) {
-            assert(!_is_in_nursery((object_t *)item->addr));
+            object_t *obj = (object_t*)item->addr;
+            struct object_s *realobj = (struct object_s *)
+                REAL_ADDRESS(pseg->pub.segment_base, item->addr);
+
+            assert(!_is_in_nursery(obj));
+            if (realobj->stm_flags & GCFLAG_HAS_CARDS)
+                _reset_object_cards(pseg, obj, CARD_CLEAR, false);
+            _cards_cleared_in_object(pseg, obj);
+
             _stm_large_free(stm_object_pages + item->addr);
         } TREE_LOOP_END;
 
@@ -377,21 +466,37 @@
 
     tree_clear(pseg->nursery_objects_shadows);
 
-    if (pseg->old_objects_with_cards) {
-        LIST_FOREACH_R(pseg->old_objects_with_cards, object_t * /*item*/,
-                       _reset_object_cards(&pseg->pub, item));
-    } else {
-        LIST_FOREACH_R(pseg->modified_old_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) {
-                   _reset_object_cards(&pseg->pub, item);
-               }
-           });
+    /* nearly all objs in old_objects_with_cards are also in 
modified_old_objects,
+       so we don't need to go through both lists: */
+    LIST_FOREACH_R(pseg->modified_old_objects, object_t * /*item*/,
+        {
+            struct object_s *realobj = (struct object_s *)
+                REAL_ADDRESS(pseg->pub.segment_base, item);
+
+            if (realobj->stm_flags & GCFLAG_HAS_CARDS) {
+                /* clear all possibly used cards in this transaction */
+                _reset_object_cards(pseg, item, CARD_CLEAR, false);
+            }
+        });
+    /* overflow objects with cards are not in modified_old_objects */
+    if (pseg->large_overflow_objects != NULL) {
+        /* some overflow objects may have cards, clear them too */
+        LIST_FOREACH_R(pseg->large_overflow_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 */
+                    _reset_object_cards(pseg, item, CARD_CLEAR, false);
+                }
+            });
     }
 
+    _verify_cards_cleared_in_all_lists(pseg);
+
     return nursery_used;
 #pragma pop_macro("STM_SEGMENT")
 #pragma pop_macro("STM_PSEGMENT")
diff --git a/c7/stm/nursery.h b/c7/stm/nursery.h
--- a/c7/stm/nursery.h
+++ b/c7/stm/nursery.h
@@ -6,7 +6,9 @@
 
 static uint32_t highest_overflow_number;
 
-static void _reset_object_cards(struct stm_segment_info_s *seg, 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);
 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/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -271,7 +271,9 @@
 /* directly after allocation one can enable card marking for any
    kind of object with stm_use_cards(obj). This enables the use
    of stm_write/read_card() barriers that do more fine-grained
-   conflict detection and garbage collection. */
+   conflict detection and garbage collection.
+   These objects need to be at least 32bytes in size!
+*/
 __attribute__((always_inline))
 static inline void stm_use_cards(object_t* o)
 {
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
@@ -227,14 +227,19 @@
         self.root_numbering = 0
         self.ref_type_map = {}
         self.root_sizes = {}
+        self.with_cards = {}
 
-    def get_new_root_name(self, is_ref_type, size):
+    def get_new_root_name(self, is_ref_type, size, with_cards):
         self.root_numbering += 1
         r = "lp_%s_%d" % ("ref" if is_ref_type else "char", 
self.root_numbering)
         self.ref_type_map[r] = is_ref_type
         self.root_sizes[r] = size
+        self.with_cards[r] = with_cards
         return r
 
+    def has_cards(self, r):
+        return self.with_cards[r]
+
     def has_ref_type(self, r):
         return self.ref_type_map[r]
 
@@ -363,10 +368,11 @@
         #"SOME_MEDIUM_SIZE+16",
         #"SOME_LARGE_SIZE+16",
     ])
-    r = global_state.get_new_root_name(False, size)
+    with_cards = int(size) >= 32
+    r = global_state.get_new_root_name(False, size, with_cards)
     thread_state.push_roots(ex)
 
-    ex.do('%s = stm_allocate(%s)' % (r, size))
+    ex.do('%s = stm_allocate(%s, %s)' % (r, size, bool(with_cards)))
     ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
     thread_state.transaction_state.add_root(r, 0, True)
 
@@ -376,9 +382,10 @@
 
 def op_allocate_ref(ex, global_state, thread_state):
     num = str(global_state.rnd.randrange(1, 100))
-    r = global_state.get_new_root_name(True, num)
+    with_cards = int(num) >= 4
+    r = global_state.get_new_root_name(True, num, with_cards)
     thread_state.push_roots(ex)
-    ex.do('%s = stm_allocate_refs(%s, True)' % (r, num))
+    ex.do('%s = stm_allocate_refs(%s, %s)' % (r, num, bool(with_cards)))
     ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
     thread_state.transaction_state.add_root(r, "ffi.NULL", True)
 
@@ -410,6 +417,7 @@
     r = thread_state.get_random_root()
     trs = thread_state.transaction_state
     is_ref = global_state.has_ref_type(r)
+    has_cards = global_state.has_cards(r)
     #
     # check for possible write-write conflict:
     was_written = False
@@ -438,13 +446,13 @@
         thread_state.abort_transaction()
     offset = global_state.get_root_size(r) + " - 1"
     if is_ref:
-        ex.do(raising_call(aborts, "stm_set_ref", r, offset, v, "True"))
+        ex.do(raising_call(aborts, "stm_set_ref", r, offset, v, has_cards))
         if not aborts:
-            ex.do(raising_call(False, "stm_set_ref", r, "0", v, "True"))
+            ex.do(raising_call(False, "stm_set_ref", r, "0", v, has_cards))
     else:
-        ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset))
+        ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset, 
has_cards))
         if not aborts:
-            ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR"))
+            ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR", 
has_cards))
 
 def op_read(ex, global_state, thread_state):
     r = thread_state.get_random_root()
@@ -556,12 +564,12 @@
         curr_thread = global_state.thread_states[0]
 
         for i in range(N_OBJECTS):
-            r = global_state.get_new_root_name(False, "384")
-            ex.do('%s = stm_allocate_old(384)' % r)
+            r = global_state.get_new_root_name(False, "384", True)
+            ex.do('%s = stm_allocate_old(384, True)' % r)
             global_state.committed_transaction_state.add_root(r, 0, False)
             global_state.prebuilt_roots.append(r)
 
-            r = global_state.get_new_root_name(True, "50")
+            r = global_state.get_new_root_name(True, "50", True)
             ex.do('%s = stm_allocate_old_refs(50, True)' % r)
             global_state.committed_transaction_state.add_root(r, "ffi.NULL", 
False)
             global_state.prebuilt_roots.append(r)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to