runningwater преди 2 години
родител
ревизия
fe51fc4d35
променени са 9 файла, в които са добавени 84 реда и са изтрити 0 реда
  1. 3 0
      common.h
  2. 8 0
      compiler.c
  3. 1 0
      compiler.h
  4. 54 0
      memory.c
  5. 3 0
      memory.h
  6. 5 0
      object.c
  7. 1 0
      object.h
  8. 7 0
      table.c
  9. 2 0
      table.h

+ 3 - 0
common.h

@@ -16,6 +16,9 @@
 #define DEBUG_TRACE_EXECUTION
 //#define DEBUG_STACK_INFO
 
+#define DEBUG_STRESS_GC
+#define DEBUG_LOG_GC
+
 #define UINT8_COUNT (UINT8_MAX + 1)
 
 #endif//CLOX__COMMON_H_

+ 8 - 0
compiler.c

@@ -13,6 +13,7 @@
 #ifdef DEBUG_PRINT_CODE
 #include "debug.h"
 #endif
+#include "memory.h"
 
 typedef struct {
   Token current;
@@ -859,3 +860,10 @@ ObjFunction *compile(const char *source) {
   ObjFunction *function = endCompiler();
   return parser.hadError ? NULL : function;
 }
+void markCompilerRoots() {
+  Compiler *compiler = current;
+  while (compiler != NULL) {
+    markObject((Obj *) compiler->function);
+    compiler = compiler->enclosing;
+  }
+}

+ 1 - 0
compiler.h

@@ -16,5 +16,6 @@
 /// \brief 编译
 /// \param source 源代码
 ObjFunction* compile(const char *source);
+void markCompilerRoots();
 
 #endif//CLOX__COMPILER_H_

+ 54 - 0
memory.c

@@ -1,6 +1,10 @@
 #include "memory.h"
 #include "vm.h"
+
+#ifdef DEBUG_LOG_GC
+#include "debug.h"
 #include <stdlib.h>
+#endif
 
 //    oldSize	 newSize	               Operation
 //    0	        Non‑zero	            Allocate new block.
@@ -8,6 +12,12 @@
 //    Non‑zero	Smaller than oldSize	Shrink existing allocation.
 //    Non‑zero	Larger than oldSize	    Grow existing allocation.
 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;
@@ -30,6 +40,10 @@ void *reallocate(void *pointer, size_t oldSize, size_t newSize) {
   return result;
 }
 static void freeObject(Obj *object) {
+#ifdef DEBUG_LOG_GC
+  printf("%p free type %d\n", (void *) object, object->type);
+#endif
+
   switch (object->type) {
     case OBJ_NATIVE:
       FREE(ObjNative, object);
@@ -63,3 +77,43 @@ void freeObjects() {
     object = next;
   }
 }
+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();
+}
+void collectGarbage() {
+#ifdef DEBUG_LOG_GC
+  printf("-- gc begin\n");
+#endif
+
+  markRoots();
+
+#ifdef DEBUG_LOG_GC
+  printf("-- gc end\n");
+#endif
+}
+void markValue(Value value) {
+  if (IS_OBJ(value)) markObject(AS_OBJ(value));
+}
+void markObject(Obj *object) {
+  if (object == NULL) return;
+#ifdef DEBUG_LOG_GC
+  printf("%p mark ", (void *) object);
+  printValue(OBJ_VAL(object));
+  printf("\n");
+#endif
+
+  object->isMarked = true;
+}

+ 3 - 0
memory.h

@@ -28,5 +28,8 @@
 //    Non‑zero	Smaller than oldSize	Shrink existing allocation.
 //    Non‑zero	Larger than oldSize	    Grow existing allocation.
 void *reallocate(void *pointer, size_t oldSize, size_t newSize);
+void markObject(Obj* object);
+void markValue(Value value);
+void collectGarbage();
 void freeObjects();
 #endif//CLOX_MEMORY_H

+ 5 - 0
object.c

@@ -121,10 +121,15 @@ ObjUpvalue *newUpvalue(Value *slot) {
 static Obj *allocateObject(size_t size, ObjType type) {
   Obj *object = (Obj *) reallocate(NULL, 0, size);
   object->type = type;
+  object->isMarked = false;
 
   object->next = vm.objects;
   vm.objects = object;
 
+#ifdef DEBUG_LOG_GC
+  printf("%p allocate %zu for %d\n", (void *) object, size, type);
+#endif
+
   return object;
 }
 /// Hash 函数 -- 使用 FNV-1a 算法

+ 1 - 0
object.h

@@ -38,6 +38,7 @@ typedef enum {
 
 struct Obj {
   ObjType type;
+  bool isMarked;
   struct Obj *next;
 };
 

+ 7 - 0
table.c

@@ -144,3 +144,10 @@ ObjString *tableFindString(Table *table, const char *chars, int length, uint32_t
   }
   return NULL;
 }
+void markTable(Table *table) {
+  for (int i = 0; i < table->capacity; i++) {
+    Entry *entry = &table->entries[i];
+    markObject((Obj *) entry->key);
+    markValue(entry->value);
+  }
+}

+ 2 - 0
table.h

@@ -39,4 +39,6 @@ void tableAddAll(Table *from, Table *to);
 /// \return  ObjString*
 ObjString *tableFindString(Table *table, const char *chars, int length, uint32_t hash);
 
+void markTable(Table *table);
+
 #endif//CLOX_TABLE_H