static void hklr_gc_collectwhite(HklrObject* object) { assert(object != NULL); if (object->color == HKL_COLOR_WHITE && !object->is_buffered) { object->color = HKL_COLOR_BLACK; switch (object->type) { // If the object is a hash table case HKL_TYPE_HASH: // Traverse the hash scanning every child hkl_hash_traverse(object->as.hash, hklr_gc_collectwhite_hash, NULL); break; // If the object is a reference case HKL_TYPE_REF: hklr_gc_collectwhite(object->as.object); break; default: break; } // queue up roots to free /* HKLR.gc_freed++; hklr_object_free(object);*/ hkl_list_push_back(HKLR.gc_to_free, object); } }
static void hklr_gc_scan(HklrObject* object) { if (object->color == HKL_COLOR_GRAY) { if (object->rc > 0) { hklr_gc_scanblack(object); } else { object->color = HKL_COLOR_WHITE; switch (object->type) { // If the object is a hash table case HKL_TYPE_HASH: // Traverse the hash scanning every child hkl_hash_traverse(object->as.hash, hklr_gc_scan_hash, NULL); break; // If the object is a reference case HKL_TYPE_REF: hklr_gc_scan(object->as.object); break; default: break; } } } }
static void hklr_gc_markgray(HklrObject* object) { if (object->color != HKL_COLOR_GRAY) { object->color = HKL_COLOR_GRAY; switch (object->type) { // If the object is a hash table case HKL_TYPE_HASH: // Traverse the hash marking every child hkl_hash_traverse(object->as.hash, hklr_gc_markgray_hash, NULL); break; // If the object is a reference case HKL_TYPE_REF: object->as.object->rc--; hklr_gc_markgray(object->as.object); break; default: break; } } }
static void hklr_gc_release(HklrObject* object) { switch (object->type) { // If the object is a hash table case HKL_TYPE_HASH: // Traverse the hash decrementing every child hkl_hash_traverse(object->as.hash, hklr_gc_dec_hash, NULL); break; // If the object is a reference case HKL_TYPE_REF: hklr_gc_dec(object->as.object); break; default: break; } object->color = HKL_COLOR_BLACK; if (!object->is_buffered) { HKLR.gc_freed++; hklr_object_free(object); } }
void hklr_scope_pop() { HklScope* scope = hkl_list_pop_back(HKLR.scopes); // decrement all the locals hkl_hash_traverse(scope->locals, hklr_gc_dec_hash, NULL); // dont dec upvals as they arent in our scope // hkl_hash_traverse(scope->upvals, hklr_gc_dec_hash, NULL); hkl_hash_free(scope->locals); hkl_hash_free(scope->upvals); hkl_free_object(scope); }
void hklr_shutdown() { hklr_scope_pop(); // free globals hkl_hash_traverse(HKLR.globals, hklr_gc_dec_hash, NULL); hkl_hash_free(HKLR.globals); // collect garbage hklr_gc_collect(); hkl_list_free(HKLR.gc_to_free); hklr_object_free(HKLR.gc_roots); hklr_object_free(HKLR.gc_tail); }
void hklr_scope_pop() { HklScope* scope = HKLR.scopes; HKLR.scopes = scope->prev; HKLR.scope_level--; // decrement all the locals hkl_hash_traverse(scope->locals, hklr_gc_dec_hash, NULL); // dont dec upvals as they arent in our scope // hkl_hash_traverse(scope->upvals, hklr_gc_dec_hash, NULL); hkl_hash_free(scope->locals); hkl_hash_free(scope->upvals); hkl_free_object(scope); }
static void hklr_gc_scanblack(HklrObject* object) { object->color = HKL_COLOR_BLACK; switch (object->type) { // If the object is a hash table case HKL_TYPE_HASH: // Traverse the hash scanning every child hkl_hash_traverse(object->as.hash, hklr_gc_scanblack_hash, NULL); break; // If the object is a reference case HKL_TYPE_REF: hklr_gc_scanblack(object->as.object); break; default: break; } }