Skip to content

Commit 7a211ea

Browse files
committed
Allocate in co-op with GC.
1 parent 6d7fa73 commit 7a211ea

File tree

5 files changed

+101
-44
lines changed

5 files changed

+101
-44
lines changed

langs/iniquity-gc/compile-ops.rkt

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@
7777
unpad-stack
7878
(Mov rax val-void))]
7979
['box
80-
(seq (allocate 1)
80+
(seq (Push rax)
81+
(allocate 1)
82+
(Pop rax)
8183
(Mov (Offset rbx 0) rax)
8284
(Mov rax rbx)
8385
(Or rax type-box)
@@ -131,19 +133,15 @@
131133
(Label done)))]))
132134

133135
(define (allocate n)
134-
(seq)
135-
#;
136-
(seq (Mov r15 rax) ; save rax
137-
(Mov rdi rsp)
138-
(Mov rsi rbp)
139-
(Mov rdx rbx)
140-
(Mov rcx n)
141-
pad-stack
142-
(Call 'alloc_val)
143-
unpad-stack
144-
;(Mov rbx rax)
145-
(Mov rax r15)))
146-
136+
(seq (Mov rdi rsp)
137+
(Mov rsi rbp)
138+
(Mov rdx rbx)
139+
(Mov rcx n)
140+
pad-stack
141+
(Call 'alloc_val)
142+
unpad-stack
143+
(Mov rbx rax)))
144+
147145
;; Op2 -> Asm
148146
(define (compile-op2 p)
149147
(match p
@@ -177,44 +175,52 @@
177175
(let ((true (gensym)))
178176
(seq (Je true)
179177
(Mov rax val-false)
180-
(Label true))))]
178+
(Label true))))]
179+
;; tricky: if you have a pointer in a register, GC might collect
180+
;; what it points to and create a dangling reference
181181
['cons
182-
(seq (allocate 2)
183-
(Mov (Offset rbx 0) rax) ;; ALLOCATE
182+
(seq (Push rax)
183+
(allocate 2)
184+
(Pop rax)
185+
(Mov (Offset rbx 0) rax)
184186
(Pop rax)
185187
(Mov (Offset rbx 8) rax)
186188
(Mov rax rbx)
187189
(Or rax type-cons)
188190
(Add rbx 16))]
189191
['eq?
190192
(seq (Pop r8)
191-
(eq r8 rax))]
193+
(eq r8 rax))]
192194
['make-vector
193195
(let ((loop (gensym))
194196
(done (gensym))
195197
(empty (gensym)))
196-
(seq (Pop r14)
197-
(assert-natural r14)
198-
(Cmp r14 0) ; special case empty vector
198+
(seq (Pop r8)
199+
(assert-natural r8)
200+
(Cmp r8 0) ; special case empty vector
199201
(Je empty)
200-
201-
(Sar r14 int-shift)
202202

203-
(Add r14 1)
204-
(allocate r14)
205-
(Sub r14 1)
203+
204+
(Push rax)
205+
(Mov rax r8)
206+
(Sar rax int-shift)
207+
(Add rax 1)
208+
(allocate rax)
209+
(Pop rax)
210+
206211

207212
(Mov r9 rbx)
208213
(Or r9 type-vect)
209-
210-
(Mov (Offset rbx 0) r14)
211-
(Add rbx 8) ;; ALLOCATE
214+
215+
(Sar r8 int-shift)
216+
(Mov (Offset rbx 0) r8)
217+
(Add rbx 8)
212218

213219
(Label loop)
214220
(Mov (Offset rbx 0) rax)
215-
(Add rbx 8) ;; ALLOCATE
216-
(Sub r14 1)
217-
(Cmp r14 0)
221+
(Add rbx 8)
222+
(Sub r8 1)
223+
(Cmp r8 0)
218224
(Jne loop)
219225

220226
(Mov rax r9)
@@ -223,7 +229,6 @@
223229
(Label empty)
224230
(Mov rax type-vect)
225231
(Label done)))]
226-
227232
['vector-ref
228233
(seq (Pop r8)
229234
(assert-vector r8)
@@ -250,12 +255,23 @@
250255
(Cmp r8 0) ; special case empty string
251256
(Je empty)
252257

258+
(Push rax)
259+
(Mov rax r8)
260+
(Sar rax int-shift)
261+
(Add rax 1) ; adds 1
262+
(Sar rax 1) ; when
263+
(Sal rax 1) ; len is odd
264+
(Add rax 1)
265+
(allocate rax)
266+
(Pop rax)
267+
268+
253269
(Mov r9 rbx)
254270
(Or r9 type-str)
255271

256272
(Sar r8 int-shift)
257273
(Mov (Offset rbx 0) r8)
258-
(Add rbx 8) ;; ALLOCATE
274+
(Add rbx 8)
259275

260276
(Sar rax char-shift)
261277

@@ -265,7 +281,7 @@
265281

266282
(Label loop)
267283
(Mov (Offset rbx 0) eax)
268-
(Add rbx 4) ;; ALLOCATE
284+
(Add rbx 4)
269285
(Sub r8 1)
270286
(Cmp r8 0)
271287
(Jne loop)
@@ -277,6 +293,7 @@
277293
(Mov rax type-str)
278294
(Label done)))]
279295

