115-two-heap.scm (2074B)
1 ; Two-heap primitives, A → B → C ergonomics. The shape Phase 3 of 2 ; CC-SCRATCH.md will use at the parse-decl-or-fn boundary. 3 ; 4 ; A: caller. Heap-unaware; just calls (B input) and uses the result. 5 ; B: boundary. Switches to scratch, runs C in scratch, switches back 6 ; to main, *clones* C's survivor into the main heap (the "promote" 7 ; walker), resets scratch, returns the main-heap clone. 8 ; C: worker. Heap-unaware; allocates freely in whatever heap is 9 ; current. Returns a freshly-allocated (sum . count) pair. 10 ; 11 ; The clone runs while main is current and reads from scratch via 12 ; ordinary pointer access — neither heap selection affects loads, only 13 ; allocations. After the clone, scratch can be wholesale reset because 14 ; nothing in main points into it. 15 16 (define (C input) 17 (let loop ((xs input) (sum 0) (count 0)) 18 (if (null? xs) 19 (cons sum count) 20 (loop (cdr xs) (+ sum (car xs)) (+ count 1))))) 21 22 ; Promote: read from scratch-allocated pair, allocate the clone in 23 ; the currently-selected heap. C's result has fixnum car/cdr so a 24 ; one-level cons is enough; real promote walkers recurse on heap- 25 ; allocated children. 26 (define (promote-pair p) 27 (cons (car p) (cdr p))) 28 29 (define (B input) 30 (use-scratch-heap!) 31 (let ((scratch-result (C input))) 32 (use-main-heap!) 33 (let ((main-result (promote-pair scratch-result))) 34 (reset-scratch-heap!) 35 main-result))) 36 37 (define (A) 38 (let ((input (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 '()))))))) 39 (B input))) 40 41 ; Drive B twice. A scratch leak would push the second call past the 42 ; cap; a missed promotion would leave r1 dangling once r2's run resets. 43 (define r1 (A)) 44 (define r2 (A)) 45 (define r1-in-main? (heap-in-main? r1)) 46 (define r2-in-main? (heap-in-main? r2)) 47 48 (sys-exit 49 (cond 50 ((not r1-in-main?) 1) ; clone landed in main 51 ((not r2-in-main?) 2) 52 ((not (= (car r1) 15)) 3) ; r1 still readable after r2's reset 53 ((not (= (cdr r1) 5)) 4) 54 ((not (= (car r2) 15)) 5) 55 ((not (= (cdr r2) 5)) 6) 56 (else 42)))