Skip to content

Support EXT1/EXT2/EXT3 operand extension opcodes#189

Open
hadashiA wants to merge 2 commits into
mainfrom
claude/admiring-saha-f5300e
Open

Support EXT1/EXT2/EXT3 operand extension opcodes#189
hadashiA wants to merge 2 commits into
mainfrom
claude/admiring-saha-f5300e

Conversation

@hadashiA

@hadashiA hadashiA commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Fixes #188

Problem

The VM never decoded mruby's EXT1/EXT2/EXT3 operand-widening prefix opcodes — they existed in the OpCode enum but fell through to ThrowInvalidOpCode. Any method whose literal pool or symbol table exceeded 255 entries (e.g. many string literals in one method) made the native compiler emit an EXT prefix, crashing with NotSupportedException: Invalid opcode EXT2.

The disassembler (CodeDump) had the same bug in a quieter form: it skipped EXT as a 1-byte no-op, so all subsequent output was misaligned.

Changes

  • Operands.cs: operand structs now expose ushort fields and take an ext parameter. The ext == 0 fast path is a single predictable branch; the widened decode (2-byte big-endian per mruby spec) is [NoInlining] out of line.
  • MRubyState.Vm.cs: the dispatch loop consumes an EXT prefix, re-fetches the real opcode, and passes ext to every widenable operand read (B/BB/BBB/BS/BSS; already-wide S/W operands are never prefixed).
  • MRubyState.Dump.cs: same treatment, so disassembly of EXT-containing ireps stays aligned.
  • Regression tests: a method with 300 string literals (pool overflow → EXT2 on STRING) and 300 distinct method definitions/calls (symbol overflow → EXT2 on SSEND), both previously crashing.

Perf

A/B-measured (in-process median, interleaved runs):

bench baseline after delta
bm_so_mandelbrot ~889 ms ~885 ms neutral
bm_ao_render ~2854 ms ~2915 ms +2.1%

The ao regression comes from ext being live across the hot switch, not from the read bodies (int/ushort/mask variants all measured identical). Making it zero-cost would require duplicating the full opcode switch as a cold path — deemed not worth the maintenance surface for a rare prefix. Correctness over the last 2% here.

Also adds a --quick-bench <script> [warmup] [iters] mode to the benchmark sandbox used for these measurements.

🤖 Generated with Claude Code

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.

Invalid opcode EXT2 when running a large script

1 participant