Only go to exception handling if `mrb->exc` is non-null.
This may cause some compatibility problems, but I doubt that it is necessary to maintain that compatibility.
Here is how I see the incompatibility with the change at this time:
- If `mrb->exc` is non-null and `mrb_vm_exec()` is called, an exception will be thrown immediately.
- If `MRB_THROW()` is used while `mrb->exc` is `NULL`, it will not go to exception handling.
Previous SWAR version assumes valid UTF-8 to count number of code points
in the string, but we need to handle invalid sequence as well. We now
use `search_nonascii` to skip counting single byte characters for
performance. The new version is even faster than SWAR version (probably
because `search_nonascii` uses SSE2 on Intel compatible CPU (which I use).
The patch assumes that `struct REnv::cxt` only performs checks with the `OP_BREAK` and `OP_RETURN_BLK` instructions, and does not reference the entity.
Therefore, by changing to a weak reference, it is possible to collect fibers that are no longer directly referenced while in the suspended state.
However, we need to detach the living env objects that remain in the call stack of the fiber.
So, in effect, it involves a revert of following commits.
- commit a3365d8b3f
- commit 57ffa1c150
Examples of the effects of change are shown below.
Note that it was built with `rake MRUBY_CONFIG=host-debug`.
```ruby
f = Fiber.new { (x, y, z) = "X", "Y", "Z"; Fiber.yield -> { [x, y, z] } }
g = f.resume
GC.start
p ObjectSpace.memsize_of_all
# => 59532
g.call
# => ["X", "Y", "Z"]
f = nil
GC.start
ObjectSpace.memsize_of_all
# BEFORE => 59532
# AFTER => 58044
g.call
# => ["X", "Y", "Z"]
```
`mrb_env_unshare()` calls `mrb_realloc_simple()` and follows `mrb_full_gc()` to avoid an infinite loop where `mrb_env_unshare()` is called again.
This does not occur at this time, but may occur in subsequent patches.
`mrb_vm_run()` is,
- It does not change the fiber context.
- When control is returned, only one ci prepared by the caller is popped.
If the ci equals cibase when called, the ci position does not change.
related commits:
- commit 4e84bdb507
- commit 34dd258c63
- commit ebd6636a1e
- commit c6736357a7
- commit 23a4e7149d
- commit 31a961acf1
Previously `\x80` was incorrectly mapped to `0`.
```ruby
"\x80\x80\x80\x80".unpack("m*")
# before => "\x00\x00\x00"
# after => ""
```
The reason is that the C string terminator is placed in `base64_dec_tab[128]` and the array length is obtained by `sizeof`.
Therefore, the length of `base64_dec_tab[]` is strictly specified and replaced with element-by-element initialization.
Also, similar changes are made to `base64chars[]`.