# 42 — roots opcode 619 pushes the data-stack index, the first live word. `gc_roots` marks from that index to the top, in the compiler and in the run-only image. a pointer sitting in a word the program has already dropped is not a root, so the next collection reclaims the block. `scrub` zeroes the unused region from `DSLO` up to the live top. the last 16 words are the ones the loop itself is using, and those are pushed as zeros. `free` still quarantines. a block something live still points at stays readable. `tests/roots.zc` plants a pointer at the bottom of the data stack, drops the local, collects, and prints `1 0`: the object is gone, and scrub cleared the planted word. the fixpoint is 110446 words. the suite is 448 passed, 0 failed: interpreter, microcore, soft-float, the small and run-only maps, both virt boards, the arm64 jit and llvm. ## sieve milliseconds per count, median of five slopes. the before column is `history/41-obytes`. the sieve does not collect. | path | before | after | | --- | ---: | ---: | | gcc -O3 -march=native, word flags | 0.150 | 0.149 | | gcc -O3 -march=native -flto, byte flags | 0.081 | 0.080 | | zc interpreter, plain, bounds-checked | 145.6 | 144.2 | | zc interpreter, o3, bounds-checked | 13.22 | 11.11 | | zc interpreter, o3, raw pointer | 7.87 | 6.87 | | zc llvm, ZYHOT=1, o3 raw pointer | 0.233 | 0.252 | | zc llvm, ZYHOT=1, o3 bounds-checked | 0.438 | 0.439 | | zc arm64 jit, qemu-user, o3 raw pointer | 1.963 | 1.920 | the interpreter's raw pointer went from 7.87 ms to 6.87 ms, and the checked o3 sieve from 13.22 ms to 11.11 ms. `bench/run.sh` timed the llvm raw pointer at 0.225 ms (0.177 to 0.244, 3517 repetitions) and the checked sieve at 0.396 ms (0.364 to 0.634, 1905 repetitions). a slope from 4000 repetitions to 16000 on the same binary is 0.252 ms for the raw pointer (0.230 to 0.287) and 0.439 ms for the checked sieve (0.427 to 0.441). those two are the after column. gcc's byte flags were 0.080 ms. ## trees milliseconds per tree of depth 12. gcc on this run was 0.091 for malloc and 0.0143 for the arena. the o3 tree stays ahead of the plain one. | path | before | after | | --- | ---: | ---: | | gcc -O3 -march=native, malloc | 0.094 | 0.091 | | gcc -O3 -march=native -flto, arena | 0.0144 | 0.0143 | | zc interpreter, plain new/free | 72.86 | 72.52 | | zc interpreter, o3 new/free | 65.55 | 64.46 | | zc interpreter, o3 arena | 1.378 | 1.353 | | zc llvm, ZYHOT=1, plain new/free | 8.08 | 7.43 | | zc llvm, ZYHOT=1, o3 new/free | 6.95 | 6.83 | | zc llvm, ZYHOT=1, o3 arena | 0.163 | 0.183 | | zc arm64 jit, qemu-user, plain new/free | 44.15 | 43.82 | | zc arm64 jit, qemu-user, o3 arena | 0.704 | 0.702 | `bench/run.sh` timed the llvm plain tree at 211 repetitions, median 7.21 ms (4.32 to 7.62), and the o3 tree at 111 repetitions, median 8.30 ms (5.74 to 11.94). a slope from 400 repetitions to 1600 on the same binary is 7.43 ms for the plain tree (7.20 to 7.60) and 6.83 ms for the o3 tree (6.75 to 7.13). those two are the after column. on the interpreter the o3 tree is 64.46 ms and the plain tree is 72.52 ms.