From c101261f452224dbe48abc890b7c78b7713f6c2b Mon Sep 17 00:00:00 2001 From: dearblue Date: Mon, 9 Jan 2023 22:47:37 +0900 Subject: [PATCH] Call `mrb_env_unshare()` in `mrb_top_run()` if necessary This is to keep the local variables of the previously created blocks consistent in case the `mrbc_context` passed to `mrb_load_exec()` is `NULL` or different. Switching between `mrbc_context` pointers that are non `NULL` can be done safely by calling `mrbc_cleanup_local_variables()`. Before this patch, the result of the following code is not as expected. ```console % cat loadstr.c #include #include int main(int argc, char *argv[]) { mrb_state *mrb = mrb_open(); mrb_load_string( mrb, "(a, b, c, d, e, f, g) = [1, 2, 3, 4, 5, 6, 7] \n" "$lambda = -> { p [a, b, c, d, e, f, g] }"); mrb_load_string(mrb, "$lambda.call"); mrb_close(mrb); return 0; } % $(bin/mruby-config --cc --cflags --ldflags) loadstr.c $(bin/mruby-config --libs) && ./a.out [main, nil, nil, main, nil, nil, main] ``` Also, since `mrb_env_unshare()` was not used before, the internal stack of simply detached `env` objects could show invalid addresses by `stack_extend()`. ref. https://github.com/kou/mruby-pp/commit/ef5951aca870183d8767cb61f6414240988ca35e --- mrbgems/mruby-compiler/core/parse.y | 1 + mrbgems/mruby-compiler/core/y.tab.c | 1 + src/vm.c | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mrbgems/mruby-compiler/core/parse.y b/mrbgems/mruby-compiler/core/parse.y index f807be1e4..0a9da0e36 100644 --- a/mrbgems/mruby-compiler/core/parse.y +++ b/mrbgems/mruby-compiler/core/parse.y @@ -6764,6 +6764,7 @@ mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c) c->syms = NULL; c->slen = 0; } + c->keep_lv = FALSE; } MRB_API void diff --git a/mrbgems/mruby-compiler/core/y.tab.c b/mrbgems/mruby-compiler/core/y.tab.c index 0bb243887..9d0b70a3b 100644 --- a/mrbgems/mruby-compiler/core/y.tab.c +++ b/mrbgems/mruby-compiler/core/y.tab.c @@ -12964,6 +12964,7 @@ mrbc_cleanup_local_variables(mrb_state *mrb, mrbc_context *c) c->syms = NULL; c->slen = 0; } + c->keep_lv = FALSE; } MRB_API void diff --git a/src/vm.c b/src/vm.c index b9ff95e5d..ec92fabdf 100644 --- a/src/vm.c +++ b/src/vm.c @@ -3097,7 +3097,11 @@ mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int st return mrb_vm_run(mrb, proc, self, stack_keep); } if (mrb->c->ci == mrb->c->cibase) { - mrb_vm_ci_env_set(mrb->c->ci, NULL); + if (stack_keep == 0) { + struct REnv *e = mrb_vm_ci_env(mrb->c->ci); + mrb_vm_ci_env_set(mrb->c->ci, NULL); + mrb_env_unshare(mrb, e, FALSE); + } return mrb_vm_run(mrb, proc, self, stack_keep); } cipush(mrb, 0, CINFO_SKIP, mrb->object_class, NULL, NULL, 0, 0);