Author: Remi Meier <[email protected]>
Branch: card-marking
Changeset: r1232:10b45dc9310d
Date: 2014-05-22 16:24 +0200
http://bitbucket.org/pypy/stmgc/changeset/10b45dc9310d/

Log:    change of API; like in pypy CARDS are done internally

diff --git a/c7/stm/contention.c b/c7/stm/contention.c
--- a/c7/stm/contention.c
+++ b/c7/stm/contention.c
@@ -194,7 +194,7 @@
         /* tell the other to commit ASAP, since it causes aborts */
         signal_other_to_commit_soon(contmgr.other_pseg);
 
-        dprintf(("abort in contention\n"));
+        dprintf(("abort in contention: kind %d\n", kind));
         STM_SEGMENT->nursery_end = abort_category;
         marker_contention(kind, false, other_segment_num, obj);
         abort_with_mutex();
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -83,7 +83,6 @@
 {
     /* is this an object from the same transaction, outside the nursery? */
     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));
 
@@ -106,17 +105,23 @@
     return false;
 }
 
-void _stm_write_slowpath(object_t *obj, uintptr_t card_index)
+void _stm_write_slowpath(object_t *obj)
 {
-    assert(IMPLY(!(obj->stm_flags & GCFLAG_HAS_CARDS), card_index == 0));
-    assert(
-        IMPLY(card_index, (card_index - 1) * CARD_SIZE < stmcb_size_rounded_up(
-                  (struct object_s*)REAL_ADDRESS(STM_SEGMENT->segment_base,
-                                                 obj))));
+    _stm_write_slowpath_card(obj, 0);
+}
+
+void _stm_write_slowpath_card(object_t *obj, uintptr_t card_index)
+{
     assert(_seems_to_be_running_transaction());
     assert(!_is_young(obj));
     assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
 
+    if (!(obj->stm_flags & GCFLAG_HAS_CARDS))
+        card_index = 0;         /* assume no cards */
+
+    assert(IMPLY(card_index, (card_index - 1) * CARD_SIZE < 
stmcb_size_rounded_up(
+                (struct object_s*)REAL_ADDRESS(STM_SEGMENT->segment_base, 
obj))));
+
     if (_stm_write_slowpath_overflow_objs(obj, card_index))
         return;
 
@@ -353,6 +358,8 @@
             ({
                 if (was_read_remote(remote_base, item, remote_version)) {
                     /* A write-read conflict! */
+                    dprintf(("write-read conflict on %p, our seg: %d, other: 
%ld\n",
+                             item, STM_SEGMENT->segment_num, i));
                     if (write_read_contention_management(i, item)) {
                         /* If we reach this point, we didn't abort, but we
                            had to wait for the other thread to commit.  If we
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -119,6 +119,8 @@
 
     object_t *o = (object_t *)(p - stm_object_pages);
     o->stm_flags = GCFLAG_WRITE_BARRIER;
+    if (size_rounded_up > CARD_SIZE)
+        o->stm_flags |= GCFLAG_HAS_CARDS;
 
     if (testing_prebuilt_objs == NULL)
         testing_prebuilt_objs = list_create();
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -114,6 +114,8 @@
          copy_large_object:;
             char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj);
             memcpy(realnobj, realobj, size);
+            if (size > CARD_SIZE)
+                nobj->stm_flags |= GCFLAG_HAS_CARDS;
 
             nobj_sync_now = ((uintptr_t)nobj) | FLAG_SYNC_LARGE;
         }
@@ -149,6 +151,7 @@
 
     /* Must trace the object later */
     LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
+    _cards_cleared_in_object(get_priv_segment(STM_SEGMENT->segment_num), nobj);
 }
 
 static void collect_roots_in_nursery(void)
@@ -332,19 +335,20 @@
         if (obj->stm_flags & GCFLAG_HAS_CARDS) {
             /* all objects that had WB cleared need to be fully synchronised
                on commit, so we have to mark all their cards */
+            struct stm_priv_segment_info_s *pseg = get_priv_segment(
+                STM_SEGMENT->segment_num);
+
             if (was_definitely_young) {
-                /* we don't mark cards on young objects */
+                /* stm_wb-slowpath should never have triggered for young objs 
*/
                 assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
                 return;
             }
 
             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);
+                _reset_object_cards(pseg, obj, CARD_CLEAR, false);
             } else {
-                _reset_object_cards(get_priv_segment(STM_SEGMENT->segment_num),
-                                    obj, CARD_MARKED_OLD, true); /* mark all */
+                _reset_object_cards(pseg, obj, CARD_MARKED_OLD, true); /* mark 
all */
             }
         }
     } if (obj->stm_flags & GCFLAG_CARDS_SET) {
@@ -362,6 +366,7 @@
     while (!list_is_empty(lst)) {
         object_t *obj = (object_t*)list_pop_item(lst);
 
+        assert(!_is_young(obj));
         assert(obj->stm_flags & GCFLAG_CARDS_SET);
         _collect_now(obj, false);
         assert(!(obj->stm_flags & GCFLAG_CARDS_SET));
@@ -640,6 +645,10 @@
 
     char *result = allocate_outside_nursery_large(size_rounded_up);
     object_t *o = (object_t *)(result - stm_object_pages);
+
+    if (size_rounded_up > CARD_SIZE)
+        o->stm_flags |= GCFLAG_HAS_CARDS;
+
     tree_insert(STM_PSEGMENT->young_outside_nursery, (uintptr_t)o, 0);
 
     memset(REAL_ADDRESS(STM_SEGMENT->segment_base, o), 0, size_rounded_up);
@@ -741,6 +750,9 @@
     memcpy(realnobj, realobj, size);
 
     obj->stm_flags |= GCFLAG_HAS_SHADOW;
+    if (size > CARD_SIZE)             /* probably not necessary */
+        nobj->stm_flags |= GCFLAG_HAS_CARDS;
+
     tree_insert(STM_PSEGMENT->nursery_objects_shadows,
                 (uintptr_t)obj, (uintptr_t)nobj);
     return nobj;
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 _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);
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -106,7 +106,8 @@
 
 /* this should use llvm's coldcc calling convention,
    but it's not exposed to C code so far */
-void _stm_write_slowpath(object_t *, uintptr_t);
+void _stm_write_slowpath(object_t *);
+void _stm_write_slowpath_card(object_t *, uintptr_t);
 object_t *_stm_allocate_slowpath(ssize_t);
 object_t *_stm_allocate_external(ssize_t);
 void _stm_become_inevitable(const char*);
@@ -216,7 +217,7 @@
 static inline void stm_write(object_t *obj)
 {
     if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0))
-        _stm_write_slowpath(obj, 0);
+        _stm_write_slowpath(obj);
 }
 
 /* The following is a GC-optimized barrier that works on the granularity
@@ -228,9 +229,8 @@
 __attribute__((always_inline))
 static inline void stm_write_card(object_t *obj, uintptr_t index)
 {
-    OPT_ASSERT(obj->stm_flags & _STM_GCFLAG_HAS_CARDS);
     if (UNLIKELY((obj->stm_flags & _STM_GCFLAG_WRITE_BARRIER) != 0))
-        _stm_write_slowpath(obj, index);
+        _stm_write_slowpath_card(obj, index);
 }
 
 /* Must be provided by the user of this library.
@@ -268,17 +268,6 @@
     return (object_t *)p;
 }
 
-/* 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.
-   These objects need to be at least 32bytes in size!
-*/
-__attribute__((always_inline))
-static inline void stm_use_cards(object_t* o)
-{
-    o->stm_flags |= _STM_GCFLAG_HAS_CARDS;
-}
 
 /* Allocate a weakref object. Weakref objects have a
    reference to an object at the byte-offset
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -43,7 +43,6 @@
 object_t *stm_allocate_weakref(ssize_t size_rounded_up);
 object_t *_stm_allocate_old(ssize_t size_rounded_up);
 
-void stm_use_cards(object_t* o);
 /*void stm_write_card(); use _checked_stm_write_card() instead */
 
 
@@ -352,7 +351,7 @@
 GCFLAG_HAS_CARDS = lib._STM_GCFLAG_HAS_CARDS
 CARD_SIZE = lib._STM_CARD_SIZE # 16b at least
 NB_SEGMENTS = lib.STM_NB_SEGMENTS
-
+FAST_ALLOC = lib._STM_FAST_ALLOC
 
 class Conflict(Exception):
     pass
@@ -365,26 +364,20 @@
 def is_in_nursery(o):
     return lib.stm_can_move(o)
 
-def stm_allocate_old(size, use_cards=False):
+def stm_allocate_old(size):
     o = lib._stm_allocate_old(size)
-    if use_cards:
-        lib.stm_use_cards(o)
     tid = 42 + size
     lib._set_type_id(o, tid)
     return o
 
-def stm_allocate_old_refs(n, use_cards=False):
+def stm_allocate_old_refs(n):
     o = lib._stm_allocate_old(HDR + n * WORD)
-    if use_cards:
-        lib.stm_use_cards(o)
     tid = 421420 + n
     lib._set_type_id(o, tid)
     return o
 
-def stm_allocate(size, use_cards=False):
+def stm_allocate(size):
     o = lib.stm_allocate(size)
-    if use_cards:
-        lib.stm_use_cards(o)
     tid = 42 + size
     lib._set_type_id(o, tid)
     return o
@@ -401,10 +394,8 @@
 def stm_get_weakref(o):
     return lib._get_weakref(o)
 
-def stm_allocate_refs(n, use_cards=False):
+def stm_allocate_refs(n):
     o = lib.stm_allocate(HDR + n * WORD)
-    if use_cards:
-        lib.stm_use_cards(o)
     tid = 421420 + n
     lib._set_type_id(o, tid)
     return o
@@ -446,7 +437,6 @@
         raise Conflict()
 
 def stm_write_card(o, index):
-    assert stm_get_flags(o) & GCFLAG_HAS_CARDS
     if lib._checked_stm_write_card(o, index):
         raise Conflict()
 
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
@@ -17,14 +17,14 @@
             self.switch(0)
 
     def test_simple(self):
-        o = stm_allocate_old(1024, True)
+        o = stm_allocate_old(1024)
         self.start_transaction()
         stm_read(o)
         stm_write(o)
         self.commit_transaction()
 
     def test_simple2(self):
-        o = stm_allocate_old(1024, True)
+        o = stm_allocate_old(1024)
         self.start_transaction()
         stm_write_card(o, 5)
         assert not stm_was_written(o) # don't remove GCFLAG_WRITE_BARRIER
@@ -34,7 +34,7 @@
     @py.test.mark.parametrize("k", range(3))
     def test_overflow(self, k):
         self.start_transaction()
-        o = stm_allocate(1024, True)
+        o = stm_allocate(1024)
 
         self.push_root(o)
         self._collect(k)
@@ -52,10 +52,10 @@
         self.commit_transaction()
 
     def test_nursery(self):
-        o = stm_allocate_old_refs(200, True)
+        o = stm_allocate_old_refs(200)
         self.start_transaction()
-        p = stm_allocate(64, True)
-        d = stm_allocate(64, True)
+        p = stm_allocate(64)
+        d = stm_allocate(64)
         stm_set_ref(o, 199, p, True)
 
         # without a write-barrier:
@@ -80,7 +80,7 @@
 
         # card cleared after last collection,
         # so no retrace of index 199:
-        d2 = stm_allocate(64, True)
+        d2 = stm_allocate(64)
         # without a write-barrier:
         lib._set_ptr(o, 199, d2)
         self.push_root(o)
@@ -92,7 +92,7 @@
         assert dn == d2
 
     def test_nursery2(self):
-        o = stm_allocate_old_refs(200, True)
+        o = stm_allocate_old_refs(200)
         self.start_transaction()
         p = stm_allocate(64)
         d = stm_allocate(64)
@@ -111,7 +111,7 @@
         assert not is_in_nursery(stm_get_ref(o, 100))
 
     def test_nursery3(self):
-        o = stm_allocate_old_refs(200, True)
+        o = stm_allocate_old_refs(200)
         self.start_transaction()
         stm_minor_collect()
 
@@ -134,7 +134,7 @@
         assert stm_get_ref(o, 100) == e # not traced
 
     def test_abort_cleanup(self):
-        o = stm_allocate_old_refs(200, True)
+        o = stm_allocate_old_refs(200)
         self.start_transaction()
         stm_minor_collect()
 
@@ -166,7 +166,7 @@
 
     @py.test.mark.parametrize("k", range(3))
     def test_major_gc(self, k):
-        o = stm_allocate_old_refs(200, True)
+        o = stm_allocate_old_refs(200)
         self.start_transaction()
         p = stm_allocate(64)
         stm_set_ref(o, 0, p, True)
@@ -188,7 +188,7 @@
         self.commit_transaction()
 
     def test_synchronize_objs(self):
-        o = stm_allocate_old(2000, True)
+        o = stm_allocate_old(2000)
 
         self.start_transaction()
         stm_set_char(o, 'a', 1000, False)
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
@@ -36,17 +36,22 @@
         # we win but cannot wait in tests...
         raise WriteWriteConflictNotTestable
 
