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