[pypy-commit] stmgc default: fix writing to write-ready objects after a minor collection
Raemi
noreply at buildbot.pypy.org
Thu Jul 11 06:40:29 CEST 2013
Author: Remi Meier <meierrem at student.ethz.ch>
Branch:
Changeset: r382:191c168da60e
Date: 2013-07-11 06:40 +0200
http://bitbucket.org/pypy/stmgc/changeset/191c168da60e/
Log: fix writing to write-ready objects after a minor collection
diff --git a/c4/nursery.c b/c4/nursery.c
--- a/c4/nursery.c
+++ b/c4/nursery.c
@@ -125,6 +125,9 @@
}
/************************************************************/
+/* list for private/protected, old roots that need to be
+ kept in old_objects_to_trace */
+static __thread struct GcPtrList private_or_protected_roots = {0, 0, NULL};
static inline gcptr create_old_object_copy(gcptr obj)
{
@@ -204,6 +207,22 @@
(revision_t)END_MARKER_ON)) {
/* 'item' is a regular, non-null pointer */
visit_if_young(end);
+
+ /* if old, private or protected, this object needs to be
+ traced again in the next minor_collect if it is
+ currently in old_objects_to_trace. Because then
+ it may be seen as write-ready in the view of
+ someone:
+ pw = write_barrier(); push_root(pw);
+ minor_collect(); pw = pop_root(); // pw still write-ready
+ */
+ if (item && item->h_tid & GCFLAG_OLD
+ && !(item->h_tid & GCFLAG_WRITE_BARRIER) /* not set in
+ obj_to_trace*/
+ && (item->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED
+ || item->h_revision == stm_private_rev_num)) {
+ gcptrlist_insert(&private_or_protected_roots, item);
+ }
}
else if (item != NULL) {
if (item == END_MARKER_OFF)
@@ -358,6 +377,19 @@
stmgc_trace(obj, &visit_if_young);
}
+
+ while (gcptrlist_size(&private_or_protected_roots) > 0) {
+ gcptr obj = gcptrlist_pop(&private_or_protected_roots);
+ /* if it has the write_barrier flag, clear it so that
+ it doesn't get inserted twice by a later write-barrier */
+ if (obj->h_tid & GCFLAG_WRITE_BARRIER) {
+ /* only insert those that were in old_obj_to_trace
+ and that we didn't insert already */
+ obj->h_tid &= ~GCFLAG_WRITE_BARRIER;
+ gcptrlist_insert(&d->old_objects_to_trace, obj);
+ dprintf(("re-add %p to old_objects_to_trace\n", obj));
+ }
+ }
}
static void fix_list_of_read_objects(struct tx_descriptor *d)
@@ -406,7 +438,7 @@
static void teardown_minor_collect(struct tx_descriptor *d)
{
- assert(gcptrlist_size(&d->old_objects_to_trace) == 0);
+ //assert(gcptrlist_size(&d->old_objects_to_trace) == 0);
assert(gcptrlist_size(&d->public_with_young_copy) == 0);
assert(gcptrlist_size(&d->public_descriptor->stolen_objects) == 0);
diff --git a/c4/test/test_et.py b/c4/test/test_et.py
--- a/c4/test/test_et.py
+++ b/c4/test/test_et.py
@@ -205,36 +205,52 @@
assert list_of_read_objects() == [p2]
def test_write_barrier_after_minor_collect():
- # maybe should fail. not sure.
p = oalloc_refs(1)
pw = lib.stm_write_barrier(p)
lib.stm_push_root(pw)
minor_collect()
+ lib.stm_push_root(ffi.NULL)
+ minor_collect()
+ lib.stm_pop_root()
+ minor_collect()
r = nalloc(HDR)
pw = lib.stm_pop_root()
assert pw.h_tid & GCFLAG_OLD
rawsetptr(pw, 0, r)
- # pw not in old_objects_to_trace. A
- # repeated write_barrier before
- # rawsetptr() would fix that
-
+ # pw needs to be readded to old_objects_to_trace
+ # before the next minor gc in order for this test to pass
lib.stm_push_root(r)
minor_collect()
+ minor_collect()
+ minor_collect()
+ q = nalloc(HDR)
r2 = lib.stm_pop_root()
check_nursery_free(r)
pr = lib.stm_read_barrier(p)
assert r != r2
- # these will fail because pw/pr was
- # not traced in the last minor_collect,
- # because they were not registered in
- # old_objects_to_trace.
assert getptr(pr, 0) != r
assert getptr(pr, 0) == r2
+ # the following shouldn't be done
+ # because pw was not saved. Just
+ # here to check that pw gets removed
+ # from old_objects_to_trace when not found
+ # on the root stack anymore
+ rawsetptr(pw, 0, q)
+ lib.stm_push_root(q)
+ minor_collect()
+ q2 = lib.stm_pop_root()
+ check_nursery_free(q)
+ pr = lib.stm_read_barrier(p)
+ assert q != q2
+ assert getptr(pr, 0) == q
+ assert getptr(pr, 0) != q2
+
+
def test_id_young_to_old():
# move out of nursery with shadow original
p = nalloc(HDR)
diff --git a/duhton/listobject.c b/duhton/listobject.c
--- a/duhton/listobject.c
+++ b/duhton/listobject.c
@@ -75,7 +75,7 @@
void _list_append(DuListObject *ob, DuObject *x)
{
- _du_read1(ob);
+ _du_write1(ob);
DuTupleObject *olditems = ob->ob_tuple;
_du_read1(olditems);
@@ -85,8 +85,6 @@
DuTupleObject *newitems = DuTuple_New(newcount);
_du_restore3(ob, x, olditems);
- _du_write1(ob);
-
for (i=0; i<newcount-1; i++)
newitems->ob_items[i] = olditems->ob_items[i];
newitems->ob_items[newcount-1] = x;
More information about the pypy-commit
mailing list