-    if our_trs.inevitable:
+    if our_trs.start_time >= other_trs.start_time:
+        abort_other = False
+    else:
+        abort_other = True
+
+    if other_trs.check_must_abort():
+        abort_other = True
+    elif our_trs.inevitable:
+        abort_other = True
+    elif other_trs.inevitable:
+        abort_other = False
+
+    if not abort_other:
+        our_trs.set_must_abort(objs_in_conflict)
+    else:
         other_trs.set_must_abort(objs_in_conflict)
-    elif other_trs.start_time < our_trs.start_time:
-        pass
-    elif not other_trs.inevitable:
-        other_trs.set_must_abort(objs_in_conflict)
-
-    if not other_trs.check_must_abort():
-        our_trs.set_must_abort(objs_in_conflict)
-    elif wait:
-        assert not our_trs.inevitable
 
 
 class TransactionState(object):
@@ -227,19 +232,14 @@
         self.root_numbering = 0
         self.ref_type_map = {}
         self.root_sizes = {}
-        self.with_cards = {}
 
-    def get_new_root_name(self, is_ref_type, size, with_cards):
+    def get_new_root_name(self, is_ref_type, size):
         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]
 
@@ -368,11 +368,10 @@
         #"SOME_MEDIUM_SIZE+16",
         #"SOME_LARGE_SIZE+16",
     ])
-    with_cards = int(size) >= 32 and global_state.rnd.randrange(1, 100) > 10
-    r = global_state.get_new_root_name(False, size, with_cards)
+    r = global_state.get_new_root_name(False, size)
     thread_state.push_roots(ex)
 
-    ex.do('%s = stm_allocate(%s, %s)' % (r, size, bool(with_cards)))
+    ex.do('%s = stm_allocate(%s)' % (r, size))
     ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
     thread_state.transaction_state.add_root(r, 0, True)
 
@@ -382,10 +381,9 @@
 
 def op_allocate_ref(ex, global_state, thread_state):
     num = str(global_state.rnd.randrange(1, 100))
-    with_cards = int(num) >= 4 and global_state.rnd.randrange(1, 100) > 10
-    r = global_state.get_new_root_name(True, num, with_cards)
+    r = global_state.get_new_root_name(True, num)
     thread_state.push_roots(ex)
-    ex.do('%s = stm_allocate_refs(%s, %s)' % (r, num, bool(with_cards)))
+    ex.do('%s = stm_allocate_refs(%s)' % (r, num))
     ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r]))))
     thread_state.transaction_state.add_root(r, "ffi.NULL", True)
 
@@ -417,7 +415,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) and global_state.rnd.randrange(1, 
100) > 5
+    try_cards = global_state.rnd.randrange(1, 100) > 5
     #
     # check for possible write-write conflict:
     was_written = False
@@ -446,13 +444,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, has_cards))
+        ex.do(raising_call(aborts, "stm_set_ref", r, offset, v, try_cards))
         if not aborts:
-            ex.do(raising_call(False, "stm_set_ref", r, "0", v, has_cards))
+            ex.do(raising_call(False, "stm_set_ref", r, "0", v, try_cards))
     else:
-        ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset, 
has_cards))
+        ex.do(raising_call(aborts, "stm_set_char", r, repr(chr(v)), offset, 
try_cards))
         if not aborts:
-            ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR", 
has_cards))
+            ex.do(raising_call(False, "stm_set_char", r, repr(chr(v)), "HDR", 
try_cards))
 
 def op_read(ex, global_state, thread_state):
     r = thread_state.get_random_root()
@@ -564,13 +562,13 @@
         curr_thread = global_state.thread_states[0]
 
         for i in range(N_OBJECTS):
-            r = global_state.get_new_root_name(False, "384", True)
-            ex.do('%s = stm_allocate_old(384, True)' % r)
+            r = global_state.get_new_root_name(False, "384")
+            ex.do('%s = stm_allocate_old(384)' % 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", True)
-            ex.do('%s = stm_allocate_old_refs(50, True)' % r)
+            r = global_state.get_new_root_name(True, "50")
+            ex.do('%s = stm_allocate_old_refs(50)' % r)
             global_state.committed_transaction_state.add_root(r, "ffi.NULL", 
False)
             global_state.prebuilt_roots.append(r)
         global_state.committed_transaction_state.write_set = set()
@@ -624,5 +622,6 @@
         return test_fun
 
     for _seed in range(5000, 5100):
+        _seed = 5004
         _fn = _make_fun(_seed)
         locals()[_fn.__name__] = _fn
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to