Make fibers real objects.

This commit is contained in:
Bob Nystrom
2013-12-22 14:31:33 -08:00
parent 7625de7536
commit 034fec6eaa
7 changed files with 156 additions and 130 deletions
+57 -45
View File
@@ -25,14 +25,12 @@ WrenVM* wrenNewVM(WrenConfiguration* configuration)
}
WrenVM* vm = reallocate(NULL, 0, sizeof(WrenVM));
vm->reallocate = reallocate;
initSymbolTable(&vm->methods);
initSymbolTable(&vm->globalSymbols);
vm->fiber = reallocate(NULL, 0, sizeof(Fiber));
vm->fiber->stackSize = 0;
vm->fiber->numFrames = 0;
vm->fiber->openUpvalues = NULL;
vm->bytesAllocated = 0;
vm->nextGC = 1024 * 1024 * 10;
@@ -66,10 +64,7 @@ WrenVM* wrenNewVM(WrenConfiguration* configuration)
vm->globals[i] = NULL_VAL;
}
vm->reallocate = reallocate;
wrenInitializeCore(vm);
return vm;
}
@@ -80,16 +75,6 @@ void wrenFreeVM(WrenVM* vm)
free(vm);
}
int wrenInterpret(WrenVM* vm, const char* source)
{
ObjFn* fn = wrenCompile(vm, source);
if (fn == NULL) return 1;
// TODO: Return error code on runtime errors.
interpret(vm, OBJ_VAL(fn));
return 0;
}
static void collectGarbage(WrenVM* vm);
void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize)
@@ -234,6 +219,33 @@ static void markUpvalue(WrenVM* vm, Upvalue* upvalue)
vm->bytesAllocated += sizeof(Upvalue);
}
static void markFiber(WrenVM* vm, ObjFiber* fiber)
{
// Don't recurse if already marked. Avoids getting stuck in a loop on cycles.
if (fiber->obj.flags & FLAG_MARKED) return;
fiber->obj.flags |= FLAG_MARKED;
// Stack functions.
for (int k = 0; k < fiber->numFrames; k++)
{
markValue(vm, fiber->frames[k].fn);
}
// Stack variables.
for (int l = 0; l < fiber->stackSize; l++)
{
markValue(vm, fiber->stack[l]);
}
// Open upvalues.
Upvalue* upvalue = fiber->openUpvalues;
while (upvalue != NULL)
{
markUpvalue(vm, upvalue);
upvalue = upvalue->next;
}
}
static void markClosure(WrenVM* vm, ObjClosure* closure)
{
// Don't recurse if already marked. Avoids getting stuck in a loop on cycles.
@@ -284,6 +296,7 @@ static void markObj(WrenVM* vm, Obj* obj)
{
case OBJ_CLASS: markClass( vm, (ObjClass*) obj); break;
case OBJ_CLOSURE: markClosure( vm, (ObjClosure*) obj); break;
case OBJ_FIBER: markFiber( vm, (ObjFiber*) obj); break;
case OBJ_FN: markFn( vm, (ObjFn*) obj); break;
case OBJ_INSTANCE: markInstance(vm, (ObjInstance*)obj); break;
case OBJ_LIST: markList( vm, (ObjList*) obj); break;
@@ -376,26 +389,6 @@ static void collectGarbage(WrenVM* vm)
pinned = pinned->previous;
}
// Stack functions.
for (int k = 0; k < vm->fiber->numFrames; k++)
{
markValue(vm, vm->fiber->frames[k].fn);
}
// Stack variables.
for (int l = 0; l < vm->fiber->stackSize; l++)
{
markValue(vm, vm->fiber->stack[l]);
}
// Open upvalues.
Upvalue* upvalue = vm->fiber->openUpvalues;
while (upvalue != NULL)
{
markUpvalue(vm, upvalue);
upvalue = upvalue->next;
}
// Collect any unmarked objects.
Obj** obj = &vm->first;
while (*obj != NULL)
@@ -498,7 +491,7 @@ Value findGlobal(WrenVM* vm, const char* name)
// ensure that multiple closures closing over the same variable actually see
// the same variable.) Otherwise, it will create a new open upvalue and add it
// the fiber's list of upvalues.
static Upvalue* captureUpvalue(WrenVM* vm, Fiber* fiber, int slot)
static Upvalue* captureUpvalue(WrenVM* vm, ObjFiber* fiber, int slot)
{
Value* local = &fiber->stack[slot];
@@ -541,7 +534,7 @@ static Upvalue* captureUpvalue(WrenVM* vm, Fiber* fiber, int slot)
return createdUpvalue;
}
static void closeUpvalue(Fiber* fiber)
static void closeUpvalue(ObjFiber* fiber)
{
Upvalue* upvalue = fiber->openUpvalues;
@@ -584,11 +577,8 @@ static void bindMethod(int methodType, int symbol, ObjClass* classObj,
// The main bytecode interpreter loop. This is where the magic happens. It is
// also, as you can imagine, highly performance critical.
Value interpret(WrenVM* vm, Value function)
static Value interpret(WrenVM* vm, ObjFiber* fiber)
{
Fiber* fiber = vm->fiber;
wrenCallFunction(fiber, function, 0);
// These macros are designed to only be invoked within this function.
// TODO: Check for stack overflow.
#define PUSH(value) (fiber->stack[fiber->stackSize++] = value)
@@ -1152,9 +1142,31 @@ Value interpret(WrenVM* vm, Value function)
// the compiler generated wrong code.
ASSERT(0, "Should not execute past end of bytecode.");
}
ASSERT(0, "Should not reach end of interpret.");
}
void wrenCallFunction(Fiber* fiber, Value function, int numArgs)
int wrenInterpret(WrenVM* vm, const char* source)
{
ObjFiber* fiber = wrenNewFiber(vm);
PinnedObj pinned;
pinObj(vm, (Obj*)fiber, &pinned);
int result = 1;
ObjFn* fn = wrenCompile(vm, source);
if (fn != NULL)
{
wrenCallFunction(fiber, OBJ_VAL(fn), 0);
// TODO: Return error code on runtime errors.
interpret(vm, fiber);
result = 0;
}
unpinObj(vm);
return result;
}
void wrenCallFunction(ObjFiber* fiber, Value function, int numArgs)
{
// TODO: Check for stack overflow.
CallFrame* frame = &fiber->frames[fiber->numFrames];