Author: Armin Rigo <ar...@tunes.org> Branch: marker Changeset: r1180:3cdcd273d6d3 Date: 2014-04-23 17:01 +0200 http://bitbucket.org/pypy/stmgc/changeset/3cdcd273d6d3/
Log: in-progress: record markers corresponding to old_modified_objects diff --git a/c7/stm/core.c b/c7/stm/core.c --- a/c7/stm/core.c +++ b/c7/stm/core.c @@ -86,6 +86,13 @@ Add it to the list 'modified_old_objects'. */ LIST_APPEND(STM_PSEGMENT->modified_old_objects, obj); + /* Add the current marker, recording where we wrote to this object */ + uintptr_t marker[2]; + marker_fetch(STM_SEGMENT->running_thread, marker); + STM_PSEGMENT->modified_old_objects_markers = + list_append2(STM_PSEGMENT->modified_old_objects_markers, + marker[0], marker[1]); + /* We need to privatize the pages containing the object, if they are still SHARED_PAGE. The common case is that there is only one page in total. */ @@ -223,12 +230,17 @@ } assert(list_is_empty(STM_PSEGMENT->modified_old_objects)); + assert(list_is_empty(STM_PSEGMENT->modified_old_objects_markers)); assert(list_is_empty(STM_PSEGMENT->young_weakrefs)); assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery)); assert(tree_is_cleared(STM_PSEGMENT->nursery_objects_shadows)); assert(tree_is_cleared(STM_PSEGMENT->callbacks_on_abort)); assert(STM_PSEGMENT->objects_pointing_to_nursery == NULL); assert(STM_PSEGMENT->large_overflow_objects == NULL); +#ifndef NDEBUG + /* this should not be used when objects_pointing_to_nursery == NULL */ + STM_PSEGMENT->modified_old_objects_markers_num_old = 99999999999999999L; +#endif check_nursery_at_transaction_start(); } @@ -458,6 +470,7 @@ })); list_clear(STM_PSEGMENT->modified_old_objects); + list_clear(STM_PSEGMENT->modified_old_objects_markers); } static void _finish_transaction(int attribute_to) @@ -596,6 +609,7 @@ })); list_clear(pseg->modified_old_objects); + list_clear(pseg->modified_old_objects_markers); } static void abort_data_structures_from_segment_num(int segment_num) diff --git a/c7/stm/core.h b/c7/stm/core.h --- a/c7/stm/core.h +++ b/c7/stm/core.h @@ -78,9 +78,17 @@ /* List of old objects (older than the current transaction) that the current transaction attempts to modify. This is used to track the STM status: they are old objects that where written to and - that need to be copied to other segments upon commit. */ + that need to be copied to other segments upon commit. Note that + every object takes three list items: the object, and two words for + the location marker. */ struct list_s *modified_old_objects; + /* For each entry in 'modified_old_objects', we have two entries + in the following list, which give the marker at the time we added + the entry to modified_old_objects. */ + struct list_s *modified_old_objects_markers; + uintptr_t modified_old_objects_markers_num_old; + /* List of out-of-nursery objects that may contain pointers to nursery objects. This is used to track the GC status: they are all objects outside the nursery on which an stm_write() occurred diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c --- a/c7/stm/gcpage.c +++ b/c7/stm/gcpage.c @@ -418,6 +418,19 @@ } } +static void mark_visit_from_markers(void) +{ + long j; + for (j = 1; j <= NB_SEGMENTS; j++) { + char *base = get_segment_base(j); + struct list_s *lst = get_priv_segment(j)->modified_old_objects_markers; + uintptr_t i; + for (i = list_count(lst); i > 0; i -= 2) { + mark_visit_object((object_t *)list_item(lst, i - 1), base); + } + } +} + static void clean_up_segment_lists(void) { long i; @@ -520,6 +533,7 @@ /* marking */ LIST_CREATE(mark_objects_to_trace); mark_visit_from_modified_objects(); + mark_visit_from_markers(); mark_visit_from_roots(); LIST_FREE(mark_objects_to_trace); diff --git a/c7/stm/list.h b/c7/stm/list.h --- a/c7/stm/list.h +++ b/c7/stm/list.h @@ -33,6 +33,18 @@ #define LIST_APPEND(lst, e) ((lst) = list_append((lst), (uintptr_t)(e))) +static inline struct list_s *list_append2(struct list_s *lst, + uintptr_t item0, uintptr_t item1) +{ + uintptr_t index = lst->count; + lst->count += 2; + if (UNLIKELY(index >= lst->last_allocated)) + lst = _list_grow(lst, index + 1); + lst->items[index + 0] = item0; + lst->items[index + 1] = item1; + return lst; +} + static inline void list_clear(struct list_s *lst) { @@ -66,6 +78,11 @@ lst->items[index] = newitem; } +static inline uintptr_t *list_ptr_to_item(struct list_s *lst, uintptr_t index) +{ + return &lst->items[index]; +} + #define LIST_FOREACH_R(lst, TYPE, CODE) \ do { \ struct list_s *_lst = (lst); \ diff --git a/c7/stm/marker.c b/c7/stm/marker.c --- a/c7/stm/marker.c +++ b/c7/stm/marker.c @@ -11,38 +11,53 @@ const char *marker); +static void marker_fetch(stm_thread_local_t *tl, uintptr_t marker[2]) +{ + struct stm_shadowentry_s *current = tl->shadowstack - 1; + struct stm_shadowentry_s *base = tl->shadowstack_base; + /* stop walking just before shadowstack_base, which contains + STM_STACK_MARKER_OLD which shouldn't be expanded */ + while (--current > base) { + if (((uintptr_t)current->ss) & 1) { + /* found the odd marker */ + marker[0] = (uintptr_t)current[0].ss; + marker[1] = (uintptr_t)current[1].ss; + return; + } + } + marker[0] = 0; + marker[1] = 0; +} + +static void marker_expand(uintptr_t marker[2], char *segment_base, + char *outmarker) +{ + if (marker[0] == 0) + return; /* no marker entry found */ + if (outmarker[0] != 0) + return; /* already collected an entry */ + if (stmcb_expand_marker != NULL) { + stmcb_expand_marker(segment_base, marker[0], (object_t *)marker[1], + outmarker, _STM_MARKER_LEN); + } +} + static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg) { - if (pseg->marker_self[0] != 0) - return; /* already collected an entry */ - - if (stmcb_expand_marker != NULL) { - stm_thread_local_t *tl = pseg->pub.running_thread; - struct stm_shadowentry_s *current = tl->shadowstack - 1; - struct stm_shadowentry_s *base = tl->shadowstack_base; - /* stop walking just before shadowstack_base, which contains - STM_STACK_MARKER_OLD which shouldn't be expanded */ - while (--current > base) { - uintptr_t x = (uintptr_t)current->ss; - if (x & 1) { - /* the stack entry is an odd number */ - stmcb_expand_marker(pseg->pub.segment_base, x, current[1].ss, - pseg->marker_self, _STM_MARKER_LEN); - - if (pseg->marker_self[0] != 0) - break; - } - } - } + uintptr_t marker[2]; + marker_fetch(pseg->pub.running_thread, marker); + marker_expand(marker, pseg->pub.segment_base, pseg->marker_self); } char *_stm_expand_marker(void) { - struct stm_priv_segment_info_s *pseg = - get_priv_segment(STM_SEGMENT->segment_num); - pseg->marker_self[0] = 0; - marker_fetch_expand(pseg); - return pseg->marker_self; + /* for tests only! */ + static char _result[_STM_MARKER_LEN]; + uintptr_t marker[2]; + _result[0] = 0; + marker_fetch(STM_SEGMENT->running_thread, marker); + marker_expand(marker, STM_SEGMENT->segment_base, _result); + return _result; } static void marker_copy(stm_thread_local_t *tl, diff --git a/c7/stm/marker.h b/c7/stm/marker.h --- a/c7/stm/marker.h +++ b/c7/stm/marker.h @@ -1,4 +1,7 @@ +static void marker_fetch(stm_thread_local_t *tl, uintptr_t marker[2]); +static void marker_expand(uintptr_t marker[2], char *segment_base, + char *outmarker); static void marker_fetch_expand(struct stm_priv_segment_info_s *pseg); static void marker_copy(stm_thread_local_t *tl, struct stm_priv_segment_info_s *pseg, diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c --- a/c7/stm/nursery.c +++ b/c7/stm/nursery.c @@ -232,6 +232,18 @@ _collect_now(item)); } +static void collect_roots_from_markers(uintptr_t num_old) +{ + /* visit the marker objects */ + struct list_s *mlst = STM_PSEGMENT->modified_old_objects_markers; + STM_PSEGMENT->modified_old_objects_markers_num_old = list_count(mlst); + uintptr_t i, total = list_count(mlst); + assert((total & 1) == 0); + for (i = num_old + 1; i < total; i += 2) { + minor_trace_if_young((object_t **)list_ptr_to_item(mlst, i)); + } +} + static size_t throw_away_nursery(struct stm_priv_segment_info_s *pseg) { /* reset the nursery by zeroing it */ @@ -296,6 +308,7 @@ /* All the objects we move out of the nursery become "overflow" objects. We use the list 'objects_pointing_to_nursery' to hold the ones we didn't trace so far. */ + uintptr_t num_old; if (STM_PSEGMENT->objects_pointing_to_nursery == NULL) { STM_PSEGMENT->objects_pointing_to_nursery = list_create(); @@ -305,7 +318,12 @@ into objects_pointing_to_nursery, but instead we use the following shortcut */ collect_modified_old_objects(); + num_old = 0; } + else + num_old = STM_PSEGMENT->modified_old_objects_markers_num_old; + + collect_roots_from_markers(num_old); collect_roots_in_nursery(); diff --git a/c7/stm/setup.c b/c7/stm/setup.c --- a/c7/stm/setup.c +++ b/c7/stm/setup.c @@ -78,6 +78,7 @@ pr->objects_pointing_to_nursery = NULL; pr->large_overflow_objects = NULL; pr->modified_old_objects = list_create(); + pr->modified_old_objects_markers = list_create(); pr->young_weakrefs = list_create(); pr->old_weakrefs = list_create(); pr->young_outside_nursery = tree_create(); @@ -115,6 +116,7 @@ assert(pr->objects_pointing_to_nursery == NULL); assert(pr->large_overflow_objects == NULL); list_free(pr->modified_old_objects); + list_free(pr->modified_old_objects_markers); list_free(pr->young_weakrefs); list_free(pr->old_weakrefs); tree_free(pr->young_outside_nursery); diff --git a/c7/test/test_marker.py b/c7/test/test_marker.py --- a/c7/test/test_marker.py +++ b/c7/test/test_marker.py @@ -159,8 +159,6 @@ @ffi.callback("void(char *, uintptr_t, object_t *, char *, size_t)") def expand_marker(base, number, ptr, outbuf, outbufsize): seen.append(number) - if ptr == ffi.NULL: - return s = '%d %r\x00' % (number, ptr) assert len(s) <= outbufsize outbuf[0:len(s)] = s @@ -174,8 +172,8 @@ self.push_root(ffi.cast("object_t *", 29)) self.push_root(ffi.cast("object_t *", ffi.NULL)) raw = lib._stm_expand_marker() - assert ffi.string(raw) == '27 %r' % (p,) - assert seen == [29, 27] + assert ffi.string(raw).startswith('29 ') + assert seen == [29] def test_double_abort_markers_cb(self): @ffi.callback("void(char *, uintptr_t, object_t *, char *, size_t)") @@ -190,6 +188,10 @@ self.push_root(ffi.cast("object_t *", 19)) self.push_root(ffi.cast("object_t *", ffi.NULL)) stm_set_char(p, 'A') + self.pop_root() + self.pop_root() + self.push_root(ffi.cast("object_t *", 17)) + self.push_root(ffi.cast("object_t *", ffi.NULL)) # self.switch(1) self.start_transaction() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit