-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmemory.c
120 lines (99 loc) · 2.35 KB
/
memory.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <stdlib.h>
#include "compiler.h"
#include "memory.h"
#include "vm.h"
#ifdef DEBUG_LOG_GC
#include <stdio.h>
#include "debug.h"
#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;
}
void* result = realloc(pointer, newSize);
if (result == NULL) exit(1);
return result;
}
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;
}
void markValue(Value value) {
if (IS_OBJ(value)) markObject(AS_OBJ(value));
}
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_CLOSURE: {
ObjClosure* closure = (ObjClosure*)object;
FREE_ARRAY(ObjUpvalue*, closure->upvalues, closure->upvalueCount);
FREE(ObjClosure, object);
break;
}
case OBJ_FUNCTION: {
ObjFunction* function = (ObjFunction*)object;
freeChunk(&function->chunk);
FREE(ObjFunction, object);
break;
}
case OBJ_NATIVE: {
FREE(ObjNative, object);
break;
}
case OBJ_STRING: {
ObjString* string = (ObjString*)object;
FREE_ARRAY(char, string->chars, string->length + 1);
// going through reallocate instead of calling free() will make it easier
// to keep track of how much memory is in use.
FREE(ObjString, object);
break;
}
case OBJ_UPVALUE: {
FREE(ObjUpvalue, object);
break;
}
}
}
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 freeObjects() {
Obj* object = vm.objects;
while (object != NULL) {
Obj* next = object->next;
freeObject(object);
object = next;
}
}