[pypy-commit] stmgc card-marking: optimize a bit the card-wise synchronize objs
Raemi
noreply at buildbot.pypy.org
Thu May 22 16:58:53 CEST 2014
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: card-marking
Changeset: r1231:8fac7b4ff774
Date: 2014-05-22 13:45 +0200
http://bitbucket.org/pypy/stmgc/changeset/8fac7b4ff774/
Log: optimize a bit the card-wise synchronize objs
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -516,7 +516,7 @@
long i, myself = STM_SEGMENT->segment_num;
/* simple heuristic to check if probably the whole object is
- marked anyway so we can do page-wise synchronize */
+ marked anyway so we should do page-wise synchronize */
if (write_locks[first_card_index + 1] == CARD_MARKED_OLD
&& write_locks[first_card_index + last_card_index] == CARD_MARKED_OLD
&& write_locks[first_card_index + (last_card_index >> 1) + 1] == CARD_MARKED_OLD) {
@@ -530,20 +530,38 @@
dprintf(("card_wise_sync syncs %p,size:%lu card-wise\n", obj, obj_size));
+ /* Combine multiple marked cards and do a memcpy for them. We don't
+ try yet to use page_copy() or otherwise take into account privatization
+ of pages (except _has_private_page_in_range) */
+ uintptr_t start = 0;
+ uintptr_t copy_size = 0;
while (card_index <= last_card_index) {
uintptr_t card_lock_idx = first_card_index + card_index;
+ uintptr_t card_byte_offset = get_card_byte_offset(card_index);
+ uint8_t card_value = write_locks[card_lock_idx];
- if (write_locks[card_lock_idx] == CARD_MARKED_OLD) {
+ OPT_ASSERT(card_value != CARD_MARKED); /* always only MARKED_OLD or CLEAR */
+
+ if (card_value == CARD_MARKED_OLD) {
write_locks[card_lock_idx] = CARD_CLEAR;
- uintptr_t card_byte_offset = get_card_byte_offset(card_index);
- uintptr_t start = (uintptr_t)obj + card_byte_offset;
- uintptr_t copy_size = CARD_SIZE;
+ if (start == 0) { /* first marked card */
+ start = (uintptr_t)obj + card_byte_offset;
+ }
- if (start - (uintptr_t)obj + copy_size > obj_size) {
+ copy_size += CARD_SIZE;
+
+ if ((start - (uintptr_t)obj) + copy_size > obj_size) {
/* don't copy over the object's bounds */
copy_size = obj_size - (start - (uintptr_t)obj);
}
+ }
+
+ if (start /* something to copy */
+ && (card_value != CARD_MARKED_OLD /* found non-marked card */
+ || card_index == last_card_index)) { /* this is the last card */
+ /* do the copying: */
+ //dprintf(("copy %lu bytes\n", copy_size));
/* since we have marked cards, at least one page here must be private */
assert(_has_private_page_in_range(myself, start, copy_size));
@@ -553,6 +571,7 @@
char *dst = REAL_ADDRESS(stm_object_pages, start);
memcpy(dst, src, copy_size);
+ /* copy to other segments */
for (i = 1; i <= NB_SEGMENTS; i++) {
if (i == myself)
continue;
@@ -562,12 +581,22 @@
dst = REAL_ADDRESS(get_segment_base(i), start);
memcpy(dst, src, copy_size);
}
- } else {
- assert(write_locks[card_lock_idx] != CARD_MARKED); /* always only MARKED_OLD */
+
+ copy_size = 0;
+ start = 0;
}
card_index++;
}
+
+#ifndef NDEBUG
+ char *src = REAL_ADDRESS(stm_object_pages, (uintptr_t)obj);
+ char *dst;
+ for (i = 1; i <= NB_SEGMENTS; i++) {
+ dst = REAL_ADDRESS(get_segment_base(i), (uintptr_t)obj);
+ assert(memcmp(dst, src, obj_size) == 0);
+ }
+#endif
}
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
@@ -186,3 +186,46 @@
assert not stm_was_written_card(o)
assert stm_get_ref(o, 0) == p
self.commit_transaction()
+
+ def test_synchronize_objs(self):
+ o = stm_allocate_old(2000, True)
+
+ self.start_transaction()
+ stm_set_char(o, 'a', 1000, False)
+ self.commit_transaction()
+
+ self.switch(1)
+
+ self.start_transaction()
+ stm_set_char(o, 'b', 1001, False)
+ assert stm_get_char(o, 1000) == 'a'
+ self.commit_transaction()
+
+ self.switch(0)
+
+ self.start_transaction()
+ assert stm_get_char(o, 1001) == 'b'
+
+ stm_set_char(o, 'c', 1000, True)
+ stm_set_char(o, 'c', 1000+CARD_SIZE, True)
+ stm_set_char(o, 'c', 1000+CARD_SIZE*2, True)
+ stm_set_char(o, 'c', 1000+CARD_SIZE*3, True)
+
+ stm_set_char(o, 'd', 1000+CARD_SIZE*10, True)
+
+ stm_set_char(o, 'e', 1000+CARD_SIZE*12, True)
+ self.commit_transaction()
+
+ self.switch(1)
+
+ self.start_transaction()
+ assert stm_get_char(o, 1000) == 'c'
+ assert stm_get_char(o, 1000+CARD_SIZE) == 'c'
+ assert stm_get_char(o, 1000+CARD_SIZE*2) == 'c'
+ assert stm_get_char(o, 1000+CARD_SIZE*3) == 'c'
+
+ assert stm_get_char(o, 1000+CARD_SIZE*10) == 'd'
+
+ assert stm_get_char(o, 1000+CARD_SIZE*12) == 'e'
+
+ self.commit_transaction()
More information about the pypy-commit
mailing list