/* Clean up STable memory. */ void MVM_6model_stable_gc_free(MVMThreadContext *tc, MVMSTable *st) { /* First have it free its repr_data if it wants. */ if (st->REPR->gc_free_repr_data) st->REPR->gc_free_repr_data(tc, st); /* free various storage. */ MVM_checked_free_null(st->type_check_cache); if (st->container_spec && st->container_spec->gc_free_data) st->container_spec->gc_free_data(tc, st); MVM_checked_free_null(st->invocation_spec); MVM_checked_free_null(st->boolification_spec); }
/* Destroys a given thread context. This will also free the nursery. * This means that it must no longer be in use, at all; this can be * ensured by a GC run at thread exit that forces evacuation of all * objects from this nursery to the second generation. Only after * that is true should this be called. */ void MVM_tc_destroy(MVMThreadContext *tc) { /* We run once again (non-blocking) to eventually close filehandles. */ uv_run(tc->loop, UV_RUN_NOWAIT); /* Free the nursery. */ free(tc->nursery_fromspace); free(tc->nursery_tospace); /* Destroy the second generation allocator. */ MVM_gc_gen2_destroy(tc->instance, tc->gen2); /* Free the thread-specific storage */ MVM_checked_free_null(tc->gc_work); MVM_checked_free_null(tc->temproots); MVM_checked_free_null(tc->gen2roots); MVM_checked_free_null(tc->frame_pool_table); /* destroy the libuv event loop */ uv_loop_delete(tc->loop); /* Free the thread context itself. */ memset(tc, 0, sizeof(MVMThreadContext)); free(tc); }