mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-compiler: optimize JMPNOT+JMP to JMPIF in pattern matching
For patterns with a single failure check (like `1 => String`), invert JMPNOT to JMPIF and eliminate the following JMP instruction. Before: JMPNOT fail; JMP end; fail: error; end: (8 bytes for jumps) After: JMPIF end; error; end: (4 bytes for jump) The optimization only applies when: 1. There's exactly one JMPNOT in the failure chain 2. The JMPNOT is immediately before the JMP (no code between) Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6402,10 +6402,23 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
genop_1(s, OP_LOADT, cursp());
|
||||
push();
|
||||
}
|
||||
match_pos = genjmp(s, OP_JMP, JMPLINK_START);
|
||||
|
||||
/* Optimize: single JMPNOT can be inverted to JMPIF, eliminating JMP */
|
||||
/* Conditions: (1) single entry in fail_pos chain, and
|
||||
* (2) JMPNOT is immediately before current position (no code between) */
|
||||
if ((int32_t)(fail_pos + 2) + (int16_t)PEEK_S(s->iseq+fail_pos) == 0 &&
|
||||
fail_pos + 2 == s->pc) {
|
||||
/* Single failure point - invert JMPNOT to JMPIF */
|
||||
s->iseq[fail_pos - 2] = OP_JMPIF;
|
||||
match_pos = fail_pos;
|
||||
}
|
||||
else {
|
||||
/* Multiple failure points - need JMP to skip error handling */
|
||||
match_pos = genjmp(s, OP_JMP, JMPLINK_START);
|
||||
dispatch_linked(s, fail_pos);
|
||||
}
|
||||
|
||||
/* Pattern failed */
|
||||
dispatch_linked(s, fail_pos);
|
||||
pop(); /* pop the value */
|
||||
if (mp->raise_on_fail) {
|
||||
/* expr => pattern: raise NoMatchingPatternError */
|
||||
|
||||
Reference in New Issue
Block a user