summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authordearblue <[email protected]>2021-04-03 21:20:59 +0900
committerdearblue <[email protected]>2021-04-03 21:20:59 +0900
commit4c196dcdaaf4127e2ce988fb79f1912c78b9dca8 (patch)
treeb42012971f1822b6bd1deef1e436078b45a4da85 /src
parentdd34ac647fb5d6842941b3529d1452797862cc23 (diff)
downloadmruby-4c196dcdaaf4127e2ce988fb79f1912c78b9dca8.tar.gz
mruby-4c196dcdaaf4127e2ce988fb79f1912c78b9dca8.zip
Reorganize `mcall()` in `mruby-method`.
Use `mrb_exec_irep()`. If possible, re-entry into the VM will be suppressed. Note that due to the effect of being a tail-call, the backtrace of `Method#call` will be lost, and it will look as if the target method was called directly. This change fixes the problem of infinite loops when redefining methods that make block calls using `mruby-method`. ```console % bin/mruby -e 'mm = method(:proc); define_method(:proc, ->(*a, &b) { mm.call(*a, &b) }); p proc { 1 }' trace (most recent call last): [257] -e:1 [256] -e:1:in proc [255] -e:1:in proc ...SNIP... [1] -e:1:in proc -e:1:in proc: stack level too deep (SystemStackError) ```
Diffstat (limited to 'src')
-rw-r--r--src/vm.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/src/vm.c b/src/vm.c
index d7f2f58d7..dbc8bd88a 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -585,7 +585,9 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t postho
else {
mrb_value ret;
if (MRB_PROC_CFUNC_P(p)) {
+ cipush(mrb, 0, CI_ACC_DIRECT, mrb_vm_ci_target_class(ci), p, ci->mid, ci->argc);
ret = MRB_PROC_CFUNC(p)(mrb, self);
+ cipop(mrb);
}
else {
int keep = (ci->argc < 0 ? 1 : ci->argc) + 2 /* receiver + block */;