forked from Mirror/wren
Tweak a few things in the new GC.
- Make sure it handles an empty gray set. - Make sure growing the gray stack doesn't itself trigger a GC. - Make sure it works when stress testing is enabled. - Ensure the tests kick off a GC.
This commit is contained in:
@ -867,15 +867,14 @@ void wrenGrayObj(WrenVM* vm, Obj* obj)
|
||||
|
||||
// Add it to the gray list so it can be recursively explored for
|
||||
// more marks later.
|
||||
if (vm->grayDepth >= vm->maxGray)
|
||||
if (vm->grayCount >= vm->grayCapacity)
|
||||
{
|
||||
size_t oldSize = vm->maxGray * sizeof(Obj*);
|
||||
size_t newSize = vm->grayDepth * 2 * sizeof(Obj*);
|
||||
vm->gray = (Obj**)wrenReallocate(vm, vm->gray, oldSize, newSize);
|
||||
vm->maxGray = vm->grayDepth * 2;
|
||||
vm->grayCapacity = vm->grayCount * 2;
|
||||
vm->gray = vm->config.reallocateFn(vm->gray,
|
||||
vm->grayCapacity * sizeof(Obj*));
|
||||
}
|
||||
|
||||
vm->gray[vm->grayDepth++] = obj;
|
||||
vm->gray[vm->grayCount++] = obj;
|
||||
}
|
||||
|
||||
void wrenGrayValue(WrenVM* vm, Value value)
|
||||
@ -1095,12 +1094,12 @@ static void blackenObject(WrenVM* vm, Obj* obj)
|
||||
|
||||
void wrenBlackenObjects(WrenVM* vm)
|
||||
{
|
||||
do
|
||||
while (vm->grayCount > 0)
|
||||
{
|
||||
// Pop an item from the gray stack.
|
||||
Obj* obj = vm->gray[--vm->grayDepth];
|
||||
Obj* obj = vm->gray[--vm->grayCount];
|
||||
blackenObject(vm, obj);
|
||||
} while (vm->grayDepth > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void wrenFreeObj(WrenVM* vm, Obj* obj)
|
||||
|
||||
@ -46,29 +46,25 @@ void wrenInitConfiguration(WrenConfiguration* config)
|
||||
config->heapGrowthPercent = 50;
|
||||
}
|
||||
|
||||
static void initializeGC(WrenVM* vm)
|
||||
{
|
||||
vm->gray = (Obj**)wrenReallocate(vm, NULL, 0, 5 * sizeof(Obj*));
|
||||
vm->grayDepth = 0;
|
||||
vm->maxGray = 5;
|
||||
}
|
||||
|
||||
WrenVM* wrenNewVM(WrenConfiguration* config)
|
||||
{
|
||||
WrenVM* vm = (WrenVM*)config->reallocateFn(NULL, sizeof(*vm));
|
||||
memset(vm, 0, sizeof(WrenVM));
|
||||
memcpy(&vm->config, config, sizeof(WrenConfiguration));
|
||||
|
||||
// TODO: Should we allocate and free this during a GC?
|
||||
vm->grayCount = 0;
|
||||
// TODO: Tune this.
|
||||
vm->grayCapacity = 4;
|
||||
vm->gray = vm->config.reallocateFn(NULL, vm->grayCapacity * sizeof(Obj*));
|
||||
vm->nextGC = config->initialHeapSize;
|
||||
|
||||
|
||||
wrenSymbolTableInit(&vm->methodNames);
|
||||
|
||||
vm->modules = wrenNewMap(vm);
|
||||
|
||||
wrenInitializeCore(vm);
|
||||
|
||||
initializeGC(vm);
|
||||
|
||||
// TODO: Lazy load these.
|
||||
#if WREN_OPT_META
|
||||
wrenLoadMetaModule(vm);
|
||||
@ -94,7 +90,7 @@ void wrenFreeVM(WrenVM* vm)
|
||||
}
|
||||
|
||||
// Free up the GC gray set.
|
||||
wrenReallocate(vm, vm->gray, vm->maxGray * sizeof(Obj*), 0);
|
||||
vm->gray = vm->config.reallocateFn(vm->gray, 0);
|
||||
|
||||
// Tell the user if they didn't free any handles. We don't want to just free
|
||||
// them here because the host app may still have pointers to them that they
|
||||
|
||||
@ -72,8 +72,8 @@ struct WrenVM
|
||||
// The "gray" set for the garbage collector. This is the stack of unprocessed
|
||||
// objects while a garbage collection pass is in process.
|
||||
Obj** gray;
|
||||
int grayDepth;
|
||||
int maxGray;
|
||||
int grayCount;
|
||||
int grayCapacity;
|
||||
|
||||
// The list of temporary roots. This is for temporary or new objects that are
|
||||
// not otherwise reachable but should not be collected.
|
||||
|
||||
@ -4,4 +4,5 @@ for (i in 1..400000) {
|
||||
head = { "next" : head }
|
||||
}
|
||||
|
||||
System.print("done") // expect: done
|
||||
System.gc()
|
||||
System.print("done") // expect: done
|
||||
|
||||
@ -10,5 +10,7 @@ for (i in 1..1000) {
|
||||
}
|
||||
found.add(bar)
|
||||
}
|
||||
|
||||
System.gc()
|
||||
System.print(found.all {|i| i == 1337}) // expect: true
|
||||
System.print("DONE!") // expect: DONE!
|
||||
System.print("done") // expect: done
|
||||
|
||||
Reference in New Issue
Block a user