[pypy-commit] stmgc c7-refactor: Fixes.
arigo
noreply at buildbot.pypy.org
Tue Feb 25 00:45:22 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: c7-refactor
Changeset: r848:c2dc9f28006f
Date: 2014-02-25 00:45 +0100
http://bitbucket.org/pypy/stmgc/changeset/c2dc9f28006f/
Log: Fixes.
diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -104,6 +104,15 @@
getting the write-lock */
assert(obj->stm_flags & GCFLAG_WRITE_BARRIER);
obj->stm_flags &= ~GCFLAG_WRITE_BARRIER;
+
+ /* for sanity, check that all other segment copies of this object
+ still have the flag */
+ long i;
+ for (i = 0; i < NB_SEGMENTS; i++) {
+ assert(i == STM_SEGMENT->segment_num ||
+ (((struct object_s *)REAL_ADDRESS(get_segment_base(i), obj))
+ ->stm_flags & GCFLAG_WRITE_BARRIER));
+ }
}
static void reset_transaction_read_version(void)
@@ -292,9 +301,9 @@
assert(write_locks[lock_idx] == STM_PSEGMENT->write_lock_num);
write_locks[lock_idx] = 0;
- /* set again the WRITE_BARRIER flag */
- assert((item->stm_flags & GCFLAG_WRITE_BARRIER) == 0);
- item->stm_flags |= GCFLAG_WRITE_BARRIER;
+ /* the WRITE_BARRIER flag should have been set again by
+ minor_collection() */
+ assert((item->stm_flags & GCFLAG_WRITE_BARRIER) != 0);
/* copy the modified object to the other segment */
char *src = REAL_ADDRESS(local_base, item);
@@ -363,6 +372,7 @@
/* update 'overflow_number' if needed */
if (has_any_overflow_object) {
highest_overflow_number += GCFLAG_OVERFLOW_NUMBER_bit0;
+ assert(highest_overflow_number != 0); /* XXX else, overflow! */
STM_PSEGMENT->overflow_number = highest_overflow_number;
}
@@ -393,9 +403,6 @@
STM_PSEGMENT->modified_old_objects,
object_t * /*item*/,
({
- /* all objects in 'modified_objects' have this flag removed */
- assert((item->stm_flags & GCFLAG_WRITE_BARRIER) == 0);
-
/* memcpy in the opposite direction than
push_modified_to_other_segments() */
char *src = REAL_ADDRESS(remote_base, item);
@@ -403,8 +410,10 @@
ssize_t size = stmcb_size_rounded_up((struct object_s *)src);
memcpy(dst, src, size);
- /* copying from the other segment added again the
- WRITE_BARRIER flag */
+ /* 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(item->stm_flags & GCFLAG_WRITE_BARRIER);
/* write all changes to the object before we release the
diff --git a/c7/stm/core.h b/c7/stm/core.h
--- a/c7/stm/core.h
+++ b/c7/stm/core.h
@@ -68,13 +68,13 @@
struct list_s *modified_old_objects;
/* List of out-of-nursery objects that may contain pointers to
- nursery objects. This is used to track the GC status: they
- are all objects outside the nursery on which an stm_write()
- occurred since the last minor collection. If there was no
- minor collection yet in the current transaction, this is NULL,
+ nursery objects. This is used to track the GC status: they are
+ all objects outside the nursery on which an stm_write() occurred
+ since the last minor collection. This list contains exactly the
+ objects without GCFLAG_WRITE_BARRIER. If there was no minor
+ collection yet in the current transaction, this is NULL,
understood as meaning implicitly "this is the same as
- 'modified_old_objects'. This list contains exactly the
- objects without GCFLAG_WRITE_BARRIER. */
+ 'modified_old_objects'". */
struct list_s *objects_pointing_to_nursery;
/* List of all large, overflowed objects. Only non-NULL after the
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -51,6 +51,7 @@
/************************************************************/
#define GCWORD_MOVED ((object_t *) -42)
+#define FLAG_SYNC_LARGE_NOW 0x01
static void minor_trace_if_young(object_t **pobj)
@@ -80,19 +81,21 @@
char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
size_t size = stmcb_size_rounded_up((struct object_s *)realobj);
object_t *nobj;
+ uintptr_t nobj_sync_now;
if (1 /*size >= GC_MEDIUM_REQUEST*/) {
/* case 1: object is not small enough.
Ask gcpage.c for an allocation via largemalloc. */
nobj = allocate_outside_nursery_large(size);
+ nobj_sync_now = (uintptr_t)nobj;
/* Copy the object */
char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj);
memcpy(realnobj, realobj, size);
if (STM_PSEGMENT->minor_collect_will_commit_now)
- synchronize_overflow_object_now(nobj);
+ nobj_sync_now |= FLAG_SYNC_LARGE_NOW;
else
LIST_APPEND(STM_PSEGMENT->large_overflow_objects, nobj);
}
@@ -107,13 +110,13 @@
}
/* Done copying the object. */
- //dprintf(("%p -> %p\n", obj, nobj));
+ //dprintf(("\t\t\t\t\t%p -> %p\n", obj, nobj));
pforwarded_array[0] = GCWORD_MOVED;
pforwarded_array[1] = nobj;
*pobj = nobj;
/* Must trace the object later */
- LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj);
+ LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
}
static void collect_roots_in_nursery(void)
@@ -127,26 +130,46 @@
}
}
+static inline void _collect_now(object_t *obj)
+{
+ assert(!_is_in_nursery(obj));
+
+ /* We must not have GCFLAG_WRITE_BARRIER so far. Add it now. */
+ assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER));
+ obj->stm_flags |= GCFLAG_WRITE_BARRIER;
+
+ /* Trace the 'obj' to replace pointers to nursery with pointers
+ outside the nursery, possibly forcing nursery objects out and
+ adding them to 'objects_pointing_to_nursery' as well. */
+ char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+ stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
+}
+
static void collect_oldrefs_to_nursery(void)
{
struct list_s *lst = STM_PSEGMENT->objects_pointing_to_nursery;
while (!list_is_empty(lst)) {
- object_t *obj = (object_t *)list_pop_item(lst);
- assert(!_is_in_nursery(obj));
+ uintptr_t obj_sync_now = list_pop_item(lst);
+ object_t *obj = (object_t *)(obj_sync_now & ~FLAG_SYNC_LARGE_NOW);
- /* We must not have GCFLAG_WRITE_BARRIER so far. Add it now. */
- assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER));
- obj->stm_flags |= GCFLAG_WRITE_BARRIER;
+ _collect_now(obj);
- /* Trace the 'obj' to replace pointers to nursery with pointers
- outside the nursery, possibly forcing nursery objects out and
- adding them to 'objects_pointing_to_nursery' as well. */
- char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
- stmcb_trace((struct object_s *)realobj, &minor_trace_if_young);
+ if (obj_sync_now & FLAG_SYNC_LARGE_NOW) {
+ /* synchronize the object to other segments *now* -- which
+ means, just after we added the WRITE_BARRIER flag and
+ traced into it, because tracing might change it again. */
+ synchronize_overflow_object_now(obj);
+ }
}
}
+static void collect_modified_old_objects(void)
+{
+ LIST_FOREACH_R(STM_PSEGMENT->modified_old_objects, object_t * /*item*/,
+ _collect_now(item));
+}
+
static void throw_away_nursery(void)
{
/* reset the nursery by zeroing it */
@@ -181,17 +204,25 @@
STM_PSEGMENT->minor_collect_will_commit_now = commit;
- /* All the objects we move out of the nursery become "overflow"
- objects. We use the list 'objects_pointing_to_nursery'
- to hold the ones we didn't trace so far. */
- if (STM_PSEGMENT->objects_pointing_to_nursery == NULL)
- STM_PSEGMENT->objects_pointing_to_nursery = list_create();
-
/* We need this to track the large overflow objects for a future
commit. We don't need it if we're committing now. */
if (!commit && STM_PSEGMENT->large_overflow_objects == NULL)
STM_PSEGMENT->large_overflow_objects = list_create();
+ /* All the objects we move out of the nursery become "overflow"
+ objects. We use the list 'objects_pointing_to_nursery'
+ to hold the ones we didn't trace so far. */
+ if (STM_PSEGMENT->objects_pointing_to_nursery == NULL) {
+ STM_PSEGMENT->objects_pointing_to_nursery = list_create();
+
+ /* See the doc of 'objects_pointing_to_nursery': if it is NULL,
+ then it is implicitly understood to be equal to
+ 'modified_old_objects'. We could copy modified_old_objects
+ into objects_pointing_to_nursery, but instead we use the
+ following shortcut */
+ collect_modified_old_objects();
+ }
+
collect_roots_in_nursery();
collect_oldrefs_to_nursery();
diff --git a/c7/test/test_random.py b/c7/test/test_random.py
--- a/c7/test/test_random.py
+++ b/c7/test/test_random.py
@@ -164,6 +164,7 @@
def pop_roots(self, ex):
for r in reversed(self.saved_roots[self.roots_on_transaction_start:]):
ex.do('%s = self.pop_root()' % r)
+ ex.do('# 0x%x' % (int(ffi.cast("uintptr_t", ex.content[r])),))
self.roots_on_stack -= 1
assert self.roots_on_stack == self.roots_on_transaction_start
@@ -175,7 +176,8 @@
for r in reversed(to_reload):
ex.do('%s = self.pop_root()' % r)
for r in to_reload:
- ex.do('self.push_root(%s)' % r)
+ ex.do('self.push_root(%s) # 0x%x' % (
+ r, int(ffi.cast("uintptr_t", ex.content[r]))))
def start_transaction(self):
assert self.transaction_state is None
More information about the pypy-commit
mailing list