Add inline VM opcodes for hot primitives (OP_ADD through OP_DEC)

16 new opcodes (160-175) bypass the CALL_PRIM hashtable lookup for
the most frequently called primitives:

  Arithmetic: OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_INC, OP_DEC, OP_NEG
  Comparison: OP_EQ, OP_LT, OP_GT, OP_NOT
  Collection: OP_LEN, OP_FIRST, OP_REST, OP_NTH, OP_CONS

The compiler (compiler.sx) recognizes these names at compile time and
emits the inline opcode instead of CALL_PRIM. The opcode is self-
contained — no constant pool index, no argc byte. Each primitive is
a single byte in the bytecode stream.

Implementation in all three VMs:
- OCaml (sx_vm.ml): direct pattern match, no allocation
- SX spec (vm.sx): delegates to existing primitives
- JS (transpiled): same as SX spec

66 new tests in spec/tests/vm-inline.sx covering arithmetic, comparison,
collection ops, composition, and edge cases.

Tests: 1314 JS (full), 1114 OCaml, 32 Playwright

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 20:10:48 +00:00
parent 5b2ef0a2af
commit eb4233ff36
6 changed files with 245 additions and 7 deletions

View File

@@ -93,6 +93,24 @@
(define OP_STR_JOIN 145) ;; (join sep list)
(define OP_SERIALIZE 146) ;; serialize TOS to SX string
;; Inline primitives (hot path — no hashtable lookup)
(define OP_ADD 160) ;; TOS-1 + TOS → push
(define OP_SUB 161) ;; TOS-1 - TOS → push
(define OP_MUL 162) ;; TOS-1 * TOS → push
(define OP_DIV 163) ;; TOS-1 / TOS → push
(define OP_EQ 164) ;; TOS-1 = TOS → push bool
(define OP_LT 165) ;; TOS-1 < TOS → push bool
(define OP_GT 166) ;; TOS-1 > TOS → push bool
(define OP_NOT 167) ;; !TOS → push bool
(define OP_LEN 168) ;; len(TOS) → push number
(define OP_FIRST 169) ;; first(TOS) → push
(define OP_REST 170) ;; rest(TOS) → push list
(define OP_NTH 171) ;; nth(TOS-1, TOS) → push
(define OP_CONS 172) ;; cons(TOS-1, TOS) → push list
(define OP_NEG 173) ;; negate TOS → push number
(define OP_INC 174) ;; TOS + 1 → push
(define OP_DEC 175) ;; TOS - 1 → push
;; Aser specialization (optional, 224-239 reserved)
(define OP_ASER_TAG 224) ;; u16 tag_name_idx — serialize HTML tag
(define OP_ASER_FRAG 225) ;; u8 child_count — serialize fragment