Author: Remi Meier Branch: c7-weakref Changeset: r986:510710368671 Date: 2014-03-12 17:21 +0100 http://bitbucket.org/pypy/stmgc/changeset/510710368671/
Log: consider major collections diff --git a/c7/stm/core.h b/c7/stm/core.h --- a/c7/stm/core.h +++ b/c7/stm/core.h @@ -111,11 +111,12 @@ struct tree_s *nursery_objects_shadows; /* List of all young weakrefs to check in minor collections. These - are the only weakrefs that may point to young objects. */ + are the only weakrefs that may point to young objects and never + contain NULL. */ struct list_s *young_weakrefs; /* List of all old weakrefs to check in major collections. These - weakrefs never point to young objects */ + weakrefs never point to young objects and never contain NULL. */ struct list_s *old_weakrefs; /* Tree of 'key->callback' associations from stm_call_on_abort() */ diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c --- a/c7/stm/gcpage.c +++ b/c7/stm/gcpage.c @@ -450,7 +450,11 @@ /* 'objects_pointing_to_nursery' should be empty, but isn't necessarily because it also lists objects that have been written to but don't actually point to the nursery. Clear - it up and set GCFLAG_WRITE_BARRIER again on the objects. */ + it up and set GCFLAG_WRITE_BARRIER again on the objects. + This is the case for transactions where + MINOR_NOTHING_TO_DO() == false + but they still did write-barriers on objects + */ lst = pseg->objects_pointing_to_nursery; if (lst != NULL) { LIST_FOREACH_R(lst, uintptr_t /*item*/, @@ -537,6 +541,9 @@ mark_visit_from_roots(); LIST_FREE(mark_objects_to_trace); + /* weakrefs: */ + stm_visit_old_weakrefs(); + /* cleanup */ clean_up_segment_lists(); diff --git a/c7/stm/weakref.c b/c7/stm/weakref.c --- a/c7/stm/weakref.c +++ b/c7/stm/weakref.c @@ -86,141 +86,38 @@ /***** Major collection *****/ -/* static _Bool is_partially_visited(gcptr obj) */ -/* { */ -/* /\* Based on gcpage.c:visit_public(). Check the code here if we change */ -/* visit_public(). Returns True or False depending on whether we find any */ -/* version of 'obj' to be MARKED or not. */ -/* *\/ */ -/* assert(IMPLIES(obj->h_tid & GCFLAG_VISITED, */ -/* obj->h_tid & GCFLAG_MARKED)); */ -/* if (obj->h_tid & GCFLAG_MARKED) */ -/* return 1; */ -/* /\* if (!(obj->h_tid & GCFLAG_PUBLIC)) *\/ */ -/* /\* return 0; *\/ */ -/* assert(!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL)); */ -/* if (obj->h_original != 0) { */ -/* gcptr original = (gcptr)obj->h_original; */ -/* assert(IMPLIES(original->h_tid & GCFLAG_VISITED, */ -/* original->h_tid & GCFLAG_MARKED)); */ -/* if (original->h_tid & GCFLAG_MARKED) */ -/* return 1; */ -/* } */ -/* return 0; */ -/* } */ +void stm_visit_old_weakrefs(void) +{ + long i; + for (i = 0; i < NB_SEGMENTS; i++) { + struct stm_priv_segment_info_s *pseg = get_priv_segment(i); + struct list_s *lst; -/* static void update_old_weakrefs_list(struct tx_public_descriptor *gcp) */ -/* { */ -/* long i, size = gcp->old_weakrefs.size; */ -/* gcptr *items = gcp->old_weakrefs.items; */ + lst = pseg->old_weakrefs; + uintptr_t n = list_count(lst); + while (n > 0) { + object_t *weakref = (object_t *)list_item(lst, --n); + if (!mark_visited_test(weakref)) { + /* weakref dies */ + list_set_item(lst, n, list_pop_item(lst)); + continue; + } -/* for (i = 0; i < size; i++) { */ -/* gcptr weakref = items[i]; */ + char *realobj = REAL_ADDRESS(pseg->pub.segment_base, weakref); + ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj); + object_t *pointing_to = *WEAKREF_PTR(weakref, size); + assert(pointing_to != NULL); + if (!mark_visited_test(pointing_to)) { + *WEAKREF_PTR(weakref, size) = NULL; -/* /\* if a weakref moved, update its position in the list *\/ */ -/* if (weakref->h_tid & GCFLAG_MOVED) { */ -/* items[i] = (gcptr)weakref->h_original; */ -/* } */ -/* } */ -/* } */ - -/* static void visit_old_weakrefs(struct tx_public_descriptor *gcp) */ -/* { */ -/* /\* Note: it's possible that a weakref points to a public stub to a */ -/* protected object, and only the protected object was marked as */ -/* VISITED so far. In this case, this function needs to mark the */ -/* public stub as VISITED too. */ -/* *\/ */ -/* long i, size = gcp->old_weakrefs.size; */ -/* gcptr *items = gcp->old_weakrefs.items; */ - -/* for (i = 0; i < size; i++) { */ -/* gcptr weakref = items[i]; */ - -/* if (!(weakref->h_tid & GCFLAG_VISITED)) { */ -/* /\* the weakref itself dies *\/ */ -/* } */ -/* else { */ -/* /\* the weakref belongs to our thread, therefore we should */ -/* always see the most current revision here: *\/ */ -/* assert(weakref->h_revision & 1); */ - -/* size_t size = stmgc_size(weakref); */ -/* gcptr pointing_to = *WEAKREF_PTR(weakref, size); */ -/* assert(pointing_to != NULL); */ -/* if (is_partially_visited(pointing_to)) { */ -/* pointing_to = stmgcpage_visit(pointing_to); */ -/* dprintf(("mweakref ptr moved %p->%p\n", */ -/* *WEAKREF_PTR(weakref, size), */ -/* pointing_to)); */ - -/* assert(pointing_to->h_tid & GCFLAG_VISITED); */ -/* *WEAKREF_PTR(weakref, size) = pointing_to; */ -/* } */ -/* else { */ -/* /\* the weakref appears to be pointing to a dying object, */ -/* but we don't know for sure now. Clearing it is left */ -/* to clean_old_weakrefs(). *\/ */ -/* } */ -/* } */ -/* } */ -/* } */ - -/* static void clean_old_weakrefs(struct tx_public_descriptor *gcp) */ -/* { */ -/* long i, size = gcp->old_weakrefs.size; */ -/* gcptr *items = gcp->old_weakrefs.items; */ - -/* for (i = size - 1; i >= 0; i--) { */ -/* gcptr weakref = items[i]; */ -/* assert(weakref->h_revision & 1); */ -/* if (weakref->h_tid & GCFLAG_VISITED) { */ -/* size_t size = stmgc_size(weakref); */ -/* gcptr pointing_to = *WEAKREF_PTR(weakref, size); */ -/* if (pointing_to->h_tid & GCFLAG_VISITED) { */ -/* continue; /\* the target stays alive, the weakref remains *\/ */ -/* } */ -/* dprintf(("mweakref lost ptr %p\n", *WEAKREF_PTR(weakref, size))); */ -/* *WEAKREF_PTR(weakref, size) = NULL; /\* the target dies *\/ */ -/* } */ -/* /\* remove this weakref from the list *\/ */ -/* items[i] = items[--gcp->old_weakrefs.size]; */ -/* } */ -/* gcptrlist_compress(&gcp->old_weakrefs); */ -/* } */ - -/* static void for_each_public_descriptor( */ -/* void visit(struct tx_public_descriptor *)) { */ -/* struct tx_descriptor *d; */ -/* for (d = stm_tx_head; d; d = d->tx_next) */ -/* visit(d->public_descriptor); */ - -/* struct tx_public_descriptor *gcp; */ -/* revision_t index = -1; */ -/* while ((gcp = stm_get_free_public_descriptor(&index)) != NULL) */ -/* visit(gcp); */ -/* } */ - -/* void stm_update_old_weakrefs_lists(void) */ -/* { */ -/* /\* go over old weakrefs lists and update the list with possibly */ -/* new pointers because of copy_over_original *\/ */ -/* for_each_public_descriptor(update_old_weakrefs_list); */ -/* } */ - - -/* void stm_visit_old_weakrefs(void) */ -/* { */ -/* /\* Figure out which weakrefs survive, which possibly */ -/* adds more objects to 'objects_to_trace'. */ -/* *\/ */ -/* for_each_public_descriptor(visit_old_weakrefs); */ -/* } */ - -/* void stm_clean_old_weakrefs(void) */ -/* { */ -/* /\* Clean up the non-surviving weakrefs */ -/* *\/ */ -/* for_each_public_descriptor(clean_old_weakrefs); */ -/* } */ + /* we don't need it in this list anymore */ + list_set_item(lst, n, list_pop_item(lst)); + continue; + } + else { + /* it survives! */ + } + } + } +} diff --git a/c7/stm/weakref.h b/c7/stm/weakref.h --- a/c7/stm/weakref.h +++ b/c7/stm/weakref.h @@ -5,9 +5,7 @@ #define WEAKREF_PTR(wr, sz) ((object_t * TLPREFIX *)(((stm_char *)(wr)) + (sz) - sizeof(void*))) void stm_move_young_weakrefs(void); -/* void stm_update_old_weakrefs_lists(void); */ -/* void stm_visit_old_weakrefs(void); */ -/* void stm_clean_old_weakrefs(void); */ +void stm_visit_old_weakrefs(void); #endif diff --git a/c7/stmgc.h b/c7/stmgc.h --- a/c7/stmgc.h +++ b/c7/stmgc.h @@ -195,7 +195,7 @@ } /* Allocate a weakref object. Weakref objects have a - reference to the referenced object at the byte-offset + reference to an object at the byte-offset stmcb_size_rounded_up(obj) - sizeof(void*) This reference becomes NULL if the referenced object was freed. You must assign the reference before the next collection may happen. _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit