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); } }
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. */ } }