Author: Armin Rigo <[email protected]>
Branch: c7-more-segments
Changeset: r1033:ece9046d8595
Date: 2014-03-16 10:56 +0100
http://bitbucket.org/pypy/stmgc/changeset/ece9046d8595/
Log: Fix major GC.
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -325,11 +325,6 @@
/* takes a normal pointer to a thread-local pointer to an object */
object_t *obj = *pobj;
- if (obj == NULL || mark_visited_test_and_set(obj))
- return; /* already visited this object */
-
- LIST_APPEND(mark_objects_to_trace, obj);
-
/* Note: this obj might be visited already, but from a different
segment. We ignore this case and skip re-visiting the object
anyway. The idea is that such an object is old (not from the
@@ -340,6 +335,10 @@
segments and only needs visiting once. (It may actually be in a
shared page, or maybe not.)
*/
+ if (obj == NULL || mark_visited_test_and_set(obj))
+ return; /* already visited this object */
+
+ LIST_APPEND(mark_objects_to_trace, obj);
}
static void mark_trace(object_t *obj, char *segment_base)
@@ -347,15 +346,6 @@
assert(list_is_empty(mark_objects_to_trace));
while (1) {
-
-#if 0
- /* first, if we're not seeing segment 0, we must change the
- flags in flag_page_private[] from PRIVATE_PAGE to
- SEGMENT1_PAGE, which will mean "can't re-share" */
- if (segment_base != stm_object_pages && RESHARE_PAGES)
- mark_flag_page_private(obj, segment_base);
-#endif
-
/* trace into the object (the version from 'segment_base') */
struct object_s *realobj =
(struct object_s *)REAL_ADDRESS(segment_base, obj);
@@ -377,45 +367,33 @@
static void mark_visit_from_roots(void)
{
-
if (testing_prebuilt_objs != NULL) {
LIST_FOREACH_R(testing_prebuilt_objs, object_t * /*item*/,
- mark_visit_object(item, get_segment_base(0)));
+ mark_visit_object(item, stm_object_pages));
}
- /* Do the following twice, so that we trace first the objects from
- segment 0, and then all others. XXX This is a hack to make it
- more likely that we'll be able to re-share pages. */
+ stm_thread_local_t *tl = stm_all_thread_locals;
+ do {
+ /* If 'tl' is currently running, its 'associated_segment_num'
+ field is the segment number that contains the correct
+ version of its overflowed objects. If not, then the
+ field is still some correct segment number, and it doesn't
+ matter which one we pick. */
+ char *segment_base = get_segment_base(tl->associated_segment_num);
- int must_be_zero;
- for (must_be_zero = 1; must_be_zero >= 0; must_be_zero--) {
+ struct stm_shadowentry_s *current = tl->shadowstack;
+ struct stm_shadowentry_s *base = tl->shadowstack_base;
+ while (current-- != base) {
+ assert(current->ss != (object_t *)-1);
+ mark_visit_object(current->ss, segment_base);
+ }
+ mark_visit_object(tl->thread_local_obj, segment_base);
- stm_thread_local_t *tl = stm_all_thread_locals;
- do {
- /* If 'tl' is currently running, its 'associated_segment_num'
- field is the segment number that contains the correct
- version of its overflowed objects. If not, then the
- field is still some correct segment number, and it doesn't
- matter which one we pick. */
- char *segment_base = get_segment_base(tl->associated_segment_num);
-
- if (must_be_zero == (segment_base == get_segment_base(0))) {
-
- struct stm_shadowentry_s *current = tl->shadowstack;
- struct stm_shadowentry_s *base = tl->shadowstack_base;
- while (current-- != base) {
- assert(current->ss != (object_t *)-1);
- mark_visit_object(current->ss, segment_base);
- }
- mark_visit_object(tl->thread_local_obj, segment_base);
- }
-
- tl = tl->next;
- } while (tl != stm_all_thread_locals);
- }
+ tl = tl->next;
+ } while (tl != stm_all_thread_locals);
long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
+ for (i = 1; i <= NB_SEGMENTS; i++) {
if (get_priv_segment(i)->transaction_state != TS_NONE)
mark_visit_object(
get_priv_segment(i)->threadlocal_at_start_of_transaction,
@@ -426,20 +404,21 @@
static void mark_visit_from_modified_objects(void)
{
/* The modified objects are the ones that may exist in two different
- versions: one in the segment that modified it, and another in
- all other segments. */
+ versions: one in the segment that modified it, and another in all
+ other segments. (It can also be more than two if we don't have
+ eager write locking.)
+ */
long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
- char *base1 = get_segment_base(i); /* two different segments */
- char *base2 = get_segment_base(!i);
+ for (i = 1; i <= NB_SEGMENTS; i++) {
+ char *base = get_segment_base(i);
LIST_FOREACH_R(
get_priv_segment(i)->modified_old_objects,
object_t * /*item*/,
({
mark_visited_test_and_set(item);
- mark_trace(item, base1);
- mark_trace(item, base2);
+ mark_trace(item, stm_object_pages); /* shared version */
+ mark_trace(item, base); /* private version */
}));
}
}
@@ -447,7 +426,7 @@
static void clean_up_segment_lists(void)
{
long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
+ for (i = 1; i <= NB_SEGMENTS; i++) {
struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
struct list_s *lst;
@@ -513,7 +492,7 @@
{
/* restore the write locks on the modified objects */
long i;
- for (i = 0; i < NB_SEGMENTS; i++) {
+ for (i = 1; i <= NB_SEGMENTS; i++) {
struct stm_priv_segment_info_s *pseg = get_priv_segment(i);
LIST_FOREACH_R(
@@ -533,8 +512,6 @@
dprintf((" .----- major collection -----------------------\n"));
assert(_has_mutex());
- if (0) { // XXX TEMP
-
/* first, force a minor collection in each of the other segments */
major_do_minor_collections();
@@ -548,7 +525,8 @@
LIST_FREE(mark_objects_to_trace);
/* weakrefs: */
- stm_visit_old_weakrefs();
+ if (0)//XXX
+ stm_visit_old_weakrefs();
/* cleanup */
clean_up_segment_lists();
@@ -568,7 +546,6 @@
dprintf((" | used after collection: %ld\n",
(long)pages_ctl.total_allocated));
- }
dprintf((" `----------------------------------------------\n"));
reset_major_collection_requested();
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit