Store compressed aspec on cfunc RProc for correct arity/parameters

Compress the 24-bit aspec into 13 free flag bits on RProc (bits 0-6
and 14-19) when wrapping cfunc methods. Field widths: req/opt 3 bits
(max 7), post/key 2 bits (max 3), rest/kdict/block 1 bit each. Values
exceeding the compressed range are clamped and rest is forced to 1.

This enables Proc#arity and Proc#parameters to return correct results
for cfunc-backed Procs (e.g. from Method#to_proc) with zero memory
overhead -- no struct change needed.

Closes #6764
This commit is contained in:
Chris Hasiński
2026-04-13 13:11:22 +02:00
parent 28c5b1b17b
commit 55f0228bf8
6 changed files with 102 additions and 17 deletions
+2 -3
View File
@@ -85,6 +85,7 @@ method_missing_prepare(mrb_state *mrb, mrb_sym *mid, mrb_value recv, struct RCla
const struct RProc *proc;
if (MRB_METHOD_FUNC_P(m)) {
struct RProc *p = mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
mrb_proc_set_cfunc_aspec(p, MRB_MT_ASPEC(m.flags));
MRB_PROC_SET_TARGET_CLASS(p, *tc);
proc = p;
}
@@ -393,9 +394,7 @@ method_search_vm(mrb_state *mrb, struct RClass **cp, mrb_sym mid)
return MRB_METHOD_PROC(m);
struct RProc *proc = mrb_proc_new_cfunc(mrb, MRB_METHOD_FUNC(m));
if (MRB_MT_ASPEC(m.flags) == 0) {
proc->flags |= MRB_PROC_NOARG;
}
mrb_proc_set_cfunc_aspec(proc, MRB_MT_ASPEC(m.flags));
return proc;
}