summaryrefslogtreecommitdiff
path: root/vm_method.c
AgeCommit message (Collapse)Author
2020-02-22Introduce disposable call-cache.Koichi Sasada
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. Notes: Merged: https://github.com/ruby/ruby/pull/2888
2020-02-22VALUE size packed callinfo (ci).Koichi Sasada
Now, rb_call_info contains how to call the method with tuple of (mid, orig_argc, flags, kwarg). Most of cases, kwarg == NULL and mid+argc+flags only requires 64bits. So this patch packed rb_call_info to VALUE (1 word) on such cases. If we can not represent it in VALUE, then use imemo_callinfo which contains conventional callinfo (rb_callinfo, renamed from rb_call_info). iseq->body->ci_kw_size is removed because all of callinfo is VALUE size (packed ci or a pointer to imemo_callinfo). To access ci information, we need to use these functions: vm_ci_mid(ci), _flag(ci), _argc(ci), _kwarg(ci). struct rb_call_info_kw_arg is renamed to rb_callinfo_kwarg. rb_funcallv_with_cc() and rb_method_basic_definition_p_with_cc() is temporary removed because cd->ci should be marked. Notes: Merged: https://github.com/ruby/ruby/pull/2888
2020-02-20suppress clang warnings卜部昌平
Starting clang 11, casts between pointer and (narrower-than-pointer) int are now warned. However all such thing in our repository are guaranteed safe. Let's suppress the warnings.
2020-01-21VALUE is narrower than rb_serial_t卜部昌平
VALUE and rb_serial_t do not agree with their width. We have to be consistent. Assigning an rb_serial_t value to a VALUE variable is practically a problem on a ILP32 environment.
2020-01-02Check Module#ruby2_keywords arityNobuyoshi Nakada
It is considered a mistake, because calling this method with no arguments has no effect. Notes: Merged: https://github.com/ruby/ruby/pull/2806
2019-12-18per-method serial number卜部昌平
Methods and their definitions can be allocated/deallocated on-the-fly. One pathological situation is when a method is deallocated then another one is allocated immediately after that. Address of those old/new method entries/definitions can be the same then, depending on underlying malloc/free implementation. So pointer comparison is insufficient. We have to check the contents. To do so we introduce def->method_serial, which is an integer unique to that specific method definition. PS: Note that method_serial being uintptr_t rather than rb_serial_t is intentional. This is because rb_serial_t can be bigger than a pointer on a 32bit system (rb_serial_t is at least 64bit). In order to preserve old packing of struct rb_call_cache, rb_serial_t is inappropriate. Notes: Merged: https://github.com/ruby/ruby/pull/2759
2019-12-17Skip optimized method check for most method IDsJohn Hawthorn
Previously every time a method was defined on a module, we would recursively walk all subclasses to see if the module was included in a class which the VM optimizes for (such as Integer#+). For most method definitions we can tell immediately that this won't be the case based on the method's name. To do this we just keep a hash with method IDs of optimized methods and if our new method isn't in that list we don't need to check subclasses at all. Notes: Merged: https://github.com/ruby/ruby/pull/2752
2019-12-17Replace debug test with assertionJohn Hawthorn
It's a Ruby bug if this ever happens check it as an assertion instead of paying the cost of the check every time. Notes: Merged: https://github.com/ruby/ruby/pull/2752
2019-12-17Check type with BUILTIN_TYPE in method cache clearJohn Hawthorn
We know that this is a heap-allocated object (a CLASS, MODULE, or ICLASS) so we don't need to check if it is an immediate value. This should be very slightly faster. Notes: Merged: https://github.com/ruby/ruby/pull/2752
2019-12-17Define PREV_CLASS_SERIALJohn Hawthorn
Avoids genereating a "throwaway" sentinel class serial. There wasn't any read harm in doing so (we're at no risk of exhaustion and there'd be no measurable performance impact), but if feels cleaner that all class serials actually end up assigned and used (especially now that we won't overwrite them in a single method definition). Notes: Merged: https://github.com/ruby/ruby/pull/2752
2019-12-17Avoid revisiting seen nodes clearing method cacheJohn Hawthorn
rb_clear_method_cache_by_class calls rb_class_clear_method_cache recursively on subclasses, where it will bump the class serial and clear some other data (callable_m_tbl, and some mjit data). Previously this could end up taking a long time to clear all the classes if the module was included a few levels deep and especially if there were multiple paths to it in the dependency tree (ie. a class includes two modules which both include the same other module) as we end up revisiting class/iclass/module objects multiple times. This commit avoids revisiting the same object, by short circuiting when revisit the same object. We can check this efficiently by comparing the class serial of each object we visit with the next class serial at the start. We know that any objects with a higher class serial have already been visited. Notes: Merged: https://github.com/ruby/ruby/pull/2752
2019-11-29vm_method.c: add top-level ruby2_keywordsYusuke Endoh
This is a top-level version of Module#ruby2_keywords. It can be used for functions (top-level methods) that delegates arguments. [Feature #16364]
2019-11-27Update documentation for ruby2_keywords [ci skip]Jeremy Evans
2019-11-19make functions static卜部昌平
These functions are used from within a compilation unit so we can make them static, for better binary size. This changeset reduces the size of generated ruby binary from 26,590,128 bytes to 26,584,472 bytes on my macihne. Notes: Merged: https://github.com/ruby/ruby/pull/2682
2019-11-05rb_method_basic_definition_p with CC卜部昌平
Noticed that rb_method_basic_definition_p is frequently called. Its callers include vm_caller_setup_args_block(), rb_hash_default_value(), rb_num_neative_int_p(), and a lot more. It seems worth caching the method resolution part. Majority of rb_method_basic_definion_p() usages take fixed class and fixed method id combinations. Calculating ------------------------------------- ours trunk so_matrix 2.379 2.115 i/s - 1.000 times in 0.420409s 0.472879s Comparison: so_matrix ours: 2.4 i/s trunk: 2.1 i/s - 1.12x slower Notes: Merged: https://github.com/ruby/ruby/pull/2629
2019-10-16Warn for calling public/protected/private/module_function without arguments ↵Jeremy Evans
inside method Calling these methods without an argument does not have the desired effect inside a method. Fixes [Bug #13249] Notes: Merged: https://github.com/ruby/ruby/pull/2562
2019-10-07Allow ruby2_keywords to be used with bmethodsJeremy Evans
There are libraries that use define_method with argument splats where they would like to pass keywords through the method. To more easily allow such libraries to use ruby2_keywords to handle backwards compatibility, it is necessary for ruby2_keywords to support bmethods. Notes: Merged: https://github.com/ruby/ruby/pull/2532
2019-10-03Revert https://github.com/ruby/ruby/pull/2486卜部昌平
This reverts commits: 10d6a3aca7 8ba48c1b85 fba8627dc1 dd883de5ba 6c6a25feca 167e6b48f1 7cb96d41a5 3207979278 595b3c4fdd 1521f7cf89 c11c5e69ac cf33608203 3632a812c0 f56506be0d 86427a3219 . 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 ```
2019-09-30rb_method_attr_t::location should be 0 or others.Koichi Sasada
method_def_location() expects that rb_method_attr_t::location is 0 (Qfalse) or not.
2019-09-30refactor constify most of rb_method_entry_t卜部昌平
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. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor add rb_method_entry_from_template卜部昌平
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. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor reduce METHOD_ENTRY_FLAGS_COPY卜部昌平
Make things more immutable. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor delete rb_method_entry_copy卜部昌平
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. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor delete rb_method_definition_set卜部昌平
Instead of destructively write fields of method entries, create a new entry and let it overwrite its owner. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor rb_method_definition_create take opts卜部昌平
Before this changeset rb_method_definition_create only allocated a memory region and we had to destructively initialize it later. That is not a good design so we change the API to return a complete struct instead. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor split rb_method_definition_set卜部昌平
Did you know that C functions can return structs? That has been true since the beginning, but not that very useful until C99. Now that we can write compound literals, this feature is much easier to use. By allowing struct-returning functions, some formerly big functions can be split into smaller ones, like this changeset. At least GCC is smart enough to inline the split functions back into one. No performance penalty is observed. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor constify most of rb_method_definition_t卜部昌平
Most (if not all) of the fields of rb_method_definition_t are never meant to be modified once after they are stored. Marking them const makes it possible for compilers to warn on unintended modifications. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-30refactor delete METHOD_ENTRY_COMPLEMENTED flag卜部昌平
Because rb_method_definition_t tracks its own complemented_count, we no longer have to check it in rb_method_entry_t side. Notes: Merged: https://github.com/ruby/ruby/pull/2486
2019-09-25Add Module#ruby2_keywords for passing keywords through regular argument splatsJeremy Evans
This approach uses a flag bit on the final hash object in the regular splat, as opposed to a previous approach that used a VM frame flag. The hash flag approach is less invasive, and handles some cases that the VM frame flag approach does not, such as saving the argument splat array and splatting it later: ruby2_keywords def foo(*args) @args = args bar end def bar baz(*@args) end def baz(*args, **kw) [args, kw] end foo(a:1) #=> [[], {a: 1}] foo({a: 1}, **{}) #=> [[{a: 1}], {}] foo({a: 1}) #=> 2.7: [[], {a: 1}] # and warning foo({a: 1}) #=> 3.0: [[{a: 1}], {}] It doesn't handle some cases that the VM frame flag handles, such as when the final hash object is replaced using Hash#merge, but those cases are probably less common and are unlikely to properly support keyword argument separation. Use ruby2_keywords to handle argument delegation in the delegate library. Notes: Merged: https://github.com/ruby/ruby/pull/2477
2019-09-20Call rb_vm_call_kw insted of rb_vm_call0 in a few casesJeremy Evans
rb_vm_call_kw handles the tmp buffer for you. Also, change method_missing so it also calls rb_vm_call_kw to handle the kw_splat flag, instead of requiring callers to handle kw_splat flag before calling method_missing. This may fix other cases where method_missing is currently called without the kw_splat being handled.
2019-09-20Make passing empty keywords to dig pass empty keywords to next dig methodJeremy Evans
If defined in Ruby, dig would be defined as def dig(arg, *rest) end, it would not use keywords. If the last dig argument was an empty hash, it could be treated as keyword arguments by the next dig method. Allow dig to pass along the empty keyword flag if called with an empty keyword, to suppress the previous behavior and force treating the hash as a positional argument and not keywords. Also handle the case where dig calls method_missing, passing the empty keyword flag to that as well. This requires adding rb_check_funcall_with_hook_kw functions, so that dig can specify how arguments are treated. It also adds kw_splat arguments to a couple static functions.
2019-09-05Add rb_funcall_with_block_kwJeremy Evans
This is needed for C functions to call methods with keyword arguments. This is a copy of rb_funcall_with_block with an extra argument for the keyword flag. There isn't a clean way to implement this that doesn't involve changing a lot of function signatures, because rb_call doesn't support a way to mark that the call has keyword arguments. So hack this in using a CALL_PUBLIC_KW call_type, which we switch for CALL_PUBLIC later in the call stack. We do need to modify rm_vm_call0 to take an argument for whether keyword arguments are used, since the call_type is no longer available at that point. Use the passed in value to set the appropriate keyword flag in both calling and ci_entry.
2019-08-29drop-in type check for rb_define_private_method卜部昌平
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.
2019-08-29drop-in type check for rb_define_method卜部昌平
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 200e0ee2fd3c1c006c528874a88f684447215524. 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.
2019-08-18Ensure non-OPT_GLOBAL_METHOD_CACHE code validNobuyoshi Nakada
2019-08-18Ensure VM_DEBUG_VERIFY_METHOD_CACHE code validNobuyoshi Nakada
2019-08-01Make attr* methods define public methods if self in caller is not same as ↵Jeremy Evans
receiver Previously, attr* methods could be private even if not in the private section of a class/module block. This uses the same approach that ruby started using for define_method in 1fc33199736f316dd71d0c551edbf514528ddde6. Fixes [Bug #4537]
2019-04-10* expand tabs.svn
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67500 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-10Reverting all commits from r67479 to r67496 because of CI failureskazu
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
2019-04-10vm_method.c: fix a warningnobu
* vm_method.c (rb_add_method_iseq): use rb_method_iseq_t, as rb_method_definition_set refers, with a cast to suppress a warning. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67494 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-09Adding `GC.compact` and compacting GC support.tenderlove
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
2019-04-05`rb_add_method` is void function.ko1
* method.h (rb_add_method): make it void function because nobody use a return value. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67444 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-05* expand tabs.svn
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67443 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-05add definemethod/definesmethod insn.ko1
* insns.def: add definemethod and definesmethod (singleton method) instructions. Old YARV contains these instructions, but it is moved to methods of FrozenCore class because remove number of instructions can improve performance for some techniques (static stack caching and so on). However, we don't employ these technique and it is hard to optimize/analysis definition sequence. So I decide to introduce them (and remove definition methods). `putiseq` insn is also removed. * vm_method.c (rb_scope_visibility_get): renamed to `vm_scope_visibility_get()` and make it accept `ec`. Same for `vm_scope_module_func_check()`. These fixes are result of refactoring `vm_define_method`. * vm_insnhelper.c (rb_vm_get_cref): renamed to `vm_get_cref` because of consistency with other functions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67442 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-28[DOC] Fix method references to Method instance methodsnobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67355 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-28[DOC] fix markups [ci skip]nobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67354 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-02-22change `cfunc->invoker` type for opt.ko1
* vm_insnhelper.c: change `call_cfunc_*` parameters order and specify a function type for the passed func ptr. This fix reduce the number of asm instructions, such as: # before this patch 0000000000000110 <call_cfunc_0>: 110: 48 89 fa mov %rdi,%rdx 113: 31 c0 xor %eax,%eax 115: 48 89 f7 mov %rsi,%rdi 118: ff e2 jmpq *%rdx 11a: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) # after this patch 0000000000000110 <call_cfunc_0>: 110: ff e1 jmpq *%rcx However, this kind of instruction reduction doesn't affect any performance because of great CPU architectures :p git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67122 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-28Add refinements support to method/instance_method.nobu
[Fix GH-2034] From: manga_osyo <manga.osyo@gmail.com> git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66935 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-09Fix styles [ci skip]nobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66762 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-18Constified to fix warning at r66442nobu
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66445 b2dd03c8-39d4-4d8f-98ff-823fe69b080e