Author: Remi Meier <remi.me...@inf.ethz.ch> Branch: Changeset: r1373:6d1bc582253e Date: 2014-09-09 10:46 +0200 http://bitbucket.org/pypy/stmgc/changeset/6d1bc582253e/
Log: re-add young_outside_nursery and pass all expected tests in test_nursery.py diff --git a/c8/stm/core.c b/c8/stm/core.c --- a/c8/stm/core.c +++ b/c8/stm/core.c @@ -257,18 +257,22 @@ /* remove the WRITE_BARRIER flag */ obj->stm_flags &= ~GCFLAG_WRITE_BARRIER; + /* also add it to the GC list for minor collections */ + LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj); + /* done fiddling with protection and privatization */ release_privatization_lock(my_segnum); /* phew, now add the obj to the write-set and register the backup copy. */ - acquire_modified_objs_lock(my_segnum); - tree_insert(STM_PSEGMENT->modified_old_objects, - (uintptr_t)obj, (uintptr_t)bk_obj); - release_modified_objs_lock(my_segnum); + /* XXX: possibly slow check; try overflow objs again? */ + if (!tree_contains(STM_PSEGMENT->modified_old_objects, (uintptr_t)obj)) { + acquire_modified_objs_lock(my_segnum); + tree_insert(STM_PSEGMENT->modified_old_objects, + (uintptr_t)obj, (uintptr_t)bk_obj); + release_modified_objs_lock(my_segnum); + } - /* also add it to the GC list for minor collections */ - LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, obj); } static void reset_transaction_read_version(void) @@ -321,7 +325,10 @@ assert(tree_is_cleared(STM_PSEGMENT->modified_old_objects)); assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery)); + assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery)); + check_nursery_at_transaction_start(); + stm_validate(NULL); } diff --git a/c8/stm/core.h b/c8/stm/core.h --- a/c8/stm/core.h +++ b/c8/stm/core.h @@ -51,6 +51,8 @@ uint8_t modified_objs_lock; struct tree_s *modified_old_objects; struct list_s *objects_pointing_to_nursery; + struct tree_s *young_outside_nursery; + uint8_t privatization_lock; uint8_t transaction_state; diff --git a/c8/stm/list.h b/c8/stm/list.h --- a/c8/stm/list.h +++ b/c8/stm/list.h @@ -135,10 +135,13 @@ //static inline void tree_delete_not_used_any_more(struct tree_s *tree)... static inline bool tree_is_cleared(struct tree_s *tree) { - assert((tree->raw_current == tree->raw_start) == (tree->count == 0)); return tree->raw_current == tree->raw_start; } +static inline bool tree_is_empty(struct tree_s *tree) { + return tree->count == 0; +} + static inline uintptr_t tree_count(struct tree_s *tree) { assert(tree->count >= 0); return tree->count; diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c --- a/c8/stm/nursery.c +++ b/c8/stm/nursery.c @@ -15,6 +15,7 @@ static void setup_nursery(void) { + assert(_STM_FAST_ALLOC <= NURSERY_SIZE); _stm_nursery_start = NURSERY_START; long i; @@ -32,7 +33,8 @@ static inline bool _is_young(object_t *obj) { - return _is_in_nursery(obj); /* XXX: young_outside_nursery */ + return (_is_in_nursery(obj) || + tree_contains(STM_PSEGMENT->young_outside_nursery, (uintptr_t)obj)); } long stm_can_move(object_t *obj) @@ -83,8 +85,14 @@ *pobj = nobj; } else { - /* XXX: young_outside_nursery */ - return; + /* The object was not in the nursery at all */ + if (LIKELY(!tree_contains(STM_PSEGMENT->young_outside_nursery, + (uintptr_t)obj))) + return; /* common case: it was an old object, nothing to do */ + + /* a young object outside the nursery */ + nobj = obj; + tree_delete_item(STM_PSEGMENT->young_outside_nursery, (uintptr_t)nobj); } /* Must trace the object later */ @@ -177,12 +185,37 @@ pseg->pub.nursery_current = (stm_char *)_stm_nursery_start; + /* free any object left from 'young_outside_nursery' */ + if (!tree_is_cleared(pseg->young_outside_nursery)) { + wlog_t *item; + + if (!tree_is_empty(pseg->young_outside_nursery)) { + /* tree may still be empty even if not cleared */ + TREE_LOOP_FORWARD(pseg->young_outside_nursery, item) { + object_t *obj = (object_t*)item->addr; + assert(!_is_in_nursery(obj)); + + /* mark slot as unread (it can only have the read marker + in this segment) */ + *((char *)(pseg->pub.segment_base + (((uintptr_t)obj) >> 4))) = 0; + + /* XXX: _stm_large_free(stm_object_pages + item->addr); */ + } TREE_LOOP_END; + } + + tree_clear(pseg->young_outside_nursery); + } + return nursery_used; #pragma pop_macro("STM_SEGMENT") #pragma pop_macro("STM_PSEGMENT") } +#define MINOR_NOTHING_TO_DO(pseg) \ + ((pseg)->pub.nursery_current == (stm_char *)_stm_nursery_start && \ + tree_is_cleared((pseg)->young_outside_nursery)) + static void _do_minor_collection(bool commit) { @@ -195,6 +228,8 @@ assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery)); throw_away_nursery(get_priv_segment(STM_SEGMENT->segment_num)); + + assert(MINOR_NOTHING_TO_DO(STM_PSEGMENT)); } static void minor_collection(bool commit) @@ -227,6 +262,7 @@ OPT_ASSERT(size_rounded_up >= 16); OPT_ASSERT((size_rounded_up & 7) == 0); + OPT_ASSERT(size_rounded_up < _STM_FAST_ALLOC); stm_char *p = STM_SEGMENT->nursery_current; stm_char *end = p + size_rounded_up; @@ -239,6 +275,26 @@ goto restart; } +object_t *_stm_allocate_external(ssize_t size_rounded_up) +{ + /* /\* first, force a collection if needed *\/ */ + /* if (is_major_collection_requested()) { */ + /* /\* use stm_collect() with level 0: if another thread does a major GC */ + /* in-between, is_major_collection_requested() will become false */ + /* again, and we'll avoid doing yet another one afterwards. *\/ */ + /* stm_collect(0); */ + /* } */ + + char *result = allocate_outside_nursery_large(size_rounded_up); + object_t *o = (object_t *)(result - stm_object_pages); + + tree_insert(STM_PSEGMENT->young_outside_nursery, (uintptr_t)o, 0); + + memset(REAL_ADDRESS(STM_SEGMENT->segment_base, o), 0, size_rounded_up); + return o; +} + + #ifdef STM_TESTS void _stm_set_nursery_free_count(uint64_t free_count) { diff --git a/c8/stm/setup.c b/c8/stm/setup.c --- a/c8/stm/setup.c +++ b/c8/stm/setup.c @@ -87,6 +87,7 @@ assert((NB_PAGES * 4096UL) >> 8 <= (FIRST_OBJECT_PAGE * 4096UL) >> 4); assert((END_NURSERY_PAGE * 4096UL) >> 8 <= (FIRST_READMARKER_PAGE * 4096UL)); + assert(_STM_FAST_ALLOC <= NB_NURSERY_PAGES * 4096); stm_object_pages = setup_mmap("initial stm_object_pages mmap()", &stm_object_pages_fd); @@ -109,6 +110,7 @@ pr->pub.segment_base = segment_base; pr->modified_old_objects = tree_create(); pr->objects_pointing_to_nursery = list_create(); + pr->young_outside_nursery = tree_create(); pr->last_commit_log_entry = &commit_log_root; pr->pub.transaction_read_version = 0xff; } @@ -140,6 +142,7 @@ assert(list_is_empty(pr->objects_pointing_to_nursery)); list_free(pr->objects_pointing_to_nursery); tree_free(pr->modified_old_objects); + tree_free(pr->young_outside_nursery); } munmap(stm_object_pages, TOTAL_MEMORY); diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -55,10 +55,11 @@ } stm_thread_local_t; #define _STM_GCFLAG_WRITE_BARRIER 0x01 - +#define _STM_FAST_ALLOC (66*1024) void _stm_write_slowpath(object_t *); object_t *_stm_allocate_slowpath(ssize_t); +object_t *_stm_allocate_external(ssize_t); void _stm_become_inevitable(const char*); object_t *_stm_allocate_old(ssize_t size_rounded_up); @@ -133,6 +134,9 @@ OPT_ASSERT(size_rounded_up >= 16); OPT_ASSERT((size_rounded_up & 7) == 0); + if (UNLIKELY(size_rounded_up >= _STM_FAST_ALLOC)) + return _stm_allocate_external(size_rounded_up); + stm_char *p = STM_SEGMENT->nursery_current; stm_char *end = p + size_rounded_up; STM_SEGMENT->nursery_current = end; diff --git a/c8/test/support.py b/c8/test/support.py --- a/c8/test/support.py +++ b/c8/test/support.py @@ -10,6 +10,7 @@ #define SIZEOF_MYOBJ ... #define STM_NB_SEGMENTS ... #define _STM_GCFLAG_WRITE_BARRIER ... +#define _STM_FAST_ALLOC ... typedef struct { ...; @@ -66,6 +67,7 @@ void _set_ptr(object_t *obj, int n, object_t *v); object_t * _get_ptr(object_t *obj, int n); +void stm_collect(long level); void _stm_set_nursery_free_count(uint64_t free_count); @@ -242,6 +244,7 @@ assert HDR == 8 GCFLAG_WRITE_BARRIER = lib._STM_GCFLAG_WRITE_BARRIER NB_SEGMENTS = lib.STM_NB_SEGMENTS +FAST_ALLOC = lib._STM_FAST_ALLOC class Conflict(Exception): pass diff --git a/c8/test/test_nursery.py b/c8/test/test_nursery.py --- a/c8/test/test_nursery.py +++ b/c8/test/test_nursery.py @@ -82,6 +82,7 @@ assert young def test_larger_than_limit_for_nursery_die(self): + py.test.xfail() obj_size = lib._STM_FAST_ALLOC + 16 self.start_transaction() @@ -120,6 +121,7 @@ assert not lp1 def test_account_for_privatized_page(self): + py.test.xfail() self.start_transaction() obj = stm_allocate(16) self.push_root(obj) @@ -180,6 +182,7 @@ self.start_transaction() stm_write(old) # old objs to trace stm_set_char(old, 'x') + assert objects_pointing_to_nursery() == [old] stm_minor_collect() stm_write(old) # old objs to trace stm_set_char(old, 'y') @@ -199,6 +202,7 @@ assert lib.stm_can_move(old) == 0 def test_marker_1(self): + py.test.xfail() self.start_transaction() p1 = stm_allocate(600) stm_set_char(p1, 'o') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit