#### Example (with `MRB_METHOD_CACHE`)
```ruby
GC.start
c = Class.new
p c #=> #<Class:0x7fd6a180e790>
c.new #=> cache `c.new`
c = nil
GC.start #=> `c` is GCed
r = Range.dup
p r #=> #<Class:0x7fd6a180e790>
# [same pointer as `c`]
r.new(2, 3) #=> ArgumentError: 'initialize':
# wrong number of arguments (2 for 0)
# [`c.new` is called instead of `r.new`]
```
#### Cause
An entry of method cache is identified by class pointer and method
id. However, reusing memory after GC may create a class with the same
pointer as the cached class.
#### Treatment
Cleared method caches of the class when the class is GCed.
If ":" is after "|" and there is no "?" or "*", the keyword argument
could not be obtained and it was not initialized with `undef`.
For example: "|oo:"
- Use `mrb_sym_name_len` instead of `mrb_sym_name` (class name should not
be escaped).
- Avoid `mrb_str_dup` (it is unnecessary to be shared string because it is
changed).
Keyword arguments can now be retrieved with the `:` specifier and
`mrb_kwargs` data.
For the interface, I referred to CRuby's `rb_get_kwargs()`.
For implementation, I referred to `OP_KARG` or etc.
We needed to preserve the original method name somewhere. We kept it in
the `env` structure pointed from aliased methods. #1457 and #1531 tried
to address this issue. But this patch is more memory efficient.
Limitation: this fix does not support `super` from methods defined by
`define_method`. This limitation may be addressed in the future, but
it's low priority.
In terms of specifiers, argv is never referenced after a method call as
shown in #3090.
Reduction of object code can be expected.
If you need to refer to argv after a method call in the same loop,
update argv after the method call.
`mrb_string_value_cstr` and `mrb_string_value_len`: obsolete
`mrb_string_cstr`: new function to retrieve NULL terminated C string
`RSTRING_CSTR`: wrapper macro of `mrb_string_cstr`
The binary sizes (gems are only `mruby-bin-mruby`) are reduced slightly in
my environment than before the introduction of new specifiers/modifiers
(5116789a) with this change.
------------+-------------------+-------------------+--------
BINARY | BEFORE (5116789a) | AFTER (This PR) | RATIO
------------+-------------------+-------------------+--------
mruby | 593416 bytes | 593208 bytes | -0.04%
libmruby.a | 769048 bytes | 767264 bytes | -0.23%
------------+-------------------+-------------------+--------
BTW, I accidentally changed `tasks/toolchains/visualcpp.rake` at #4613,
so I put it back.
Before this patch:
$ bin/mruby -e 'p Module.new.freeze.dup.frozen?' #=> true
After this patch (same as Ruby):
$ bin/mruby -e 'p Module.new.freeze.dup.frozen?' #=> false
Before this patch:
$ bin/mruby -e 'p Struct.new("A-")'
#=> Struct::"A-"
After this patch:
$ bin/mruby -e 'p Struct.new("A-")'
#=> NameError: identifier A- needs to be constant
Before this patch:
p (class << Object.new.freeze; self end).frozen? #=> false
sc = class << (o=Object.new); self end; o.freeze; p sc.frozen? #=> false
After this patch / Ruby:
p (class << Object.new.freeze; self end).frozen? #=> true
sc = class << (o=Object.new); self end; o.freeze; p sc.frozen? #=> true