296+
280297
['string-ref
281298
(seq (Pop r8)
282299
(assert-string r8)

langs/iniquity-gc/compile.rkt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@
8888
(if (zero? len)
8989
(seq (Mov rax type-str))
9090
(seq (Mov rax len)
91+
(Push rax)
92+
(allocate (add1 (quotient (add1 len) 2)))
93+
(Pop rax)
9194
(Mov (Offset rbx 0) rax)
9295
(compile-string-chars (string->list s) 8)
9396
(Mov rax rbx)

langs/iniquity-gc/gc.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ void step(val_t** to_curr, val_t** to_next, int count, int* t_back) {
2929
val_t *ptr_v;
3030
for (i = 0; i < count; i++) {
3131
v = **to_curr;
32-
ptr_v = val_unwrap(v);
3332
t = val_typeof(v);
3433
switch (t) {
3534
case T_BOX:
3635
case T_CONS:
3736
case T_VECT:
3837
case T_STR:
38+
ptr_v = val_unwrap(v);
3939
if (ptr_v >= from && ptr_v < from + heap_size) {
4040
// this is a pointer to from space so we need to deal with it
41-
if (val_unwrap(*ptr_v) >= to &&
42-
val_unwrap(*ptr_v) < to + heap_size) {
41+
if (val_unwrap(*ptr_v) >= to &&
42+
val_unwrap(*ptr_v) < to + heap_size) {
4343
// it points to a fwd pointer (points in to to-space), so just set
4444
// curr to what it points to.
4545
**to_curr = *ptr_v;
@@ -70,6 +70,10 @@ void step(val_t** to_curr, val_t** to_next, int count, int* t_back) {
7070

7171

7272
int64_t* collect_garbage(int64_t* rsp, int64_t *rbp, int64_t* rbx) {
73+
74+
printf("Collect garbage: rsp = %" PRIx64 ", rbp = %" PRIx64 ", rbx = %" PRIx64 "\n",
75+
(int64_t)rsp, (int64_t)rbp, (int64_t)rbx);
76+
7377
int stack_count = rbp - rsp;
7478

7579
val_t *tmp;
@@ -82,7 +86,6 @@ int64_t* collect_garbage(int64_t* rsp, int64_t *rbp, int64_t* rbx) {
8286
// Step through everything on the stack
8387
val_t *rsp_curr = rsp;
8488
step(&rsp_curr, &to_next, stack_count, &t_back);
85-
8689
int vi;
8790
// now play catch up between to_curr and to_next
8891
while (to_curr != to_next) {
@@ -139,8 +142,9 @@ int64_t* alloc_val(int64_t* rsp, int64_t* rbp, int64_t* rbx, int words) {
139142
rbx = collect_garbage(rsp, rbp, rbx);
140143
if (rbx + words >= from + heap_size) {
141144
printf("OUT OF MEMORY!!\n");
142-
exit(1);
145+
error_handler();
143146
}
144147
}
148+
// printf("returning %" PRIx64 "\n", (int64_t)rbx);
145149
return rbx;
146150
}

langs/iniquity-gc/interp.rkt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
[(Prim0 'void) (void)]
4141
[(Prim0 'read-byte) (read-byte)]
4242
[(Prim0 'peek-byte) (peek-byte)]
43+
[(Prim0 'dump-memory-stats) (dump-memory-stats)]
44+
[(Prim0 'collect-garbage) (collect-garbage)]
4345
[(Prim1 p e)
4446
(match (interp-env e r ds)
4547
['err 'err]

langs/iniquity-gc/test/test-runner.rkt

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
(check-equal? (run '(eq? (cons 1 2) (cons 1 2))) #f)
108108
(check-equal? (run '(let ((x (cons 1 2))) (eq? x x))) #t)
109109

110-
;; Hoax examples
110+
;; Hoax examples
111111
(check-equal? (run '(make-vector 0 0)) #())
112112
(check-equal? (run '(make-vector 1 0)) #(0))
113113
(check-equal? (run '(make-vector 3 0)) #(0 0 0))
@@ -126,9 +126,9 @@
126126
(check-equal? (run '(let ((x (make-vector 3 5)))
127127
(begin (vector-set! x 1 4)
128128
x)))
129-
#(5 4 5))
129+
#(5 4 5))
130130
(check-equal? (run '(vector-length (make-vector 3 #f))) 3)
131-
(check-equal? (run '(vector-length (make-vector 0 #f))) 0)
131+
(check-equal? (run '(vector-length (make-vector 0 #f))) 0)
132132
(check-equal? (run '"") "")
133133
(check-equal? (run '"fred") "fred")
134134
(check-equal? (run '"wilma") "wilma")
@@ -179,7 +179,38 @@
179179
(cons (add1 (car xs))
180180
(map-add1 (cdr xs)))))
181181
'(map-add1 (cons 1 (cons 2 (cons 3 '())))))
182-
'(2 3 4)))
182+
'(2 3 4))
183+
184+
(check-equal? (run '(collect-garbage)) (void))
185+
(check-equal? (run '(begin (box 0) (collect-garbage))) (void))
186+
(check-equal? (run '(begin (collect-garbage) (box 0))) (box 0))
187+
(check-equal? (run '(let ((x (box 0))) (collect-garbage))) (void))
188+
(check-equal? (run '(let ((x (box 0)))
189+
(begin (collect-garbage)
190+
x)))
191+
(box 0))
192+
;; GC tests
193+
(check-equal? (run
194+
'(define (n-boxes n)
195+
(if (zero? n)
196+
(void)
197+
(begin (box 0)
198+
(n-boxes (sub1 n)))))
199+
'(n-boxes 10001))
200+
(void))
201+
202+
;; can't test this in the interpreter, because it doesn't exhaust the heap there.
203+
#;
204+
(check-equal? (run
205+
'(define (nested-boxes n)
206+
(if (zero? n)
207+
(void)
208+
(box (nested-boxes (sub1 n)))))
209+
'(begin (nested-boxes 10001) (void)))
210+
'err)
211+
)
212+
213+
183214

184215
(define (test-runner-io run)
185216
;; Evildoer examples

0 commit comments

Comments
 (0)