Age | Commit message (Collapse) | Author |
---|
| 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://.com/ruby/ruby/pull/2629 |
| Apply __attribute__((__returns_nonnull__)) when available. |
| malloc can fail. Should treat such situations. |
| |
| This reverts commit 54eb51d72bc43f90b595f0d7ffb5069ebf1a56d9. Windows build failure. See also https://.com/ruby/ruby/runs/278718805 |
| |
| Previously this was restricted to only gcc because of the GCC_VERSION_SINCE check (which explicitly excludes clang). GCC 3.3.0 is quite old so I feel relatively safe assuming that all reasonable versions of clang support this. Notes: Merged: https://.com/ruby/ruby/pull/2628 |
| Replacing adjacent struct rb_call_info and struct rb_call_cache into a struct rb_call_data. |
| Requested by ko1 that ability of calling rb_raise from anywhere outside of GVL is "too much". Give up that part, move the GVL aquisition routine into gc.c, and make our new gc_raise(). |
| This changeset basically replaces `ruby_xmalloc(x * y)` into `ruby_xmalloc2(x, y)`. Some convenient functions are also provided for instance `rb_xmalloc_mul_add(x, y, z)` which allocates x * y + z byes. Notes: Merged: https://.com/ruby/ruby/pull/2540 |
| Make them gcc friendly. Note that realloc canot be __malloc__ attributed, according to the GCC manual. Notes: Merged: https://.com/ruby/ruby/pull/2540 |
| Seems nobody has actually used this macro. Such an obvious typo. Notes: Merged: https://.com/ruby/ruby/pull/2540 |
| This function has been used wrongly always at first, "allocate a buffer then wrap it with tmpbuf". This order can cause a memory , as tmpbuf creation also can raise a NoMemoryError exception. The right order is "create a tmpbuf then allocate&wrap a buffer". So the argument of this function is rather harmful than just useless. TODO: * Rename this function to more proper name, as it is not used "temporary" (function local) purpose. * Allocate and wrap at once safely, like `ALLOCV`. |
| The parser needs to determine whether a local varaiable is defined or not in outer scope. For the sake, "base_block" field has kept the outer block. However, the whole block was actually unneeded; the parser used only base_block->iseq. So, this change lets parser_params have the iseq directly, instead of the whole block. Notes: Merged: https://.com/ruby/ruby/pull/2519 |
| 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 ``` |
| At last, not only myself but also your compiler are fully confident that the method entries pointed from call caches are immutable. We don't have to worry about silent updates. Just delete the branch that is now always false. Calculating ------------------------------------- ours trunk vm2_poly_same_method 2.142M 2.070M i/s - 6.000M times in 2.801148s 2.898994s Comparison: vm2_poly_same_method ours: 2141979.2 i/s trunk: 2069683.8 i/s - 1.03x slower Notes: Merged: https://.com/ruby/ruby/pull/2486 |
| We are calling this in a few other files, it is better to have it in a header than adding s to the other files. Notes: Merged: https://.com/ruby/ruby/pull/2491 |
| 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://.com/ruby/ruby/pull/2477 |
| 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. Notes: Merged-By: jeremyevans <[email protected]> |
| 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. |
| When Object#to_enum is passed a block, the block is called to get a size with the arguments given to to_enum. This calls the block with the same keyword flag as to_enum is called with. This requires adding rb_check_funcall_kw and rb_check_funcall_default_kw to handle keyword flags. |
| 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. |
| I noticed that in case of cache misshit, re-calculated cc->me can be the same method entry than the pevious one. That is an okay situation but can't we partially reuse the cache, because cc->call should still be valid then? One thing that has to be special-cased is when the method entry gets amended by some refinements. That happens behind-the-scene of call cache mechanism. We have to check if cc->me->def points to the previously saved one. Calculating ------------------------------------- trunk ours vm2_poly_same_method 1.534M 2.025M i/s - 6.000M times in 3.910203s 2.962752s Comparison: vm2_poly_same_method ours: 2025143.9 i/s trunk: 1534447.2 i/s - 1.32x slower Notes: Merged: https://.com/ruby/ruby/pull/2468 |
| Remove rb_add_empty_keyword, and instead of calling that every place you need to add empty keyword hashes, run that code in a single static function in vm_eval.c. Add 4 defines to include/ruby/ruby.h, these are to be used as int kw_splat values when calling the various rb_*_kw functions: RB_NO_KEYWORDS :: Do not pass keywords RB_PASS_KEYWORDS :: Pass final argument (which should be hash) as keywords RB_PASS_EMPTY_KEYWORDS :: Add an empty hash to arguments and pass as keywords RB_PASS_CALLED_KEYWORDS :: Passes same keyword type as current method was called with (for method delegation) rb_empty_keyword_given_p needs to stay. It is required if argument delegation is done but delayed to a later point, which Enumerator does. Use RB_PASS_CALLED_KEYWORDS in rb_call_super to correctly delegate keyword arguments to super method. |
| "GCC diagnostic push/pop" seems appeared at gcc 4.6. |
| Method#call, UnboundMethod#bind_call Also add keyword argument separation warnings for Class#new and Method#call. To allow for keyword argument to required positional hash converstion in cfuncs, add a vm frame flag indicating the cfunc was called with an empty keyword hash (which was removed before calling the cfunc). The cfunc can check this frame flag and add back an empty hash if it is passing its arguments to another Ruby method. Add rb_empty_keyword_given_p function for checking if called with an empty keyword hash, and rb_add_empty_keyword for adding back an empty hash to argv. All of this empty keyword argument support is only for 2.7. It will be removed in 3.0 as Ruby 3 will not convert empty keyword arguments to required positional hash arguments. Comment all of the relevent code to make it obvious this is expected to be removed. Add rb_funcallv_kw as an public C-API function, just like rb_funcallv but with a keyword flag. This is used by rb_obj_call_init (internals of Class#new). This also required expected call_type enum with CALL_FCALL_KW, similar to the recent addition of CALL_PUBLIC_KW. Add rb_vm_call_kw as a internal function, used by call_method_data (internals of Method#call and UnboundMethod#bind_call). Add tests for UnboundMethod#bind_call keyword handling. Notes: Merged: https://.com/ruby/ruby/pull/2432 |
| Make rb_sym_proc_call take a flag for whether a keyword argument is used, and use the new rb_funcall_with_block_kw function to pass that information. |
| Requested by ko1. Also, because now that this function is internal use only, why not just directly use struct rb_call_cache to purge the ZALLOC. |
| This fixes MJIT after rb_hash_stlike_foreach used vm_args.c. Notes: Merged: https://.com/ruby/ruby/pull/2395 |
| Treat the ** syntax as passing a copy of the hash as the last positional argument. If the hash being double splatted is empty, do not add a positional argument. Remove rb_no_keyword_hash, no longer needed. Notes: Merged: https://.com/ruby/ruby/pull/2395 |
| And, allow non-symbol keys as a keyword arugment Notes: Merged: https://.com/ruby/ruby/pull/2395 |
| After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. This function has only one call site so adding appropriate is trivial. |
| After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. There is only one usage of MEMO::u3::func in load.c (where void Init_Foobar(vodi) is registered) so why not just be explicit. |
| After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. This commit adds function s for rb_hash_foreach / st_foreach_safe. Also fixes some mismatches. |
| After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. This commit deletes ANYARGS from rb_ensure, which also revealed many arity / type mismatches. |
| After 5e86b005c0f2ef30df2f9906c7e2f3abefe286a2, I now think ANYARGS is dangerous and should be extinct. This commit deletes ANYARGS from struct vm_ifunc, but in doing so we also have to decouple the usage of this struct in compile.c, which (I think) is an abuse of ANYARGS. |
| Ko1 missed this in d5893b91faa7dc77ca6c9728d1054dabd757aead. |
| rp() macro for debug also shows file location and function name such as: [OBJ_INFO:[email protected]:73] 0x000056147741b248 ... Notes: Merged-By: ko1 |
| And pass rb_execution_context_t as an argument. |
| |
| debug utility macro rp() (rp_m()) and bp() are introduced. * rp(obj) shows obj information w/o any side-effect to STDERR. * rp_m(m, obj) is similar to rp(obj), but show m before. * bp() is alias of ruby_debug_breakpoint(), which is registered as a breakpoint in run.gdb (used by `make gdb` or make gdb-ruby`). |
| 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 introduce new RCLASS_CLONED flag which are set when if class/module is cloned (both orig and dst). [Bug #15877] |
| Inspired by 346aa557b31fe96760e505d30da26eb7a846bac9 Closes: https://.com/ruby/ruby/pull/2321 |
| # Benchmark zero? ``` require 'benchmark/ips' Numeric.class_eval do def ruby_zero? self == 0 end end Benchmark.ips do |x| x.report('0.zero?') { 0.ruby_zero? } x.report('1.zero?') { 1.ruby_zero? } x.compare! end ``` ## VM No significant impact for VM. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) [x86_64-linux] 0.zero?: 21855445.5 i/s 1.zero?: 21770817.3 i/s - same-ish: difference falls within error ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] 1.zero?: 21958912.3 i/s 0.zero?: 21881625.9 i/s - same-ish: difference falls within error ## JIT The performance improves about 1.23x. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) +JIT [x86_64-linux] 0.zero?: 36343111.6 i/s 1.zero?: 36295153.3 i/s - same-ish: difference falls within error ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] 0.zero?: 44740467.2 i/s 1.zero?: 44363616.1 i/s - same-ish: difference falls within error # Benchmark str == str / str != str ``` # frozen_string_literal: true require 'benchmark/ips' Benchmark.ips do |x| x.report('a == a') { 'a' == 'a' } x.report('a == b') { 'a' == 'b' } x.report('a != a') { 'a' != 'a' } x.report('a != b') { 'a' != 'b' } x.compare! end ``` ## VM No significant impact for VM. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) [x86_64-linux] a == a: 27286219.0 i/s a != a: 24892389.5 i/s - 1.10x slower a == b: 23623635.8 i/s - 1.16x slower a != b: 21800958.0 i/s - 1.25x slower ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) [x86_64-linux] a == a: 27224016.2 i/s a != a: 24490109.5 i/s - 1.11x slower a == b: 23391052.4 i/s - 1.16x slower a != b: 21811321.7 i/s - 1.25x slower ## JIT The performance improves on JIT a little. ### before ruby 2.7.0dev (2019-08-04T02:56:02Z master 2d8c037e97) +JIT [x86_64-linux] a == a: 42010674.7 i/s a != a: 38920311.2 i/s - same-ish: difference falls within error a == b: 32574262.2 i/s - 1.29x slower a != b: 32099790.3 i/s - 1.31x slower ### after ruby 2.7.0dev (2019-08-04T11:17:10Z opt-eq-leaf 6404bebd6a) +JIT [x86_64-linux] a == a: 46902738.8 i/s a != a: 43097258.6 i/s - 1.09x slower a == b: 35822018.4 i/s - 1.31x slower a != b: 33377257.8 i/s - 1.41x slower This is needed towards Bug#15589. Closes: https://.com/ruby/ruby/pull/2318 |
| |
| Hash hint for ar_array is 1 byte (unsigned char). This introduce ar_hint_t which represents hint type. |
| 13e84d5c0a changes enum to macro, but the flags usage information are lost in internal.h. It should be same place with other flags information. |
| Get rid of "ISO C restricts enumerator values to range of 'int'" error. |
| On ar_table, Do not keep a full-length hash value (FLHV, 8 bytes) but keep a 1 byte hint from a FLHV (lowest byte of FLHV). An ar_table only contains at least 8 entries, so hints consumes 8 bytes at most. We can store hints in RHash::ar_hint. On 32bit CPU, we use 4 entries ar_table. The advantages: * We don't need to keep FLHV so ar_table only consumes 16 bytes (VALUEs of key and value) * 8 entries = 128 bytes. * We don't need to scan ar_table, but only need to check hints in many cases. Especially we don't need to access ar_table if there is no match entries (in many cases). It will increase memory cache locality. The disadvantages: * This technique can increase `#eql?` time because hints can conflicts (in theory, it conflicts once in 256 times). It can introduce incompatibility if there is a object x where x.eql? returns true even if hash values are different. I believe we don't need to care such irregular case. * We need to re-calculate FLHV if we need to switch from ar_table to st_table (e.g. exceeds 8 entries). It also can introduce incompatibility, on mutating key objects. I believe we don't need to care such irregular case too. Add new debug counters to measure the performance: * artable_hint_hit - hint is matched and eql?#=>true * artable_hint_miss - hint is not matched but eql?#=>false * artable_hint_notfound - lookup counts |
| iter_lev is used to detect the hash is iterating or not. Usually, iter_lev should be very small number (1 or 2) so `int` is overkill. This introduce iter_lev in flags (7 bits, FL13 to FL19) and if iter_lev exceeds this range, save it in hidden attribute. We can get 1 word in RHash. We can't modify frozen objects. Therefore I added new internal API `rb_ivar_set_internal()` which allows us to set an attribute even if the target object is frozen if the name is hidden ivar (the name without `@` prefix). |