mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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:
+12
-1
@@ -412,7 +412,18 @@ mrb_proc_arity(const struct RProc *p)
|
||||
int ma, op, ra, pa, arity;
|
||||
|
||||
if (MRB_PROC_CFUNC_P(p)) {
|
||||
/* TODO cfunc aspec not implemented yet */
|
||||
uint32_t caspec_bits = p->flags & MRB_PROC_CASPEC_MASK;
|
||||
if (caspec_bits != 0) {
|
||||
aspec = mrb_proc_decompress_caspec(caspec_bits);
|
||||
ma = MRB_ASPEC_REQ(aspec);
|
||||
op = MRB_ASPEC_OPT(aspec);
|
||||
ra = MRB_ASPEC_REST(aspec);
|
||||
pa = MRB_ASPEC_POST(aspec);
|
||||
return ra || op ? -(ma + pa + 1) : ma + pa;
|
||||
}
|
||||
if (MRB_PROC_NOARG_P(p)) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -901,7 +901,11 @@ exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
|
||||
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
||||
CI_PROC_SET(ci, p);
|
||||
if (MRB_PROC_CFUNC_P(p)) {
|
||||
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
||||
uint32_t caspec_bits = p->flags & MRB_PROC_CASPEC_MASK;
|
||||
if (caspec_bits != 0) {
|
||||
check_argument_count(mrb, ci, mrb_proc_decompress_caspec(caspec_bits));
|
||||
}
|
||||
else if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
||||
check_argument_count(mrb, ci, 0);
|
||||
}
|
||||
return MRB_PROC_CFUNC(p)(mrb, self);
|
||||
@@ -1052,7 +1056,11 @@ send_method(mrb_state *mrb, mrb_value self, mrb_bool pub)
|
||||
MRB_PROC_RESOLVE_ALIAS(ci, p);
|
||||
CI_PROC_SET(ci, p);
|
||||
if (MRB_PROC_CFUNC_P(p)) {
|
||||
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
||||
uint32_t caspec_bits = p->flags & MRB_PROC_CASPEC_MASK;
|
||||
if (caspec_bits != 0) {
|
||||
check_argument_count(mrb, ci, mrb_proc_decompress_caspec(caspec_bits));
|
||||
}
|
||||
else if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
|
||||
check_argument_count(mrb, ci, 0);
|
||||
}
|
||||
return MRB_PROC_CFUNC(p)(mrb, self);
|
||||
|
||||
Reference in New Issue
Block a user