#include "gc.h"
#include "gc_heap.h"
#include "gc_mark.h"
#include "gc_sweep.h"
#include "gc_roots.h"
#include "../runtime.h"
#include <stdio.h>
#include <string.h>
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);
}