[pypy-commit] stmgc parallel-pulling: a bit of code dedup
Raemi
noreply at buildbot.pypy.org
Fri Jun 20 09:57:16 CEST 2014
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: parallel-pulling
Changeset: r1256:b4e04b28f446
Date: 2014-06-20 09:57 +0200
http://bitbucket.org/pypy/stmgc/changeset/b4e04b28f446/
Log: a bit of code dedup
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -301,61 +301,68 @@
return false;
}
-static void copy_object_to_shared(object_t *obj, int source_segment_num)
+static void copy_obj_from_to_segment(
+ int from_segment_num, int to_segment_num, object_t *obj,
+ bool nodebug)
{
- /* Only used by major GC. XXX There is a lot of code duplication
- with synchronize_object_now() but I don't completely see how to
- improve...
- */
- assert(!_is_young(obj));
+ /* page-wise copy of an object from one segment to another */
- char *segment_base = get_segment_base(source_segment_num);
+ OPT_ASSERT(from_segment_num != to_segment_num);
+
+ char *from_base = get_segment_base(from_segment_num);
+ char *to_base = get_segment_base(to_segment_num);
+
+ char *realobj = REAL_ADDRESS(from_base, obj);
+ ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+
+ /* XXX: copied from sync_object_now */
uintptr_t start = (uintptr_t)obj;
uintptr_t first_page = start / 4096UL;
- struct object_s *realobj = (struct object_s *)
- REAL_ADDRESS(segment_base, obj);
- if (realobj->stm_flags & GCFLAG_SMALL_UNIFORM) {
+ if (((struct object_s *)realobj)->stm_flags & GCFLAG_SMALL_UNIFORM) {
abort();//XXX WRITE THE FAST CASE
- }
- else {
- ssize_t obj_size = stmcb_size_rounded_up(realobj);
- assert(obj_size >= 16);
- uintptr_t end = start + obj_size;
+ } else {
+ uintptr_t end = start + size;
uintptr_t last_page = (end - 1) / 4096UL;
for (; first_page <= last_page; first_page++) {
+ uintptr_t copy_size;
+ if (first_page == last_page) {
+ /* this is the final fragment */
+ copy_size = end - start;
+ }
+ else {
+ /* this is a non-final fragment, going up to the
+ page's end */
+ copy_size = 4096 - (start & 4095);
+ }
- /* Copy the object into the shared page, if needed */
- if (is_private_page(source_segment_num, first_page)) {
-
- uintptr_t copy_size;
- if (first_page == last_page) {
- /* this is the final fragment */
- copy_size = end - start;
- }
- else {
- /* this is a non-final fragment, going up to the
- page's end */
- copy_size = 4096 - (start & 4095);
- }
- /* double-check that the result fits in one page */
- assert(copy_size > 0);
- assert(copy_size + (start & 4095) <= 4096);
-
- char *src = REAL_ADDRESS(segment_base, start);
- char *dst = REAL_ADDRESS(stm_object_pages, start);
+ /* copy from shared page to private, if needed */
+ char *dst = REAL_ADDRESS(to_base, start);
+ char *src = REAL_ADDRESS(from_base, start);
+ if ((from_segment_num == 0 || is_private_page(from_segment_num, first_page))
+ && (to_segment_num == 0 || is_private_page(to_segment_num, first_page))) {
+ /* at least one of them is a private page, or both */
if (copy_size == 4096)
pagecopy(dst, src);
else
memcpy(dst, src, copy_size);
}
+ else if (!nodebug) {
+ /* nodebug=true only used for the trick in major_reshare_pages that
+ removes the privatization bit even if contents differ */
+ assert(memcmp(dst, src, copy_size) == 0); /* same page */
+ }
start = (start + 4096) & ~4095;
}
}
+
+ write_fence();
}
+
+
static void synchronize_object_now(object_t *obj, bool lazy_on_commit)
{
/* Copy around the version of 'obj' that lives in our own segment.
@@ -591,67 +598,7 @@
abort_with_mutex();
}
-static void copy_objs_from_segment_0(int segment_num, struct list_s *lst)
-{
- /* pull the list of objects from segment 0. This either resets
- modifications or just updates the view of the current segment.
- */
- char *local_base = get_segment_base(segment_num);
- char *zero_base = get_segment_base(0);
- LIST_FOREACH_R(lst, object_t * /*item*/,
- ({
- /* memcpy in the opposite direction than
- push_modified_to_other_segments() */
- char *realobj = REAL_ADDRESS(zero_base, item);
- ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
-
- /* XXX: copied from sync_object_now */
- uintptr_t start = (uintptr_t)item;
- uintptr_t first_page = start / 4096UL;
-
- if (((struct object_s *)realobj)->stm_flags & GCFLAG_SMALL_UNIFORM) {
- abort();//XXX WRITE THE FAST CASE
- }
- else {
- uintptr_t end = start + size;
- uintptr_t last_page = (end - 1) / 4096UL;
- long myself = segment_num;
-
- for (; first_page <= last_page; first_page++) {
- uintptr_t copy_size;
- if (first_page == last_page) {
- /* this is the final fragment */
- copy_size = end - start;
- }
- else {
- /* this is a non-final fragment, going up to the
- page's end */
- copy_size = 4096 - (start & 4095);
- }
-
- /* copy from shared page to private, if needed */
- char *dst = REAL_ADDRESS(local_base, start);
- char *src = REAL_ADDRESS(zero_base, start);
- if (is_private_page(myself, first_page)) {
- if (copy_size == 4096)
- pagecopy(dst, src);
- else
- memcpy(dst, src, copy_size);
- }
- else {
- assert(memcmp(dst, src, copy_size) == 0); /* same page */
- }
-
- start = (start + 4096) & ~4095;
- }
- }
-
- /* all objs in segment 0 should have the WB flag: */
- assert(((struct object_s *)realobj)->stm_flags & GCFLAG_WRITE_BARRIER);
- }));
- write_fence();
-}
static void pull_committed_changes(struct stm_priv_segment_info_s *pseg)
{
@@ -659,7 +606,14 @@
if (list_count(lst)) {
dprintf(("pulling %lu objects from shared segment\n", list_count(lst)));
- copy_objs_from_segment_0(pseg->pub.segment_num, lst);
+
+ LIST_FOREACH_R(lst, object_t * /*item*/,
+ ({
+ /* memcpy in the opposite direction than
+ push_modified_to_other_segments() */
+ copy_obj_from_to_segment(0, pseg->pub.segment_num, item, false);
+ }));
+
list_clear(lst);
}
}
@@ -678,7 +632,6 @@
*/
struct stm_priv_segment_info_s *pseg = get_priv_segment(segment_num);
char *local_base = get_segment_base(segment_num);
- char *remote_base = get_segment_base(0);
LIST_FOREACH_R(
pseg->modified_old_objects,
@@ -686,16 +639,14 @@
({
/* memcpy in the opposite direction than
push_modified_to_other_segments() */
- char *src = REAL_ADDRESS(remote_base, item);
- char *dst = REAL_ADDRESS(local_base, item);
- ssize_t size = stmcb_size_rounded_up((struct object_s *)src);
- memcpy(dst, src, size);
+ copy_obj_from_to_segment(0, segment_num, item, false);
/* objects in 'modified_old_objects' usually have the
WRITE_BARRIER flag, unless they have been modified
recently. Ignore the old flag; after copying from the
other segment, we should have the flag. */
- assert(((struct object_s *)dst)->stm_flags & GCFLAG_WRITE_BARRIER);
+ char *dst = REAL_ADDRESS(local_base, item);
+ OPT_ASSERT(((struct object_s *)dst)->stm_flags & GCFLAG_WRITE_BARRIER);
/* write all changes to the object before we release the
write lock below. This is needed because we need to
@@ -704,7 +655,7 @@
write_fence() ensures in particular that 'src' has been
fully read before we release the lock: reading it
is necessary to write 'dst'. */
- write_fence();
+ //write_fence(); - done by copy_obj_from_to_segment()
/* clear the write-lock */
uintptr_t lock_idx = (((uintptr_t)item) >> 4) - WRITELOCK_START;
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -260,7 +260,8 @@
asm("/* workaround for llvm bug */");
}
-static void copy_object_to_shared(object_t *obj, int source_segment_num);
+static void copy_obj_from_to_segment(
+ int from_segment_num, int to_segment_num, object_t *obj, bool nodebug);
static void synchronize_object_now(object_t *obj, bool lazy_on_commit);
static void pull_committed_changes(struct stm_priv_segment_info_s *pseg);
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -281,7 +281,11 @@
*/
struct list_s *lst = get_priv_segment(i)->large_overflow_objects;
if (lst != NULL) {
- LIST_FOREACH_R(lst, object_t *, copy_object_to_shared(item, i));
+ LIST_FOREACH_R(lst, object_t *,
+ ({
+ copy_obj_from_to_segment(i, 0, item,
+ /* nodebug */ true);
+ }));
}
}
More information about the pypy-commit
mailing list