Author: Remi Meier <meier...@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; _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit