Garbage Collection 26

This commit is contained in:
nazrin 2025-06-12 06:07:25 +00:00
parent dc4e6d33b2
commit 6d5dff6e3d
10 changed files with 444 additions and 211 deletions

134
src/clox/gc.d Normal file
View file

@ -0,0 +1,134 @@
module clox.gc;
import core.stdc.stdio : printf;
import std.stdio : writeln;
import std.typecons : Tuple, tuple;
import clox.compiler;
import clox.memory;
import clox.obj;
import clox.util;
import clox.value;
import clox.vm;
import clox.container.dynarray;
import clox.container.table;
void collectGarbage(){
debug(disableGC)
return;
debug(stressGC) {} else {
debug(logGC)
writeln("bytesAllocated ", vm.bytesAllocated, ", nextGC ", vm.nextGC);
if(vm.bytesAllocated < vm.nextGC)
return;
}
debug(logGC)
printf(colour!(" -- GC begin\n", Colour.Yellow).ptr);
debug {
static bool isAlreadyRunning = false;
assert(!isAlreadyRunning);
isAlreadyRunning = true;
scope(exit)
isAlreadyRunning = false;
}
markRoots();
traceReferences();
vm.strings.removeWhite();
auto sweepStats = sweep();
debug(logGC)
printf(colour!(" -- GC end %zu/%zu\n", Colour.Yellow).ptr, sweepStats.collected, sweepStats.total);
debug(stressGC) {} else {
vm.nextGC = cast(size_t)(vm.bytesAllocated * 2);
}
}
void mark(Obj* object){
if(object is null || object.isMarked)
return;
debug(logGC)
writeln("\t", object.prettyPtr, colour!(" (-) ", "200", "200", "240"), Obj.toString(object));
object.isMarked = true;
vm.greyStack ~= object;
}
void mark(Value value){
if(value.isType(Value.Type.Obj))
mark(value.asObj);
}
void mark(Table!(Obj.String*, Value) table){
foreach(entry; table.pool){
mark(cast(Obj*)entry.key);
mark(entry.val);
}
}
void mark(T)(DynArray!T darray){
foreach(item; darray[]){
mark(item);
}
}
private void markRoots(){
for(Value* slot = vm.stack.ptr; slot < vm.stackTop; slot++){
mark(*slot);
}
foreach(frame; vm.frames[0 .. vm.frameCount]){
mark(cast(Obj*)frame.closure);
}
for(Obj.Upvalue* upvalue = vm.openUpvalues; upvalue !is null; upvalue = upvalue.next){
mark(cast(Obj*)upvalue);
}
mark(vm.globals);
markCompilerRoots();
}
private void blacken(Obj* object){
debug(logGC)
writeln("\t", object.prettyPtr, colour!(" (#) ", Colour.Black), Obj.toString(object));
final switch(object.type){
case Obj.Type.NativeFunction:
case Obj.Type.String:
break;
case Obj.Type.Upvalue:
mark(object.asUpvalue.closed);
break;
case Obj.Type.Function:
Obj.Function* func = object.asFunc;
mark(cast(Obj*)func.name);
mark(func.chunk.constants);
break;
case Obj.Type.Closure:
Obj.Closure* closure = object.asClosure;
mark(cast(Obj*)closure.func);
foreach(upvalue; closure.upvalues)
mark(cast(Obj*)upvalue);
break;
case Obj.Type.None: assert(0);
}
}
private void traceReferences(){
while(vm.greyStack.count > 0){
Obj* object = vm.greyStack.pop();
blacken(object);
}
}
private auto sweep(){
size_t nCollected, total;
Obj* previous = null;
Obj* object = vm.objects;
while(object !is null){
total++;
if(object.isMarked){
object.isMarked = false;
previous = object;
object = object.next;
} else {
Obj* unreached = object;
object = object.next;
if(previous !is null){
previous.next = object;
} else {
vm.objects = object;
}
freeObject(unreached);
nCollected++;
}
}
return tuple!("collected", "total")(nCollected, total);
}