Get finalizers working.
This commit is contained in:
+1
-1
@@ -1089,7 +1089,7 @@ void wrenFreeObj(WrenVM* vm, Obj* obj)
|
||||
}
|
||||
|
||||
case OBJ_FOREIGN:
|
||||
// TODO: Call finalizer.
|
||||
wrenFinalizeForeign(vm, (ObjForeign*)obj);
|
||||
break;
|
||||
|
||||
case OBJ_LIST:
|
||||
|
||||
+33
-4
@@ -125,7 +125,7 @@ void wrenSetCompiler(WrenVM* vm, Compiler* compiler)
|
||||
vm->compiler = compiler;
|
||||
}
|
||||
|
||||
static void collectGarbage(WrenVM* vm)
|
||||
void wrenCollectGarbage(WrenVM* vm)
|
||||
{
|
||||
#if WREN_DEBUG_TRACE_MEMORY || WREN_DEBUG_TRACE_GC
|
||||
printf("-- gc --\n");
|
||||
@@ -222,9 +222,9 @@ void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize)
|
||||
#if WREN_DEBUG_GC_STRESS
|
||||
// Since collecting calls this function to free things, make sure we don't
|
||||
// recurse.
|
||||
if (newSize > 0) collectGarbage(vm);
|
||||
if (newSize > 0) wrenCollectGarbage(vm);
|
||||
#else
|
||||
if (newSize > 0 && vm->bytesAllocated > vm->nextGC) collectGarbage(vm);
|
||||
if (newSize > 0 && vm->bytesAllocated > vm->nextGC) wrenCollectGarbage(vm);
|
||||
#endif
|
||||
|
||||
return vm->reallocate(memory, newSize);
|
||||
@@ -615,10 +615,13 @@ static void bindForeignClass(WrenVM* vm, ObjClass* classObj, ObjModule* module)
|
||||
int symbol = wrenSymbolTableEnsure(vm, &vm->methodNames, "<allocate>", 10);
|
||||
wrenBindMethod(vm, classObj, symbol, method);
|
||||
|
||||
// Add the symbol even if there is no finalizer so we can ensure that the
|
||||
// symbol itself is always in the symbol table.
|
||||
symbol = wrenSymbolTableEnsure(vm, &vm->methodNames, "<finalize>", 10);
|
||||
|
||||
if (methods.finalize != NULL)
|
||||
{
|
||||
method.fn.foreign = methods.finalize;
|
||||
symbol = wrenSymbolTableEnsure(vm, &vm->methodNames, "<finalize>", 10);
|
||||
wrenBindMethod(vm, classObj, symbol, method);
|
||||
}
|
||||
}
|
||||
@@ -686,6 +689,32 @@ static void createForeign(WrenVM* vm, ObjFiber* fiber, Value* stack)
|
||||
// TODO: Check that allocateForeign was called.
|
||||
}
|
||||
|
||||
void wrenFinalizeForeign(WrenVM* vm, ObjForeign* foreign)
|
||||
{
|
||||
// TODO: Don't look up every time.
|
||||
int symbol = wrenSymbolTableFind(&vm->methodNames, "<finalize>", 10);
|
||||
ASSERT(symbol != -1, "Should have defined <finalize> symbol.");
|
||||
|
||||
// If there are no finalizers, don't finalize it.
|
||||
if (symbol == -1) return;
|
||||
|
||||
// If the class doesn't have a finalizer, bail out.
|
||||
ObjClass* classObj = foreign->obj.classObj;
|
||||
if (symbol >= classObj->methods.count) return;
|
||||
|
||||
Method* method = &classObj->methods.data[symbol];
|
||||
if (method->type == METHOD_NONE) return;
|
||||
|
||||
ASSERT(method->type == METHOD_FOREIGN, "Finalizer should be foreign.");
|
||||
|
||||
// Pass the constructor arguments to the allocator as well.
|
||||
Value slot = OBJ_VAL(foreign);
|
||||
vm->foreignCallSlot = &slot;
|
||||
vm->foreignCallNumArgs = 1;
|
||||
|
||||
method->fn.foreign(vm);
|
||||
}
|
||||
|
||||
// The main bytecode interpreter loop. This is where the magic happens. It is
|
||||
// also, as you can imagine, highly performance critical. Returns `true` if the
|
||||
// fiber completed without error.
|
||||
|
||||
+8
-5
@@ -89,17 +89,17 @@ struct WrenVM
|
||||
Obj* tempRoots[WREN_MAX_TEMP_ROOTS];
|
||||
|
||||
int numTempRoots;
|
||||
|
||||
|
||||
// Pointer to the first node in the linked list of active value handles or
|
||||
// NULL if there are no handles.
|
||||
WrenValue* valueHandles;
|
||||
|
||||
// Foreign function data:
|
||||
|
||||
// During a foreign function call, this will point to the first argument (the
|
||||
// receiver) of the call on the fiber's stack.
|
||||
Value* foreignCallSlot;
|
||||
|
||||
// Pointer to the first node in the linked list of active value handles or
|
||||
// NULL if there are no handles.
|
||||
WrenValue* valueHandles;
|
||||
|
||||
// During a foreign function call, this will contain the number of arguments
|
||||
// to the function.
|
||||
int foreignCallNumArgs;
|
||||
@@ -143,6 +143,9 @@ struct WrenVM
|
||||
// [oldSize] will be zero. It should return NULL.
|
||||
void* wrenReallocate(WrenVM* vm, void* memory, size_t oldSize, size_t newSize);
|
||||
|
||||
// Invoke the finalizer for the foreign object referenced by [foreign].
|
||||
void wrenFinalizeForeign(WrenVM* vm, ObjForeign* foreign);
|
||||
|
||||
// Creates a new [WrenValue] for [value].
|
||||
WrenValue* wrenCaptureValue(WrenVM* vm, Value value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user