Example #1
0
void lily_gc_collect_list(lily_value *v)
{
    lily_list_val *list_val = v->value.list;
    /* The first check is done because this list might be inside of an any
       that is being collected. So it may not be in the gc, but it needs to be
       destroyed because it was trapped in a circular ref.
       The second check acts as a 'lock' to make sure that this cannot be done
       twice for the same list, thus preventing recursion. */
    int marked = 0;
    if (list_val->gc_entry == NULL ||
        (list_val->gc_entry->last_pass != -1 &&
         list_val->gc_entry->value.generic != NULL)) {

        if (list_val->gc_entry) {
            list_val->gc_entry->last_pass = -1;
            /* If this list has a gc entry, then it can contains elements which
               refer to itself. Set last_pass to -1 to indicate that everything
               inside this list has already been deleted. The gc will delete the
               list later. */
            marked = 1;
        }

        int i;

        for (i = 0;i < list_val->num_values;i++) {
            /* Pass stuff off to the gc to collect. This will use a typical
                deref for stuff like string. */
            lily_value *elem = list_val->elems[i];
            if (elem->flags & VAL_IS_DEREFABLE) {
                lily_raw_value v = elem->value;
                if (v.generic->refcount == 1)
                    lily_gc_collect_value(elem);
                else
                    v.generic->refcount--;
            }
            lily_free(elem);
        }

        lily_free(list_val->elems);
        if (marked == 0)
            lily_free(list_val);
    }
}
Example #2
0
void lily_gc_collect_any(lily_any_val *any_val)
{
    if (any_val->gc_entry->value.generic != NULL &&
            any_val->gc_entry->last_pass != -1) {
        /* Setting ->last_pass to -1 indicates that everything within the any
           has been free'd except the any. The gc will free the any once
           all inner values have been deref'd/deleted. */
        any_val->gc_entry->last_pass = -1;
        lily_value *inner_value = any_val->inner_value;
        if ((inner_value->flags & VAL_IS_NOT_DEREFABLE) == 0) {
            lily_generic_val *generic_val = inner_value->value.generic;
            if (generic_val->refcount == 1)
                lily_gc_collect_value(inner_value->type,
                                      inner_value->value);
            else
                generic_val->refcount--;
        }

        lily_free(any_val->inner_value);
        /* Do not free any_val here: Let the gc do that later. */
    }
}