Author: Remi Meier <[email protected]>
Branch: c8-private-pages
Changeset: r1528:290f1d2c1891
Date: 2015-01-15 10:18 +0100
http://bitbucket.org/pypy/stmgc/changeset/290f1d2c1891/

Log:    start porting gcpage tests

diff --git a/c8/stm/misc.c b/c8/stm/misc.c
--- a/c8/stm/misc.c
+++ b/c8/stm/misc.c
@@ -43,6 +43,14 @@
 
 
 #ifdef STM_TESTS
+bool _stm_is_accessible_page(uintptr_t pagenum)
+{
+    acquire_privatization_lock(STM_SEGMENT->segment_num);
+    bool res = get_page_status_in(STM_SEGMENT->segment_num, pagenum) == 
PAGE_ACCESSIBLE;
+    release_privatization_lock(STM_SEGMENT->segment_num);
+    return res;
+}
+
 long _stm_count_modified_old_objects(void)
 {
     assert(STM_PSEGMENT->modified_old_objects);
diff --git a/c8/stmgc.h b/c8/stmgc.h
--- a/c8/stmgc.h
+++ b/c8/stmgc.h
@@ -74,6 +74,8 @@
 bool _stm_was_read(object_t *obj);
 bool _stm_was_written(object_t *obj);
 
+bool _stm_is_accessible_page(uintptr_t pagenum);
+
 long stm_can_move(object_t *obj);
 void _stm_test_switch(stm_thread_local_t *tl);
 void _stm_test_switch_segment(int segnum);
diff --git a/c8/test/support.py b/c8/test/support.py
--- a/c8/test/support.py
+++ b/c8/test/support.py
@@ -64,6 +64,7 @@
 char *_stm_real_address(object_t *o);
 void _stm_test_switch(stm_thread_local_t *tl);
 void _stm_test_switch_segment(int segnum);
+bool _stm_is_accessible_page(uintptr_t pagenum);
 
 void clear_jmpbuf(stm_thread_local_t *tl);
 long _check_start_transaction(stm_thread_local_t *tl);
@@ -428,8 +429,8 @@
 def stm_major_collect():
     lib.stm_collect(1)
 
-def stm_get_private_page(pagenum):
-    return lib._stm_get_private_page(pagenum)
+def stm_is_accessible_page(pagenum):
+    return lib._stm_is_accessible_page(pagenum)
 
 def stm_get_obj_size(o):
     res = lib._checked_stmcb_size_rounded_up(stm_get_real_address(o))
diff --git a/c8/test/test_gcpage.py b/c8/test/test_gcpage.py
new file mode 100644
--- /dev/null
+++ b/c8/test/test_gcpage.py
@@ -0,0 +1,254 @@
+from support import *
+import py
+
+
+LMO = LARGE_MALLOC_OVERHEAD
+
+
+class TestGCPage(BaseTest):
+
+    def test_large_obj_alloc(self):
+        # test obj which doesn't fit into the size_classes
+        # for now, we will still allocate it in the nursery.
+        # expects: GC_N_SMALL_REQUESTS  36
+        size_class = 1000 # too big
+        obj_size = size_class * 8
+        assert obj_size > 4096 # we want more than 1 page
+        assert obj_size < lib._STM_FAST_ALLOC # in the nursery
+
+        self.start_transaction()
+        new = stm_allocate(obj_size)
+        assert is_in_nursery(new)
+        self.push_root(new)
+        stm_minor_collect()
+        new = self.pop_root()
+
+        pages = stm_get_obj_pages(new)
+        assert len(pages) == 2
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [1, 1])
+
+        assert not is_in_nursery(new)
+        stm_write(new)
+        self.commit_transaction()
+
+        # now proceed to write into the object in a new transaction
+        self.start_transaction()
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [True, True])
+        stm_write(new)
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [True, True])
+
+        # write to 2nd page of object!!
+        wnew = stm_get_real_address(new)
+        wnew[4097] = 'x'
+
+        self.switch(1)
+        self.start_transaction()
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [False, False])
+        stm_read(new)
+        rnew = stm_get_real_address(new)
+        assert rnew[4097] == '\0'
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [False, True])
+        self.abort_transaction()
+
+        self.switch(0)
+        self.abort_transaction()
+        assert ([stm_is_accessible_page(p) for p in pages]
+                == [True, True])
+
+    def test_partial_alloced_pages(self):
+        self.start_transaction()
+        new = stm_allocate(16)
+        self.push_root(new)
+        stm_minor_collect()
+        new = self.pop_root()
+
+        assert stm_get_private_page(stm_get_obj_pages(new)[0]) == 0
+        assert stm_get_flags(new) & GCFLAG_WRITE_BARRIER
+
+        stm_write(new)
+        assert not (stm_get_flags(new) & GCFLAG_WRITE_BARRIER)
+
+        self.commit_transaction()
+        assert stm_get_private_page(stm_get_obj_pages(new)[0]) == 0
+        assert stm_get_flags(new) & GCFLAG_WRITE_BARRIER
+
+        self.start_transaction()
+        newer = stm_allocate(16)
+        self.push_root(newer)
+        stm_minor_collect()
+        newer = self.pop_root()
+        # 'new' is still in shared_page and committed
+        assert stm_get_private_page(stm_get_obj_pages(new)[0]) == 0
+        assert stm_get_flags(new) & GCFLAG_WRITE_BARRIER
+        # 'newer' is now part of the SHARED page with 'new', but
+        # uncommitted, so no privatization has to take place:
+        assert stm_get_obj_pages(new) == stm_get_obj_pages(newer)
+        assert stm_get_flags(newer) & GCFLAG_WRITE_BARRIER
+        stm_write(newer) # does not privatize
+        assert not (stm_get_flags(newer) & GCFLAG_WRITE_BARRIER)
+        assert stm_get_private_page(stm_get_obj_pages(newer)[0]) == 0
+        self.commit_transaction()
+
+        assert stm_get_private_page(stm_get_obj_pages(newer)[0]) == 0
+        assert stm_get_flags(newer) & GCFLAG_WRITE_BARRIER
+
+    def test_major_collection(self):
+        self.start_transaction()
+        new = stm_allocate(5000)
+        self.push_root(new)
+        stm_minor_collect()
+        assert lib._stm_total_allocated() == 5000 + LMO
+
+        self.pop_root()
+        stm_minor_collect()
+        assert lib._stm_total_allocated() == 5000 + LMO
+
+        stm_major_collect()
+        assert lib._stm_total_allocated() == 0
+
+    def test_mark_recursive(self):
+        def make_chain(sz):
+            prev = ffi.cast("object_t *", ffi.NULL)
+            for i in range(10):
+                self.push_root(prev)
+                new = stm_allocate_refs(sz/8-1)
+                prev = self.pop_root()
+                stm_set_ref(new, 42, prev)
+                prev = new
+            return prev
+
+        self.start_transaction()
+        self.push_root(make_chain(5000))
+        self.push_root(make_chain(4312))
+        stm_minor_collect()
+        assert lib._stm_total_allocated() == (10 * (5000 + LMO) +
+                                              10 * (4312 + LMO))
+        stm_major_collect()
+        assert lib._stm_total_allocated() == (10 * (5000 + LMO) +
+                                              10 * (4312 + LMO))
+        stm_major_collect()
+        assert lib._stm_total_allocated() == (10 * (5000 + LMO) +
+                                              10 * (4312 + LMO))
+        self.pop_root()
+        stm_major_collect()
+        assert lib._stm_total_allocated() == 10 * (5000 + LMO)
+
+    def test_trace_all_versions(self):
+        self.start_transaction()
+        x = stm_allocate(5000)
+        stm_set_char(x, 'A')
+        stm_set_char(x, 'a', 4999)
+        self.push_root(x)
+        self.commit_transaction()
+        assert lib._stm_total_allocated() == 5000 + LMO
+
+        self.start_transaction()
+        x = self.pop_root()
+        self.push_root(x)
+        assert lib._stm_total_allocated() == 5000 + LMO
+        stm_set_char(x, 'B')
+        stm_set_char(x, 'b', 4999)
+        assert lib._stm_total_allocated() == 5000 + LMO + 2 * 4096  # 2 pages
+        stm_major_collect()
+
+        assert stm_get_char(x)       == 'B'
+        assert stm_get_char(x, 4999) == 'b'
+
+        self.switch(1)
+        self.start_transaction()
+        assert stm_get_char(x)       == 'A'
+        assert stm_get_char(x, 4999) == 'a'
+
+        self.switch(0)
+        assert stm_get_char(x)       == 'B'
+        assert stm_get_char(x, 4999) == 'b'
+        assert lib._stm_total_allocated() == 5000 + LMO + 2 * 4096  # 2 pages
+
+    def test_trace_correct_version_of_overflow_objects_1(self, size=32):
+        self.start_transaction()
+        #
+        self.switch(1)
+        self.start_transaction()
+        x = stm_allocate(size)
+        stm_set_char(x, 'E', size - 1)
+        self.push_root(x)
+        #
+        self.switch(0)
+        stm_major_collect()
+        #
+        self.switch(1)
+        x = self.pop_root()
+        assert stm_get_char(x, size - 1) == 'E'
+
+    def test_trace_correct_version_of_overflow_objects_2(self):
+        self.test_trace_correct_version_of_overflow_objects_1(size=5000)
+
+    def test_reshare_if_no_longer_modified_0(self, invert=0):
+        if invert:
+            self.switch(1)
+        self.start_transaction()
+        x = stm_allocate(5000)
+        self.push_root(x)
+        self.commit_transaction()
+        x = self.pop_root()
+        #
+        self.switch(1 - invert)
+        self.start_transaction()
+        self.push_root(x)
+        stm_set_char(x, 'A')
+        stm_major_collect()
+        assert lib._stm_total_allocated() == 5000 + LMO + 2 * 4096  # 2 pages
+        self.commit_transaction()
+        #
+        self.start_transaction()
+        stm_major_collect()
+        assert lib._stm_total_allocated() == 5000 + LMO    # shared again
+
+    def test_reshare_if_no_longer_modified_1(self):
+        self.test_reshare_if_no_longer_modified_0(invert=1)
+
+    def test_threadlocal_at_start_of_transaction(self):
+        self.start_transaction()
+        x = stm_allocate(16)
+        stm_set_char(x, 'L')
+        self.set_thread_local_obj(x)
+        self.commit_transaction()
+
+        self.start_transaction()
+        assert stm_get_char(self.get_thread_local_obj()) == 'L'
+        self.set_thread_local_obj(stm_allocate(32))
+        stm_minor_collect()
+        self.abort_transaction()
+
+        self.start_transaction()
+        assert stm_get_char(self.get_thread_local_obj()) == 'L'
+        self.set_thread_local_obj(stm_allocate(32))
+        stm_major_collect()
+        self.abort_transaction()
+
+        self.start_transaction()
+        assert stm_get_char(self.get_thread_local_obj()) == 'L'
+
+    def test_marker_1(self):
+        self.start_transaction()
+        p1 = stm_allocate(600)
+        stm_set_char(p1, 'o')
+        self.push_root(p1)
+        self.push_root(ffi.cast("object_t *", 123))
+        p2 = stm_allocate(600)
+        stm_set_char(p2, 't')
+        self.push_root(p2)
+        stm_major_collect()
+        assert lib._stm_total_allocated() == 2 * 616
+        #
+        p2 = self.pop_root()
+        m = self.pop_root()
+        assert m == ffi.cast("object_t *", 123)
+        p1 = self.pop_root()
+        assert stm_get_char(p1) == 'o'
+        assert stm_get_char(p2) == 't'
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
@@ -581,7 +581,7 @@
             op_minor_collect,
             #op_major_collect,
         ]
-        for _ in range(1000):
+        for _ in range(2000):
             # make sure we are in a transaction:
             curr_thread = op_switch_thread(ex, global_state, curr_thread)
 
@@ -618,6 +618,6 @@
         test_fun.__name__ = 'test_random_%d' % seed
         return test_fun
 
-    for _seed in range(5000, 5400):
+    for _seed in range(5000, 5200):
         _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