1
0
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:
Bob Nystrom
2015-10-29 07:38:09 -07:00
parent 25bd182c58
commit 2ff8acbe1a
5 changed files with 22 additions and 24 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -4,4 +4,5 @@ for (i in 1..400000) {
head = { "next" : head }
}
System.print("done") // expect: done
System.gc()
System.print("done") // expect: done

View File

@ -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