garbage collection
This commit is contained in:
@@ -68,6 +68,7 @@ local files = {
|
||||
'src/parser.c',
|
||||
'src/compiler.c',
|
||||
'src/vm.c',
|
||||
'src/gc.c',
|
||||
'src/main.c',
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ pub fn build(b: *std.Build) void {
|
||||
"src/parser.c",
|
||||
"src/compiler.c",
|
||||
"src/vm.c",
|
||||
"src/gc.c",
|
||||
"src/error.c",
|
||||
"src/main.c",
|
||||
}
|
||||
|
||||
89
src/gc.c
Normal file
89
src/gc.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include "noom.h"
|
||||
#include "vm.h"
|
||||
|
||||
static void noomG_grayObj(noom_LuaVM *vm, noomV_Object *obj);
|
||||
|
||||
static void noomG_grayValue(noom_LuaVM *vm, noomV_Value value) {
|
||||
if(value.tag != NOOMV_VOBJ) return;
|
||||
noomG_grayObj(vm, value.obj);
|
||||
}
|
||||
|
||||
static void noomG_grayObj(noom_LuaVM *vm, noomV_Object *obj) {
|
||||
if(obj == 0) return;
|
||||
if(obj->marked) return;
|
||||
obj->marked = 1;
|
||||
obj->nextGray = vm->graySet;
|
||||
vm->graySet = obj;
|
||||
}
|
||||
|
||||
void noomG_markObj(noom_LuaVM *vm, noomV_Object *obj) {
|
||||
if(obj->tag == NOOMV_OPOINTER) {
|
||||
noomV_Pointer *p = (noomV_Pointer *)obj;
|
||||
noomG_grayValue(vm, p->value);
|
||||
return;
|
||||
}
|
||||
if(obj->tag == NOOMV_OFUNC) {
|
||||
noomV_Function *f = (noomV_Function *)obj;
|
||||
noomG_grayObj(vm, &f->chunkname->obj);
|
||||
noomG_grayObj(vm, &f->env->obj);
|
||||
for(noom_uint_t i = 0; i < f->constsize; i++) {
|
||||
noomG_grayValue(vm, f->consts[i]);
|
||||
}
|
||||
for(noom_uint_t i = 0; i < f->protosize; i++) {
|
||||
noomG_grayObj(vm, (noomV_Object *)f->protos[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(obj->tag == NOOMV_OTABLE) {
|
||||
noomV_Table *t = (noomV_Table *)obj;
|
||||
noomG_grayObj(vm, (noomV_Object *)t->meta);
|
||||
for(noom_uint_t i = 0; i < t->entries*2; i++) {
|
||||
noomG_grayValue(vm, t->entrydata[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(obj->tag == NOOMV_OTHREAD) {
|
||||
noomV_Thread *thrd = (noomV_Thread *)obj;
|
||||
for(noom_uint_t i = 0; i < thrd->stacklen; i++) {
|
||||
noomG_grayValue(vm, thrd->stack[i]);
|
||||
}
|
||||
for(noom_uint_t i = 0; i < thrd->calldepth; i++) {
|
||||
noomV_CallFrame cf = thrd->calls[i];
|
||||
noomG_grayValue(vm, cf.errhandler);
|
||||
}
|
||||
noomG_grayValue(vm, thrd->errObj);
|
||||
noomG_grayObj(vm, (noomV_Object *)thrd->resuming);
|
||||
noomG_grayObj(vm, (noomV_Object *)thrd->resumedBy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void noom_gc(noom_LuaVM* vm) {
|
||||
vm->graySet = 0;
|
||||
|
||||
noomG_grayObj(vm, (noomV_Object *)vm->mainThread);
|
||||
noomG_grayObj(vm, (noomV_Object *)vm->globals);
|
||||
noomG_grayObj(vm, (noomV_Object *)vm->registry);
|
||||
|
||||
while(vm->graySet) {
|
||||
noomG_markObj(vm, vm->graySet);
|
||||
vm->graySet = vm->graySet->nextGray;
|
||||
}
|
||||
|
||||
noomV_Object **sweep = &vm->heap;
|
||||
while(*sweep) {
|
||||
noomV_Object *current = *sweep;
|
||||
if(current->marked) {
|
||||
sweep = ¤t->next;
|
||||
} else {
|
||||
*sweep = current->next;
|
||||
noomV_freeObj(vm, current);
|
||||
}
|
||||
}
|
||||
|
||||
vm->gcTarget = vm->objCount * vm->gcRatio;
|
||||
}
|
||||
|
||||
void noom_trygc(noom_LuaVM* vm) {
|
||||
if(vm->objCount >= vm->gcTarget) noom_gc(vm);
|
||||
}
|
||||
@@ -299,6 +299,11 @@ noom_Exit noom_cast2str(noom_LuaVM* vm, noom_slot_t x);
|
||||
// DO NOT RUN IN THE ALLOCATOR IF ANY IS SUPPLIED, OR YOU WILL GET THE WORST POSSIBLE ERRORS.
|
||||
void noom_gc(noom_LuaVM* vm);
|
||||
|
||||
// Like [noom_gc], except it will only do things if the GC feels like it.
|
||||
// You can sneak this in your long-running C functions to reduce memory usage
|
||||
// without destroying this CPU.
|
||||
void noom_trygc(noom_LuaVM* vm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
11
src/vm.c
11
src/vm.c
@@ -163,6 +163,7 @@ noomV_Object* noomV_allocObj(noom_LuaVM* vm, noomV_ObjTag tag, noom_uint_t size)
|
||||
o->next = vm->heap;
|
||||
o->nextGray = 0;
|
||||
vm->heap = o;
|
||||
vm->objCount++;
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -444,7 +445,7 @@ noom_Exit noomV_setErrorFromExit(noom_LuaVM *vm, noomV_Thread *coro, noom_Exit e
|
||||
return exit;
|
||||
}
|
||||
|
||||
void noomV_freeObj(noomV_Object* obj) {
|
||||
void noomV_freeObj(noom_LuaVM *vm, noomV_Object* obj) {
|
||||
if(obj->tag == NOOMV_OFUNC) {
|
||||
noomV_Function *f = (noomV_Function *)obj;
|
||||
noom_free(f->consts);
|
||||
@@ -462,6 +463,7 @@ void noomV_freeObj(noomV_Object* obj) {
|
||||
noom_free(thrd->calls);
|
||||
}
|
||||
noom_free(obj);
|
||||
vm->objCount--;
|
||||
}
|
||||
|
||||
noom_Exit noomV_pushCallFrame(noom_LuaVM *vm, noomV_Thread *coro, noomV_CallFrame cf);
|
||||
@@ -513,6 +515,9 @@ noom_LuaVM* noom_createVM(noom_LuaVersion version) {
|
||||
vm->mainThread = 0;
|
||||
vm->currentThread = 0;
|
||||
vm->version = version;
|
||||
vm->objCount = 0;
|
||||
vm->gcTarget = 100;
|
||||
vm->gcRatio = 2;
|
||||
|
||||
const char *oomStr = "out of memory";
|
||||
vm->oomVal.obj = (noomV_Object *)noomV_allocStr(vm, oomStr, noom_strlen(oomStr));
|
||||
@@ -539,6 +544,8 @@ noom_LuaVM* noom_createVM(noom_LuaVersion version) {
|
||||
|
||||
assert(noomV_rawequalValue(noomV_rawgetTable(vm->registry, _GKey), _GVal));
|
||||
|
||||
noom_gc(vm);
|
||||
|
||||
return vm;
|
||||
rip:
|
||||
noom_destroyVM(vm);
|
||||
@@ -550,7 +557,7 @@ void noom_destroyVM(noom_LuaVM* vm) {
|
||||
while (iter) {
|
||||
noomV_Object* cur = iter;
|
||||
iter = iter->next;
|
||||
noomV_freeObj(cur);
|
||||
noomV_freeObj(vm, cur);
|
||||
}
|
||||
noom_free(vm);
|
||||
}
|
||||
|
||||
5
src/vm.h
5
src/vm.h
@@ -352,6 +352,9 @@ struct noom_LuaVM {
|
||||
noomV_Thread* mainThread;
|
||||
noomV_Thread* currentThread;
|
||||
noom_LuaVersion version;
|
||||
noom_uint_t objCount;
|
||||
noom_uint_t gcTarget;
|
||||
double gcRatio;
|
||||
};
|
||||
|
||||
// for conveniently passing around nil
|
||||
@@ -379,7 +382,7 @@ void noomV_setErrorStr(noom_LuaVM *vm, noomV_Thread *coro, const char *str);
|
||||
// Returns the exit for convenience
|
||||
noom_Exit noomV_setErrorFromExit(noom_LuaVM *vm, noomV_Thread *coro, noom_Exit exit);
|
||||
|
||||
void noomV_freeObj(noomV_Object* obj);
|
||||
void noomV_freeObj(noom_LuaVM *vm, noomV_Object* obj);
|
||||
|
||||
noom_Exit noomV_pushCallFrame(noom_LuaVM *vm, noomV_Thread *coro, noomV_CallFrame cf);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user