#include "gc_sweep.h"
#include "gc_heap.h"
#include "../runtime.h"
#include <stdlib.h>
#include <unistd.h>
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;
}
}