vm.c: use `prepare_missing` in `mrb_funcall_with_block`

Remove code duplication.
parent 5ca17c2d
...@@ -430,6 +430,52 @@ mrb_ci_nregs(mrb_callinfo *ci) ...@@ -430,6 +430,52 @@ mrb_ci_nregs(mrb_callinfo *ci)
return nregs; return nregs;
} }
mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
static mrb_method_t
prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
{
mrb_sym missing = MRB_SYM(method_missing);
mrb_callinfo *ci = mrb->c->ci;
uint16_t b = *c;
mrb_int n = b & 0xf;
mrb_int nk = (b>>4) & 0xf;
mrb_value *argv = &ci->stack[a+1];
mrb_value args;
mrb_method_t m;
/* pack positional arguments */
if (n == 15) args = argv[0];
else args = mrb_ary_new_from_values(mrb, n, argv);
if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
method_missing:
if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
else mrb_method_missing(mrb, mid, recv, args);
/* not reached */
}
if (mid != missing) {
*clsp = mrb_class(mrb, recv);
}
m = mrb_method_search_vm(mrb, clsp, missing);
if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
mrb_stack_extend(mrb, a+4);
argv = &ci->stack[a+1]; /* maybe reallocated */
argv[0] = args;
if (nk == 0) {
argv[1] = blk;
}
else {
mrb_assert(nk == 15);
argv[1] = argv[n];
argv[2] = blk;
}
*c = 15 | (nk<<4);
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
return m;
}
MRB_API mrb_value MRB_API mrb_value
mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk) mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk)
{ {
...@@ -478,24 +524,15 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ...@@ -478,24 +524,15 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
c = mrb_class(mrb, self); c = mrb_class(mrb, self);
m = mrb_method_search_vm(mrb, &c, mid); m = mrb_method_search_vm(mrb, &c, mid);
mrb_stack_extend(mrb, n + argc + 3); mrb_stack_extend(mrb, n + argc + 3);
if (MRB_METHOD_UNDEF_P(m) || argc >= 15) { if (argc >= 15) {
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); ci->stack[n+1] = mrb_ary_new_from_values(mrb, argc, argv);
ci->stack[n+1] = args;
argc = 15; argc = 15;
} }
if (MRB_METHOD_UNDEF_P(m)) { if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = MRB_SYM(method_missing); uint16_t ac = (uint16_t)argc;
mrb_value args = ci->stack[n+1]; m = prepare_missing(mrb, self, mid, &c, n, &ac, mrb_nil_value(), 0);
argc = (mrb_int)ac;
m = mrb_method_search_vm(mrb, &c, missing); mid = MRB_SYM(method_missing);
if (MRB_METHOD_UNDEF_P(m)) {
mrb_method_missing(mrb, mid, self, args);
}
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
mrb_stack_extend(mrb, n+2);
ci->stack[n+1] = args;
argc = 15;
} }
ci = cipush(mrb, n, 0, c, NULL, mid, argc); ci = cipush(mrb, n, 0, c, NULL, mid, argc);
if (MRB_METHOD_PROC_P(m)) { if (MRB_METHOD_PROC_P(m)) {
...@@ -1123,52 +1160,6 @@ hash_new_from_values(mrb_state *mrb, mrb_int argc, mrb_value *regs) ...@@ -1123,52 +1160,6 @@ hash_new_from_values(mrb_state *mrb, mrb_int argc, mrb_value *regs)
return hash; return hash;
} }
mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod);
static mrb_method_t
prepare_missing(mrb_state *mrb, mrb_value recv, mrb_sym mid, struct RClass **clsp, uint32_t a, uint16_t *c, mrb_value blk, int super)
{
mrb_sym missing = MRB_SYM(method_missing);
mrb_callinfo *ci = mrb->c->ci;
uint16_t b = *c;
mrb_int n = b & 0xf;
mrb_int nk = (b>>4) & 0xf;
mrb_value *argv = &ci->stack[a+1];
mrb_value args;
mrb_method_t m;
/* pack positional arguments */
if (n == 15) args = argv[0];
else args = mrb_ary_new_from_values(mrb, n, argv);
if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) {
method_missing:
if (super) mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid);
else mrb_method_missing(mrb, mid, recv, args);
/* not reached */
}
if (mid != missing) {
*clsp = mrb_class(mrb, recv);
}
m = mrb_method_search_vm(mrb, clsp, missing);
if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */
mrb_stack_extend(mrb, a+4);
argv = &ci->stack[a+1]; /* maybe reallocated */
argv[0] = args;
if (nk == 0) {
argv[1] = blk;
}
else {
mrb_assert(nk == 15);
argv[1] = argv[n];
argv[2] = blk;
}
*c = 15 | (nk<<4);
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
return m;
}
void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid); void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid);
mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len); mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment