diff options
| -rw-r--r-- | src/class.c | 11 | ||||
| -rw-r--r-- | src/proc.c | 6 | ||||
| -rw-r--r-- | src/vm.c | 113 |
3 files changed, 66 insertions, 64 deletions
diff --git a/src/class.c b/src/class.c index ec9c648e5..f97cc4c40 100644 --- a/src/class.c +++ b/src/class.c @@ -929,6 +929,13 @@ mrb_block_given_p(mrb_state *mrb) MRB_API mrb_int mrb_get_args(mrb_state *mrb, const char *format, ...) { +#define ADJUST_STACK() do { \ + if (argv_on_stack) { \ + ci = mrb->c->ci; \ + argv = mrb->c->ci->stack + 1; \ + } \ +} while (0) + const char *fmt = format; char c; int i = 0; @@ -1191,6 +1198,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_float*); if (pickarg) { *p = mrb_as_float(mrb, *pickarg); + ADJUST_STACK(); } } break; @@ -1202,6 +1210,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) p = va_arg(ap, mrb_int*); if (pickarg) { *p = mrb_as_int(mrb, *pickarg); + ADJUST_STACK(); } } break; @@ -1364,6 +1373,8 @@ mrb_get_args(mrb_state *mrb, const char *format, ...) finish: va_end(ap); return i; + +#undef ADJUST_STACK } static struct RClass* diff --git a/src/proc.c b/src/proc.c index e11cb7fec..01a69fbf1 100644 --- a/src/proc.c +++ b/src/proc.c @@ -207,12 +207,12 @@ mrb_proc_copy(mrb_state *mrb, struct RProc *a, struct RProc *b) /* already initialized proc */ return; } + if (!MRB_PROC_CFUNC_P(b) && b->body.irep) { + mrb_irep_incref(mrb, (mrb_irep*)b->body.irep); + } a->flags = b->flags; a->body = b->body; a->upper = b->upper; - if (!MRB_PROC_CFUNC_P(a) && a->body.irep) { - mrb_irep_incref(mrb, (mrb_irep*)a->body.irep); - } a->e.env = b->e.env; /* a->e.target_class = a->e.target_class; */ } @@ -430,6 +430,52 @@ mrb_ci_nregs(mrb_callinfo *ci) 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_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 c = mrb_class(mrb, self); m = mrb_method_search_vm(mrb, &c, mid); mrb_stack_extend(mrb, n + argc + 3); - if (MRB_METHOD_UNDEF_P(m) || argc >= 15) { - mrb_value args = mrb_ary_new_from_values(mrb, argc, argv); - - ci->stack[n+1] = args; + if (argc >= 15) { + ci->stack[n+1] = mrb_ary_new_from_values(mrb, argc, argv); argc = 15; } if (MRB_METHOD_UNDEF_P(m)) { - mrb_sym missing = MRB_SYM(method_missing); - mrb_value args = ci->stack[n+1]; - - m = mrb_method_search_vm(mrb, &c, 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; + uint16_t ac = (uint16_t)argc; + m = prepare_missing(mrb, self, mid, &c, n, &ac, mrb_nil_value(), 0); + argc = (mrb_int)ac; + mid = MRB_SYM(method_missing); } ci = cipush(mrb, n, 0, c, NULL, mid, argc); if (MRB_METHOD_PROC_P(m)) { @@ -1123,52 +1160,6 @@ hash_new_from_values(mrb_state *mrb, mrb_int argc, mrb_value *regs) 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); mrb_value mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value len); |
