Value wrenListRemoveAt(WrenVM* vm, ObjList* list, int index) { Value removed = list->elements[index]; if (IS_OBJ(removed)) WREN_PIN(vm, AS_OBJ(removed)); // Shift items up. for (int i = index; i < list->count - 1; i++) { list->elements[i] = list->elements[i + 1]; } // If we have too much excess capacity, shrink it. if (list->capacity / LIST_GROW_FACTOR >= list->count) { list->elements = wrenReallocate(vm, list->elements, sizeof(Value) * list->capacity, sizeof(Value) * (list->capacity / LIST_GROW_FACTOR)); list->capacity /= LIST_GROW_FACTOR; } if (IS_OBJ(removed)) WREN_UNPIN(vm); list->count--; return removed; }
void wrenSymbolTableClear(WrenVM* vm, SymbolTable* symbols) { for (int i = 0; i < symbols->names.count; i++) { wrenReallocate(vm, symbols->names.data[i], 0, 0); } wrenStringBufferClear(vm, &symbols->names); }
void wrenFreeObj(WrenVM* vm, Obj* obj) { #if WREN_DEBUG_TRACE_MEMORY printf("free "); wrenPrintValue(OBJ_VAL(obj)); printf(" @ %p\n", obj); #endif switch (obj->type) { case OBJ_CLASS: wrenMethodBufferClear(vm, &((ObjClass*)obj)->methods); break; case OBJ_FIBER: { ObjFiber* fiber = ((ObjFiber*)obj); if (fiber->error != NULL) wrenReallocate(vm, fiber->error, 0, 0); break; } case OBJ_FN: { ObjFn* fn = (ObjFn*)obj; wrenReallocate(vm, fn->constants, 0, 0); wrenReallocate(vm, fn->bytecode, 0, 0); wrenReallocate(vm, fn->debug->name, 0, 0); wrenReallocate(vm, fn->debug->sourceLines, 0, 0); wrenReallocate(vm, fn->debug, 0, 0); break; } case OBJ_LIST: wrenReallocate(vm, ((ObjList*)obj)->elements, 0, 0); break; case OBJ_STRING: wrenReallocate(vm, ((ObjString*)obj)->value, 0, 0); break; case OBJ_CLOSURE: case OBJ_INSTANCE: case OBJ_RANGE: case OBJ_UPVALUE: break; } wrenReallocate(vm, obj, 0, 0); }
static int addSymbol(WrenVM* vm, SymbolTable* symbols, const char* name, size_t length) { char* heapString = wrenReallocate(vm, NULL, 0, sizeof(char) * (length + 1)); strncpy(heapString, name, length); heapString[length] = '\0'; wrenStringBufferWrite(vm, &symbols->names, heapString); return symbols->names.count - 1; }
// Grows [list] if needed to ensure it can hold [count] elements. static void ensureListCapacity(WrenVM* vm, ObjList* list, int count) { if (list->capacity >= count) return; int capacity = list->capacity * LIST_GROW_FACTOR; if (capacity < LIST_MIN_CAPACITY) capacity = LIST_MIN_CAPACITY; list->capacity *= 2; list->elements = wrenReallocate(vm, list->elements, list->capacity * sizeof(Value), capacity * sizeof(Value)); // TODO: Handle allocation failure. list->capacity = capacity; }
void wrenFreeVM(WrenVM* vm) { // TODO: Check for already freed. // Free all of the GC objects. Obj* obj = vm->first; while (obj != NULL) { Obj* next = obj->next; wrenFreeObj(vm, obj); obj = next; } wrenSymbolTableClear(vm, &vm->methodNames); wrenSymbolTableClear(vm, &vm->globalNames); wrenValueBufferClear(vm, &vm->globals); wrenReallocate(vm, vm, 0, 0); }
static void* allocate(WrenVM* vm, size_t size) { return wrenReallocate(vm, NULL, 0, size); }