mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
vm: add OP_TDEF/OP_SDEF for fused method definition
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>
This commit is contained in:
@@ -113,6 +113,8 @@ OPCODE(CLASS, BB) /* R[a] = newclass(R[a],Syms[b],R[a+1]) */
|
||||
OPCODE(MODULE, BB) /* R[a] = newmodule(R[a],Syms[b]) */
|
||||
OPCODE(EXEC, BB) /* R[a] = blockexec(R[a],Irep[b]) */
|
||||
OPCODE(DEF, BB) /* R[a].newmethod(Syms[b],R[a+1]); R[a] = Syms[b] */
|
||||
OPCODE(TDEF, BBB) /* target_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b] */
|
||||
OPCODE(SDEF, BBB) /* R[a].singleton_class.newmethod(Syms[b],Irep[c]); R[a] = Syms[b] */
|
||||
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms[a],Syms[b]) */
|
||||
OPCODE(UNDEF, B) /* undef_method(target_class,Syms[a]) */
|
||||
OPCODE(SCLASS, B) /* R[a] = R[a].singleton_class */
|
||||
|
||||
@@ -5017,12 +5017,18 @@ codegen_def(codegen_scope *s, node *varnode, int val)
|
||||
/* For NODE_DEF, args should contain the full locals structure from defn_setup */
|
||||
int idx = lambda_body(s, def_n->locals, def_n->args, def_n->body, 0);
|
||||
|
||||
genop_1(s, OP_TCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
push(); pop();
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
if (idx <= 0xff) {
|
||||
/* TDEF fusion: TCLASS + METHOD + DEF -> TDEF */
|
||||
genop_3(s, OP_TDEF, cursp(), sym, idx);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_TCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
push(); pop();
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
}
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
@@ -6400,12 +6406,18 @@ codegen_sdef(codegen_scope *s, const node *varnode, int val)
|
||||
|
||||
codegen(s, recv, VAL);
|
||||
pop();
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
push(); pop();
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
if (idx <= 0xff) {
|
||||
/* SDEF fusion: SCLASS + METHOD + DEF -> SDEF */
|
||||
genop_3(s, OP_SDEF, cursp(), sym, idx);
|
||||
}
|
||||
else {
|
||||
genop_1(s, OP_SCLASS, cursp());
|
||||
push();
|
||||
genop_2(s, OP_METHOD, cursp(), idx);
|
||||
push(); pop();
|
||||
pop();
|
||||
genop_2(s, OP_DEF, cursp(), sym);
|
||||
}
|
||||
if (val) push();
|
||||
}
|
||||
|
||||
|
||||
@@ -427,6 +427,12 @@ codedump(mrb_state *mrb, const mrb_irep *irep, FILE *out)
|
||||
CASE(OP_DEF, BB):
|
||||
fprintf(out, "DEF\t\tR%d\t:%s\t(R%d)\n", a, mrb_sym_dump(mrb, irep->syms[b]),a+1);
|
||||
break;
|
||||
CASE(OP_TDEF, BBB):
|
||||
fprintf(out, "TDEF\t\tR%d\t:%s\tI[%d]\n", a, mrb_sym_dump(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
CASE(OP_SDEF, BBB):
|
||||
fprintf(out, "SDEF\t\tR%d\t:%s\tI[%d]\n", a, mrb_sym_dump(mrb, irep->syms[b]), c);
|
||||
break;
|
||||
CASE(OP_UNDEF, B):
|
||||
fprintf(out, "UNDEF\t\t:%s\n", mrb_sym_dump(mrb, irep->syms[a]));
|
||||
break;
|
||||
|
||||
@@ -3396,6 +3396,42 @@ RETRY_TRY_BLOCK:
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_TDEF, BBB) {
|
||||
struct RClass *target = check_target_class(mrb);
|
||||
if (!target) goto L_RAISE;
|
||||
struct RProc *p = mrb_proc_new(mrb, irep->reps[c]);
|
||||
mrb_method_t m;
|
||||
mrb_sym mid = irep->syms[b];
|
||||
|
||||
p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
MRB_METHOD_SET_VISIBILITY(m, MRB_METHOD_VDEFAULT_FL);
|
||||
mrb_define_method_raw(mrb, target, mid, m);
|
||||
mrb_method_added(mrb, target, mid);
|
||||
ci = mrb->c->ci;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
regs[a] = mrb_symbol_value(mid);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SDEF, BBB) {
|
||||
mrb_value recv = regs[a];
|
||||
struct RClass *target = mrb_class_ptr(mrb_singleton_class(mrb, recv));
|
||||
struct RProc *p = mrb_proc_new(mrb, irep->reps[c]);
|
||||
mrb_method_t m;
|
||||
mrb_sym mid = irep->syms[b];
|
||||
|
||||
p->flags |= MRB_PROC_SCOPE | MRB_PROC_STRICT;
|
||||
MRB_METHOD_FROM_PROC(m, p);
|
||||
MRB_METHOD_SET_VISIBILITY(m, MRB_METHOD_VDEFAULT_FL);
|
||||
mrb_define_method_raw(mrb, target, mid, m);
|
||||
mrb_method_added(mrb, target, mid);
|
||||
ci = mrb->c->ci;
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
regs[a] = mrb_symbol_value(mid);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_SCLASS, B) {
|
||||
regs[a] = mrb_singleton_class(mrb, regs[a]);
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
|
||||
Reference in New Issue
Block a user