The first keyword argument was dropped because gen_hash() was
called with callargs->keyword_args->cdr instead of
callargs->keyword_args.
Co-authored-by: Claude <noreply@anthropic.com>
Preparation for future grammar simplification that may
require parentheses for method calls with arguments on
the right-hand side of assignments.
Co-authored-by: Claude <noreply@anthropic.com>
These opcodes use BB format instead of BBB, saving 1 byte per call.
In the standard library, this saves ~790 bytes (568 SEND0 + 222 SSEND0).
Co-authored-by: Claude <noreply@anthropic.com>
Change default stack growth from linear (+128) to exponential (1.5x).
This reduces reallocation frequency while maintaining reasonable memory
usage. The minimum growth is still MRB_STACK_GROWTH (128) to ensure
small programs don't over-allocate.
MRB_STACK_EXTEND_DOUBLING (2x growth) remains available for maximum
performance when memory is not a concern.
Co-authored-by: Claude <noreply@anthropic.com>
Add single-byte opcodes for returning true/false directly, completing
the set of literal return opcodes (RETSELF, RETNIL, RETTRUE, RETFALSE).
Codegen applies peephole optimization to fuse LOADTRUE/LOADFALSE + RETURN.
Co-authored-by: Claude <noreply@anthropic.com>
Rename boolean load opcodes for consistency with LOADNIL/LOADSELF.
Backward compatibility aliases are provided in opcode.h.
Co-authored-by: Claude <noreply@anthropic.com>
Add a new opcode that returns nil without requiring LOADNIL + RETURN.
This avoids loading nil into a register by setting the return value (v)
directly. The implementation uses a separate label (L_RETURN_NIL) to
bypass v = regs[a], preserving self in regs[0] for ensure blocks.
Codegen applies peephole optimization to fuse LOADNIL + RETURN -> RETNIL.
Co-authored-by: Claude <noreply@anthropic.com>
Both opcodes had nearly identical code for creating procs and
defining methods. Now they share a common L_DEF_METHOD label,
reducing code duplication by ~10 lines.
Co-authored-by: Claude <noreply@anthropic.com>
Replace block.call(x) with yield x in core iteration methods to take
advantage of the new OP_BLKCALL optimization. This improves Integer#times
by 13% and Array#each by 7%.
Methods updated:
- Integer#times, Integer#upto, Integer#downto
- Array#each, Array#each_index
Co-authored-by: Claude <noreply@anthropic.com>
Bypass method dispatch when calling blocks via yield. The new OP_BLKCALL
instruction directly invokes the proc without looking up Proc#call,
resulting in 13-17% faster yield performance.
Co-authored-by: Claude <noreply@anthropic.com>
TDEF fuses TCLASS+METHOD+DEF for normal method definitions.
SDEF fuses SCLASS+METHOD+DEF for singleton method definitions.
Saves 4 bytes per method definition (8 bytes -> 4 bytes).
Falls back to unfused instructions if irep index exceeds 255.
Co-authored-by: Claude <noreply@anthropic.com>
Fuses MOVE+LOADI_0+GETIDX pattern into single instruction.
Saves 4 bytes per arr[0] access (7 bytes -> 3 bytes).
Co-authored-by: Claude <noreply@anthropic.com>
fuse MOVE+ADDI+MOVE and MOVE+SUBI+MOVE patterns into single instructions.
ADDILV/SUBILV add/subtract an immediate to a local variable in-place.
BBB format: a=local, b=working space for method call, c=immediate.
saves 5 bytes per instance (9->4 bytes), 40 occurrences in stdlib.
Co-authored-by: Claude <noreply@anthropic.com>
Change OP_MATCHERR from Z format (unconditional) to B format
(conditional on register). This allows fusing JMPIF + MATCHERR
sequence into a single MATCHERR instruction for simple patterns.
Before: JMPIF R2 target (4 bytes) + MATCHERR (1 byte) = 5 bytes
After: MATCHERR R2 (2 bytes)
Saves 3 bytes per pattern match with raise_on_fail.
Co-authored-by: Claude <noreply@anthropic.com>
Replace 4-instruction sequence (GETCONST + STRING + SEND + RAISEIF)
with single OP_MATCHERR instruction that raises NoMatchingPatternError
with "pattern not matched" message.
Bump RITE binary format version from 0300 to 0400 due to opcode
number shift.
Co-authored-by: Claude <noreply@anthropic.com>
- Add mrb_likely/mrb_unlikely macros to common.h for branch prediction
- Optimize OP_GETIDX array fast path:
- Cache RArray pointer to avoid repeated RARRAY() calls
- Single ARY_EMBED_P check instead of two (via RARRAY_LEN + RARRAY_PTR)
- Use unsigned comparison for bounds check
- Add branch prediction hints for common cases
- Convert switch statement to if-else chain for better branch prediction
Benchmark shows ~3% improvement for array read operations.
Co-authored-by: Claude <noreply@anthropic.com>
Add comprehensive benchmarks for measuring VM performance:
- vm_optimization_bench.rb: Ruby-level benchmarks covering dispatch,
arithmetic, method calls, array/hash access, loops, and recursion
- vm_dispatch_bench.c: C-level micro-benchmarks for precise measurement
These benchmarks are designed to measure the effect of potential VM
optimizations such as tail-call threading, register variables,
fused opcodes, and inline caching.
Usage:
# Ruby benchmark
./build/host/bin/mruby benchmark/vm_optimization_bench.rb
# C benchmark
cc -O2 -I include -I build/host/include \
benchmark/vm_dispatch_bench.c \
build/host/lib/libmruby.a -lm -o vm_dispatch_bench
./vm_dispatch_bench
Co-authored-by: Claude <noreply@anthropic.com>
Added error handling for file descriptors larger than FD_SETSIZE in mrb_hal_io_fdset_set and mrb_hal_io_fdset_isset functions, for posix hal.
I actually don't know how to fix this on windows, or if it needs fixing.
The purpose is to avoid using the `MRB_TT_CPTR` object.
The reasons are as follows:
- The `MRB_WORD_BOXING` setting involves object creation.
- If object creation fails, the `ary_set_t` data leaks memory.
expose the previously internal outer_class() function as a public API
for mrbgems to retrieve the enclosing class/module of a given class.
closes#6705.
Co-authored-by: Claude <noreply@anthropic.com>
wrap hash and eql callbacks with mrb_protect_error() to catch exceptions
during khash table rebuild. when an exception occurs (e.g., SystemStackError
from infinite recursion), return a safe default value and store the exception
in mrb->exc for later processing. this prevents memory leaks from orphaned
allocations when exceptions propagate through khash rebuild.
Co-authored-by: Claude <noreply@anthropic.com>
Function was only called once and contained just 2 lines of code.
Inlining directly reduces code size and improves clarity.
Co-authored-by: Claude <noreply@anthropic.com>
Add CPython-style parsing for base-10 string to integer conversion:
- Parse 9 digits at a time into decimal-base array
- Convert decimal-base to binary in single pass
- Use memory pool for temporary decimal buffer
- Use realloc for result buffer to reduce allocations
Also add digit_pairs lookup table for faster to_s output.
Performance: 2-5x faster for to_i, 60% fewer allocations.
Co-authored-by: Claude <noreply@anthropic.com>
- Add mrb_gc_protect() after arena_restore to prevent result from being collected before returning to caller
- Add comment to suspend_task_internal explaining why WAITING and DORMANT tasks can also be suspended
- Move argc/argv cast at the beginning of function with comment