#include "gc.h" #include "gc_heap.h" #include "gc_mark.h" #include "gc_sweep.h" #include "gc_roots.h" #include "../runtime.h" #include #include static RavaVM_t *g_current_vm = NULL; static RavaGCStats_t g_stats; void rava_gc_init(void) { rava_gc_heap_init(); rava_gc_mark_init(); memset(&g_stats, 0, sizeof(g_stats)); g_current_vm = NULL; } void rava_gc_shutdown(void) { RavaGCHeap_t *heap = rava_gc_get_heap(); RavaGCHeader_t *obj = heap->all_objects; while (obj) { RavaGCHeader_t *next = obj->gc_next; rava_gc_finalize_object(obj); obj = next; } heap->all_objects = NULL; rava_gc_heap_shutdown(); } void rava_gc_set_vm(RavaVM_t *vm) { g_current_vm = vm; } void* rava_gc_alloc(size_t size, uint8_t type) { RavaGCState_t *state = rava_gc_get_state(); if (state->gc_enabled && !state->gc_active) { rava_gc_collect_if_needed(); } void *ptr = rava_gc_heap_alloc(size, type); if (ptr) { g_stats.objects_allocated++; g_stats.bytes_allocated += size; g_stats.current_live_objects++; g_stats.current_live_bytes += size; if (g_stats.current_live_bytes > g_stats.peak_live_bytes) { g_stats.peak_live_bytes = g_stats.current_live_bytes; } } return ptr; } void rava_gc_free(void *ptr) { (void)ptr; } void rava_gc_collect(void) { RavaGCState_t *state = rava_gc_get_state(); if (state->gc_active) { return; } state->gc_active = true; state->objects_marked = 0; state->bytes_marked = 0; state->gray_count = 0; rava_gc_scan_roots(g_current_vm); rava_gc_process_gray_stack(); size_t live_before = g_stats.current_live_objects; rava_gc_sweep(); rava_gc_recycle_blocks(); size_t freed = live_before - state->objects_marked; g_stats.objects_freed += freed; g_stats.current_live_objects = state->objects_marked; g_stats.current_live_bytes = state->bytes_marked; g_stats.total_collections++; state->gc_active = false; } void rava_gc_collect_if_needed(void) { RavaGCHeap_t *heap = rava_gc_get_heap(); if (heap->total_allocated > heap->gc_threshold) { rava_gc_collect(); } } void rava_gc_enable(void) { RavaGCState_t *state = rava_gc_get_state(); state->gc_enabled = true; } void rava_gc_disable(void) { RavaGCState_t *state = rava_gc_get_state(); state->gc_enabled = false; } bool rava_gc_is_enabled(void) { RavaGCState_t *state = rava_gc_get_state(); return state->gc_enabled; } void rava_gc_pin(void *ptr) { if (!ptr) return; RavaGCHeader_t *header = (RavaGCHeader_t*)ptr; header->gc_flags |= RAVA_GC_FLAG_PINNED; } void rava_gc_unpin(void *ptr) { if (!ptr) return; RavaGCHeader_t *header = (RavaGCHeader_t*)ptr; header->gc_flags &= ~RAVA_GC_FLAG_PINNED; } RavaGCStats_t rava_gc_get_stats(void) { return g_stats; } void rava_gc_print_stats(void) { printf("GC Statistics:\n"); printf(" Total collections: %zu\n", g_stats.total_collections); printf(" Objects allocated: %zu\n", g_stats.objects_allocated); printf(" Objects freed: %zu\n", g_stats.objects_freed); printf(" Current live objects: %zu\n", g_stats.current_live_objects); printf(" Current live bytes: %zu\n", g_stats.current_live_bytes); printf(" Peak live bytes: %zu\n", g_stats.peak_live_bytes); }