3
3
type memory = struct {
4
4
envs: []*env,
5
5
hashs: []hashmap,
6
- symbols: []symbol ,
6
+ symbols: (void | hashmap) ,
7
7
funcs: []function,
8
8
lists: []list,
9
9
vecs: []vector,
@@ -19,25 +19,53 @@ type garbage_collector = struct {
19
19
20
20
let gc = garbage_collector {
21
21
marked = memory {
22
+ symbols = void,
22
23
funcs = [],
23
24
...
24
25
},
25
26
memory = memory {
27
+ symbols = void,
26
28
funcs = [],
27
29
...
28
30
},
29
31
};
30
32
33
+ fn reset_memory(memory: *memory) void = {
34
+
35
+ memory.envs = memory.envs[..0];
36
+ memory.hashs = memory.hashs[..0];
37
+ memory.funcs = memory.funcs[..0];
38
+ memory.lists = memory.lists[..0];
39
+ memory.vecs = memory.vecs[..0];
40
+ memory.strings = memory.strings[..0];
41
+ memory.atoms = memory.atoms[..0];
42
+ memory.intrinsics = memory.intrinsics[..0];
43
+
44
+ match(memory.symbols){
45
+ case let hm: hashmap =>
46
+ hm.data = hm.data[..0];
47
+ case void =>
48
+ void;
49
+ };
50
+ };
51
+
31
52
fn finish_memory(memory: memory) void = {
53
+
32
54
free(memory.envs);
33
55
free(memory.hashs);
34
- free(memory.symbols);
35
56
free(memory.funcs);
36
57
free(memory.lists);
37
58
free(memory.vecs);
38
59
free(memory.strings);
39
60
free(memory.atoms);
40
61
free(memory.intrinsics);
62
+
63
+ match(memory.symbols){
64
+ case let hm: hashmap =>
65
+ hm_free(hm);
66
+ case void =>
67
+ void;
68
+ };
41
69
};
42
70
43
71
fn mark_hash(hm: hashmap) void = {
@@ -75,6 +103,12 @@ fn mark_col(col: []MalType) void = {
75
103
76
104
fn mark (val: MalType) void = {
77
105
106
+ match(gc.marked.symbols){
107
+ case void =>
108
+ gc.marked.symbols = hm_init(false);
109
+ case => void;
110
+ };
111
+
78
112
match(val){
79
113
case let v: vector =>
80
114
for(let x .. gc.marked.vecs){
@@ -121,10 +155,11 @@ fn mark (val: MalType) void = {
121
155
};
122
156
mark_hash(h);
123
157
case let s: symbol =>
124
- for(let x .. gc.marked.symbols){
125
- if(x == s) return void;
158
+ match(hm_get(gc.marked.symbols: hashmap, s)){
159
+ case undefined_key =>
160
+ hm_add(gc.marked.symbols: hashmap, s, s);
161
+ case => void;
126
162
};
127
- append(gc.marked.symbols, s);
128
163
case let s: string =>
129
164
for(let x .. gc.marked.strings){
130
165
if(x == s) return void;
@@ -143,83 +178,93 @@ fn mark (val: MalType) void = {
143
178
144
179
fn sweep() void ={
145
180
146
- // since we're only ever comparing pointers and never dereferencing here
147
- // it should be ok to not call delete(gc.memory.<t>[i-1]) on the after
148
- // freeing the value.
149
- //
150
- // This means doing anything with gc.memory after calling this function
151
- // is extremely unsafe.
181
+ const marked_symbols = match(gc.marked.symbols){
182
+ case void =>
183
+ gc.marked.symbols = hm_init(false);
184
+ yield gc.marked.symbols: hashmap;
185
+ case let hm: hashmap =>
186
+ yield hm;
187
+ };
152
188
153
- for :sweep (let i: size = len(gc.memory.symbols); i > 0; i -= 1) {
154
- for(let x .. gc.marked.symbols){
155
- if(x == gc.memory.symbols[i-1]) continue :sweep;
189
+ const memory_symbols = match(gc.memory.symbols){
190
+ case void =>
191
+ gc.memory.symbols = hm_init(false);
192
+ yield gc.memory.symbols: hashmap;
193
+ case let hm: hashmap =>
194
+ yield hm;
195
+ };
196
+
197
+ for (let i: size = 0; len(memory_symbols.data) > i; i += 1) {
198
+ match(hm_get(marked_symbols, memory_symbols.data[i].key)){
199
+ case undefined_key =>
200
+ free(memory_symbols.data[i].key: symbol);
201
+ case =>
202
+ void;
156
203
};
157
- free(gc.memory.symbols[i-1]);
158
204
};
159
- for :sweep (let i: size = len(gc.memory.atoms); i > 0 ; i - = 1) {
205
+ for :sweep (let i: size = 0; len(gc.memory.atoms) > i ; i + = 1) {
160
206
for(let x .. gc.marked.atoms){
161
- if(x == gc.memory.atoms[i-1 ]) continue :sweep;
207
+ if(x == gc.memory.atoms[i]) continue :sweep;
162
208
};
163
- free(gc.memory.atoms[i-1 ]);
209
+ free(gc.memory.atoms[i]);
164
210
};
165
- for :sweep (let i: size = len(gc.memory.strings); i > 0 ; i - = 1) {
211
+ for :sweep (let i: size = 0; len(gc.memory.strings) > i ; i + = 1) {
166
212
for(let x .. gc.marked.strings){
167
- if(x == gc.memory.strings[i-1 ]) continue :sweep;
213
+ if(x == gc.memory.strings[i]) continue :sweep;
168
214
};
169
- free_string(gc.memory.strings[i-1 ]);
215
+ free_string(gc.memory.strings[i]);
170
216
};
171
- for :sweep (let i: size = len(gc.memory.hashs); i > 0 ; i - = 1) {
217
+ for :sweep (let i: size = 0; len(gc.memory.hashs) > i ; i + = 1) {
172
218
for(let x .. gc.marked.hashs){
173
- if(x == gc.memory.hashs[i-1 ]) continue :sweep;
219
+ if(x == gc.memory.hashs[i]) continue :sweep;
174
220
};
175
- hm_free(gc.memory.hashs[i-1 ]);
221
+ hm_free(gc.memory.hashs[i]);
176
222
};
177
- for :sweep (let i: size = len(gc.memory.envs); i > 0 ; i - = 1) {
223
+ for :sweep (let i: size = 0; len(gc.memory.envs) > i ; i + = 1) {
178
224
for(let x .. gc.marked.envs){
179
- if(x == gc.memory.envs[i-1 ]) continue :sweep;
225
+ if(x == gc.memory.envs[i]) continue :sweep;
180
226
};
181
- free(gc.memory.envs[i-1 ]); //.data is collected as a hashmap
227
+ free(gc.memory.envs[i]); //.data is collected as a hashmap
182
228
};
183
- for :sweep (let i: size = len(gc.memory.vecs); i > 0 ; i - = 1) {
229
+ for :sweep (let i: size = 0; len(gc.memory.vecs) > i ; i + = 1) {
184
230
for(let x .. gc.marked.vecs){
185
- if(x == gc.memory.vecs[i-1 ]) continue :sweep;
231
+ if(x == gc.memory.vecs[i]) continue :sweep;
186
232
};
187
- free_vec(gc.memory.vecs[i-1 ]);
233
+ free_vec(gc.memory.vecs[i]);
188
234
};
189
- for :sweep (let i: size = len(gc.memory.lists); i > 0 ; i - = 1) {
235
+ for :sweep (let i: size = 0; len(gc.memory.lists) > i ; i + = 1) {
190
236
for(let x .. gc.marked.lists){
191
- if(x == gc.memory.lists[i-1 ]) continue :sweep;
237
+ if(x == gc.memory.lists[i]) continue :sweep;
192
238
};
193
- free_list(gc.memory.lists[i-1 ]);
239
+ free_list(gc.memory.lists[i]);
194
240
};
195
- for :sweep (let i: size = len(gc.memory.funcs); i > 0 ; i - = 1) {
241
+ for :sweep (let i: size = 0; len(gc.memory.funcs) > i ; i + = 1) {
196
242
for(let x .. gc.marked.funcs){
197
- if(x == gc.memory.funcs[i-1 ]) continue :sweep;
243
+ if(x == gc.memory.funcs[i]) continue :sweep;
198
244
};
199
- free_func(gc.memory.funcs[i-1 ]);
245
+ free_func(gc.memory.funcs[i]);
200
246
};
201
- for :sweep (let i: size = len(gc.memory.intrinsics); i > 0 ; i - = 1) {
247
+ for :sweep (let i: size = 0; len(gc.memory.intrinsics) > i ; i + = 1) {
202
248
for(let x .. gc.marked.intrinsics){
203
- if(x == gc.memory.intrinsics[i-1 ]) continue :sweep;
249
+ if(x == gc.memory.intrinsics[i]) continue :sweep;
204
250
};
205
- free(gc.memory.intrinsics[i-1]);
251
+ free(gc.memory.intrinsics[i]);
252
+ };
253
+
254
+ reset_memory(&gc.memory);
255
+
256
+ gc = garbage_collector {
257
+ marked = gc.memory,
258
+ memory = gc.marked,
206
259
};
207
260
};
208
261
209
- // it doesn't make sense to call this with anything but the global repl_env.
262
+ // it doesn't make sense to call this with anything but the global repl_env,
263
+ // because as of this version there's no way to keep track of objects reachable
264
+ // through the ast of the current evaluation and it's possible continuations.
210
265
211
266
export fn run_gc(envi: *env) void = {
212
267
213
268
mark_env(envi);
214
269
sweep();
215
- finish_memory(gc.memory);
216
-
217
- gc = garbage_collector {
218
- marked = memory {
219
- funcs = [],
220
- ...
221
- },
222
- memory = gc.marked,
223
- };
224
270
};
225
-
0 commit comments