The correct technique now is "Token Threading".
However, the new name was chosen because it was felt that if a different technique was added in the future, there would be no need to replace it.
Passing a proc generated by the following method to `mrb_yield()` or `mrb_yield_argv()` no longer causes `SIGSEGV`:
- C functions made into proc objects with `mrb_proc_new_cfunc()`.
- A proc object which is the top level of a program generated by `mrb_load_string_cxt()` etc. with `mrbc_context::no_exec` enabled.
See also: #5932
The `REnv` object is difficult to deal with, and it would be ideal if the user did not have to manipulate it directly.
In some previous situations, it was necessary to call `mrb_env_unshare()`, a non-API function, after `mrb_load_string()` or similar.
With this patch, it is no longer necessary for users to use `mrb_env_unshare()` directly, as it is now handled internally simply by using the `mrb_vm_ci_env_clear()` function.
Also, `mrb_vm_ci_env_set()` is demoted from the `MRB_API` function for the same reason.
ref. commit 1ab3da6f08
Move the detachment of the "env" object, now done by `mrb_top_run()` by #5904, to `mrb_vm_run()`.
This is because `mrb_vm_run()` can remove `mrb_env_unshare()` which is called from `bin/mirb`.
Also, even if the mruby VM is already running, either of the following conditions should be used to detach "env":
- If the `stack_keep` variable is 0.
- If the stack length of "env" is longer than `irep->nlocals`.
The reason for the change is that the stack beyond `irep->nlocals` is used inside the called method, and previously it was possible to reference and manipulate the state inside the method via "env".
env stack | |
main stack | top | m1 | m2 |
|<--------------->|
operable via env stack (including self)
If the problematic block is called from the `m2` method above, it is possible to replace `self` in `m1` and `m2` as well as the internal variables.
This change may cause compatibility problems, but I believe it is better to make `MRB_API`, `mrb_vm_run()` safe.
If a dangerous procedure is absolutely necessary, `mrb_vm_exec()` can still be called as before.
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
It fixes a bug that instance_eval for immediate objects defines methods
in Object, instead of raising error.
```ruby
1.instance_eval do
def foo
p :foo
end
end
```
- Now that it is called after `cipush()`, pass in a new ci pointer.
- Removed the parameters `clsp`, `a`, and `c`, which are no longer needed since they now operate directly on `ci`.
- Change the parameter `super`, which is treated as a boolean, to `mrb_bool`.
- Leave the parameter `mid`.
Because if `prepare_missing()` raises the exception `NoMethodError`, `ci->mid` must not be set when suppressing extra information on the stack trace.
However, set `ci->mid` here, since the preparation is completed at the end of the function.
Raising a `SystemStackError` exception in an out-of-memory situation will generate backtrace information.
This can eventually lead to a `NoMemoryError` exception, and this process flow is completely undesirable.
In effect, this change means that it will include a revert of commit 0dbb9e6e41.
Transforms the value of a splat inside a return statement (similar
to an array). For example, `return *nil` should return `nil.to_a`,
while `return *1` should return `[1]`
Since `callinfo::blk` is not marked in the GC, it may be reclaimed in
the sweep phase. When it reclaimed, it will become either (a) a non Proc
object, or (b) a Proc object that happen to have the same address.
For case (a), adding `b->tt == MRB_TT_PROC` check works. We should avoid
the following `MRB_PROC_STRICT_P()` and `MRB_PROC_ENV()` operations for
non Proc objects.
For case (b), `MRB_PROC_ENV(b) == CI_ENV(&c->ci[-1])` check should work.
Unrelated Proc objects should be filtered by the check.
We don't need to clear `callinfo::blk` by `NULL` because the callinfo
struct will be discarded afterward in the `cipop()` function.
This reverts commit c28ac75a87.
This change caused SEGV in the case like the following:
```
class C
class << self
attr_accessor :a
alias :const_missing :a=
end
end
p C::CONST
```
The common parts of `OP_SEND` and `OP_SUPER` have been merged so they no longer need to be independent.
This effectively means revert commit d0e8637e30.