Skip to content

JS WAM mixed-mode lowering for the peerhailer argparser (GP-PERF) - #4209

Draft
s243a wants to merge 6 commits into
grok/wamjs-cli-argsfrom
grok/wamjs-perf
Draft

JS WAM mixed-mode lowering for the peerhailer argparser (GP-PERF)#4209
s243a wants to merge 6 commits into
grok/wamjs-cli-argsfrom
grok/wamjs-perf

Conversation

@s243a

@s243a s243a commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

GP-PERF item 1: mixed-mode JS WAM lowering + ground-fact intern for the peerhailer argparser.

Speedup: 1.48× on the 5067-line differential (A2 interpreter 4.639s → mixed 3.144s). Stretch ≥5× was not met. Corpus 17/17, differential 0 divergences / 0 message mismatches.

What changed

  • emit_mode(mixed) for examples/cli_args/wamjs/ — lower every eligible predicate, interpret the rest.
  • Loud fallback: stdout + // wamjs lower fallback: comments.
  • T4+ITE for det/semidet helpers; depth-aware ITE fold so nested \+ does not abort T4 (lenient_loop/5, strict_loop/8, parse_args/3 now lower).
  • Direct Runtime.op_* (no per-instruction I.* allocation). Interpreter Runtime.step shares the same helpers; GetList defaults a missing fid to [|].
  • Cheap ITE restore (trail + A1–A8) only for pure comparison conditions (==/2, =:=/2, …). Unifying conditions still snapshot_machine.
  • Ground-fact intern (program.ground_memo) via copy_term. Live-term intern is unsound.
  • Execute of a non-self callee — including JS WAM builtins — stays on the interpreter.

Still interpret (and why)

  • parse_args/2, first_equals_index/2, looks_like_legacy_flag/1, lenient_result/2, merge_flags/3, is_long_flag/1, js_object_prototype_key/1 — Execute of non-self (nested Runtime.run with cp=0 steals CP).
  • substring_from/3, substring_range/4 — Execute of sub_string/5.
  • drop_brackets/2multi_clause_1; T4+ITE did not match.

Testing

  • node --test examples/cli_args/wamjs/cliArgs.wamjs.test.mjs → 17/17
  • run_differential_wamjs.sh → 5067 lines, 0/0; oracle 0.054s, wamjs 3.144s
  • tests/test_wam_javascript_lowered.pl, builtins, fact-sources, CONFORMANCE_TARGETS=javascript — green
  • UW_PROFILE=1 200-line: string_member/2* still 1804 calls

Constraints honoured

  • Frozen files under examples/cli_args/ outside wamjs/ are untouched.
  • Wrong-but-fast stays as fallback. Profiling remains zero-cost when off.
Open in Web Open in Cursor 

cursoragent and others added 6 commits September 1, 2026 12:03
Emit T4/ITE/det functions for eligible cli_args predicates, intern ground
facts after first success, and keep shapes the emitter cannot honour
(multi_clause_1, Execute of a non-self callee) on the interpreter.
ITE else restores a full machine snapshot; nested Runtime.run of an
interpreted callee is isolated so it cannot steal the caller's CPs.

Co-authored-by: johns243a <johns243a@gmail.com>
switch_on_structure re-emits the same ground clause on a try/retry/trust
chain; treat identical ground copies as one deterministic body so the
ground-memo intern still fires (GP-PERF item 2).

Co-authored-by: johns243a <johns243a@gmail.com>
Lowered helpers were still allocating I.* objects and snapshotting the
whole machine on every T4/ITE step, so mixed mode was no faster than
the interpreter. Call Runtime.op_* instead, restore A-registers on
builtin-only ITE, intern ground facts without copy_term, and allow
Execute of JS WAM builtins (substring_from/3 and friends).

Co-authored-by: johns243a <johns243a@gmail.com>
Those paths overflowed string_member/2 (cyclic GetList write) and
broke the 17-case corpus. Mixed-mode T4+ITE via Runtime.step remains
the correct fast path.

Co-authored-by: johns243a <johns243a@gmail.com>
Lowered helpers still allocated I.* objects and snapshot_machine on every
==/2 step. Call the shared op_* implementations (same semantics as
Runtime.step, including [|] fid default) and restore only A-registers for
pure comparison conditions. Keep copy_term ground intern and keep Execute
of non-self callees (including builtins) on the interpreter.

Co-authored-by: johns243a <johns243a@gmail.com>
The shared structure_ite/2 split_commit took the first cut inside a
nested negation, so T4+ITE rejected the argparser loops. A depth-aware
fold in the JS emitter lowers those loops and parse_args/3. Execute of
a non-self callee (including builtins) stays interpreted. Regenerated
wamjs/js/; document GP-PERF timings (4.639s → 3.144s, 1.48×).

Co-authored-by: johns243a <johns243a@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants