Commit Graph
1 Commits
Author SHA1 Message Date
Malte Ubl 425386b877 Call array-method callbacks directly and pass plain elements
Array HOF helpers (%arr.map/filter/forEach/flatMap/find*/some/every/
reduce*) called every callback through its closure, bracketed by the
ambient JS receiver stack, with each element boxed as T | undefined.

- Intern a helper per literal callback and admit %arr.* helpers as
  constant-callback consumers: the callback becomes a guarded direct
  call that LLVM inlines into the loop.
- Replace the scalar-only receiver check with an exact module fixpoint
  (AmbientReceiverReaders) over direct calls, constructors and virtual
  dispatch; known callbacks that cannot reach a receiver read skip the
  push/pop.
- For inline arrows over plain element types, lower the callback a
  second time with the element type and split each visit on the array
  state: present values take the fast closure with no union box; holes
  and present undefined keep the original closure and undefined arm.
- Resolve factory-made callbacks (every return yields one function) and
  immutable captured callbacks at their closure creation sites.
- Read and write scalar capture boxes in place instead of calling
  scr_box_get_f64/scr_box_set_*.

Corpus 4140-4142 pin the split visit, receiver brackets on the direct
path, and factory/captured callbacks.

Linux x64 (sandbox, --layouts=4 --runs=16, baseline stack 06 tip):

| workload | baseline ms | candidate ms | change | 95% CI | verdict | size | node ms | candidate/node |
| --- | ---: | ---: | ---: | --- | --- | ---: | ---: | ---: |
| json-records | 192.5 | 193.8 | +0.7% | -2.1% .. +2.4% | neutral | +0.0% | 436.3 | 0.44x |
| regex-logs | 166.4 | 165.5 | -0.5% | -1.8% .. +0.9% | neutral | +0.0% | 243.9 | 0.68x |
| ast-interp | 264.9 | 243.0 | -8.3% | -9.5% .. -6.9% | faster | +0.0% | 232.2 | 1.05x |
| records-sort | 593.2 | 576.4 | -2.8% | -6.6% .. +0.3% | neutral | +3.0% | 210.3 | 2.74x |
| template-render | 69.3 | 68.6 | -1.0% | -3.2% .. +2.6% | neutral | +0.0% | 189.0 | 0.36x |
| functional-pipeline | 215.8 | 111.0 | -48.6% | -49.6% .. -46.3% | faster | +3.8% | 255.8 | 0.43x |
| async-pipeline | 194.8 | 196.8 | +1.0% | -1.1% .. +12.0% | neutral | +0.0% | 85.9 | 2.29x |
| word-graph | 271.8 | 270.1 | -0.6% | -7.0% .. +5.5% | neutral | +3.0% | 517.1 | 0.52x |
| alloc-trees | 314.4 | 316.6 | +0.7% | -0.4% .. +1.9% | neutral | +0.0% | 124.9 | 2.53x |
| numeric-kernels | 46.2 | 45.7 | -1.1% | -2.5% .. +1.5% | neutral | +0.0% | 128.2 | 0.36x |
| validate-errors | 179.7 | 174.5 | -2.9% | -5.4% .. +0.7% | neutral | +0.0% | 711.1 | 0.24x |
| csv-numbers | 343.0 | 338.9 | -1.2% | -7.3% .. +0.7% | neutral | +0.0% | 519.6 | 0.65x |
| log-summary | 166.1 | 168.3 | +1.3% | -4.4% .. +9.1% | neutral | +0.0% | 300.0 | 0.56x |
| inventory-report | 298.1 | 290.1 | -2.7% | -14.6% .. +5.4% | neutral | +1.3% | 421.4 | 0.69x |

Geomean -5.9%; candidate/node 0.715x. macOS arm64 (shared host):
geomean -4.7%, functional-pipeline -44.1%, ast-interp -11.0%,
inventory-report -8.0%; none slower (records-sort -0.5% on a calmer
rerun).
2026-10-08 15:38:45 -05:00