Skip to content

Register VM opcode handlers on first use instead of at module load - #21584

Draft
NullVoxPopuli-ai-agent wants to merge 1 commit into
emberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/opcodes-1-runtime-handlers
Draft

Register VM opcode handlers on first use instead of at module load#21584
NullVoxPopuli-ai-agent wants to merge 1 commit into
emberjs:mainfrom
NullVoxPopuli-ai-agent:nvp/opcodes-1-runtime-handlers

Conversation

@NullVoxPopuli-ai-agent

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent commented Aug 27, 2026 •

Copy link
Copy Markdown
Contributor

Part 1 of 4 for importable wire format opcodes. Base: main. Next: NullVoxPopuli-ai-agent#3.

Each syscall handler in runtime/lib/compiled/opcodes/ becomes a named export that carries its opcode number. syscall(VM_X_OP, fn) returns { type, evaluate } and registers nothing. The compile-time code in opcode-compiler pushes the handler object instead of the number, and encodeOp registers it in the dispatch table on first push.

Why: runtime/lib/bootstrap.ts had eight side-effect imports that put every handler into any bundle that used the VM. With this change a bundler drops a handler when no compile-time code that emits it survives tree-shaking.

What does not change:

  • The numeric dispatch table and the int32 heap layout.
  • The wire format. Templates still ship JSON blocks.
  • The 7 machine ops in low-level.ts.

How to check:

  1. pnpm type-check:internals
  2. pnpm test

Output of pnpm test on the full stack: 9470 tests, 17 skipped, 0 failures.

Context: https://claude.ai/code/artifact/153fb9f5-67b3-44e3-b2d9-d6f2f618f25b

🤖 Generated with Claude Code

https://claude.ai/code/session_017PQyBrSj4CZaqMcKc7aW81

Each syscall handler in `runtime/lib/compiled/opcodes/` is now a named
export that carries its opcode number: `syscall(VM_X_OP, fn)` returns
`{ type, evaluate }` and registers nothing. The compile-time code in
`opcode-compiler` pushes the handler object instead of the bare number,
and `encodeOp` registers it in the dispatch table the first time a
template pushes it.

This removes `runtime/lib/bootstrap.ts`, whose eight side-effect imports
forced every handler into any bundle that used the VM. A bundler can now
drop a handler when no compile-time code that emits it survives
tree-shaking. The `/*#__PURE__*/` annotation on each `syscall(...)` call
is what lets the bundler drop it.

The numeric dispatch table and the int32 heap layout are unchanged. In
DEBUG, an opcode with no registered handler throws with the opcode number
instead of failing inside `unwrap`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PQyBrSj4CZaqMcKc7aW81
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