Instead of on read. Once it's in the inline cache we never have to make
one again. We want to eventually put the value into the cache, and the
best opportunity to do that is when you write the value.
This change implements a cache for class variables. Previously there was
no cache for cvars. Cvar access is slow due to needing to travel all the
way up th ancestor tree before returning the cvar value. The deeper the
ancestor tree the slower cvar access will be.
The benefits of the cache are more visible with a higher number of
included modules due to the way Ruby looks up class variables. The
benchmark here includes 26 modules and shows with the cache, this branch
is 6.5x faster when accessing class variables.
```
compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105ca45) [x86_64-darwin19]
built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be0093ae) [x86_64-darwin19]
| |compare-ruby|built-ruby|
|:--------|-----------:|---------:|
|vm_cvar | 5.681M| 36.980M|
| | -| 6.51x|
```
Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails
application. ActiveRecord::Base.logger has 71 ancestors. The more
ancestors a tree has, the more clear the speed increase. IE if Base had
only one ancestor we'd see no improvement. This benchmark is run on a
vanilla Rails application.
Benchmark code:
```ruby
require "benchmark/ips"
require_relative "config/environment"
Benchmark.ips do |x|
x.report "logger" do
ActiveRecord::Base.logger
end
end
```
Ruby 3.0 master / Rails 6.1:
```
Warming up --------------------------------------
logger 155.251k i/100ms
Calculating -------------------------------------
```
Ruby 3.0 with cvar cache / Rails 6.1:
```
Warming up --------------------------------------
logger 1.546M i/100ms
Calculating -------------------------------------
logger 14.857M (± 4.8%) i/s - 74.198M in 5.006202s
```
Lastly we ran a benchmark to demonstate the difference between master
and our cache when the number of modules increases. This benchmark
measures 1 ancestor, 30 ancestors, and 100 ancestors.
Ruby 3.0 master:
```
Warming up --------------------------------------
1 module 1.231M i/100ms
30 modules 432.020k i/100ms
100 modules 145.399k i/100ms
Calculating -------------------------------------
1 module 12.210M (± 2.1%) i/s - 61.553M in 5.043400s
30 modules 4.354M (± 2.7%) i/s - 22.033M in 5.063839s
100 modules 1.434M (± 2.9%) i/s - 7.270M in 5.072531s
Comparison:
1 module: 12209958.3 i/s
30 modules: 4354217.8 i/s - 2.80x (± 0.00) slower
100 modules: 1434447.3 i/s - 8.51x (± 0.00) slower
```
Ruby 3.0 with cvar cache:
```
Warming up --------------------------------------
1 module 1.641M i/100ms
30 modules 1.655M i/100ms
100 modules 1.620M i/100ms
Calculating -------------------------------------
1 module 16.279M (± 3.8%) i/s - 82.038M in 5.046923s
30 modules 15.891M (± 3.9%) i/s - 79.459M in 5.007958s
100 modules 16.087M (± 3.6%) i/s - 81.005M in 5.041931s
Comparison:
1 module: 16279458.0 i/s
100 modules: 16087484.6 i/s - same-ish: difference falls within error
30 modules: 15891406.2 i/s - same-ish: difference falls within error
```
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
To invalidate some callable method entries, we replace the entry in the
class. Most types of method entries are on the method table of the
origin class, but refinement entries without an orig_me are housed in
the method table of the class itself. They are there because refinements
take priority over prepended methods.
By unconditionally inserting a copy of the refinement entry into the
origin class, clearing the method cache created situations where there
are refinement entry duplicates in the lookup chain, leading to infinite
loops and other problems.
Update the replacement logic to use the right class that houses the
method entry. Also, be more selective about cache invalidation when
moving refinement entries for prepend. This avoids calling
clear_method_cache_by_id_in_class() before refinement entries are in the
place it expects.
[Bug #17806]
In every caller of `rb_class_ivar_set` it checks for the `RCLASS_IV_TBL`
and then creates it if it doesn't exist. Instead of repeating this in
every caller, this can be done once in `rb_class_ivar_set`.
It's important to only make the origin when the prepend goes
through, as the precense of the origin informs whether to do an
origin backfill.
This plus 2d877327e fix [Bug #17590].
Check for cyclic prepend before making any changes. This requires
scanning the module ancestor chain twice, but in general modules
do not have large numbers of ancestors.
Previously, if a class included a module and then prepended the
same module, the prepend had no effect. This changes the behavior
so that the prepend has an effect unless the module is already
prepended the receiver.
While here, rename the origin_seen variable in include_modules_at,
since it is misleading. The variable tracks whether c has been seen,
not whether the origin of klass has been.
Fixes [Bug #17423]
cee02d754d resets pCMC and `me`
will be a invalidated and continuing the invalidated `me`,
it will break the data structure. This patch tris to clear
all methods of specified class before manipulating the `me`s.
[Issue #17417]
Module#include should only be able to insert modules after the origin,
otherwise it ends up working like Module#prepend.
This fixes the case where one of the modules in the included module
chain is included in a module that is already prepended to the receiver.
Fixes [Bug #7844]
Before this commit, `clone` gave different results depending on whether the original object
had an attached singleton class or not.
Consider the following setup:
```
class Foo; end
Foo.singleton_class.define_method(:foo) {}
obj = Foo.new
obj.singleton_class if $call_singleton
clone = obj.clone
```
When `$call_singleton = false`, neither `obj.singleton_class.singleton_class` nor
`clone.singleton_class.singleton_class` own any methods.
However, when `$call_singleton = true`, `clone.singleton_class.singleton_class` would own a copy of
`foo` from `Foo.singleton_class`, even though `obj.singleton_class.singleton_class` does not.
The latter case is unexpected and results in a visibly different clone, depending on if the original object
had an attached class or not.
Co-authored-by: Ufuk Kayserilioglu <ufuk.kayserilioglu@shopify.com>
Before this commit, iclasses were "shady", or not protected by write
barriers. Because of that, the GC needs to spend more time marking these
objects than otherwise.
Applications that make heavy use of modules should see reduction in GC
time as they have a significant number of live iclasses on the heap.
- Put logic for iclass method table ownership into a function
- Remove calls to WB_UNPROTECT and insert write barriers for iclasses
This commit relies on the following invariant: for any non oirigin
iclass `I`, `RCLASS_M_TBL(I) == RCLASS_M_TBL(RBasic(I)->klass)`. This
invariant did not hold prior to 98286e9 for classes and modules that
have prepended modules.
[Feature #16984]
98286e9850 made it so that
`Module#include` allocates an origin iclass on each use. Since `include`
is widely used, the extra allocation can contribute significantly to
memory usage.
Instead of always allocating in anticipation of prepend, this change
takes a different approach. The new setup inserts a origin iclass into
the super chains of all the children of the module when prepend happens
for the first time.
rb_ensure_origin is made static again since now that adding an origin
now means walking over all usages, we want to limit the number of places
where we do it.
3556a834a2 added support for
Module#include to affect the iclasses of the module. It didn't add
support for Module#prepend because there were bugs in the object model
and GC at the time that prevented it. Those problems have been
addressed in ad729a1d11 and
98286e9850, and now adding support for
it is straightforward and does not break any tests or specs.
Fixes [Bug #9573]
This fixes various issues when a module is included in or prepended
to a module or class, and then refined, or refined and then included
or prepended to a module or class.
Implement by renaming ensure_origin to rb_ensure_origin, making it
non-static, and calling it when refining a module.
Fix Module#initialize_copy to handle origins correctly. Previously,
Module#initialize_copy did not handle origins correctly. For example,
this code:
```ruby
module B; end
class A
def b; 2 end
prepend B
end
a = A.dup.new
class A
def b; 1 end
end
p a.b
```
Printed 1 instead of 2. This is because the super chain for
a.singleton_class was:
```
a.singleton_class
A.dup
B(iclass)
B(iclass origin)
A(origin) # not A.dup(origin)
```
The B iclasses would not be modified, so the includer entry would be
still be set to A and not A.dup.
This modifies things so that if the class/module has an origin,
all iclasses between the class/module and the origin are duplicated
and have the correct includer entry set, and the correct origin
is created.
This requires other changes to make sure all tests still pass:
* rb_undef_methods_from doesn't automatically handle classes with
origins, so pass it the origin for Comparable when undefing
methods in Complex. This fixed a failure in the Complex tests.
* When adding a method, the method cache was not cleared
correctly if klass has an origin. Clear the method cache for
the klass before switching to the origin of klass. This fixed
failures in the autoload tests related to overridding require,
without breaking the optimization tests. Also clear the method
cache for both the module and origin when removing a method.
* Module#include? is fixed to skip origin iclasses.
* Refinements are fixed to use the origin class of the module that
has an origin.
* RCLASS_REFINED_BY_ANY is removed as it was only used in a single
place and is no longer needed.
* Marshal#dump is fixed to skip iclass origins.
* rb_method_entry_make is fixed to handled overridden optimized
methods for modules that have origins.
Fixes [Bug #16852]
If a module has an origin, and that module is included in another
module or class, previously the iclass created for the module had
an origin pointer to the module's origin instead of the iclass's
origin.
Setting the origin pointer correctly requires using a stack, since
the origin iclass is not created until after the iclass itself.
Use a hidden ruby array to implement that stack.
Correctly assigning the origin pointers in the iclass caused a
use-after-free in GC. If a module with an origin is included
in a class, the iclass shares a method table with the module
and the iclass origin shares a method table with module origin.
Mark iclass origin with a flag that notes that even though the
iclass is an origin, it shares a method table, so the method table
should not be garbage collected. The shared method table will be
garbage collected when the module origin is garbage collected.
I've tested that this does not introduce a memory leak.
This change caused a VM assertion failure, which was traced to callable
method entries using the incorrect defined_class. Update
rb_vm_check_redefinition_opt_method and find_defined_class_by_owner
to treat iclass origins different than class origins to avoid this
issue.
This also includes a fix for Module#included_modules to skip
iclasses with origins.
Fixes [Bug #16736]
If a module has an origin, and that module is included in another
module or class, previously the iclass created for the module had
an origin pointer to the module's origin instead of the iclass's
origin.
Setting the origin pointer correctly requires using a stack, since
the origin iclass is not created until after the iclass itself.
Use a hidden ruby array to implement that stack.
Correctly assigning the origin pointers in the iclass caused a
use-after-free in GC. If a module with an origin is included
in a class, the iclass shares a method table with the module
and the iclass origin shares a method table with module origin.
Mark iclass origin with a flag that notes that even though the
iclass is an origin, it shares a method table, so the method table
should not be garbage collected. The shared method table will be
garbage collected when the module origin is garbage collected.
I've tested that this does not introduce a memory leak.
This also includes a fix for Module#included_modules to skip
iclasses with origins.
Fixes [Bug #16736]
When calling Module#include, if the receiver is a module,
walk the subclasses list and include the argument module in each
iclass.
This does not affect Module#prepend, as fixing that is significantly
more involved.
Fixes [Bug #9573]
This patch contains several ideas:
(1) Disposable inline method cache (IMC) for race-free inline method cache
* Making call-cache (CC) as a RVALUE (GC target object) and allocate new
CC on cache miss.
* This technique allows race-free access from parallel processing
elements like RCU.
(2) Introduce per-Class method cache (pCMC)
* Instead of fixed-size global method cache (GMC), pCMC allows flexible
cache size.
* Caching CCs reduces CC allocation and allow sharing CC's fast-path
between same call-info (CI) call-sites.
(3) Invalidate an inline method cache by invalidating corresponding method
entries (MEs)
* Instead of using class serials, we set "invalidated" flag for method
entry itself to represent cache invalidation.
* Compare with using class serials, the impact of method modification
(add/overwrite/delete) is small.
* Updating class serials invalidate all method caches of the class and
sub-classes.
* Proposed approach only invalidate the method cache of only one ME.
See [Feature #16614] for more details.
1. By substituting `n_var` with its initializer, `0 < n_var` is
equivalent to `argc > argi + n_trail`.
2. As `argi` is non-negative, so `argi + n_trail >= n_trail`, and
the above expression is equivalent to `argc > n_trail`.
3. Therefore, `f_last` is always false, and `last_hash` is no
longer used.
http://ci.rvm.jp/results/trunk_gcc7@silicon-docker/2539622
```
/tmp/ruby/v2/src/trunk_gcc7/class.c: In function 'rb_scan_args_parse':
/tmp/ruby/v2/src/trunk_gcc7/class.c:1971:12: warning: unused variable 'tmp_buffer' [-Wunused-variable]
VALUE *tmp_buffer = arg->tmp_buffer;
^~~~~~~~~~
```
```
In file included from /tmp/ruby/v2/src/trunk_gcc7/vm_insnhelper.c:1895:0,
from /tmp/ruby/v2/src/trunk_gcc7/vm.c:349:
/tmp/ruby/v2/src/trunk_gcc7/vm_args.c:212:1: warning: 'args_stored_kw_argv_to_hash' defined but not used [-Wunused-function]
args_stored_kw_argv_to_hash(struct args_info *args)
^~~~~~~~~~~~~~~~~~~~~~~~~~~
```
This removes the warnings added in 2.7, and changes the behavior
so that a final positional hash is not treated as keywords or
vice-versa.
To handle the arg_setup_block splat case correctly with keyword
arguments, we need to check if we are taking a keyword hash.
That case didn't have a test, but it affects real-world code,
so add a test for it.
This removes rb_empty_keyword_given_p() and related code, as
that is not needed in Ruby 3. The empty keyword case is the
same as the no keyword case in Ruby 3.
This changes rb_scan_args to implement keyword argument
separation for C functions when the : character is used.
For backwards compatibility, it returns a duped hash.
This is a bad idea for performance, but not duping the hash
breaks at least Enumerator::ArithmeticSequence#inspect.
Instead of having RB_PASS_CALLED_KEYWORDS be a number,
simplify the code by just making it be rb_keyword_given_p().
Saves comitters' daily life by avoid #include-ing everything from
internal.h to make each file do so instead. This would significantly
speed up incremental builds.
We take the following inclusion order in this changeset:
1. "ruby/config.h", where _GNU_SOURCE is defined (must be the very
first thing among everything).
2. RUBY_EXTCONF_H if any.
3. Standard C headers, sorted alphabetically.
4. Other system headers, maybe guarded by #ifdef
5. Everything else, sorted alphabetically.
Exceptions are those win32-related headers, which tend not be self-
containing (headers have inclusion order dependencies).
(old)
test.rb:4: warning: The last argument is used as the keyword parameter
test.rb:1: warning: for `foo' defined here; maybe ** should be added to the call?
(new)
test.rb:4: warning: The last argument is used as keyword parameters; maybe ** should be added to the call
test.rb:1: warning: The called method `foo' is defined here
This makes behavior the same as super in instance_eval in method
in class. The reason this wasn't implemented before is that
there is a check to determine if the self in the current context
is of the expected class, and a module itself can be included
in multiple classes, so it doesn't have an expected class.
Implementing this requires giving iclasses knowledge of which
class created them, so that super call in the module method
knows the expected class for super calls. This reference
is called includer, and should only be set for iclasses.
Note that the approach Ruby uses in this check is not robust. If
you instance_eval another object of the same class and call super,
instead of an TypeError, you get super called with the
instance_eval receiver instead of the method receiver. Truly
fixing super would require keeping a reference to the super object
(method receiver) in each frame where scope has changed, and using
that instead of current self when calling super.
Fixes [Bug #11636]
After the previous commit, this was still broken. The reason it
was broken is that a refined module that hasn't been prepended to
yet keeps the refined methods in the module's method table. When
prepending, the module's method table is moved to the origin
iclass, and then the refined methods are moved from the method
table to a new method table in the module itself.
Unfortunately, that means that if a class has included the module,
prepending breaks the refinements, because when the methods are
moved from the origin iclass method table to the module method
table, they are removed from the method table from the iclass
created when the module was included earlier.
Fix this by always creating an origin class when including a
module that has any refinements, even if the refinements are
not currently used. I wasn't sure the best way to do that.
The approach I choose was to use an object flag. The flag is
set on the module when Module#refine is called, and if the
flag is present when the module is included in another module
or class, an origin iclass is created for the module.
Fixes [Bug #13446]
This previously did not work, and the reason it did not work is
that:
1) Refining a module or class that prepends other modules places
the refinements in the class itself and not the origin iclass.
2) Inclusion of a module that prepends other modules skips the
module itself, including only iclasses for the prepended modules
and the origin iclass.
Those two behaviors combined meant that the method table for the
refined methods for the included module never ends up in the
method lookup chain for the class including the module.
Fix this by not skipping the module itself when the module is
included. This requires some code rearranging in
rb_include_class_new to make sure the correct method tables and
origin settings are used for the created iclass.
As origin iclasses shouldn't be exposed to Ruby, this also
requires skipping modules that have origin iclasses in
Module#ancestors (classes that have origin iclasses were already
skipped).
Fixes [Bug #16242]
This removes the related tests, and puts the related specs behind
version guards. This affects all code in lib, including some
libraries that may want to support older versions of Ruby.
This reverts commits: 10d6a3aca78ba48c1b85fba8627dc1dd883de5ba6c6a25feca167e6b48f17cb96d41a53207979278595b3c4fdd1521f7cf89c11c5e69accf336082033632a812c0f56506be0d86427a3219 .
The reason for the revert is that we observe ABA problem around
inline method cache. When a cache misshits, we search for a
method entry. And if the entry is identical to what was cached
before, we reuse the cache. But the commits we are reverting here
introduced situations where a method entry is freed, then the
identical memory region is used for another method entry. An
inline method cache cannot detect that ABA.
Here is a code that reproduce such situation:
```ruby
require 'prime'
class << Integer
alias org_sqrt sqrt
def sqrt(n)
raise
end
GC.stress = true
Prime.each(7*37){} rescue nil # <- Here we populate CC
class << Object.new; end
# These adjacent remove-then-alias maneuver
# frees a method entry, then immediately
# reuses it for another.
remove_method :sqrt
alias sqrt org_sqrt
end
Prime.each(7*37).to_a # <- SEGV
```
Now that we have eliminated most destructive operations over the
rb_method_entry_t / rb_callable_method_entry_t, let's make them
mostly immutabe and mark them const.
One exception is rb_export_method(), which destructively modifies
visibilities of method entries. I have left that operation as is
because I suspect that destructiveness is the nature of that
function.
Tired of rb_method_entry_create(..., rb_method_definition_create(
..., &(rb_method_foo_t) {...})) maneuver. Provide a function that
does the thing to reduce copy&paste.
The deleted function was to destructively overwrite existing method
entries, which is now considered to be a bad idea. Delete it, and
assign a newly created method entry instead.
Cfuncs that use rb_scan_args with the : entry suffer similar keyword
argument separation issues that Ruby methods suffer if the cfuncs
accept optional or variable arguments.
This makes the following changes to : handling.
* Treats as **kw, prompting keyword argument separation warnings
if called with a positional hash.
* Do not look for an option hash if empty keywords are provided.
For backwards compatibility, treat an empty keyword splat as a empty
mandatory positional hash argument, but emit a a warning, as this
behavior will be removed in Ruby 3. The argument number check
needs to be moved lower so it can correctly handle an empty
positional argument being added.
* If the last argument is nil and it is necessary to treat it as an option
hash in order to make sure all arguments are processed, continue to
treat the last argument as the option hash. Emit a warning in this case,
as this behavior will be removed in Ruby 3.
* If splitting the keyword hash into two hashes, issue a warning, as we
will not be splitting hashes in Ruby 3.
* If the keyword argument is required to fill a mandatory positional
argument, continue to do so, but emit a warning as this behavior will
be going away in Ruby 3.
* If keyword arguments are provided and the last argument is not a hash,
that indicates something wrong. This can happen if a cfunc is calling
rb_scan_args multiple times, and providing arguments that were not
passed to it from Ruby. Callers need to switch to the new
rb_scan_args_kw function, which allows passing of whether keywords
were provided.
This commit fixes all warnings caused by the changes above.
It switches some function calls to *_kw versions with appropriate
kw_splat flags. If delegating arguments, RB_PASS_CALLED_KEYWORDS
is used. If creating new arguments, RB_PASS_KEYWORDS is used if
the last argument is a hash to be treated as keywords.
In open_key_args in io.c, use rb_scan_args_kw.
In this case, the arguments provided come from another C
function, not Ruby. The last argument may or may not be a hash,
so we can't set keyword argument mode. However, if it is a
hash, we don't want to warn when treating it as keywords.
In Ruby files, make sure to appropriately use keyword splats
or literal keywords when calling Cfuncs that now issue keyword
argument separation warnings through rb_scan_args. Also, make
sure not to pass nil in place of an option hash.
Work around Kernel#warn warnings due to problems in the Rubygems
override of the method. There is an open pull request to fix
these issues in Rubygems, but part of the Rubygems tests for
their override fail on ruby-head due to rb_scan_args not
recognizing empty keyword splats, which this commit fixes.
Implementation wise, adding rb_scan_args_kw is kind of a pain,
because rb_scan_args takes a variable number of arguments.
In order to not duplicate all the code, the function internals need
to be split into two functions taking a va_list, and to avoid passing
in a ton of arguments, a single struct argument is used to handle
the variables previously local to the function.
This function was created as a variant of st_copy with firing write
barrier.
It should have more explicit name, such as st_copy_with_write_barrier.
But because it is used only for copying iv_tbl, so I rename it to
rb_iv_tbl_copy now. If we face other use case than iv_tbl, we may want
to rename it to more general name.
We can check the function pointer passed to rb_define_private_method
like how we do so in rb_define_method. Doing so revealed some
problematic usages of rb_obj_dummy. They had to be split according
to their arity.
We can check the function pointer passed to
rb_define_protected_method like how we do so in rb_define_method.
This changeset revealed no prototypes mismatches.
We can check the function pointer passed to rb_define_method_id
like how we do so in rb_define_method. This method is relatively
rarely used so there are less problems found than the other APIs.
We can check the function pointer passed to rb_define_global_function
like we do so in rb_define_method. It turns out that almost anybody
is misunderstanding the API.
We can check the function pointer passed to rb_define_module_function
like how we do so in rb_define_method. The difference is that this
changeset reveales lots of atiry mismatches.
The rb_define_method function takes a pointer to ANYARGS-ed functions,
which in fact varies 18 different prototypes. We still need to
preserve ANYARGS for storages but why not check the consistencies if
possible.
Q&As:
Q: Where did the magic number "18" came from in the description above?
A: Count the case branch of vm_method.c:call_cfunc_invoker_func().
Note also that the 18 branches has lasted for at least 25 years.
See also 200e0ee2fd.
Q: What is this __weakref__ thing?
A: That is a kind of function overloading mechanism that GCC provides.
In this case for instance rb_define_method0 is an alias of
rb_define_method, with a strong type.
Q: What is this __transparent_union__ thing?
A: That is another kind of function overloading mechanism that GCC
provides. In this case the attributed function pointer is either
VALUE(*)(int,VALUE*,VALUE) or VALUE(*)(int,const VALUE*,VALUE).
This is better than void* or ANYARGS because we can reject all
other possibilities than the two.
Q: What does this rb_define_method macro mean?
A: It selects appropriate alias of the rb_define_method function,
depending on the arity.
Q: Why the prototype change of rb_f_notimplement?
A: Function pointer to rb_f_notimplement is special cased in
vm_method.c:rb_add_method_cfunc(). That should be handled by the
__builtin_choose_expr chain inside of rb_define_method macro
expansion. In order to do so, comparison like (func ==
rb_f_notimplement) is inappropriate for __builtin_choose_expr's
expression (which must be a compile-time integer constant but the
address of rb_f_notimplement is not fixed until the linker). So
instead we are using __builtin_types_compatible_p, and in doing so
we need to distinguish rb_f_notimplement from others, by type.
Methods on duplicated class/module refer same constant inline
cache (IC). Constant access lookup should be done for cloned
class/modules but inline cache doesn't check it.
To check it, this patch introduce new RCLASS_CLONED flag which
are set when if class/module is cloned (both orig and dst).
[Bug #15877]
Same as last commit, make some fields `const`.
include/ruby/ruby.h:
* Rasic::klass
* RArray::heap::aux::shared_root
* RRegexp::src
internal.h:
* rb_classext_struct::origin_, redefined_class
* vm_svar::cref_or_me, lastline, backref, others
* vm_throw_data::throw_obj
* vm_ifunc::data
* MEMO::v1, v2, u3::value
While modifying this patch, I found write-barrier miss on
rb_classext_struct::redefined_class.
Also vm_throw_data::throw_state is only `int` so change the type.
* variable.c: make the hidden ivars `classpath` and `tmp_classpath` the source
of truth for module and constant names. Assign to them when modules are bind
to constants.
* variable.c: remove references to module name cache, as what used to be the cache
is now the source of truth. Remove rb_class_path_no_cache().
* variable.c: remove the hidden ivar `classid`. This existed for the purposes of
module name search, which is now replaced. Also, remove the associated
rb_name_class().
* class.c: use rb_set_class_path_string to set the name of Object during boot.
Must use a fstring as this runs before rb_cString is initialized and
creating a normal string leads to a VALUE without a class.
* spec/ruby/core/module/name_spec.rb: add a few specs to specify what happens
to Module#name across multiple operations. These specs pass without other
code changes in this commit.
[Feature #15765]
Before this commit, classes and modules would be registered with the
VM's `defined_module_hash`. The key was the ID of the class, but that
meant that it was possible for hash collisions to occur. The compactor
doesn't allow classes in the `defined_module_hash` to move, but if there
is a conflict, then it's possible a class would be removed from the hash
and not get pined.
This commit changes the key / value of the hash just to be the class
itself, thus preventing movement.
For some reason symbols (or classes) are being overridden in trunk
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67598 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit adds the new method `GC.compact` and compacting GC support.
Please see this issue for caveats:
https://bugs.ruby-lang.org/issues/15626
[Feature #15626]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67576 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Because hard to specify commits related to r67479 only.
So please commit again.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67499 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit adds the new method `GC.compact` and compacting GC support.
Please see this issue for caveats:
https://bugs.ruby-lang.org/issues/15626
[Feature #15626]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67479 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* hash.c, internal.h: support theap for small Hash.
Introduce RHASH_ARRAY (li_table) besides st_table and small Hash
(<=8 entries) are managed by an array data structure.
This array data can be managed by theap.
If st_table is needed, then converting array data to st_table data.
For st_table using code, we prepare "stlike" APIs which accepts hash value
and are very similar to st_ APIs.
This work is based on the GSoC achievement
by tacinight <tacingiht@gmail.com> and refined by ko1.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65454 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_keyword_error_new): use RARRAY_AREF() because
RARRAY_CONST_PTR() can introduce additional overhead in a futre.
Same fixes for other files.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65430 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Just refactoring. Despite its name, the function does NOT return a
boolean but raises an exception when the class given is frozen.
I don't think the new name "rb_class_modify_check" is the best, but
it follows the precedeint "rb_ary_modify_check", and is definitely
better than "*_p".
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64078 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
which has been developed by Takashi Kokubun <takashikkbn@gmail> as
YARV-MJIT. Many of its bugs are fixed by wanabe <s.wanabe@gmail.com>.
This JIT compiler is designed to be a safe migration path to introduce
JIT compiler to MRI. So this commit does not include any bytecode
changes or dynamic instruction modifications, which are done in original
MJIT.
This commit even strips off some aggressive optimizations from
YARV-MJIT, and thus it's slower than YARV-MJIT too. But it's still
fairly faster than Ruby 2.5 in some benchmarks (attached below).
Note that this JIT compiler passes `make test`, `make test-all`, `make
test-spec` without JIT, and even with JIT. Not only it's perfectly safe
with JIT disabled because it does not replace VM instructions unlike
MJIT, but also with JIT enabled it stably runs Ruby applications
including Rails applications.
I'm expecting this version as just "initial" JIT compiler. I have many
optimization ideas which are skipped for initial merging, and you may
easily replace this JIT compiler with a faster one by just replacing
mjit_compile.c. `mjit_compile` interface is designed for the purpose.
common.mk: update dependencies for mjit_compile.c.
internal.h: declare `rb_vm_insn_addr2insn` for MJIT.
vm.c: exclude some definitions if `-DMJIT_HEADER` is provided to
compiler. This avoids to include some functions which take a long time
to compile, e.g. vm_exec_core. Some of the purpose is achieved in
transform_mjit_header.rb (see `IGNORED_FUNCTIONS`) but others are
manually resolved for now. Load mjit_helper.h for MJIT header.
mjit_helper.h: New. This is a file used only by JIT-ed code. I'll
refactor `mjit_call_cfunc` later.
vm_eval.c: add some #ifdef switches to skip compiling some functions
like Init_vm_eval.
win32/mkexports.rb: export thread/ec functions, which are used by MJIT.
include/ruby/defines.h: add MJIT_FUNC_EXPORTED macro alis to clarify
that a function is exported only for MJIT.
array.c: export a function used by MJIT.
bignum.c: ditto.
class.c: ditto.
compile.c: ditto.
error.c: ditto.
gc.c: ditto.
hash.c: ditto.
iseq.c: ditto.
numeric.c: ditto.
object.c: ditto.
proc.c: ditto.
re.c: ditto.
st.c: ditto.
string.c: ditto.
thread.c: ditto.
variable.c: ditto.
vm_backtrace.c: ditto.
vm_insnhelper.c: ditto.
vm_method.c: ditto.
I would like to improve maintainability of function exports, but I
believe this way is acceptable as initial merging if we clarify the
new exports are for MJIT (so that we can use them as TODO list to fix)
and add unit tests to detect unresolved symbols.
I'll add unit tests of JIT compilations in succeeding commits.
Author: Takashi Kokubun <takashikkbn@gmail.com>
Contributor: wanabe <s.wanabe@gmail.com>
Part of [Feature #14235]
---
* Known issues
* Code generated by gcc is faster than clang. The benchmark may be worse
in macOS. Following benchmark result is provided by gcc w/ Linux.
* Performance is decreased when Google Chrome is running
* JIT can work on MinGW, but it doesn't improve performance at least
in short running benchmark.
* Currently it doesn't perform well with Rails. We'll try to fix this
before release.
---
* Benchmark reslts
Benchmarked with:
Intel 4.0GHz i7-4790K with 16GB memory under x86-64 Ubuntu 8 Cores
- 2.0.0-p0: Ruby 2.0.0-p0
- r62186: Ruby trunk (early 2.6.0), before MJIT changes
- JIT off: On this commit, but without `--jit` option
- JIT on: On this commit, and with `--jit` option
** Optcarrot fps
Benchmark: https://github.com/mame/optcarrot
| |2.0.0-p0 |r62186 |JIT off |JIT on |
|:--------|:--------|:--------|:--------|:--------|
|fps |37.32 |51.46 |51.31 |58.88 |
|vs 2.0.0 |1.00x |1.38x |1.37x |1.58x |
** MJIT benchmarks
Benchmark: https://github.com/benchmark-driver/mjit-benchmarks
(Original: https://github.com/vnmakarov/ruby/tree/rtl_mjit_branch/MJIT-benchmarks)
| |2.0.0-p0 |r62186 |JIT off |JIT on |
|:----------|:--------|:--------|:--------|:--------|
|aread |1.00 |1.09 |1.07 |2.19 |
|aref |1.00 |1.13 |1.11 |2.22 |
|aset |1.00 |1.50 |1.45 |2.64 |
|awrite |1.00 |1.17 |1.13 |2.20 |
|call |1.00 |1.29 |1.26 |2.02 |
|const2 |1.00 |1.10 |1.10 |2.19 |
|const |1.00 |1.11 |1.10 |2.19 |
|fannk |1.00 |1.04 |1.02 |1.00 |
|fib |1.00 |1.32 |1.31 |1.84 |
|ivread |1.00 |1.13 |1.12 |2.43 |
|ivwrite |1.00 |1.23 |1.21 |2.40 |
|mandelbrot |1.00 |1.13 |1.16 |1.28 |
|meteor |1.00 |2.97 |2.92 |3.17 |
|nbody |1.00 |1.17 |1.15 |1.49 |
|nest-ntimes|1.00 |1.22 |1.20 |1.39 |
|nest-while |1.00 |1.10 |1.10 |1.37 |
|norm |1.00 |1.18 |1.16 |1.24 |
|nsvb |1.00 |1.16 |1.16 |1.17 |
|red-black |1.00 |1.02 |0.99 |1.12 |
|sieve |1.00 |1.30 |1.28 |1.62 |
|trees |1.00 |1.14 |1.13 |1.19 |
|while |1.00 |1.12 |1.11 |2.41 |
** Discourse's script/bench.rb
Benchmark: https://github.com/discourse/discourse/blob/v1.8.7/script/bench.rb
NOTE: Rails performance was somehow a little degraded with JIT for now.
We should fix this.
(At least I know opt_aref is performing badly in JIT and I have an idea
to fix it. Please wait for the fix.)
*** JIT off
Your Results: (note for timings- percentile is first, duration is second in millisecs)
categories_admin:
50: 17
75: 18
90: 22
99: 29
home_admin:
50: 21
75: 21
90: 27
99: 40
topic_admin:
50: 17
75: 18
90: 22
99: 32
categories:
50: 35
75: 41
90: 43
99: 77
home:
50: 39
75: 46
90: 49
99: 95
topic:
50: 46
75: 52
90: 56
99: 101
*** JIT on
Your Results: (note for timings- percentile is first, duration is second in millisecs)
categories_admin:
50: 19
75: 21
90: 25
99: 33
home_admin:
50: 24
75: 26
90: 30
99: 35
topic_admin:
50: 19
75: 20
90: 25
99: 30
categories:
50: 40
75: 44
90: 48
99: 76
home:
50: 42
75: 48
90: 51
99: 89
topic:
50: 49
75: 55
90: 58
99: 99
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62197 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_scan_args), include/ruby/ruby.h (rb_scan_args_set):
return non-keywords elements only in the last hash when keyword
arguments are extracted from it, as well as methods defined in
ruby level. [ruby-core:82427] [Bug #13830]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59626 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_keyword_error_new): get rid of an intermediate
string and check if keys are symbols.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59622 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This hasn't been used since r36709 (2012-08-15)
("Kernel#inspect: improve consistency and do not call #to_s.")
and was never part of public API in include/ruby/
* class.c (rb_obj_basic_to_s_p): remove function
* internal.h (rb_obj_basic_to_s_p): remove declaration
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59208 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (ensure_includable): cannot include refinement
module, or the type and the class do not match.
[ruby-core:79632] [Bug #13236]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58083 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (ensure_includable): extract checks to include and
prepend.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58082 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_extract_keywords): keep the class of non-keyword
elements hash as the original. [ruby-core:77813] [Bug #12884]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57360 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_get_kwargs): when values are stored, corresponding
keys have been remove from the keyword hash, and the hash should
be empty in that case. [ruby-dev:49893] [Bug #13004]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (singleton_class_of): just copy FROZEN flag without
conditions.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56739 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_undef_methods_from): undefine methods defined in
super from klass.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56482 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* array.c, class.c: Fixed documentation where Fixnum was referred
directly to use Integer, as Fixnum and Bignum are now unified
into Integer and direct usage is deprecated. [Fix GH-1459]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56382 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This helps hit inline method caches more frequently. Before this
commit:
```
[aaron@TC ruby (trunk)]$ time ./ruby -v benchmark/bm_vm2_poly_singleton.rb
ruby 2.4.0dev (2016-09-12 trunk 56141) [x86_64-darwin15]
real 0m3.679s
user 0m3.632s
sys 0m0.022s
```
After this commit:
```
[aaron@TC ruby (trunk)]$ time ./ruby -v benchmark/bm_vm2_poly_singleton.rb
ruby 2.4.0dev (2016-09-12 trunk 56141) [x86_64-darwin15]
last_commit=Copy the serial number from the super class to the singleton class
real 0m2.246s
user 0m2.203s
sys 0m0.020s
```
[Feature #12364]
[ruby-core:75425]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56144 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (ins_methods_i, ins_methods_prot_i, ins_methods_priv_i),
(ins_methods_pub_i): check for each conditions to match.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56086 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (Init_class_hierarchy): prevent rb_cObject which is the
class tree root, from GC. [ruby-dev:49666] [Bug #12492]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55429 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
effect of `#undef rb_scan_args` the minimum.
* include/ruby/ruby.h (rb_scan_args): overwrite only if GCC and
optimized. Visual C++ 14 or later can compile it but make it
conservative.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55110 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This reverts "* include/ruby/ruby.h (rb_scan_args): don't use ALWAYS_INLINE with"
This rb_scan_args macro is GCCism.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55104 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_define_class, rb_define_class_id_under): raise
ArgumentError if super is 0, deprecated behavior which has been
warned long time.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@54015 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This further avoids class name resolution issues which came
about due to relying on hash table ordering before r53376.
Pre-caching the class name when it is never used raises memory
use, but the overall gain from moving away from st still gives
us a small gain. Reverting r53376 and this patch and testing with
"valgrind -v ./ruby -rrdoc -eexit" on x86 (32-bit) shows:
before:
in use at exit: 1,662,239 bytes in 25,286 blocks
total heap usage: 49,514 allocs, 24,228 frees, 6,005,561 bytes allocated
after, with this change:
in use at exit: 1,646,529 bytes in 24,572 blocks
total heap usage: 48,891 allocs, 24,319 frees, 6,003,921 bytes allocated
* class.c (Init_class_hierarchy): resolve name for rb_cObject ASAP
* object.c (rb_mod_const_set): move name resolution to rb_const_set
* variable.c (rb_const_set): do class resolution here
[ruby-core:72807] [Bug #11977]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53518 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* gc.c (internal_object_p): should not expose singleton classes
without a metaclass. based on patches by ko1 and shugo.
[Bug #11740]
* class.c (rb_singleton_class_object_p): added.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@53243 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* variable.c (rb_class_ivar_set): rename as class specific ivar
setter, and st_table is no longer involved.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52380 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Minor simplification; this will hopefully make future patches
for switching to id_table easier-to-review.
* internal.h (rb_st_insert_id_and_value): update prototype
* variable.c (rb_st_insert_id_and_value): reduce args
(find_class_path): adjust call for less args
(rb_ivar_set): ditto
(rb_cvar_set): ditto
* class.c (rb_singleton_class_attached): ditto
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52374 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
from an original class to a created (cloned) method entry.
* test/ruby/test_refinement.rb: add a test.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51728 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
(such as ST_CONTINUE) for enum rb_id_table_iterator_result.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51544 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
[Feature #11420]
This table only manage ID->VALUE table to reduce overhead of st.
Some functions prefixed rb_id_table_* are provided.
* id_table.c: implement rb_id_table_*.
There are several algorithms to implement it.
Now, there are roughly 4 types:
* st
* array
* hash (implemented by Yura Sokolov)
* mix of array and hash
The macro ID_TABLE_IMPL can choose implementation.
You can see detailes about them at the head of id_table.c.
At the default, I choose 34 (mix of list and hash).
This is not final decision.
Please report your suitable parameters or
your data structure.
* symbol.c: introduce rb_id_serial_t and rb_id_to_serial()
to represent ID by serial number.
* internal.h: use id_table for method tables.
* class.c, gc.c, marshal.c, vm.c, vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51541 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
All contents of previous rb_iseq_t is in rb_iseq_t::body.
Remove rb_iseq_t::self because rb_iseq_t is an object.
RubyVM::InstructionSequence is wrapper object points T_IMEMO/iseq.
So RubyVM::ISeq.of(something) method returns different wrapper
objects but they point the same T_IMEMO/iseq object.
This patch is big, but most of difference is replacement of
iseq->xxx to iseq->body->xxx.
(previous) rb_iseq_t::compile_data is also located to
rb_iseq_t::compile_data.
It was moved from rb_iseq_body::compile_data.
Now rb_iseq_t has empty two pointers.
I will split rb_iseq_body data into static data and dynamic data.
* compile.c: rename some functions/macros.
Now, we don't need to separate iseq and iseqval (only VALUE).
* eval.c (ruby_exec_internal): `n' is rb_iseq_t (T_IMEMO/iseq).
* ext/objspace/objspace.c (count_imemo_objects): count T_IMEMO/iseq.
* gc.c: check T_IMEMO/iseq.
* internal.h: add imemo_type::imemo_iseq.
* iseq.c: define RubyVM::InstructionSequnce as T_OBJECT.
Methods are implemented by functions named iseqw_....
* load.c (rb_load_internal0): rb_iseq_new_top() returns
rb_iseq_t (T_IMEMO/iesq).
* method.h (rb_add_method_iseq): accept rb_iseq_t (T_IMEMO/iseq).
* vm_core.h (GetISeqPtr): removed because it is not T_DATA now.
* vm_core.h (struct rb_iseq_body): remove padding for
[Bug #10037][ruby-core:63721].
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51327 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
clone iseq any more.
* class.c (clone_method): share iseq between cloned methods. All of
method dependent information are able to refer from method entry.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51171 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_control_frame_t::klass.
[Bug #11278], [Bug #11279]
rb_method_entry_t data belong to modules/classes.
rb_method_entry_t::owner points defined module or class.
module M
def foo; end
end
In this case, owner is M.
rb_callable_method_entry_t data belong to only classes.
For modules, MRI creates corresponding T_ICLASS internally.
rb_callable_method_entry_t can also belong to T_ICLASS.
rb_callable_method_entry_t::defined_class points T_CLASS or
T_ICLASS.
rb_method_entry_t data for classes (not for modules) are also
rb_callable_method_entry_t data because it is completely same data.
In this case, rb_method_entry_t::owner == rb_method_entry_t::defined_class.
For example, there are classes C and D, and incldues M,
class C; include M; end
class D; include M; end
then, two T_ICLASS objects for C's super class and D's super class
will be created.
When C.new.foo is called, then M#foo is searcheed and
rb_callable_method_t data is used by VM to invoke M#foo.
rb_method_entry_t data is only one for M#foo.
However, rb_callable_method_entry_t data are two (and can be more).
It is proportional to the number of including (and prepending)
classes (the number of T_ICLASS which point to the module).
Now, created rb_callable_method_entry_t are collected when
the original module M was modified. We can think it is a cache.
We need to select what kind of method entry data is needed.
To operate definition, then you need to use rb_method_entry_t.
You can access them by the following functions.
* rb_method_entry(VALUE klass, ID id);
* rb_method_entry_with_refinements(VALUE klass, ID id);
* rb_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method(VALUE refinements, const rb_method_entry_t *me);
To invoke methods, then you need to use rb_callable_method_entry_t
which you can get by the following APIs corresponding to the
above listed functions.
* rb_callable_method_entry(VALUE klass, ID id);
* rb_callable_method_entry_with_refinements(VALUE klass, ID id);
* rb_callable_method_entry_without_refinements(VALUE klass, ID id);
* rb_resolve_refined_method_callable(VALUE refinements, const rb_callable_method_entry_t *me);
VM pushes rb_callable_method_entry_t, so that rb_vm_frame_method_entry()
returns rb_callable_method_entry_t.
You can check a super class of current method by
rb_callable_method_entry_t::defined_class.
* method.h: renamed from rb_method_entry_t::klass to
rb_method_entry_t::owner.
* internal.h: add rb_classext_struct::callable_m_tbl to cache
rb_callable_method_entry_t data.
We need to consider abotu this field again because it is only
active for T_ICLASS.
* class.c (method_entry_i): ditto.
* class.c (rb_define_attr): rb_method_entry() does not takes
defiend_class_ptr.
* gc.c (mark_method_entry): mark RCLASS_CALLABLE_M_TBL() for T_ICLASS.
* cont.c (fiber_init): rb_control_frame_t::klass is removed.
* proc.c: fix `struct METHOD' data structure because
rb_callable_method_t has all information.
* vm_core.h: remove several fields.
* rb_control_frame_t::klass.
* rb_block_t::klass.
And catch up changes.
* eval.c: catch up changes.
* gc.c: ditto.
* insns.def: ditto.
* vm.c: ditto.
* vm_args.c: ditto.
* vm_backtrace.c: ditto.
* vm_dump.c: ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This simplifies all the callers and makes code easier to use
and review. I was confused about the need for RB_GC_GUARD
in define_{aset,aref}_method of struct.c without reading
rb_add_method_iseq.
Likewise, do the same for rb_iseq_clone, where the GC guard
only seems neccesary iff RGenGC is disabled.
* vm_method.c (rb_add_method_iseq): add RB_GC_GUARD
* class.c (clone_method): remove RB_GC_GUARD
* struct.c (define_aref_method): ditto
(define_aset_method): ditto
* vm.c (vm_define_method):
* iseq.c (rb_iseq_clone): add RB_GC_GUARD
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51079 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_check_inheritable): preserve encoding in an error
message when the superclass is not a class.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51050 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* class.c (rb_define_class_id_under): raise TypeError exception
same as ruby level class definition when superclass mismatch.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51048 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
rb_method_entry_t.
r50728 changed sharing `def's to isolating `def's
on alias and so on. However, this change conflicts
future improvement plan. So I change back to sharing approach.
* method.h: move rb_method_definition_t::flags to
rb_method_entry_t::attr::flags.
rb_method_entry_t::attr is union with VALUE because this field
should have same size of VALUE. rb_method_entry_t is T_IMEMO).
And also add the following access macros to it's fileds.
* METHOD_ENTRY_VISI(me)
* METHOD_ENTRY_BASIC(me)
* METHOD_ENTRY_SAFE(me)
* vm_method.c (rb_method_definition_addref): added instead of
rb_method_definition_clone().
Do not create new definition, but increment alias_count.
* class.c (clone_method): catch up this fix.
* class.c (method_entry_i): ditto.
* proc.c (mnew_internal): ditto.
* proc.c (mnew_missing): ditto.
* vm_eval.c: ditto.
* vm_insnhelper.c: ditto.
* vm_method.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50792 b2dd03c8-39d4-4d8f-98ff-823fe69b080e