#include "gc_mark.h" #include "gc_roots.h" #include "../runtime.h" #include static RavaGCState_t g_gc_state; void rava_gc_mark_init(void) { memset(&g_gc_state, 0, sizeof(g_gc_state)); g_gc_state.gc_enabled = true; } RavaGCState_t* rava_gc_get_state(void) { return &g_gc_state; } void rava_gc_mark_object(RavaGCHeader_t *obj) { if (!obj || obj->gc_mark != RAVA_GC_WHITE) { return; } obj->gc_mark = RAVA_GC_GRAY; if (g_gc_state.gray_count < RAVA_GC_GRAY_STACK_SIZE) { g_gc_state.gray_stack[g_gc_state.gray_count++] = obj; } else { rava_gc_process_object(obj); } } static void _rava_gc_trace_object(RavaObject_t *obj) { for (size_t i = 0; i < obj->field_count; i++) { rava_gc_mark_value(obj->field_values[i]); } } static void _rava_gc_trace_array(RavaArray_t *arr) { if (arr->element_type == RAVA_VAL_OBJECT || arr->element_type == RAVA_VAL_ARRAY) { RavaValue_t *values = (RavaValue_t*)arr->data; for (size_t i = 0; i < arr->length; i++) { rava_gc_mark_value(values[i]); } } } static void _rava_gc_trace_arraylist(RavaArrayList_t *list) { for (size_t i = 0; i < list->size; i++) { rava_gc_mark_value(list->data[i]); } } static void _rava_gc_trace_hashmap(RavaHashMap_t *map) { for (size_t i = 0; i < map->bucket_count; i++) { if (map->buckets[i].occupied) { rava_gc_mark_value(map->buckets[i].value); } } } static void _rava_gc_trace_methodref(RavaMethodRef_t *ref) { if (ref->has_target) { rava_gc_mark_value(ref->target); } } void rava_gc_process_object(RavaGCHeader_t *obj) { obj->gc_mark = RAVA_GC_BLACK; g_gc_state.objects_marked++; g_gc_state.bytes_marked += obj->gc_size; switch (obj->gc_type) { case RAVA_GC_TYPE_OBJECT: { RavaObject_t *o = (RavaObject_t*)obj; _rava_gc_trace_object(o); break; } case RAVA_GC_TYPE_ARRAY: { RavaArray_t *a = (RavaArray_t*)obj; _rava_gc_trace_array(a); break; } case RAVA_GC_TYPE_ARRAYLIST: { RavaArrayList_t *l = (RavaArrayList_t*)obj; _rava_gc_trace_arraylist(l); break; } case RAVA_GC_TYPE_HASHMAP: { RavaHashMap_t *m = (RavaHashMap_t*)obj; _rava_gc_trace_hashmap(m); break; } case RAVA_GC_TYPE_METHODREF: { RavaMethodRef_t *r = (RavaMethodRef_t*)obj; _rava_gc_trace_methodref(r); break; } default: break; } } void rava_gc_process_gray_stack(void) { while (g_gc_state.gray_count > 0) { RavaGCHeader_t *obj = g_gc_state.gray_stack[--g_gc_state.gray_count]; rava_gc_process_object(obj); } }