From 14b3866ac09c80b8f34d79227d743eabb2da0f2a Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sat, 4 Jun 2022 22:00:27 -0700 Subject: Chapter 26.1, 26.2, 26.3, and 26.4 --- clox/src/memory.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'clox/src/memory.c') diff --git a/clox/src/memory.c b/clox/src/memory.c index 1db1c61..7d403d1 100644 --- a/clox/src/memory.c +++ b/clox/src/memory.c @@ -1,9 +1,21 @@ #include +#include "compiler.h" #include "memory.h" #include "vm.h" +#ifdef DEBUG_LOG_GC +#include "debug.h" +#include +#endif + void *reallocate(void *pointer, size_t oldSize, size_t newSize) { + if (newSize > oldSize) { +#ifdef DEBUG_STRESS_GC + collectGarbage(); +#endif + } + if (newSize == 0) { free(pointer); return NULL; @@ -15,7 +27,76 @@ void *reallocate(void *pointer, size_t oldSize, size_t newSize) { return result; } +void markObject(Obj *object) { + if (object == NULL) + return; + if (object->isMarked) + return; + +#ifdef DEBUG_LOG_GC + printf("%p mark ", (void *)object); + printValue(OBJ_VAL(object)); + printf("\n"); +#endif + object->isMarked = true; + + if (vm.grayCapacity < vm.grayCount + 1) { + vm.grayCapacity = GROW_CAPACITY(vm.grayCapacity); + vm.grayStack = + (Obj **)realloc(vm.grayStack, sizeof(Obj *) * vm.grayCapacity); + if (vm.grayStack == NULL) + exit(1); + } + + vm.grayStack[vm.grayCount++] = object; +} + +void markValue(Value value) { + if (IS_OBJ(value)) + markObject(AS_OBJ(value)); +} + +static void markArray(ValueArray *array) { + for (int i = 0; i < array->count; i++) { + markValue(array->values[i]); + } +} + +static void blackenObject(Obj *object) { +#ifdef DEBUG_LOG_GC + printf("%p blacken ", (void *)object); + printValue(OBJ_VAL(object)); + printf("\n"); +#endif + switch (object->type) { + case OBJ_CLOSURE: { + ObjClosure *closure = (ObjClosure *)object; + markObject((Obj *)closure->function); + for (int i = 0; i < closure->upvalueCount; i++) { + markObject((Obj *)closure->upvalues[i]); + } + break; + } + case OBJ_FUNCTION: { + ObjFunction *function = (ObjFunction *)object; + markObject((Obj *)function->name); + markArray(&function->chunk.constants); + break; + } + case OBJ_UPVALUE: + markValue(((ObjUpvalue *)object)->closed); + break; + case OBJ_NATIVE: + case OBJ_STRING: + break; + } +} + static void freeObject(Obj *object) { +#ifdef DEBUG_LOG_GC + printf("%p free type %d\n", (void *)object, object->type); +#endif // DEBUG_LOG_GC + switch (object->type) { case OBJ_CLOSURE: { ObjClosure *closure = (ObjClosure *)object; @@ -44,6 +125,44 @@ static void freeObject(Obj *object) { } } +static void markRoots() { + for (Value *slot = vm.stack; slot < vm.stackTop; slot++) { + markValue(*slot); + } + + for (int i = 0; i < vm.frameCount; i++) { + markObject((Obj *)vm.frames[i].closure); + } + + for (ObjUpvalue *upvalue = vm.openUpvalues; upvalue != NULL; + upvalue = upvalue->next) { + markObject((Obj *)upvalue); + } + + markTable(&vm.globals); + markCompilerRoots(); +} + +static void traceReferences() { + while (vm.grayCount > 0) { + Obj *object = vm.grayStack[--vm.grayCount]; + blackenObject(object); + } +} + +void collectGarbage() { +#ifdef DEBUG_LOG_GC + printf("-- gc begin\n"); +#endif + + markRoots(); + traceReferences(); + +#ifdef DEBUG_LOG_GC + printf("-- gd end\n"); +#endif +} + void freeObjects() { Obj *object = vm.objects; while (object != NULL) { @@ -51,4 +170,6 @@ void freeObjects() { freeObject(object); object = next; } + + free(vm.grayStack); } -- cgit v1.2.3-54-g00ecf