This commit is contained in:
Lobo 2026-02-06 11:52:53 -03:00
parent 2ac2f85512
commit 90175b7e26
12 changed files with 300 additions and 77 deletions

View file

@ -67,38 +67,40 @@ GrowlObjectHeader *growl_gc_alloc_tenured(GrowlVM *vm, size_t size) {
static void scan(GrowlVM *vm, GrowlObjectHeader *hdr) {
switch (hdr->type) {
case GROWL_STRING:
case GROWL_TYPE_STRING:
break;
case GROWL_LIST: {
case GROWL_TYPE_LIST: {
GrowlList *list = (GrowlList *)(hdr + 1);
list->head = forward(vm, list->head);
list->tail = forward(vm, list->tail);
break;
}
case GROWL_TUPLE: {
case GROWL_TYPE_TUPLE: {
GrowlTuple *tuple = (GrowlTuple *)(hdr + 1);
for (size_t i = 0; i < tuple->count; ++i) {
tuple->data[i] = forward(vm, tuple->data[i]);
}
break;
}
case GROWL_QUOTATION: {
case GROWL_TYPE_QUOTATION: {
GrowlQuotation *quot = (GrowlQuotation *)(hdr + 1);
quot->constants = forward(vm, quot->constants);
break;
}
case GROWL_COMPOSE: {
case GROWL_TYPE_COMPOSE: {
GrowlCompose *comp = (GrowlCompose *)(hdr + 1);
comp->first = forward(vm, comp->first);
comp->second = forward(vm, comp->second);
break;
}
case GROWL_CURRY: {
case GROWL_TYPE_CURRY: {
GrowlCurry *comp = (GrowlCurry *)(hdr + 1);
comp->value = forward(vm, comp->value);
comp->callable = forward(vm, comp->callable);
break;
}
case GROWL_TYPE_ALIEN:
break;
case UINT32_MAX:
fprintf(stderr, "gc: fwd pointer during scan\n");
abort();
@ -109,15 +111,22 @@ static void scan(GrowlVM *vm, GrowlObjectHeader *hdr) {
}
static void gc_print_stats(GrowlVM *vm, const char *label) {
size_t used = vm->from.free - vm->from.start;
size_t total = vm->from.end - vm->from.start;
fprintf(stderr, "[%s] used=%zu/%zu bytes (%.1f%%)\n", label, used, total,
(double)used / (double)total * 100.0);
size_t nursery_used = vm->from.free - vm->from.start;
size_t nursery_total = vm->from.end - vm->from.start;
size_t tenured_used = vm->arena.free - vm->arena.start;
size_t tenured_total = vm->arena.end - vm->arena.start;
fprintf(stderr, "%s:\n", label);
fprintf(stderr, " tenured: %zu/%zu bytes (%.1f%%)\n", tenured_used,
nursery_total, (double)tenured_used / (double)tenured_total * 100.0);
fprintf(stderr, " nursery: %zu/%zu bytes (%.1f%%)\n", nursery_used,
nursery_total, (double)nursery_used / (double)nursery_total * 100.0);
}
void growl_gc_collect(GrowlVM *vm) {
uint8_t *gc_scan = vm->to.free;
fprintf(stderr, ">>> starting garbage collection\n");
gc_print_stats(vm, "before GC");
for (size_t i = 0; i < GROWL_STACK_SIZE; ++i) {
@ -141,6 +150,26 @@ void growl_gc_collect(GrowlVM *vm) {
gc_scan += ALIGN(hdr->size);
}
gc_scan = vm->from.start;
while (gc_scan < vm->from.free) {
GrowlObjectHeader *hdr = (GrowlObjectHeader *)gc_scan;
if (hdr->type != UINT32_MAX) {
switch (hdr->type) {
case GROWL_TYPE_ALIEN: {
GrowlAlien *alien = (GrowlAlien *)(hdr + 1);
if (alien->type->finalizer != NULL) {
alien->type->finalizer(alien->data);
alien->data = NULL;
}
break;
}
default:
break;
}
}
gc_scan += ALIGN(hdr->size);
}
GrowlGCArena tmp = vm->from;
vm->from = vm->to;
vm->to = tmp;
@ -148,6 +177,7 @@ void growl_gc_collect(GrowlVM *vm) {
vm->scratch.free = vm->scratch.start;
gc_print_stats(vm, "after GC");
fprintf(stderr, ">>> garbage collection finished\n");
}
void growl_gc_root(GrowlVM *vm, Growl *ptr) {