1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# 43 — names, an arena, a byte buffer
`u`, `m` and `d` are ordinary names in the resident compiler. a tag is still `.u`, `.m` or `.d`. `u*x` with no space before the star is still a recast; a space is multiplication. `zc0.c` keeps the old rule, so the runtime and the compiler still do not use those letters as names. `tests/names.zc` prints `12 1 8`. `tests/umd.zc` is unchanged.
untyped `new(n)` inside o3 calls `new_oz`. that zeroes the words that were asked for and leaves the type word at `-(n + 1)`, so a later `fatten` can still stamp it. `new_raw` itself does not zero those words, so typed `new` does not zero them twice. `tests/o3zero.zc` reads the header inside the region and prints `1`.
`lib/std.zc` adds `arena`, `aalloc` and `areset` over the bump allocator, and `bnew`, `blen`, `bcap`, `bget` and `bset` for a packed byte buffer. `tests/stdbuf.zc` prints `4 1 266 8`.
the fixpoint is 110623 words. the stage-0 image is 106266, still inside the 110592-word small reservation. the suite is 460 passed, 0 failed: interpreter, microcore, soft-float, the small and run-only maps, both virt boards, the arm64 jit and llvm.
the kernels below are the same programs as `history/42-roots`. zeroing an untyped `new` does not sit on the typed-new tree, and the sieve does not allocate.
## sieve
milliseconds per count, median of five slopes. the before column is `history/42-roots`.
| path | before | after |
| --- | ---: | ---: |
| gcc -O3 -march=native, word flags | 0.149 | 0.148 |
| gcc -O3 -march=native -flto, byte flags | 0.080 | 0.080 |
| zc interpreter, plain, bounds-checked | 144.2 | 144.9 |
| zc interpreter, o3, bounds-checked | 11.11 | 11.08 |
| zc interpreter, o3, raw pointer | 6.87 | 6.86 |
| zc llvm, ZYHOT=1, o3 raw pointer | 0.252 | 0.235 |
| zc llvm, ZYHOT=1, o3 bounds-checked | 0.439 | 0.435 |
| zc arm64 jit, qemu-user, o3 raw pointer | 1.920 | 1.936 |
`bench/run.sh` timed the llvm raw pointer at 0.219 ms (0.083 to 0.286, 3135 repetitions) and the checked sieve at 0.400 ms (0.168 to 0.480, 1923 repetitions). a slope from 4000 repetitions to 16000 on the same binary is 0.235 ms for the raw pointer (0.227 to 0.246) and 0.435 ms for the checked sieve (0.429 to 0.440). 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.0144 for the arena. the o3 tree stays ahead of the plain one.
| path | before | after |
| --- | ---: | ---: |
| gcc -O3 -march=native, malloc | 0.091 | 0.091 |
| gcc -O3 -march=native -flto, arena | 0.0143 | 0.0144 |
| zc interpreter, plain new/free | 72.52 | 73.02 |
| zc interpreter, o3 new/free | 64.46 | 64.62 |
| zc interpreter, o3 arena | 1.353 | 1.305 |
| zc llvm, ZYHOT=1, plain new/free | 7.43 | 7.50 |
| zc llvm, ZYHOT=1, o3 new/free | 6.83 | 6.99 |
| zc llvm, ZYHOT=1, o3 arena | 0.183 | 0.172 |
| zc arm64 jit, qemu-user, plain new/free | 43.82 | 43.88 |
| zc arm64 jit, qemu-user, o3 arena | 0.702 | 0.724 |
`bench/run.sh` timed the llvm plain tree at 47 repetitions, median 6.89 ms (1.66 to 7.67), and the o3 tree at 115 repetitions, median 7.14 ms (6.82 to 7.61). a slope from 400 repetitions to 1600 on the same binary is 7.50 ms for the plain tree (7.46 to 7.63) and 6.99 ms for the o3 tree (6.94 to 7.06). those two are the after column. on the interpreter the o3 tree is 64.62 ms and the plain tree is 73.02 ms.
## later
zc0 no longer reserves `u`, `m` and `d`: they are ordinary names there too, as in the resident compiler, and a recast is the letter with the star touching it (`u*x`). see the header of `src/tools/zc0.c`.
|