flan/test/programs/destroy-region.flan

74 lines
2.9 KiB
Plaintext

;;;; stale-region.flan's trap, reached through arena-destroy rather than
;;;; free-all. The difference is what the check reads: free-all keeps the
;;;; allocator and bumps its epoch, while arena-destroy hands the arena back,
;;;; and a container made from it still points at the allocator to read the
;;;; epoch from. The allocator therefore outlives its arena, so that read is of
;;;; memory that is still there and the trap names the site.
;;;;
;;;; Argument 1 is the other use of a destroyed arena: a new container made
;;;; from it, which has no stale epoch to catch and reaches the allocator
;;;; itself.
;;;;
;;;; Argument 2 is a destroyed allocator taken back by the next arena-new. The
;;;; container made before the destroy still traps, because the epoch on a
;;;; header only ever rises.
;;;;
;;;; Arguments 4, 5 and 6 use the destroyed Allocator value itself after the
;;;; next arena-new took its record back — for a new container, through
;;;; with-allocator, and in a second destroy. The value carries the incarnation
;;;; it was made for, so each traps instead of reaching the new arena.
;;;;
;;;; Argument 3 makes and destroys arenas in a loop, as many times as the
;;;; second argument says. A retired allocator is reused rather than kept, so
;;;; the loop's memory stays flat however long it runs.
(defn main [args [string]] i32
(let [which (if (> (length args) 1) (i32 (bytes->i64 (bytes-view (at args 1)))) 0)
a (arena-new 4096)]
(cond
(= which 1)
(do
(arena-destroy a)
(let [w (vec-new i32 a)]
(push w 1)
(println (length w))))
(= which 2)
(let [v (vec-new i32 a)]
(push v 1)
(arena-destroy a)
(let [b (arena-new 4096)
w (vec-new i32 b)]
(push w 5)
(println (at w 0))
(println (at v 0))))
;; The Allocator value itself, kept past its destroy, after arena-new
;; took its record back: b works, and a traps rather than naming b's
;; arena. Argument 5 is the same through with-allocator, and 6 through
;; a second arena-destroy.
(>= which 4)
(do
(arena-destroy a)
(let [b (arena-new 4096)
w (vec-new i32 b)]
(push w 5)
(println (at w 0))
(cond
(= which 4) (let [x (vec-new i32 a)] (push x 1))
(= which 5) (with-allocator a (let [x (vec-new i32)] (push x 1)))
:else (arena-destroy a))
(println "unreachable")))
(= which 3)
(let [n (bytes->i64 (bytes-view (at args 2)))]
(arena-destroy a)
(dotimes [i (i32 n)]
(let [b (arena-new 64)]
(arena-destroy b)))
(println "done"))
:else
(let [v (vec-new i32 a)]
(push v 1)
(push v 2)
(println (at v 1))
(arena-destroy a)
(println (at v 1)))))
0)