Commit graph

972 commits

Author SHA1 Message Date
git
dd81af7b6a * remove trailing spaces. [ci skip] 2019-09-06 09:50:59 +09:00
Jeremy Evans
d3cf0eb214 Mark rb_warn_keyword_to_last_hash as static inline
mame pointed out that vm_args.c is included in vm_insnhelper.c.
2019-09-05 17:47:12 -07:00
Jeremy Evans
729de9ee68 Convert empty keyword hash to required positional argument and warn for 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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
e220b467ef Convert empty keyword hash to required positional argument and warn for sym 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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
e2878a96f7 Convert empty keyword hash to required positional argument and warn for 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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
e7274a8ec4 Convert empty keyword hash to required positional argument and warn
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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
d1ef73b59c Always remove empty keyword hashes when calling methods
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.
2019-09-05 17:47:12 -07:00
Yusuke Endoh
55b96c5d2d Add a keyword-to-last-hash warning for some case of define_method method
and lambda.

When define_method is a simple iseq (`define_method(:m) {|x| ... }`),
passing keywords to it (`m(**kw)`) didn't print a warning.
2019-09-05 17:47:12 -07:00
Yusuke Endoh
dd83f7bf98 define_method should not drop the empty keyword hash
Similar to 38e9c1bc35d5549575fbb263afff560e97db068e
2019-09-05 17:47:12 -07:00
Yusuke Endoh
70f2780892 vm_call_bmethod should not drop the empty keyword hash
Similar to 38e9c1bc35d5549575fbb263afff560e97db068e
2019-09-05 17:47:12 -07:00
Yusuke Endoh
252e299009 vm_call_opt_send should not drop the empty keyword hash
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.
2019-09-05 17:47:12 -07:00
Yusuke Endoh
acee630241 vm_insnhelper.c: Do not read ci->flag after CALLER_SETUP_ARG
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
```
2019-09-05 17:47:12 -07:00
Yusuke Endoh
eda8dcea16 Add a comment that some ci->flag is inconsistent after CALLER_SETUP_ARG 2019-09-05 17:47:12 -07:00
Yusuke Endoh
0bfe3bf4d1 Ignore an empty keyword splat for attr_reader/writer methods 2019-09-05 17:47:12 -07:00
Yusuke Endoh
437ff40879 C method should accept a keyword hash (for compatibility with 2.6) 2019-09-05 17:47:12 -07:00
Yusuke Endoh
c5555e2eb8 CALLER_SETUP_ARG removes an empty keyword hash from argv
...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.
2019-09-05 17:47:12 -07:00
Yusuke Endoh
a23ddf7ff5 vm_argc.c (vm_caller_setup_arg_kw): "cfunc" argument is no longer used 2019-09-05 17:47:12 -07:00
Yusuke Endoh
030b8e5edf Set calling->kw_splat = 1 in vm_caller_setup_arg_kw
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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
1fffd33189 Fix passing keywords without splats to sym procs, define_method, and method_missing 2019-09-05 17:47:12 -07:00
Jeremy Evans
6f9b86616a Make Symbol#to_proc calls handle keyword arguments
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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
38dae1d510 If removing an empty keyword splat hash, unset the kw_splat flag
Otherwise the last positional hash could be considered as the
keyword arguments.
2019-09-05 17:47:12 -07:00
Jeremy Evans
7fc874bf4c Add rb_funcall_with_block_kw
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-09-05 17:47:12 -07:00
Jeremy Evans
e3cb3e11af Set VM_FRAME_FLAG_CFRAME_KW if kw_splat set in vm_yield_with_cfunc 2019-09-05 17:47:12 -07:00
Yusuke Endoh
ce04392d8d Propagate kw_splat information
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.
2019-09-05 17:47:12 -07:00
Jeremy Evans
39c3252cd1
Merge pull request #2422 from jeremyevans/rb_keyword_given_p
Add rb_keyword_given_p to the C-API
2019-09-03 11:32:02 -07:00
Urabe, Shyouhei
79e3d6bb9e fix shortcut condition
rb_reg_match expects its first argument to be a Regexp instance.
Should check that.
2019-09-02 13:56:40 +09:00
Urabe, Shyouhei
ec80d5c4f3 delete unused function 2019-09-02 13:56:40 +09:00
Urabe, Shyouhei
8ad7fafcdd opt_regexpmatch1 is actually making things slower.
----

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
2019-09-02 13:56:40 +09:00
Jeremy Evans
f58db5a6f5 Simplify setting of VM_CALL_KW_SPLAT in vm_call_method_missing
Pointed out by ko1.
2019-09-01 19:46:19 -07:00
Jeremy Evans
3fde9ef937 Fix keyword argument separation warning in method_missing
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.
2019-09-01 16:08:42 -07:00
Jeremy Evans
d646a292cd Fix keyword argument separation warning when using send
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.
2019-08-31 23:06:49 -07:00
Jeremy Evans
15757390ff Don't pass an empty keyword hash when double splatting empty hash when 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.
2019-08-31 21:54:06 -07:00
Jeremy Evans
1f18b578ce Don't pass an empty keyword hash when double splatting empty hash 2019-08-30 23:50:50 -07:00
Yusuke Endoh
16c6984bb9 Separate keyword arguments from positional arguments
And, allow non-symbol keys as a keyword arugment
2019-08-30 12:39:31 -07:00
Nobuyoshi Nakada
761346a960
Show the previous definition location,
when reopened class/module redefinition mismatched the previous
definition.  [Feature #11460]
2019-08-29 13:24:00 +09:00
卜部昌平
b8fd2e83e7 decouple compile.c usage of imemo_ifunc
After 5e86b005c0, 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.
2019-08-27 15:52:26 +09:00
Nobuyoshi Nakada
dc020b06ff
Hoisted out search_refined_method
[Bug #16107]
2019-08-17 12:32:34 +09:00
Nobuyoshi Nakada
11a9f7ab94 Search refinement module along nested usings
[Bug #16107]
2019-08-17 12:30:38 +09:00
git
d053a57014 * expand tabs. [ci skip] 2019-08-15 01:51:19 +09:00
Jeremy Evans
fbcd065294 Remove support for nil::Constant
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]
2019-08-14 09:50:14 -07:00
git
4e9382a827 * expand tabs. 2019-08-09 11:11:18 +09:00
Koichi Sasada
71efad1ed3 introduce RCLASS_CLONED flag for inline cache.
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]
2019-08-09 11:05:11 +09:00
git
3e6b9926b7 * expand tabs. 2019-08-06 20:59:41 +09:00
卜部昌平
b5146e375a
leafify opt_plus
Inspired by 346aa557b3

Closes: https://github.com/ruby/ruby/pull/2321
2019-08-06 20:59:19 +09:00
Takashi Kokubun
346aa557b3
Make opt_eq and opt_neq insns leaf
# 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
2019-08-04 22:20:12 +09:00
Yusuke Endoh
086ffe72c7 Revert "Revert "Add a specialized instruction for .nil? calls""
This reverts commit a0980f2446.

Retry for macOS Mojave.
2019-08-02 23:25:38 +09:00
Yusuke Endoh
a0980f2446 Revert "Add a specialized instruction for .nil? calls"
This reverts commit 9faef3113f.

It seemed to cause a failure on macOS Mojave, though I'm unsure how.
20190802T034503Z.fail.html.gz

This tentative revert is to check if the issue is actually caused by the
change or not.
2019-08-02 15:03:34 +09:00
Aaron Patterson
9faef3113f
Add a specialized instruction for .nil? calls
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>
2019-07-31 16:21:25 -07:00
Samuel Williams
9dda0a03cc
Remove rb_vm_push_frame as it is no longer used. 2019-07-19 11:10:01 +12:00
Yusuke Endoh
49362ddac6 Add a /* fall through */ comment 2019-07-14 22:21:10 +09:00