#include "gc_sweep.h" #include "gc_heap.h" #include "../runtime.h" #include #include static void _rava_gc_finalize_object_data(RavaObject_t *o) { free(o->class_name); for (size_t i = 0; i < o->field_count; i++) { free(o->field_names[i]); } free(o->field_names); free(o->field_values); } static void _rava_gc_finalize_array_data(RavaArray_t *a) { free(a->data); } static void _rava_gc_finalize_arraylist_data(RavaArrayList_t *l) { free(l->data); } static void _rava_gc_finalize_hashmap_data(RavaHashMap_t *m) { for (size_t i = 0; i < m->bucket_count; i++) { if (m->buckets[i].occupied) { free(m->buckets[i].key); } } free(m->buckets); } static void _rava_gc_finalize_socket_data(RavaSocket_t *s) { if (!s->closed && s->fd >= 0) { close(s->fd); } } static void _rava_gc_finalize_methodref_data(RavaMethodRef_t *r) { free(r->class_name); free(r->method_name); } void rava_gc_finalize_object(RavaGCHeader_t *obj) { switch (obj->gc_type) { case RAVA_GC_TYPE_OBJECT: { RavaObject_t *o = (RavaObject_t*)obj; _rava_gc_finalize_object_data(o); break; } case RAVA_GC_TYPE_ARRAY: { RavaArray_t *a = (RavaArray_t*)obj; _rava_gc_finalize_array_data(a); break; } case RAVA_GC_TYPE_ARRAYLIST: { RavaArrayList_t *l = (RavaArrayList_t*)obj; _rava_gc_finalize_arraylist_data(l); break; } case RAVA_GC_TYPE_HASHMAP: { RavaHashMap_t *m = (RavaHashMap_t*)obj; _rava_gc_finalize_hashmap_data(m); break; } case RAVA_GC_TYPE_SOCKET: { RavaSocket_t *s = (RavaSocket_t*)obj; _rava_gc_finalize_socket_data(s); break; } case RAVA_GC_TYPE_METHODREF: { RavaMethodRef_t *r = (RavaMethodRef_t*)obj; _rava_gc_finalize_methodref_data(r); break; } default: break; } if (obj->gc_flags & RAVA_GC_FLAG_PINNED) { free(obj); } } void rava_gc_sweep(void) { RavaGCHeap_t *heap = rava_gc_get_heap(); RavaGCHeader_t **ptr = &heap->all_objects; size_t freed_count = 0; size_t freed_bytes = 0; while (*ptr) { RavaGCHeader_t *obj = *ptr; if (obj->gc_mark == RAVA_GC_WHITE) { *ptr = obj->gc_next; freed_bytes += obj->gc_size; freed_count++; rava_gc_finalize_object(obj); } else { obj->gc_mark = RAVA_GC_WHITE; obj->gc_age++; ptr = &obj->gc_next; } } heap->live_bytes = heap->total_allocated - freed_bytes; heap->total_allocated = heap->live_bytes; if (heap->live_bytes > 0) { heap->gc_threshold = heap->live_bytes * 2; } else { heap->gc_threshold = RAVA_GC_INITIAL_THRESHOLD; } }