From 724a2e26387b3a5f34939fa24a6eb16b218ebf73 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 19 Jan 2026 14:15:28 +0900 Subject: [PATCH] vm: add OP_RETSELF instruction for returning self Fuse LOADSELF + RETURN sequence into single RETSELF instruction. Saves 2 bytes per occurrence (3 bytes -> 1 byte). Found 25 occurrences in mrblib, saving 50 bytes total. Co-authored-by: Claude --- include/mruby/ops.h | 1 + mrbgems/mruby-compiler/core/codegen.c | 7 ++++++- src/codedump.c | 3 +++ src/vm.c | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/mruby/ops.h b/include/mruby/ops.h index f8b91728b..9602dc51b 100644 --- a/include/mruby/ops.h +++ b/include/mruby/ops.h @@ -71,6 +71,7 @@ OPCODE(KEYEND, Z) /* raise unless kdict.empty? */ OPCODE(KARG, BB) /* R[a] = kdict[Syms[b]]; kdict.delete(Syms[b]) */ OPCODE(RETURN, B) /* return R[a] (normal) */ OPCODE(RETURN_BLK, B) /* return R[a] (in-block return) */ +OPCODE(RETSELF, Z) /* return self */ OPCODE(BREAK, B) /* break R[a] */ OPCODE(BLKPUSH, BS) /* R[a] = block (16=m5:r1:m5:d1:lv4) */ OPCODE(ADD, B) /* R[a] = R[a]+R[a+1] */ diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 36a60b1d1..9a0c2d257 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -1141,7 +1141,12 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) rewind_pc(s); genop_1(s, op, data.b); } - else if (data.insn != OP_RETURN) { + else if (data.insn == OP_LOADSELF && src == data.a && op == OP_RETURN) { + /* LOADSELF + RETURN -> RETSELF */ + rewind_pc(s); + genop_0(s, OP_RETSELF); + } + else if (data.insn != OP_RETURN && data.insn != OP_RETSELF) { genop_1(s, op, src); } } diff --git a/src/codedump.c b/src/codedump.c index 2bc3c9110..58962c83d 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -390,6 +390,9 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out) fprintf(out, "RETURN_BLK\tR%d\t", a); print_lv_a(mrb, irep, a, out); break; + CASE(OP_RETSELF, Z): + fprintf(out, "RETSELF\n"); + break; CASE(OP_BREAK, B): fprintf(out, "BREAK\t\tR%d\t", a); print_lv_a(mrb, irep, a, out); diff --git a/src/vm.c b/src/vm.c index 21d5d3907..5568ff54b 100644 --- a/src/vm.c +++ b/src/vm.c @@ -2661,6 +2661,10 @@ RETRY_TRY_BLOCK: RAISE_LIT(mrb, E_LOCALJUMP_ERROR, "unexpected return"); /* not reached */ } + CASE(OP_RETSELF, Z) { + a = 0; + goto NORMAL_RETURN; + } CASE(OP_RETURN, B) { mrb_int acc; mrb_value v;