summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-eval
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-03-17 15:55:18 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-03-17 15:55:18 +0900
commitfca17b41c7a9c93787c90b715f1fb054021fab28 (patch)
tree863b5ff7dc5f01333c1ae105a2142776dba55d4a /mrbgems/mruby-eval
parent9ecebebf3e12d6d8125a7a24b8ac4e124c7cd98a (diff)
downloadmruby-fca17b41c7a9c93787c90b715f1fb054021fab28.tar.gz
mruby-fca17b41c7a9c93787c90b715f1fb054021fab28.zip
Avoid trampoline when #eval is called from mrb_funcall(); fix #3522
Diffstat (limited to 'mrbgems/mruby-eval')
-rw-r--r--mrbgems/mruby-eval/src/eval.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/mrbgems/mruby-eval/src/eval.c b/mrbgems/mruby-eval/src/eval.c
index 8b402e78c..5e8952f0d 100644
--- a/mrbgems/mruby-eval/src/eval.c
+++ b/mrbgems/mruby-eval/src/eval.c
@@ -133,7 +133,9 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
break;
case OP_STOP:
- irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
+ if (mrb->c->ci->acc >= 0) {
+ irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
+ }
break;
}
}
@@ -210,6 +212,19 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
}
static mrb_value
+exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
+{
+ if (mrb->c->ci->acc < 0) {
+ mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
+ if (mrb->exc) {
+ mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
+ }
+ return ret;
+ }
+ return mrb_exec_irep(mrb, self, proc);
+}
+
+static mrb_value
f_eval(mrb_state *mrb, mrb_value self)
{
char *s;
@@ -223,11 +238,9 @@ f_eval(mrb_state *mrb, mrb_value self)
proc = create_proc_from_string(mrb, s, len, binding, file, line);
mrb_assert(!MRB_PROC_CFUNC_P(proc));
- return mrb_exec_irep(mrb, self, proc);
+ return exec_irep(mrb, self, proc);
}
-#define CI_ACC_SKIP -1
-
static mrb_value
f_instance_eval(mrb_state *mrb, mrb_value self)
{
@@ -250,7 +263,7 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
proc->target_class = mrb_class_ptr(cv);
mrb->c->ci->env = NULL;
mrb_assert(!MRB_PROC_CFUNC_P(proc));
- return mrb_exec_irep(mrb, self, proc);
+ return exec_irep(mrb, self, proc);
}
else {
mrb_get_args(mrb, "&", &b);