static bool tidyWeakList()

in rts/sm/MarkWeak.c [228:309]


static bool tidyWeakList(generation *gen)
{
    StgWeak *w, **last_w, *next_w;
    const StgInfoTable *info;
    StgClosure *new;
    bool flag = false;
    last_w = &gen->old_weak_ptr_list;
    for (w = gen->old_weak_ptr_list; w != NULL; w = next_w) {

        /* There might be a DEAD_WEAK on the list if finalizeWeak# was
         * called on a live weak pointer object.  Just remove it.
         */
        if (w->header.info == &stg_DEAD_WEAK_info) {
            next_w = w->link;
            *last_w = next_w;
            continue;
        }

        info = get_itbl((StgClosure *)w);
        switch (info->type) {

        case WEAK:
            /* Now, check whether the key is reachable.
             */
            new = isAlive(w->key);
            if (new != NULL) {
                generation *new_gen;

                w->key = new;

                // Find out which generation this weak ptr is in, and
                // move it onto the weak ptr list of that generation.

                new_gen = Bdescr((P_)w)->gen;
                gct->evac_gen_no = new_gen->no;
                gct->failed_to_evac = false;

                // evacuate the fields of the weak ptr
                scavengeLiveWeak(w);

                if (gct->failed_to_evac) {
                    debugTrace(DEBUG_weak,
                               "putting weak pointer %p into mutable list",
                               w);
                    gct->failed_to_evac = false;
                    recordMutableGen_GC((StgClosure *)w, new_gen->no);
                }

                // remove this weak ptr from the old_weak_ptr list
                *last_w = w->link;
                next_w  = w->link;

                // and put it on the correct weak ptr list.
                w->link = new_gen->weak_ptr_list;
                new_gen->weak_ptr_list = w;
                flag = true;

                if (gen->no != new_gen->no) {
                    debugTrace(DEBUG_weak,
                      "moving weak pointer %p from %d to %d",
                      w, gen->no, new_gen->no);
                }


                debugTrace(DEBUG_weak,
                           "weak pointer still alive at %p -> %p",
                           w, w->key);
                continue;
            }
            else {
                last_w = &(w->link);
                next_w = w->link;
                continue;
            }

        default:
            barf("tidyWeakList: not WEAK: %d, %p", info->type, w);
        }
    }

    return flag;
}