Age | Commit message (Collapse) | Author |
|
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://github.com/ruby/ruby/pull/2432
|
|
|
|
mame pointed out that vm_args.c is included in vm_insnhelper.c.
|
|
method_missing
This is the same as the bmethod, sym proc, and send cases,
where we don't remove the keyword splat, so later code can
move it to a required positional parameter and warn.
|
|
procs
This is the same as the bmethod and send cases, where we don't
remove the keyword splat, so later code can move it to to a
a required positional parameter and warn.
|
|
lambda and bmethod
The lambda case is similar to the attr_writer case, except we have
to determine the number of required parameters from the iseq
instead of being able to assume a single required parameter.
This fixes a lot of lambda tests which were switched to require
warnings for all usage of keyword arguments. Similar to method
handling, we do not warn when passing keyword arguments to
lambdas that do not accept keyword arguments, the argument is
just passed as a positional hash in that case, unless it is empty.
If it is empty and not the final required parameter, then we
ignore it. If it is empty and the final required parameter, then
we pass it for backwards compatibility and emit a warning, as in
Ruby 3 we will not pass it.
The bmethod case is similar to the send case, in that we do not
want to remove empty keyword splats in vm_call_bmethod, as that
prevents later call handling from moving them to required
positional arguments and warning.
|
|
In general, we want to ignore empty keyword hashes. The only case
where we want to allow them for backwards compatibility is when
they are necessary to satify the final required positional argument.
In that case, we want to not ignore them, but we do want to warn,
as that will be going away in Ruby 3.
This commit implements this support for regular methods and
attr_writer methods.
In order to allow send to forward arguments correctly, send no
longer removes empty keyword hashes. It is the responsibility of
the final method to remove the empty keyword hashes now. This
change was necessary as otherwise send could remove the empty
keyword hashes before the regular or attr_writer methods could
move them to required positional arguments.
For completeness, add tests for keyword handling regular
methods calls.
This makes rb_warn_keyword_to_last_hash non-static in vm_args.c
so it can be reused in vm_insnhelper.c, and also moves declarations
before statements in the rb_warn_* functions in vm_args.c.
|
|
While doing so is not backwards compatible with Ruby 2.6, it is
necessary for generic argument forwarding to work for all methods:
```ruby
def foo(*args, **kw, &block)
bar(*args, **kw, &block)
end
```
If you do not remove empty keyword hashes, and bar does not accept
keyword arguments, then a call to foo without keyword arguments
calls bar with an extra positional empty hash argument.
|
|
and lambda.
When define_method is a simple iseq (`define_method(:m) {|x| ... }`),
passing keywords to it (`m(**kw)`) didn't print a warning.
|
|
Similar to 38e9c1bc35d5549575fbb263afff560e97db068e
|
|
Similar to 38e9c1bc35d5549575fbb263afff560e97db068e
|
|
Now the mechanism that conveys kw_splat flag is gradually established,
so the hack to drop the empty keyword hash is not needed for
vm_call_opt_send.
|
|
Actually, the following call is wrongly warned without this change.
```
class C
def method_missing(x, *args, **opt)
end
end
C.new.foo(k: 1)
# warning: The last argument is used as the keyword parameter
# warning: for `method_missing' defined here
```
|
|
|
|
|
|
|
|
...only when a "remove_empty_keyword_hash" flag is specified.
After CALLER_SETUP_ARG is called, `ci->flag & VM_CALL_KW_SPLAT` must not
be used. Instead. use `calling->kw_splat`. This is because
CALLER_SETUP_ARG may modify argv and update `calling->kw_splat`, and
`ci->flag & VM_CALL_KW_SPLAT` may be inconsistent with the result.
|
|
|
|
There are two styles that argv contains keyword arguments: one is
VM_CALL_KWARG which contains value elements in argv (to avoid a hash
object creation if possible), and the other is VM_CALL_KW_SPLAT which
contains one last hash in argv.
vm_caller_setup_arg_kw translates argv from the VM_CALL_KWARG style to
the VM_CALL_KW_SPLAT style.
`calling->kw_splat` means that argv is the VM_CALL_KW_SPLAT style.
So, instead of setting `calling->kw_splat` at many places, it would be
better to do so when vm_caller_setup_arg_kw is called.
|
|
method_missing
|
|
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.
|
|
Otherwise the last positional hash could be considered as the
keyword arguments.
|
|
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.
|
|
|
|
The kw_splat flag is whether the original call passes keyword or not.
Some types of methods (e.g., bmethod and sym_proc) drops the
information. This change tries to propagate the flag to the final
callee, as far as I can.
|
|
Add rb_keyword_given_p to the C-API
Notes:
Merged-By: jeremyevans <code@jeremyevans.net>
|
|
rb_reg_match expects its first argument to be a Regexp instance.
Should check that.
Notes:
Merged: https://github.com/ruby/ruby/pull/1959
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/1959
|
|
----
trunk: ruby 2.6.0dev (2018-09-18 trunk 64767) [x86_64-darwin15]
ours: ruby 2.6.0dev (2018-09-18 opt_regexpmatch 64775) [x86_64-darwin15]
last_commit=opt_regexpmatch1 is actually making things slower.
Calculating -------------------------------------
trunk ours
Optcarrot Lan_Master.nes 33.877 35.282 fps
Comparison:
Optcarrot Lan_Master.nes
ours: 35.3 fps
trunk: 33.9 fps - 1.04x slower
Notes:
Merged: https://github.com/ruby/ruby/pull/1959
|
|
Pointed out by ko1.
|
|
vm_call_method_missing was dropping VM_CALL_KW_SPLAT, so this just
makes it not drop it, to get the same behavior as calling the method
directly.
|
|
vm_call_opt_send was dropping VM_CALL_KW_SPLAT, so this just makes
it not drop it, to get the same behavior as calling the method
directly.
|
|
calling cfunc
This mirrors earlier changes in keyword argument separation for
calling Ruby methods and calling procs/lambdas, so that behavior
is kept the same.
|
|
|
|
And, allow non-symbol keys as a keyword arugment
Notes:
Merged: https://github.com/ruby/ruby/pull/2395
|
|
when reopened class/module redefinition mismatched the previous
definition. [Feature #11460]
|
|
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.
|
|
[Bug #16107]
|
|
[Bug #16107]
Notes:
Merged: https://github.com/ruby/ruby/pull/2373
|
|
|
|
This was an intentional bug added in 1.9.
The approach taken here is to add a second operand to the
getconstant instruction for whether nil should be allowed and
treated as current scope.
Fixes [Bug #11718]
|
|
|
|
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]
|
|
|
|
Inspired by 346aa557b31fe96760e505d30da26eb7a846bac9
Closes: https://github.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://github.com/ruby/ruby/pull/2318
|
|
This reverts commit a0980f2446c0db735b8ffeb37e241370c458a626.
Retry for macOS Mojave.
|
|
This reverts commit 9faef3113fb4331524b81ba73005ba13fa0ef6c6.
It seemed to cause a failure on macOS Mojave, though I'm unsure how.
https://rubyci.org/logs/rubyci.s3.amazonaws.com/osx1014/ruby-master/log/20190802T034503Z.fail.html.gz
This tentative revert is to check if the issue is actually caused by the
change or not.
|
|
This commit adds a specialized instruction for called to `.nil?`. It is
about 27% faster than master in the case where the object is nil or not
nil. In the case where an object implements `nil?`, I think it may be
slightly slower. Here is a benchmark:
```ruby
require "benchmark/ips"
class Niller
def nil?; true; end
end
not_nil = Object.new
xnil = nil
niller = Niller.new
Benchmark.ips do |x|
x.report("nil?") { xnil.nil? }
x.report("not nil") { not_nil.nil? }
x.report("niller") { niller.nil? }
end
```
On Ruby master:
```
[aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 429.195k i/100ms
not nil 437.889k i/100ms
niller 437.935k i/100ms
Calculating -------------------------------------
nil? 20.166M (± 8.1%) i/s - 100.002M in 5.002794s
not nil 20.046M (± 7.6%) i/s - 99.839M in 5.020086s
niller 22.467M (± 6.1%) i/s - 112.111M in 5.013817s
[aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 449.660k i/100ms
not nil 433.836k i/100ms
niller 443.073k i/100ms
Calculating -------------------------------------
nil? 19.997M (± 8.8%) i/s - 99.375M in 5.020458s
not nil 20.529M (± 7.0%) i/s - 102.385M in 5.020689s
niller 21.796M (± 8.0%) i/s - 108.110M in 5.002300s
[aaron@TC ~/g/ruby (master)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 402.119k i/100ms
not nil 438.968k i/100ms
niller 398.226k i/100ms
Calculating -------------------------------------
nil? 20.050M (±12.2%) i/s - 98.519M in 5.008817s
not nil 20.614M (± 8.0%) i/s - 102.280M in 5.004531s
niller 22.223M (± 8.8%) i/s - 110.309M in 5.013106s
```
On this branch:
```
[aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 468.371k i/100ms
not nil 456.517k i/100ms
niller 454.981k i/100ms
Calculating -------------------------------------
nil? 27.849M (± 7.8%) i/s - 138.169M in 5.001730s
not nil 26.417M (± 8.7%) i/s - 131.020M in 5.011674s
niller 21.561M (± 7.5%) i/s - 107.376M in 5.018113s
[aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 477.259k i/100ms
not nil 428.712k i/100ms
niller 446.109k i/100ms
Calculating -------------------------------------
nil? 28.071M (± 7.3%) i/s - 139.837M in 5.016590s
not nil 25.789M (±12.9%) i/s - 126.470M in 5.011144s
niller 20.002M (±12.2%) i/s - 98.144M in 5.001737s
[aaron@TC ~/g/ruby (specialized-nilp)]$ ./ruby compil.rb
Warming up --------------------------------------
nil? 467.676k i/100ms
not nil 445.791k i/100ms
niller 415.024k i/100ms
Calculating -------------------------------------
nil? 26.907M (± 8.0%) i/s - 133.755M in 5.013915s
not nil 25.319M (± 7.9%) i/s - 125.713M in 5.007758s
niller 19.569M (±11.8%) i/s - 96.286M in 5.008533s
```
Co-Authored-By: Ashe Connor <kivikakk@github.com>
|
|
|