summaryrefslogtreecommitdiff
path: root/vm_args.c
Commit message (Collapse)AuthorAgeFilesLines
* `Hash#dup` for kwsplat argumentsKoichi Sasada2023-03-151-3/+17
| | | | | | | On `f(*a, **kw)` method calls, a rest keyword parameter is identically same Hash object is passed and it should make `#dup`ed Hahs. fix https://bugs.ruby-lang.org/issues/19526
* Stop exporting symbols for MJITTakashi Kokubun2023-03-061-3/+0
|
* Change bytecode of `f(*a, **kw)`Koichi Sasada2023-03-061-73/+55
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `f(*a, **kw)` is compiled to `f([*a, kw])` but it makes an dummy array, so change it to pass two arguments `a` and `kw` with calling flags. ``` ruby 3.2.0 (2022-12-29 revision a7d467a792) [x86_64-linux] Calculating ------------------------------------- foo() 15.354M (± 4.2%) i/s - 77.295M in 5.043650s dele() 13.439M (± 3.9%) i/s - 67.109M in 5.001974s dele(*) 6.265M (± 4.5%) i/s - 31.730M in 5.075649s dele(*a) 6.286M (± 3.3%) i/s - 31.719M in 5.051516s dele(*a, **kw) 1.926M (± 4.5%) i/s - 9.753M in 5.076487s dele(*, **) 1.927M (± 4.2%) i/s - 9.710M in 5.048224s dele(...) 5.871M (± 3.9%) i/s - 29.471M in 5.028023s forwardable 4.969M (± 4.1%) i/s - 25.233M in 5.087498s ruby 3.3.0dev (2023-01-13T01:28:00Z master 7e8802fa5b) [x86_64-linux] Calculating ------------------------------------- foo() 16.354M (± 4.7%) i/s - 81.799M in 5.014561s dele() 14.256M (± 3.5%) i/s - 71.656M in 5.032883s dele(*) 6.701M (± 3.8%) i/s - 33.948M in 5.074938s dele(*a) 6.681M (± 3.3%) i/s - 33.578M in 5.031720s dele(*a, **kw) 4.200M (± 4.4%) i/s - 21.258M in 5.072583s dele(*, **) 4.197M (± 5.3%) i/s - 21.322M in 5.096684s dele(...) 6.039M (± 6.8%) i/s - 30.355M in 5.052662s forwardable 4.788M (± 3.2%) i/s - 24.033M in 5.024875s ```
* Using UNDEF_P macroS-H-GAMELINKS2022-11-161-3/+3
|
* Rename rb_ary_tmp_new to rb_ary_hidden_newPeter Zhu2022-07-261-3/+3
| | | | | | rb_ary_tmp_new suggests that the array is temporary in some way, but that's not true, it just creates an array that's hidden and not on the transient heap. This commit renames it to rb_ary_hidden_new.
* Expand tabs [ci skip]Takashi Kokubun2022-07-211-261/+261
| | | | [Misc #18891]
* Unflag a splatted flagged hash if the method doesn't use ruby2_keywordsJeremy Evans2022-04-051-1/+13
| | | | | | | | | | | | | | | | | | | | | | | | For a method such as: def foo(*callee_args) end If this method is called with a flagged hash (created by a method flagged with ruby2_keywords), this previously passed the hash through without modification. With this change, it acts as if the last hash was passed as keywords, so a call to: foo(*caller_args) where the last element of caller_args is a flagged hash, will be treated as: foo(*caller_args[0...-1], **caller_args[-1]) As a result, inside foo, callee_args[-1] is an unflagged duplicate of caller_args[-1] (all other elements of callee_args match caller_args). Fixes [Bug #18625]
* Do not autosplat array in block call just because keywords acceptedJeremy Evans2022-03-301-1/+3
| | | | | | | | | | | If the block only accepts a single positional argument plus keywords, then do not autosplat. Still autosplat if the block accepts more than one positional argument in addition to keywords. Autosplatting a single positional argument plus keywords made sense in Ruby 2, since a final positional hash could be used as keywords, but it does not make sense in Ruby 3. Fixes [Bug #18633]
* Add ISEQ_BODY macroPeter Zhu2022-03-241-43/+43
| | | | | | Use ISEQ_BODY macro to get the rb_iseq_constant_body of the ISeq. Using this macro will make it easier for us to change the allocation strategy of rb_iseq_constant_body when using Variable Width Allocation.
* Using NIL_P macro instead of `== Qnil`S.H2021-10-031-1/+1
|
* Remove printf family from the mjit headerNobuyoshi Nakada2021-09-111-1/+1
| | | | | Linking printf family functions makes mjit objects to link unnecessary code.
* remove unused declKoichi Sasada2021-01-081-2/+0
|
* Run method_missing in the same execution contextNobuyoshi Nakada2020-07-061-2/+2
|
* Suppress probably impossible maybe-uninitialized warningNobuyoshi Nakada2020-05-111-1/+1
|
* Reduce allocations for keyword argument hashesJeremy Evans2020-03-171-27/+58
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, passing a keyword splat to a method always allocated a hash on the caller side, and accepting arbitrary keywords in a method allocated a separate hash on the callee side. Passing explicit keywords to a method that accepted a keyword splat did not allocate a hash on the caller side, but resulted in two hashes allocated on the callee side. This commit makes passing a single keyword splat to a method not allocate a hash on the caller side. Passing multiple keyword splats or a mix of explicit keywords and a keyword splat still generates a hash on the caller side. On the callee side, if arbitrary keywords are not accepted, it does not allocate a hash. If arbitrary keywords are accepted, it will allocate a hash, but this commit uses a callinfo flag to indicate whether the caller already allocated a hash, and if so, the callee can use the passed hash without duplicating it. So this commit should make it so that a maximum of a single hash is allocated during method calls. To set the callinfo flag appropriately, method call argument compilation checks if only a single keyword splat is given. If only one keyword splat is given, the VM_CALL_KW_SPLAT_MUT callinfo flag is not set, since in that case the keyword splat is passed directly and not mutable. If more than one splat is used, a new hash needs to be generated on the caller side, and in that case the callinfo flag is set, indicating the keyword splat is mutable by the callee. In compile_hash, used for both hash and keyword argument compilation, if compiling keyword arguments and only a single keyword splat is used, pass the argument directly. On the caller side, in vm_args.c, the callinfo flag needs to be recognized and handled. Because the keyword splat argument may not be a hash, it needs to be converted to a hash first if not. Then, unless the callinfo flag is set, the hash needs to be duplicated. The temporary copy of the callinfo flag, kw_flag, is updated if a hash was duplicated, to prevent the need to duplicate it again. If we are converting to a hash or duplicating a hash, we need to update the argument array, which can including duplicating the positional splat array if one was passed. CALLER_SETUP_ARG and a couple other places needs to be modified to handle similar issues for other types of calls. This includes fairly comprehensive tests for different ways keywords are handled internally, checking that you get equal results but that keyword splats on the caller side result in distinct objects for keyword rest parameters. Included are benchmarks for keyword argument calls. Brief results when compiled without optimization: def kw(a: 1) a end def kws(**kw) kw end h = {a: 1} kw(a: 1) # about same kw(**h) # 2.37x faster kws(a: 1) # 1.30x faster kws(**h) # 2.19x faster kw(a: 1, **h) # 1.03x slower kw(**h, **h) # about same kws(a: 1, **h) # 1.16x faster kws(**h, **h) # 1.14x faster
* Do not autosplat when calling procs that accept rest and keywordsJeremy Evans2020-03-081-2/+2
| | | | | | | | | When providing a single array to a block that takes a splat, pass the array as one argument of the splat instead of as the splat itself, even if the block also accepts keyword arguments. Previously, this behavior was only used for blocks that did not accept keywords. Implements [Feature#16166]
* Proc from Symbol needs a receiverNobuyoshi Nakada2020-02-221-1/+1
| | | | | | | So its arity should be -2 instead of -1. [Bug #16640] https://bugs.ruby-lang.org/issues/16640#change-84337
* VALUE size packed callinfo (ci).Koichi Sasada2020-02-221-14/+13
| | | | | | | | | | | | | | | | | | | | 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.
* `Proc` made by `Symbol#to_proc` should be a lambda [Bug #16260]Nobuyoshi Nakada2020-02-221-1/+1
| | | | With refinements, too.
* Do not autosplat when calling proc with empty keyword splatJeremy Evans2020-01-241-1/+2
| | | | | | | | | | | | With the removal of the splatted argument when using an empty keyword splat, the autosplat code considered an empty keyword splat the same as no argument at all. However, that results in autosplat behavior changing dependent on the content of the splatted hash, which is not what anyone would expect or want. This change always skips an autosplat if keywords were provided. Fixes [Bug #16560]
* Remove empty keyword splats when calling even when using ruby2_keywordsJeremy Evans2020-01-231-27/+9
| | | | | | | | | Keeping empty keyword splats for ruby2_keywords methods was necessary in 2.7 to prevent the final positional hash being treated as keywords. Now that keyword argument separation has been committed, the final positional hash is never treated as keywords, so there is no need to keep empty keyword splats when using ruby2_keywords.
* Fix unused warningsKazuhiro NISHIYAMA2020-01-031-23/+0
| | | | | | | | | | | | | | | | | 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) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ ```
* Fully separate positional arguments and keyword argumentsJeremy Evans2020-01-021-347/+36
| | | | | | | | | | | | | | | | | | | | | | | | 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().
* Reword keyword arguments warning messages to convey these are deprecation ↵Marc-Andre Lafortune2019-12-231-7/+7
| | | | warnings
* Kernel#lambda: return forwarded block as non-lambda procAlan Wu2019-12-211-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | Before this commit, Kernel#lambda can't tell the difference between a directly passed literal block and one passed with an ampersand. A block passed with an ampersand is semantically speaking already a non-lambda proc. When Kernel#lambda receives a non-lambda proc, it should simply return it. Implementation wise, when the VM calls a method with a literal block, it places the code for the block on the calling control frame and passes a pointer (block handler) to the callee. Before this commit, the VM forwards block arguments by simply forwarding the block handler, which leaves the slot for block code unused when a control frame forwards its block argument. I use the vacant space to indicate that a frame has forwarded its block argument and inspect that in Kernel#lambda to detect forwarded blocks. This is a very ad-hoc solution and relies *heavily* on the way block passing works in the VM. However, it's the most self-contained solution I have. [Bug #15620]
* vm_args.c: rephrase the warning message of keyword argument separationYusuke Endoh2019-12-201-8/+8
| | | | | | | | | | (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
* Manage deprecation warnings about keyword argumentNobuyoshi Nakada2019-12-191-0/+2
|
* Adjusted the formatNobuyoshi Nakada2019-12-191-2/+4
|
* vm_core.h (iseq_unique_id): prefer uintptr_t instead of unsigned longYusuke Endoh2019-12-101-8/+8
| | | | It produced a warning about type cast in LLP64 (i.e., windows).
* vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointerYusuke Endoh2019-12-091-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | (This is the second try of 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e.) If iseq is GC'ed, the pointer of iseq may be reused, which may hide a deprecation warning of keyword argument change. http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 ``` 1) Failure: TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: --- expected +++ actual @@ -1 +1 @@ -/The keyword argument is passed as the last hash parameter.* for `m'/m +"" ``` This change ad-hocly adds iseq_unique_id for each iseq, and use it instead of iseq pointer. This covers the case where caller is GC'ed. Still, the case where callee is GC'ed, is not covered. But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it just hides some warnings. It's no big deal.
* Revert "vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointer"Yusuke Endoh2019-12-091-5/+1
| | | | | | | | | This reverts commit 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e. This caused a failure on iseq_binary mode. http://ci.rvm.jp/results/trunk-iseq_binary@silicon-docker/2474587 Numbering iseqs is not trivial due to dump/load.
* Revert "vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_id"Yusuke Endoh2019-12-091-1/+1
| | | | This reverts commit 751a9b32e5a53336768eb878de1827245a3292bf.
* vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_idYusuke Endoh2019-12-091-1/+1
| | | | The function assumed that the LSB of `callee` was 0.
* vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointerYusuke Endoh2019-12-091-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | If iseq is GC'ed, the pointer of iseq may be reused, which may hide a deprecation warning of keyword argument change. http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 ``` 1) Failure: TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: --- expected +++ actual @@ -1 +1 @@ -/The keyword argument is passed as the last hash parameter.* for `m'/m +"" ``` This change ad-hocly adds iseq_unique_id for each iseq, and use it instead of iseq pointer. This covers the case where caller is GC'ed. Still, the case where callee is GC'ed, is not covered. But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it just hides some warnings. It's no big deal.
* vm_args.c: make the keyword deprecation message helpfulYusuke Endoh2019-12-031-3/+3
| | | | | | | | ``` $ ./miniruby -e 'def foo(kw: 1); end; h = {kw: 1}; foo(h)' -e:1: warning: The last argument is used as the keyword parameter -e:1: warning: for `foo' defined here; maybe ** should be added to the call? ```
* Reduce duplicated warnings for the change of Ruby 3 keyword argumentsYusuke Endoh2019-11-291-10/+61
| | | | | | | | | | | | | | | By this change, the following code prints only one warning. ``` def foo(**opt); end 100.times { foo({kw:1}) } ``` A global variable `st_table *caller_to_callees` is a map from caller to a set of callee methods. It remembers that a warning is already printed for each pair of caller and callee. [Feature #16289]
* Don't modify rest array when using ruby2_keywordsJeremy Evans2019-11-271-2/+1
| | | | | | Previously, the rest array was modified, but it turns out that is not necessary. Not modifying the rest array fixes cases when the rest array is used more than once.
* Always forward declaration is neededNobuyoshi Nakada2019-11-201-1/+2
| | | | | | `rb_resolve_refined_method_callable` is referenced in `refine_sym_proc_call`, even when pre-compiling mjit header on mswin.
* make functions static卜部昌平2019-11-191-0/+3
| | | | | | | 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.
* Handle case where ruby2_keywords method splats to ruby2_keywords methodJeremy Evans2019-10-241-0/+3
| | | | | | Previously, the keyword hash was duped (which results in a regular hash), but the dup was not marked as a keyword hash, causing the hash not to be marked as keyword hash even though it should be.
* Dup hash with keyword flag when converted to keywordsJeremy Evans2019-10-151-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | When ruby2_keywords is used on a method, keywords passed to the method are flagged. When the hash is passed as the last element of an argument splat to another method, the hash should be treated as a keyword splat. When keyword splatting a hash, a duplicate of the hash is made. So when auto-splatting the hash with the keyword flag, a duplicate of the hash should also be made. This fixes cases where the hash is later passed to another method and would be treated as keywords there: class Object ruby2_keywords def foo(*a) bar(*a) end def bar(*a) baz(*a) end def baz(*a, **kw) [a, kw] end end foo(:a=>1) Previously, this would pass the :a=>1 as keywords to bar and also as keywords to baz. Now it only passes :a=>1 as keywords to bar, but bar passes :a=>1 as a positional hash to baz (which in this case generates a warning in 2.7).
* Remove VM_NO_KEYWORDS, replace with RB_NO_KEYWORDSJeremy Evans2019-09-291-1/+1
| | | | | VM_NO_KEYWORDS was introduced first in vm_core.h, but it is best to only use a single definition for this.
* Adjusted spaces [ci skip]Nobuyoshi Nakada2019-09-271-6/+7
|
* Add rb_adjust_argv_kw_splat to internal.hJeremy Evans2019-09-261-1/+0
| | | | | We are calling this in a few other files, it is better to have it in a header than adding prototypes to the other files.
* Add Module#ruby2_keywords for passing keywords through regular argument splatsJeremy Evans2019-09-251-10/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Fix keyword argument separation issues with sym procs when using refinementsJeremy Evans2019-09-171-2/+11
| | | | | | | | | | | | Make sure that vm_yield_with_cfunc can correctly set the empty keyword flag by passing 2 as the kw_splat value when calling it in vm_invoke_ifunc_block. Make sure calling.kw_splat is set to 1 and not 128 in vm_sendish, so we can safely check for different kw_splat values. vm_args.c needs to call add_empty_keyword, and to make JIT happy, the function needs to be exported. Rename the function to rb_adjust_argv_kw_splat to more accurately reflect what it does, and mark it as MJIT exported.
* Pass keyword argument flag when rb_call_super_kw calls method_missingJeremy Evans2019-09-171-2/+2
| | | | | | | | This makes method_missing take a flag for whether keyword arguments were passed. Adds tests both for rb_call_super_kw usage as well as general usage of super calling method_missing in Ruby methods.
* Emit missing keyword argument separation warnings for define_methodJeremy Evans2019-09-111-8/+24
| | | | | | | | | Previously, the warning functions skipped warning in these cases. This removes the skipping, and uses a less descriptive warning instead. This affected both last argument to keyword warnings and keyword split warnings.
* Fix invalid keyword argument separation warning for delegating callsJeremy Evans2019-09-081-7/+2
| | | | | | | | | | | | | | | | | | | | This removes an invalid keyword argument separation warning for code such as: ```ruby def foo(arg) arg end kw = {} foo(*[1], **kw) ``` This warning was caused because the remove_empty_keyword_hash was set based on a comparison with two variables, and in this case, one of the variables was updated after the check and we need to use the updated variable. Simplify things by just inlining the comparison.
* Enable keyword argument warnings when called from CJeremy Evans2019-09-061-6/+3
| | | | | | Previously, Ruby did not warn in these cases, and in some cases did not have the same behavior. This makes calls from C handled the same way as calls from Ruby.