Author: Remi Meier <remi.me...@inf.ethz.ch> Branch: Changeset: r1339:99ad13731c25 Date: 2014-09-03 13:33 +0200 http://bitbucket.org/pypy/stmgc/changeset/99ad13731c25/
Log: do simple minor collections diff --git a/c8/stm/gcpage.h b/c8/stm/gcpage.h --- a/c8/stm/gcpage.h +++ b/c8/stm/gcpage.h @@ -5,3 +5,4 @@ static void setup_gcpage(void); static void teardown_gcpage(void); +static char *allocate_outside_nursery_large(uint64_t size); diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c --- a/c8/stm/nursery.c +++ b/c8/stm/nursery.c @@ -30,6 +30,11 @@ return (uintptr_t)obj < NURSERY_END; } +static inline bool _is_young(object_t *obj) +{ + return _is_in_nursery(obj); /* XXX: young_outside_nursery */ +} + long stm_can_move(object_t *obj) { /* 'long' return value to avoid using 'bool' in the public interface */ @@ -38,6 +43,83 @@ /************************************************************/ +#define GCWORD_MOVED ((object_t *) -1) + +static void minor_trace_if_young(object_t **pobj) +{ + /* takes a normal pointer to a thread-local pointer to an object */ + object_t *obj = *pobj; + object_t *nobj; + char *realobj; + size_t size; + + if (obj == NULL) + return; + assert((uintptr_t)obj < NB_PAGES * 4096UL); + + if (_is_in_nursery(obj)) { + /* If the object was already seen here, its first word was set + to GCWORD_MOVED. In that case, the forwarding location, i.e. + where the object moved to, is stored in the second word in 'obj'. */ + object_t *TLPREFIX *pforwarded_array = (object_t *TLPREFIX *)obj; + + realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj); + size = stmcb_size_rounded_up((struct object_s *)realobj); + + /* XXX: small objs */ + char *allocated = allocate_outside_nursery_large(size); + nobj = (object_t *)(allocated - stm_object_pages); + + char *realnobj = REAL_ADDRESS(STM_SEGMENT->segment_base, nobj); + memcpy(realnobj, realobj, size); + + pforwarded_array[0] = GCWORD_MOVED; + pforwarded_array[1] = nobj; + *pobj = nobj; + } + else { + /* XXX: young_outside_nursery */ + return; + } + + /* Must trace the object later */ + LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, (uintptr_t)nobj); +} + + +static inline void _collect_now(object_t *obj) +{ + assert(!_is_young(obj)); + + dprintf(("_collect_now: %p\n", obj)); + + assert(!(obj->stm_flags & GCFLAG_WRITE_BARRIER)); + + char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj); + stmcb_trace((struct object_s *)realobj, &minor_trace_if_young); + + obj->stm_flags |= GCFLAG_WRITE_BARRIER; +} + + +static void collect_oldrefs_to_nursery(void) +{ + dprintf(("collect_oldrefs_to_nursery\n")); + struct list_s *lst = STM_PSEGMENT->objects_pointing_to_nursery; + + while (!list_is_empty(lst)) { + object_t *obj = (object_t *)list_pop_item(lst);; + + _collect_now(obj); + + /* XXX: only if commit now and only for big objs */ + _push_obj_to_other_segments(obj); + + /* the list could have moved while appending */ + lst = STM_PSEGMENT->objects_pointing_to_nursery; + } +} + static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg) { @@ -77,6 +159,8 @@ { dprintf(("minor_collection commit=%d\n", (int)commit)); + collect_oldrefs_to_nursery(); + assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery)); throw_away_nursery(get_priv_segment(STM_SEGMENT->segment_num)); diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -109,6 +109,7 @@ }; extern ssize_t stmcb_size_rounded_up(struct object_s *); +void stmcb_trace(struct object_s *obj, void visit(object_t **)); __attribute__((always_inline)) static inline void stm_read(object_t *obj) diff --git a/c8/test/support.py b/c8/test/support.py --- a/c8/test/support.py +++ b/c8/test/support.py @@ -182,6 +182,22 @@ } } + +void stmcb_trace(struct object_s *obj, void visit(object_t **)) +{ + int i; + struct myobj_s *myobj = (struct myobj_s*)obj; + if (myobj->type_id < 421420) { + /* basic case: no references */ + return; + } + for (i=0; i < myobj->type_id - 421420; i++) { + object_t **ref = ((object_t **)(myobj + 1)) + i; + visit(ref); + } +} + + ''', sources=source_files, define_macros=[('STM_TESTS', '1'), ('STM_NO_AUTOMATIC_SETJMP', '1'), diff --git a/c8/test/test_basic.py b/c8/test/test_basic.py --- a/c8/test/test_basic.py +++ b/c8/test/test_basic.py @@ -62,6 +62,7 @@ def test_write_on_old(self): lp1 = stm_allocate_old(16) + self.start_transaction() assert stm_get_char(lp1) == '\0' stm_write(lp1) @@ -80,6 +81,8 @@ def test_read_write_1(self): lp1 = stm_allocate_old(16) stm_get_real_address(lp1)[HDR] = 'a' #setchar + lib._push_obj_to_other_segments(lp1) + # self.start_transaction() self.commit_transaction() # @@ -88,7 +91,7 @@ assert modified_old_objects() == [] stm_write(lp1) assert modified_old_objects() == [lp1] - assert objects_pointing_to_nursery() == None + assert objects_pointing_to_nursery() == [lp1] assert stm_get_char(lp1) == 'a' stm_set_char(lp1, 'b') # _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit