189 lines
4.6 KiB
C
Raw Normal View History

2025-12-05 01:12:39 +01:00
#include "gc_heap.h"
#include "../runtime.h"
#include <stdlib.h>
#include <string.h>
static RavaGCHeap_t g_heap;
void rava_gc_heap_init(void) {
memset(&g_heap, 0, sizeof(g_heap));
g_heap.gc_threshold = RAVA_GC_INITIAL_THRESHOLD;
g_heap.all_blocks = NULL;
g_heap.current_block = NULL;
g_heap.free_blocks = NULL;
g_heap.recyclable_blocks = NULL;
g_heap.all_objects = NULL;
}
void rava_gc_heap_shutdown(void) {
RavaGCBlock_t *block = g_heap.all_blocks;
while (block) {
RavaGCBlock_t *next = block->next;
free(block);
block = next;
}
block = g_heap.free_blocks;
while (block) {
RavaGCBlock_t *next = block->next;
free(block);
block = next;
}
memset(&g_heap, 0, sizeof(g_heap));
}
static RavaGCBlock_t* _rava_gc_create_block(void) {
RavaGCBlock_t *block = calloc(1, sizeof(RavaGCBlock_t));
if (!block) return NULL;
block->flags = 0;
block->free_lines = RAVA_GC_LINES_PER_BLOCK;
memset(block->line_marks, 0, sizeof(block->line_marks));
return block;
}
bool rava_gc_request_block(void) {
if (g_heap.free_blocks) {
RavaGCBlock_t *block = g_heap.free_blocks;
g_heap.free_blocks = block->next;
block->next = g_heap.all_blocks;
block->prev = NULL;
if (g_heap.all_blocks) {
g_heap.all_blocks->prev = block;
}
g_heap.all_blocks = block;
g_heap.current_block = block;
g_heap.bump_ptr = block->data;
g_heap.block_limit = block->data + RAVA_GC_BLOCK_SIZE;
return true;
}
if (g_heap.recyclable_blocks) {
RavaGCBlock_t *block = g_heap.recyclable_blocks;
g_heap.recyclable_blocks = block->next;
block->next = g_heap.all_blocks;
block->prev = NULL;
if (g_heap.all_blocks) {
g_heap.all_blocks->prev = block;
}
g_heap.all_blocks = block;
g_heap.current_block = block;
g_heap.bump_ptr = block->data;
g_heap.block_limit = block->data + RAVA_GC_BLOCK_SIZE;
return true;
}
RavaGCBlock_t *block = _rava_gc_create_block();
if (!block) return false;
block->next = g_heap.all_blocks;
block->prev = NULL;
if (g_heap.all_blocks) {
g_heap.all_blocks->prev = block;
}
g_heap.all_blocks = block;
g_heap.current_block = block;
g_heap.bump_ptr = block->data;
g_heap.block_limit = block->data + RAVA_GC_BLOCK_SIZE;
return true;
}
void* rava_gc_heap_alloc(size_t size, uint8_t type) {
size = RAVA_ALIGN(size, 8);
if (size > RAVA_GC_BLOCK_SIZE) {
RavaGCHeader_t *obj = calloc(1, size);
if (!obj) return NULL;
obj->gc_type = type;
obj->gc_mark = RAVA_GC_WHITE;
obj->gc_age = 0;
obj->gc_flags = RAVA_GC_FLAG_PINNED;
obj->gc_size = (uint32_t)size;
obj->gc_next = g_heap.all_objects;
g_heap.all_objects = obj;
g_heap.total_allocated += size;
return obj;
}
if (!g_heap.current_block || g_heap.bump_ptr + size > g_heap.block_limit) {
if (!rava_gc_request_block()) {
return NULL;
}
}
RavaGCHeader_t *obj = (RavaGCHeader_t*)g_heap.bump_ptr;
g_heap.bump_ptr += size;
g_heap.total_allocated += size;
obj->gc_type = type;
obj->gc_mark = RAVA_GC_WHITE;
obj->gc_age = 0;
obj->gc_flags = 0;
obj->gc_size = (uint32_t)size;
obj->gc_next = g_heap.all_objects;
g_heap.all_objects = obj;
return obj;
}
void rava_gc_heap_free(void *ptr, size_t size) {
(void)ptr;
(void)size;
}
void rava_gc_recycle_blocks(void) {
RavaGCBlock_t *block = g_heap.all_blocks;
RavaGCBlock_t *prev = NULL;
while (block) {
RavaGCBlock_t *next = block->next;
bool has_live = false;
for (size_t i = 0; i < RAVA_GC_LINES_PER_BLOCK; i++) {
if (block->line_marks[i]) {
has_live = true;
break;
}
}
if (!has_live && block != g_heap.current_block) {
if (prev) {
prev->next = next;
} else {
g_heap.all_blocks = next;
}
if (next) {
next->prev = prev;
}
block->next = g_heap.free_blocks;
block->prev = NULL;
g_heap.free_blocks = block;
memset(block->line_marks, 0, sizeof(block->line_marks));
block->flags = 0;
block->free_lines = RAVA_GC_LINES_PER_BLOCK;
} else {
prev = block;
}
block = next;
}
}
RavaGCHeap_t* rava_gc_get_heap(void) {
return &g_heap;
}