Author: Armin Rigo <ar...@tunes.org> Branch: c7-refactor Changeset: r854:4302246a0ad0 Date: 2014-02-25 09:50 +0100 http://bitbucket.org/pypy/stmgc/changeset/4302246a0ad0/
Log: Actually implement surviving young_outside_nursery diff --git a/c7/stm/core.c b/c7/stm/core.c --- a/c7/stm/core.c +++ b/c7/stm/core.c @@ -12,7 +12,7 @@ void _stm_write_slowpath(object_t *obj) { assert(_running_transaction()); - assert(!_is_in_nursery(obj)); + assert(!_is_young(obj)); /* is this an object from the same transaction, outside the nursery? */ if ((obj->stm_flags & -GCFLAG_OVERFLOW_NUMBER_bit0) == @@ -225,7 +225,7 @@ static void synchronize_overflow_object_now(object_t *obj) { - assert(!_is_in_nursery(obj)); + assert(!_is_young(obj)); assert((obj->stm_flags & GCFLAG_SMALL_UNIFORM) == 0); char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj); diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c --- a/c7/stm/nursery.c +++ b/c7/stm/nursery.c @@ -42,6 +42,12 @@ return (uintptr_t)obj < NURSERY_END; } +static inline bool _is_young(object_t *obj) +{ + return (_is_in_nursery(obj) || + tree_contains(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj)); +} + bool _stm_in_nursery(object_t *obj) { return _is_in_nursery(obj); @@ -54,6 +60,19 @@ #define FLAG_SYNC_LARGE_NOW 0x01 +static void minor_young_outside_nursery(object_t *obj) +{ + tree_delete_item(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj); + + uintptr_t nobj_sync_now = (uintptr_t)obj; + if (STM_PSEGMENT->minor_collect_will_commit_now) + nobj_sync_now |= FLAG_SYNC_LARGE_NOW; + else + LIST_APPEND(STM_PSEGMENT->large_overflow_objects, obj); + + LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now); +} + static void minor_trace_if_young(object_t **pobj) { /* takes a normal pointer to a thread-local pointer to an object */ @@ -61,8 +80,13 @@ if (obj == NULL) return; assert((uintptr_t)obj < NB_PAGES * 4096UL); - if (!_is_in_nursery(obj)) - return; + if (!_is_in_nursery(obj)) { + if (UNLIKELY(tree_contains(STM_PSEGMENT->young_outside_nursery, + (uintptr_t)obj))) { + minor_young_outside_nursery(obj); + } + return; /* else old object, nothing to do */ + } /* If the object was already seen here, its first word was set to GCWORD_MOVED. In that case, the forwarding location, i.e. @@ -133,7 +157,7 @@ static inline void _collect_now(object_t *obj) { - assert(!_is_in_nursery(obj)); + assert(!_is_young(obj)); /* We must not have GCFLAG_WRITE_BARRIER so far. Add it now. */ assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER)); diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py --- a/c7/test/test_nursery.py +++ b/c7/test/test_nursery.py @@ -81,7 +81,7 @@ assert old assert young - def test_larger_than_limit_for_nursery(self): + def test_larger_than_limit_for_nursery_die(self): obj_size = lib._STM_FAST_ALLOC + 16 self.start_transaction() @@ -93,6 +93,28 @@ seen.add(new) assert len(seen) < 5 # addresses are reused + def test_larger_than_limit_for_nursery_dont_die(self): + obj_nrefs = (lib._STM_FAST_ALLOC + 16) // 8 + + self.start_transaction() + lp1 = ffi.cast("object_t *", 0) + seen = set() + for i in range(100): + self.push_root(lp1) + stm_minor_collect() + lp1 = self.pop_root() + new = stm_allocate_refs(obj_nrefs) + assert not is_in_nursery(new) + seen.add(new) + stm_set_ref(new, i, lp1) + lp1 = new + assert len(seen) == 100 # addresses are not reused + + for i in reversed(range(100)): + assert lp1 + lp1 = stm_get_ref(lp1, i) + assert not lp1 + def test_reset_partial_alloc_pages(self): py.test.skip("a would-be-nice feature, but not actually needed: " "the next major GC will take care of it") _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit