add a collector that moves things around (in a dumb kind of a way)
catches the bug fixed in acbc80edd
This commit is contained in:
parent
f6a200b6c2
commit
21807d3790
130
pkgs/plai/tests/gc2/good-collectors/trivial-moving-collector.rkt
Normal file
130
pkgs/plai/tests/gc2/good-collectors/trivial-moving-collector.rkt
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
#lang plai/gc2/collector
|
||||||
|
#|
|
||||||
|
|
||||||
|
This is just like trivial-collector.rkt, except
|
||||||
|
it moves all addresses forward by one on each
|
||||||
|
allocation
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
(define heap-ptr 'uninitialized-heap-ptr)
|
||||||
|
(define starting-point 0)
|
||||||
|
|
||||||
|
(define (alloc n roots)
|
||||||
|
(when (> (+ heap-ptr n) (heap-size))
|
||||||
|
(error "out of memory"))
|
||||||
|
|
||||||
|
;; slide everything in the heap forward by one address
|
||||||
|
(for ([i (in-range (- heap-ptr 1) (- starting-point 1) -1)])
|
||||||
|
(heap-set! (+ i 1) (heap-ref i)))
|
||||||
|
(heap-set! starting-point 'before-start)
|
||||||
|
(set! starting-point (+ starting-point 1))
|
||||||
|
(set! heap-ptr (+ heap-ptr 1))
|
||||||
|
|
||||||
|
;; update all the roots
|
||||||
|
(for ([root (in-list (append roots (get-root-set)))])
|
||||||
|
(set-root! root (+ (read-root root) 1)))
|
||||||
|
|
||||||
|
;; update all the internal pointers
|
||||||
|
(let loop ([addr starting-point])
|
||||||
|
(when (< addr heap-ptr)
|
||||||
|
(case (heap-ref addr)
|
||||||
|
[(closure)
|
||||||
|
(define size (heap-ref (+ addr 2)))
|
||||||
|
(for ([i (in-range size)])
|
||||||
|
(inc-at-addr (+ addr 2 i)))
|
||||||
|
(loop (+ addr size 3))]
|
||||||
|
[(prim)
|
||||||
|
(loop (+ addr 2))]
|
||||||
|
[(cons)
|
||||||
|
(inc-at-addr (+ addr 1))
|
||||||
|
(inc-at-addr (+ addr 2))
|
||||||
|
(loop (+ addr 3))]
|
||||||
|
[else (error 'alloc "unknown value at addr ~a: ~s" addr (heap-ref addr))])))
|
||||||
|
|
||||||
|
;; do the actual allocation
|
||||||
|
(define old-heap-ptr heap-ptr)
|
||||||
|
(set! heap-ptr (+ heap-ptr n))
|
||||||
|
old-heap-ptr)
|
||||||
|
|
||||||
|
(define (print-heap)
|
||||||
|
(for ([i (in-range (+ heap-ptr 4))])
|
||||||
|
(printf "~a: ~a\n" i (heap-ref i)))
|
||||||
|
(newline))
|
||||||
|
|
||||||
|
(define (inc-at-addr a)
|
||||||
|
(heap-set! a (+ (heap-ref a) 1)))
|
||||||
|
|
||||||
|
(define (init-allocator)
|
||||||
|
(set! heap-ptr 0))
|
||||||
|
|
||||||
|
(define (gc:closure code roots)
|
||||||
|
(define len (length roots))
|
||||||
|
(define heap-ptr (alloc (+ len 3) roots))
|
||||||
|
(heap-set! heap-ptr 'closure)
|
||||||
|
(heap-set! (+ heap-ptr 1) code)
|
||||||
|
(heap-set! (+ heap-ptr 2) len)
|
||||||
|
(for ([r (in-list roots)]
|
||||||
|
[i (in-naturals 3)])
|
||||||
|
(heap-set! (+ i heap-ptr) (read-root r)))
|
||||||
|
heap-ptr)
|
||||||
|
|
||||||
|
(define (gc:closure-code-ptr a)
|
||||||
|
(heap-ref (+ a 1)))
|
||||||
|
(define (gc:closure-env-ref a i)
|
||||||
|
(heap-ref (+ a 3 i)))
|
||||||
|
(define (gc:closure? a)
|
||||||
|
(eq? (heap-ref a) 'closure))
|
||||||
|
|
||||||
|
(define (gc:alloc-flat p)
|
||||||
|
(define heap-ptr (alloc 2 '()))
|
||||||
|
(heap-set! heap-ptr 'prim)
|
||||||
|
(heap-set! (+ 1 heap-ptr) p)
|
||||||
|
heap-ptr)
|
||||||
|
|
||||||
|
(define (gc:cons f r)
|
||||||
|
(define heap-ptr (alloc 3 (list f r)))
|
||||||
|
(heap-set! heap-ptr 'cons)
|
||||||
|
(heap-set! (+ 1 heap-ptr) (read-root f))
|
||||||
|
(heap-set! (+ 2 heap-ptr) (read-root r))
|
||||||
|
heap-ptr)
|
||||||
|
|
||||||
|
(define (gc:deref a)
|
||||||
|
(heap-ref (+ 1 a)))
|
||||||
|
|
||||||
|
; number -> boolean
|
||||||
|
(define (gc:cons? a)
|
||||||
|
(eq? (heap-ref a) 'cons))
|
||||||
|
|
||||||
|
; number -> any
|
||||||
|
(define (gc:first a)
|
||||||
|
(heap-ref (+ 1 a)))
|
||||||
|
|
||||||
|
; number -> number
|
||||||
|
(define (gc:rest a)
|
||||||
|
(heap-ref (+ 2 a)))
|
||||||
|
|
||||||
|
(define (gc:set-first! a f)
|
||||||
|
(if (gc:cons? a)
|
||||||
|
(heap-set! (+ 1 a) f)
|
||||||
|
(error 'set-first! "expects address of cons")))
|
||||||
|
|
||||||
|
(define (gc:set-rest! a r)
|
||||||
|
(heap-set! (+ 2 a) r))
|
||||||
|
|
||||||
|
; function number -> boolean
|
||||||
|
(define (gc:flat? a)
|
||||||
|
(eq? 'prim (heap-ref a)))
|
||||||
|
|
||||||
|
(module+ test
|
||||||
|
(require rackunit)
|
||||||
|
|
||||||
|
(check-equal? (let ([h (make-vector 7)])
|
||||||
|
(with-heap
|
||||||
|
h
|
||||||
|
(init-allocator)
|
||||||
|
(define one (gc:alloc-flat 1))
|
||||||
|
(define clos (gc:closure 'something (list (make-root 'dummy (λ () one) void))))
|
||||||
|
(gc:alloc-flat 2))
|
||||||
|
h)
|
||||||
|
(vector 'prim 1 'closure 'something 0 'prim 2)))
|
19
pkgs/plai/tests/gc2/good-mutators/test-moving.rkt
Normal file
19
pkgs/plai/tests/gc2/good-mutators/test-moving.rkt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#lang plai/gc2/mutator
|
||||||
|
(allocator-setup "../good-collectors/trivial-moving-collector.rkt" 40)
|
||||||
|
|
||||||
|
;; just some random allocation here
|
||||||
|
;; this is really about testing
|
||||||
|
;; things moving around in a moving collector
|
||||||
|
|
||||||
|
;; the 'let' is important as it means that the
|
||||||
|
;; closure is the only thing holding onto the '2'
|
||||||
|
|
||||||
|
(define f (cons 1 (let ([y 2]) (λ (x) (+ y x)))))
|
||||||
|
(define a ((rest f) 11))
|
||||||
|
(define b ((rest f) 22))
|
||||||
|
|
||||||
|
(define c
|
||||||
|
((let ([x (cons 1 2)])
|
||||||
|
(λ (y)
|
||||||
|
((first y) (first x))))
|
||||||
|
(λ (z) z)))
|
Loading…
Reference in New Issue
Block a user