Author: Remi Meier <remi.me...@gmail.com>
Branch: 
Changeset: r1992:ffae8e3eb78b
Date: 2016-06-29 13:37 +0200
http://bitbucket.org/pypy/stmgc/changeset/ffae8e3eb78b/

Log:    fix not removing noconflict objs from certain lists

        After resetting a noconflict obj with committed state, the obj
        should appear to be untouched in the current transaction. This was
        not the case, as the obj was still in some lists where it shouldn't
        be.

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -151,6 +151,7 @@
 }
 
 static void reset_modified_from_backup_copies(int segment_num, object_t 
*only_obj);  /* forward */
+static void undo_modifications_to_single_obj(int segment_num, object_t 
*only_obj); /* forward */
 
 static bool _stm_validate(void)
 {
@@ -268,7 +269,8 @@
                                backup copy completely: */
                             /* XXX: this browses through the whole list of 
modified
                                fragments; this may become a problem... */
-                            reset_modified_from_backup_copies(my_segnum, obj);
+                            undo_modifications_to_single_obj(my_segnum, obj);
+
                             continue;
                         }
 
@@ -1276,6 +1278,37 @@
         invoke_general_finalizers(tl);
 }
 
+static void undo_modifications_to_single_obj(int segment_num, object_t *obj)
+{
+    /* special function used for noconflict objs to reset all their
+     * modifications and make them appear untouched in the current transaction.
+     * I.e., reset modifications and remove from all lists. */
+
+    struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
+
+    reset_modified_from_backup_copies(segment_num, obj);
+
+    LIST_FOREACH_R(pseg->old_objects_with_cards_set, object_t * /*item*/,
+       {
+           if (item == obj) {
+               _reset_object_cards(pseg, item, CARD_CLEAR, false, false);
+               /* copy last element over this one (HACK) */
+               _lst->count -= 1;
+               _lst->items[_i] = _lst->items[_lst->count];
+               break;
+           }
+       });
+    LIST_FOREACH_R(pseg->objects_pointing_to_nursery, object_t * /*item*/,
+       {
+           if (item == obj) {
+               /* copy last element over this one (HACK) */
+               _lst->count -= 1;
+               _lst->items[_i] = _lst->items[_lst->count];
+               break;
+           }
+       });
+}
+
 static void reset_modified_from_backup_copies(int segment_num, object_t 
*only_obj)
 {
 #pragma push_macro("STM_PSEGMENT")
@@ -1284,6 +1317,9 @@
 #undef STM_SEGMENT
     assert(modification_lock_check_wrlock(segment_num));
 
+    /* WARNING: resetting the obj will remove the WB flag. Make sure you either
+     * re-add it or remove it from lists where it was added based on the flag. 
*/
+
     struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
     struct list_s *list = pseg->modified_old_objects;
     struct stm_undo_s *undo = (struct stm_undo_s *)list->items;
@@ -1310,12 +1346,10 @@
         free_bk(undo);
 
         if (only_obj != NULL) {
+            /* WB_EXECUTED should be set on small objs, but not on card objs */
             assert(IMPLY(only_obj != NULL,
                          (((struct object_s *)dst)->stm_flags
-                          & (GCFLAG_NO_CONFLICT
-                             | GCFLAG_WRITE_BARRIER
-                             | GCFLAG_WB_EXECUTED))
-                         == (GCFLAG_NO_CONFLICT | GCFLAG_WRITE_BARRIER)));
+                          & GCFLAG_NO_CONFLICT)));
             /* copy last element over this one */
             end--;
             list->count -= 3;
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -1,6 +1,11 @@
 import cffi, weakref
 from common import parent_dir, source_files
 
+import os
+# enable some malloc debug checks:
+os.environ["MALLOC_CHECK_"] = "3"
+
+
 # ----------
 
 ffi = cffi.FFI()
@@ -668,6 +673,7 @@
      force_generic_engine=True)
 
 
+
 WORD = 8
 HDR = lib.SIZEOF_MYOBJ
 assert HDR == 8
diff --git a/c8/test/test_noconfl.py b/c8/test/test_noconfl.py
--- a/c8/test/test_noconfl.py
+++ b/c8/test/test_noconfl.py
@@ -153,3 +153,56 @@
         self.switch(1, False)
         stm_validate()
         assert stm_get_char(o) == 'a'
+
+    def test_obj_reset_on_validate_like_it_was_never_written_to(self):
+        get_card_value = lib._stm_get_card_value
+
+        # if noconfl objs are reset during stm_validate(), their WB flag gets
+        # lost. make sure it is not in any of the lists where the WB flag is
+        # required / expected.
+        self.start_transaction()
+        o = stm_allocate_noconflict(16)
+        oh = stm_allocate_noconflict(1000+20*CARD_SIZE)
+        self.push_root(o)
+        self.push_root(oh)
+        self.commit_transaction()
+
+        self.start_transaction()
+        oh = self.pop_root()
+        o = self.pop_root()
+        self.push_root(o)
+        self.push_root(oh)
+
+        stm_set_char(o, 'a')
+        stm_set_char(oh, 'x', use_cards=True)
+        assert o in modified_old_objects()
+        assert oh in modified_old_objects()
+        assert o in objects_pointing_to_nursery()
+        assert oh not in objects_pointing_to_nursery()
+        assert get_card_value(oh, 0) == CARD_MARKED
+        assert oh in old_objects_with_cards_set()
+
+        self.switch(1)
+        self.start_transaction()
+        stm_set_char(o, 'b')
+        stm_set_char(oh, 'y', use_cards=True)
+        self.commit_transaction()
+
+        self.switch(0, False)
+        assert stm_get_char(o) == 'a'
+        assert stm_get_char(oh) == 'x'
+        assert o in modified_old_objects()
+        assert oh in modified_old_objects()
+        assert o in objects_pointing_to_nursery()
+        assert oh not in objects_pointing_to_nursery()
+        assert oh in old_objects_with_cards_set()
+        stm_validate()
+        assert stm_get_char(o) == 'b'
+        assert stm_get_char(oh) == 'y'
+        assert o not in modified_old_objects()
+        assert oh not in modified_old_objects()
+        assert o not in objects_pointing_to_nursery()
+        assert oh not in objects_pointing_to_nursery()
+        assert get_card_value(oh, 0) == CARD_CLEAR
+        assert oh not in old_objects_with_cards_set()
+        stm_minor_collect()
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to