summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/class.c11
-rw-r--r--src/proc.c6
-rw-r--r--src/vm.c113
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; */
}
diff --git a/src/vm.c b/src/vm.c
index 1a411b534..0d197098d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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);