Skip to content

Commit 9123ef4

Browse files
matzclaude
andcommitted
vm: add OP_SEND0 and OP_SSEND0 for zero-argument method calls
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>
1 parent f7988c9 commit 9123ef4

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

include/mruby/ops.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ OPCODE(RESCUE, BB) /* R[b] = R[a].isa?(R[b]) */
6060
OPCODE(RAISEIF, B) /* raise(R[a]) if R[a] */
6161
OPCODE(MATCHERR, B) /* raise NoMatchingPatternError unless R[a] */
6262
OPCODE(SSEND, BBB) /* R[a] = self.send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n|k<<4) */
63+
OPCODE(SSEND0, BB) /* R[a] = self.send(Syms[b]) (no args) */
6364
OPCODE(SSENDB, BBB) /* R[a] = self.send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..,&R[a+n+2k+1]) */
6465
OPCODE(SEND, BBB) /* R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..) (c=n|k<<4) */
66+
OPCODE(SEND0, BB) /* R[a] = R[a].send(Syms[b]) (no args) */
6567
OPCODE(SENDB, BBB) /* R[a] = R[a].send(Syms[b],R[a+1]..,R[a+n+1]:R[a+n+2]..,&R[a+n+2k+1]) */
6668
OPCODE(CALL, Z) /* self.call(*, **, &) (But overlay the current call frame; tailcall) */
6769
OPCODE(BLKCALL, BB) /* R[a] = R[a].call(R[a+1],... ,R[a+b]); direct block call */

mrbgems/mruby-compiler/core/codegen.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3643,7 +3643,15 @@ codegen_call(codegen_scope *s, node *varnode, int val)
36433643
/* constant folding succeeded */
36443644
}
36453645
else if (noself) {
3646-
genop_3(s, blk ? OP_SSENDB : OP_SSEND, cursp(), sym_idx(s, sym), n|(nk<<4));
3646+
if (!blk && n == 0 && nk == 0) {
3647+
genop_2(s, OP_SSEND0, cursp(), sym_idx(s, sym));
3648+
}
3649+
else {
3650+
genop_3(s, blk ? OP_SSENDB : OP_SSEND, cursp(), sym_idx(s, sym), n|(nk<<4));
3651+
}
3652+
}
3653+
else if (!blk && n == 0 && nk == 0) {
3654+
genop_2(s, OP_SEND0, cursp(), sym_idx(s, sym));
36473655
}
36483656
else {
36493657
genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), sym_idx(s, sym), n|(nk<<4));

src/codedump.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out)
336336
fprintf(out, "SSEND\t\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
337337
print_args(c, out);
338338
break;
339+
CASE(OP_SSEND0, BB):
340+
fprintf(out, "SSEND0\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b]));
341+
break;
339342
CASE(OP_SSENDB, BBB):
340343
fprintf(out, "SSENDB\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
341344
print_args(c, out);
@@ -344,6 +347,9 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out)
344347
fprintf(out, "SEND\t\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
345348
print_args(c, out);
346349
break;
350+
CASE(OP_SEND0, BB):
351+
fprintf(out, "SEND0\t\tR%d\t:%s\n", a, mrb_sym_dump(mrb, irep->syms[b]));
352+
break;
347353
CASE(OP_SENDB, BBB):
348354
fprintf(out, "SENDB\t\tR%d\t:%s\t", a, mrb_sym_dump(mrb, irep->syms[b]));
349355
print_args(c, out);

src/vm.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,12 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq
22112211
}
22122212
goto L_SENDB;
22132213

2214+
CASE(OP_SSEND0, BB) {
2215+
regs[a] = regs[0];
2216+
c = 0;
2217+
}
2218+
goto L_SENDB;
2219+
22142220
CASE(OP_SSENDB, BBB) {
22152221
regs[a] = regs[0];
22162222
}
@@ -2219,6 +2225,11 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq
22192225
CASE(OP_SEND, BBB)
22202226
goto L_SENDB;
22212227

2228+
CASE(OP_SEND0, BB) {
2229+
c = 0;
2230+
}
2231+
goto L_SENDB;
2232+
22222233
L_SEND_SYM:
22232234
c = 1;
22242235
/* push nil after arguments */
@@ -2259,7 +2270,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq
22592270
}
22602271

22612272
mrb_assert(bidx < irep->nregs);
2262-
if (insn == OP_SEND || insn == OP_SSEND) {
2273+
if (insn == OP_SEND || insn == OP_SEND0 || insn == OP_SSEND || insn == OP_SSEND0) {
22632274
/* clear block argument */
22642275
SET_NIL_VALUE(regs[new_bidx]);
22652276
SET_NIL_VALUE(blk);
@@ -2280,7 +2291,7 @@ mrb_vm_exec(mrb_state *mrb, const struct RProc *begin_proc, const mrb_code *iseq
22802291
else {
22812292
ci->mid = mid;
22822293
}
2283-
if (insn == OP_SEND || insn == OP_SENDB) {
2294+
if (insn == OP_SEND || insn == OP_SEND0 || insn == OP_SENDB) {
22842295
mrb_bool priv = TRUE;
22852296
if (m.flags & MRB_METHOD_PRIVATE_FL) {
22862297
vis_err:;

0 commit comments

Comments
 (0)