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 <mruby.h>
#include <mruby/compile.h>

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
This commit is contained in:
dearblue
2023-01-09 22:47:37 +09:00
parent e2ffcbab6e
commit c101261f45
3 changed files with 7 additions and 1 deletions
+1
View File
@@ -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
+1
View File
@@ -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
+5 -1
View File
@@ -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);