From 8c4a58a0a3bbc86a76af58b9b7fcb2bfee6564ca Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Wed, 25 Dec 2013 16:12:07 -0800 Subject: [PATCH] Make CallFrame and Method use Obj* for functions. There's no point in packing it in a Value since it will always be an ObjFn or ObjClosure. Leaving it an Obj* is a bit faster. Also fixed a bug where it was freeing the closure's flexible array of upvalues. --- src/wren_core.c | 34 ++++++++++++++++---------------- src/wren_value.c | 4 +--- src/wren_value.h | 4 ++-- src/wren_vm.c | 50 +++++++++++++++++++++++------------------------- src/wren_vm.h | 2 +- 5 files changed, 45 insertions(+), 49 deletions(-) diff --git a/src/wren_core.c b/src/wren_core.c index a8860efa..acdab5a4 100644 --- a/src/wren_core.c +++ b/src/wren_core.c @@ -119,23 +119,23 @@ DEF_NATIVE(bool_toString) // the callstack, we again use as many arguments. That ensures that the result // of evaluating the block goes into the slot that the caller of *this* // primitive is expecting. -DEF_FIBER_NATIVE(fn_call0) { wrenCallFunction(fiber, args[0], 1); } -DEF_FIBER_NATIVE(fn_call1) { wrenCallFunction(fiber, args[0], 2); } -DEF_FIBER_NATIVE(fn_call2) { wrenCallFunction(fiber, args[0], 3); } -DEF_FIBER_NATIVE(fn_call3) { wrenCallFunction(fiber, args[0], 4); } -DEF_FIBER_NATIVE(fn_call4) { wrenCallFunction(fiber, args[0], 5); } -DEF_FIBER_NATIVE(fn_call5) { wrenCallFunction(fiber, args[0], 6); } -DEF_FIBER_NATIVE(fn_call6) { wrenCallFunction(fiber, args[0], 7); } -DEF_FIBER_NATIVE(fn_call7) { wrenCallFunction(fiber, args[0], 8); } -DEF_FIBER_NATIVE(fn_call8) { wrenCallFunction(fiber, args[0], 9); } -DEF_FIBER_NATIVE(fn_call9) { wrenCallFunction(fiber, args[0], 10); } -DEF_FIBER_NATIVE(fn_call10) { wrenCallFunction(fiber, args[0], 11); } -DEF_FIBER_NATIVE(fn_call11) { wrenCallFunction(fiber, args[0], 12); } -DEF_FIBER_NATIVE(fn_call12) { wrenCallFunction(fiber, args[0], 13); } -DEF_FIBER_NATIVE(fn_call13) { wrenCallFunction(fiber, args[0], 14); } -DEF_FIBER_NATIVE(fn_call14) { wrenCallFunction(fiber, args[0], 15); } -DEF_FIBER_NATIVE(fn_call15) { wrenCallFunction(fiber, args[0], 16); } -DEF_FIBER_NATIVE(fn_call16) { wrenCallFunction(fiber, args[0], 17); } +DEF_FIBER_NATIVE(fn_call0) { wrenCallFunction(fiber, AS_OBJ(args[0]), 1); } +DEF_FIBER_NATIVE(fn_call1) { wrenCallFunction(fiber, AS_OBJ(args[0]), 2); } +DEF_FIBER_NATIVE(fn_call2) { wrenCallFunction(fiber, AS_OBJ(args[0]), 3); } +DEF_FIBER_NATIVE(fn_call3) { wrenCallFunction(fiber, AS_OBJ(args[0]), 4); } +DEF_FIBER_NATIVE(fn_call4) { wrenCallFunction(fiber, AS_OBJ(args[0]), 5); } +DEF_FIBER_NATIVE(fn_call5) { wrenCallFunction(fiber, AS_OBJ(args[0]), 6); } +DEF_FIBER_NATIVE(fn_call6) { wrenCallFunction(fiber, AS_OBJ(args[0]), 7); } +DEF_FIBER_NATIVE(fn_call7) { wrenCallFunction(fiber, AS_OBJ(args[0]), 8); } +DEF_FIBER_NATIVE(fn_call8) { wrenCallFunction(fiber, AS_OBJ(args[0]), 9); } +DEF_FIBER_NATIVE(fn_call9) { wrenCallFunction(fiber, AS_OBJ(args[0]), 10); } +DEF_FIBER_NATIVE(fn_call10) { wrenCallFunction(fiber, AS_OBJ(args[0]), 11); } +DEF_FIBER_NATIVE(fn_call11) { wrenCallFunction(fiber, AS_OBJ(args[0]), 12); } +DEF_FIBER_NATIVE(fn_call12) { wrenCallFunction(fiber, AS_OBJ(args[0]), 13); } +DEF_FIBER_NATIVE(fn_call13) { wrenCallFunction(fiber, AS_OBJ(args[0]), 14); } +DEF_FIBER_NATIVE(fn_call14) { wrenCallFunction(fiber, AS_OBJ(args[0]), 15); } +DEF_FIBER_NATIVE(fn_call15) { wrenCallFunction(fiber, AS_OBJ(args[0]), 16); } +DEF_FIBER_NATIVE(fn_call16) { wrenCallFunction(fiber, AS_OBJ(args[0]), 17); } // Grows [list] if needed to ensure it can hold [count] elements. static void ensureListCapacity(WrenVM* vm, ObjList* list, int count) diff --git a/src/wren_value.c b/src/wren_value.c index 1d7d1faa..d93863dd 100644 --- a/src/wren_value.c +++ b/src/wren_value.c @@ -278,9 +278,7 @@ static void printObject(Obj* obj) case OBJ_INSTANCE: printf("[instance %p]", obj); break; case OBJ_LIST: printList((ObjList*)obj); break; case OBJ_STRING: printf("%s", ((ObjString*)obj)->value); break; - case OBJ_UPVALUE: - ASSERT(0, "Upvalues should not be used as first-class objects."); - break; + case OBJ_UPVALUE: printf("[upvalue %p]", obj); break; } } diff --git a/src/wren_value.h b/src/wren_value.h index c6a0f44e..019dfb30 100644 --- a/src/wren_value.h +++ b/src/wren_value.h @@ -133,7 +133,7 @@ typedef struct unsigned char* ip; // The function or closure being executed. - Value fn; + Obj* fn; // Index of the first stack slot used by this call frame. This will contain // the receiver, followed by the function's parameters, then local variables @@ -214,7 +214,7 @@ typedef struct FiberPrimitive fiberPrimitive; // May be a [ObjFn] or [ObjClosure]. - Value fn; + Obj* fn; }; } Method; diff --git a/src/wren_vm.c b/src/wren_vm.c index f0c5ccba..001eb03c 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -118,6 +118,7 @@ void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize) } static void markValue(WrenVM* vm, Value value); +static void markObj(WrenVM* vm, Obj* obj); static void markClass(WrenVM* vm, ObjClass* classObj) { @@ -136,7 +137,7 @@ static void markClass(WrenVM* vm, ObjClass* classObj) { if (classObj->methods[i].type == METHOD_BLOCK) { - markValue(vm, classObj->methods[i].fn); + markObj(vm, classObj->methods[i].fn); } } @@ -228,7 +229,7 @@ static void markFiber(WrenVM* vm, ObjFiber* fiber) // Stack functions. for (int k = 0; k < fiber->numFrames; k++) { - markValue(vm, fiber->frames[k].fn); + markObj(vm, fiber->frames[k].fn); } // Stack variables. @@ -280,7 +281,7 @@ static void markString(WrenVM* vm, ObjString* string) vm->bytesAllocated += strlen(string->value); } -static void markObj(WrenVM* vm, Obj* obj) +void markObj(WrenVM* vm, Obj* obj) { #if WREN_TRACE_MEMORY static int indent = 0; @@ -330,10 +331,6 @@ static void freeObj(WrenVM* vm, Obj* obj) switch (obj->type) { - case OBJ_CLOSURE: - deallocate(vm, ((ObjClosure*)obj)->upvalues); - break; - case OBJ_FN: deallocate(vm, ((ObjFn*)obj)->bytecode); deallocate(vm, ((ObjFn*)obj)->constants); @@ -348,6 +345,7 @@ static void freeObj(WrenVM* vm, Obj* obj) break; case OBJ_CLASS: + case OBJ_CLOSURE: case OBJ_INSTANCE: case OBJ_UPVALUE: break; @@ -564,13 +562,13 @@ static void bindMethod(int methodType, int symbol, ObjClass* classObj, { case CODE_METHOD_INSTANCE: classObj->methods[symbol].type = METHOD_BLOCK; - classObj->methods[symbol].fn = method; + classObj->methods[symbol].fn = AS_OBJ(method); break; case CODE_METHOD_STATIC: // Statics are defined on the metaclass. classObj->metaclass->methods[symbol].type = METHOD_BLOCK; - classObj->metaclass->methods[symbol].fn = method; + classObj->metaclass->methods[symbol].fn = AS_OBJ(method); break; } } @@ -600,18 +598,18 @@ static Value interpret(WrenVM* vm, ObjFiber* fiber) // Use this after a CallFrame has been pushed or popped to refresh the local // variables. - #define LOAD_FRAME() \ - frame = &fiber->frames[fiber->numFrames - 1]; \ - ip = frame->ip; \ - if (IS_FN(frame->fn)) \ - { \ - fn = AS_FN(frame->fn); \ - upvalues = NULL; \ - } \ - else \ - { \ - fn = AS_CLOSURE(frame->fn)->fn; \ - upvalues = AS_CLOSURE(frame->fn)->upvalues; \ + #define LOAD_FRAME() \ + frame = &fiber->frames[fiber->numFrames - 1]; \ + ip = frame->ip; \ + if (frame->fn->type == OBJ_FN) \ + { \ + fn = (ObjFn*)frame->fn; \ + upvalues = NULL; \ + } \ + else \ + { \ + fn = ((ObjClosure*)frame->fn)->fn; \ + upvalues = ((ObjClosure*)frame->fn)->upvalues; \ } #if WREN_COMPUTED_GOTO @@ -1169,7 +1167,7 @@ int wrenInterpret(WrenVM* vm, const char* source) ObjFn* fn = wrenCompile(vm, source); if (fn != NULL) { - wrenCallFunction(fiber, OBJ_VAL(fn), 0); + wrenCallFunction(fiber, (Obj*)fn, 0); // TODO: Return error code on runtime errors. interpret(vm, fiber); result = 0; @@ -1179,7 +1177,7 @@ int wrenInterpret(WrenVM* vm, const char* source) return result; } -void wrenCallFunction(ObjFiber* fiber, Value function, int numArgs) +void wrenCallFunction(ObjFiber* fiber, Obj* function, int numArgs) { // TODO: Check for stack overflow. CallFrame* frame = &fiber->frames[fiber->numFrames]; @@ -1187,13 +1185,13 @@ void wrenCallFunction(ObjFiber* fiber, Value function, int numArgs) frame->stackStart = fiber->stackSize - numArgs; frame->ip = 0; - if (IS_FN(function)) + if (function->type == OBJ_FN) { - frame->ip = AS_FN(function)->bytecode; + frame->ip = ((ObjFn*)function)->bytecode; } else { - frame->ip = AS_CLOSURE(function)->fn->bytecode; + frame->ip = ((ObjClosure*)function)->fn->bytecode; } fiber->numFrames++; diff --git a/src/wren_vm.h b/src/wren_vm.h index 4a760164..16fc3274 100644 --- a/src/wren_vm.h +++ b/src/wren_vm.h @@ -275,7 +275,7 @@ Value findGlobal(WrenVM* vm, const char* name); // Pushes [function] onto [fiber]'s callstack and invokes it. Expects [numArgs] // arguments (including the receiver) to be on the top of the stack already. // [function] can be an `ObjFn` or `ObjClosure`. -void wrenCallFunction(ObjFiber* fiber, Value function, int numArgs); +void wrenCallFunction(ObjFiber* fiber, Obj* function, int numArgs); // Mark [obj] as a GC root so that it doesn't get collected. Initializes // [pinned], which must be then passed to [unpinObj].