Граф коммитов

837 Коммитов

Автор SHA1 Сообщение Дата
卜部昌平 7cb96d41a5 refactor 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.
2019-09-30 10:26:38 +09:00
卜部昌平 3207979278 refactor delete rb_method_definition_set
Instead of destructively write fields of method entries, create a
new entry and let it overwrite its owner.
2019-09-30 10:26:38 +09:00
卜部昌平 595b3c4fdd refactor 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.
2019-09-30 10:26:38 +09:00
卜部昌平 cf33608203 refactor 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.
2019-09-30 10:26:38 +09:00
Jeremy Evans 6fdd701472 Remove VM_NO_KEYWORDS, replace with RB_NO_KEYWORDS
VM_NO_KEYWORDS was introduced first in vm_core.h, but it is best
to only use a single definition for this.
2019-09-29 16:41:00 -07:00
Jeremy Evans 7814b6c657 Correctly issue ArgumentError when calling method that accepts no keywords
If a method accepts no keywords and was called with a keyword, an
ArgumentError was not always issued previously.  Force methods that
accept no keywords to go through setup_parameters_complex so that
an ArgumentError is raised if keywords are provided.
2019-09-27 11:21:50 -07:00
Nobuyoshi Nakada 8d0ff88727
Adjusted spaces [ci skip] 2019-09-27 14:06:07 +09:00
Nobuyoshi Nakada 0c6f36668a
Adjusted spaces [ci skip] 2019-09-27 10:20:56 +09:00
Jeremy Evans 3b302ea8c9 Add Module#ruby2_keywords for passing keywords through regular argument splats
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.
2019-09-25 12:33:52 -07:00
Takashi Kokubun 6e0dd3e7c1
Use RUBY_VM_NEXT_CONTROL_FRAME macro
in vm_push_frame and limit scope of i.
Just a minor maintainability improvement.
2019-09-20 21:06:08 +09:00
卜部昌平 fcfe36b733 fix spec failure
See also https://travis-ci.org/ruby/ruby/jobs/586452224
2019-09-19 15:18:10 +09:00
卜部昌平 d74fa8e55c reuse cc->call
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
2019-09-19 15:18:10 +09:00
卜部昌平 bcd5f2e9d3 delete unused variable 2019-09-18 11:06:24 +09:00
Jeremy Evans 775365cbd2 Fix keyword argument separation issues with sym procs when using refinements
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.
2019-09-17 16:22:44 -07:00
Jeremy Evans 37a2c660aa Convert keyword argument to required positional hash argument for Class#new, 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.
2019-09-06 19:41:23 -07:00
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.
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.
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
Jeremy Evans 5e018214e7 Fix SystemStackError when calling a method in an unused refinement
Fixes [Bug #15720]
2019-06-11 09:43:38 -07:00
git b487b39b85 * expand tabs. 2019-06-01 13:34:55 +09:00
Yusuke Endoh 65e63af377 Make opt_aref instruction support Integer#[]
only when its receiver and the argument are both Integers.

Since 6bedbf4625, Integer#[] has supported a range extraction.
This means that Integer#[] now accepts multiple arguments, which made
the method very slow unfortunately.

This change fixes the performance issue by adding a special handling for
its traditional use case: `num[idx]` where both `num` and `idx` are
Integers.
2019-06-01 13:15:43 +09:00
Nobuyoshi Nakada b1aecef873
Use UNALIGNED_MEMBER_PTR
* internal.h (UNALIGNED_MEMBER_ACCESS, UNALIGNED_MEMBER_PTR):
  moved from eval_intern.h.

* compile.c iseq.c, vm.c: use UNALIGNED_MEMBER_PTR for `entries`
  in `struct iseq_catch_table`.

* vm_eval.c, vm_insnhelper.c: use UNALIGNED_MEMBER_PTR for `body`
  in `rb_method_definition_t`.
2019-05-31 16:04:16 +09:00
Urabe, Shyouhei 2a863d4bab avoid buffer overflow in vm_check_canary
ec->cfp->iseq might not exist at the very beginning of a thread.

=================================================================
==82954==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7fc86f334810 at pc 0x55ceaf013125 bp 0x7ffe2eddbbf0 sp 0x7ffe2eddbbe8
READ of size 8 at 0x7fc86f334810 thread T0
    #0 0x55ceaf013124 in vm_check_canary vm_insnhelper.c:217:24
    #1 0x55ceaefb4796 in vm_push_frame vm_insnhelper.c:276:5
    #2 0x55ceaf0124bd in th_init vm.c:2661:5
    #3 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5
    #4 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5
    #5 0x55ceaef0038b in thread_s_new thread.c:872:20
    #6 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12
    #7 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11
    #8 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12
    #9 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9
    #10 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13
    #11 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12
    #12 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11
    #13 0x55ceaefc95bb in vm_exec_core insns.def:771:11
    #14 0x55ceaf006700 in rb_vm_exec vm.c:1892:22
    #15 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11
    #16 0x55ceaea250ca in ruby_exec_internal eval.c:262:2
    #17 0x55ceaea2498b in ruby_exec_node eval.c:326:12
    #18 0x55ceaea247d0 in ruby_run_node eval.c:318:25
    #19 0x55ceae88c486 in main main.c:42:9
    #20 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310
    #21 0x55ceae7e5289 in _start (miniruby+0x15f289)

0x7fc86f334810 is located 16 bytes to the right of 1048576-byte region [0x7fc86f234800,0x7fc86f334800)
allocated by thread T0 here:
    #0 0x55ceae85d56d in malloc (miniruby+0x1d756d)
    #1 0x55ceaea71d12 in objspace_xmalloc0 gc.c:9416:5
    #2 0x55ceaea71cd2 in ruby_xmalloc2_body gc.c:9623:12
    #3 0x55ceaea7d09c in ruby_xmalloc2 gc.c:11479:12
    #4 0x55ceaf00c3b7 in rb_thread_recycle_stack vm.c:2462:12
    #5 0x55ceaf012256 in th_init vm.c:2656:29
    #6 0x55ceaf00d5eb in ruby_thread_init vm.c:2690:5
    #7 0x55ceaf00d4b1 in rb_thread_alloc vm.c:2703:5
    #8 0x55ceaef0038b in thread_s_new thread.c:872:20
    #9 0x55ceaf04d8c1 in call_cfunc_m1 vm_insnhelper.c:2041:12
    #10 0x55ceaf03118d in vm_call_cfunc_with_frame vm_insnhelper.c:2207:11
    #11 0x55ceaf017985 in vm_call_cfunc vm_insnhelper.c:2225:12
    #12 0x55ceaf01548b in vm_call_method_each_type vm_insnhelper.c:2560:9
    #13 0x55ceaf014c96 in vm_call_method vm_insnhelper.c:2686:13
    #14 0x55ceaefb5de4 in vm_call_general vm_insnhelper.c:2730:12
    #15 0x55ceaf03c868 in vm_sendish vm_insnhelper.c:3623:11
    #16 0x55ceaefc95bb in vm_exec_core insns.def:771:11
    #17 0x55ceaf006700 in rb_vm_exec vm.c:1892:22
    #18 0x55ceaf00acbf in rb_iseq_eval_main vm.c:2151:11
    #19 0x55ceaea250ca in ruby_exec_internal eval.c:262:2
    #20 0x55ceaea2498b in ruby_exec_node eval.c:326:12
    #21 0x55ceaea247d0 in ruby_run_node eval.c:318:25
    #22 0x55ceae88c486 in main main.c:42:9
    #23 0x7fc874330b96 in __libc_start_main /build/glibc-OTsEL5/glibc-2.27/csu/../csu/libc-start.c:310

SUMMARY: AddressSanitizer: heap-buffer-overflow vm_insnhelper.c:217:24 in vm_check_canary
Shadow bytes around the buggy address:
  0x0ff98de5e8b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ff98de5e8c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ff98de5e8d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ff98de5e8e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ff98de5e8f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ff98de5e900: fa fa[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ff98de5e910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ff98de5e920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ff98de5e930: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ff98de5e940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0ff98de5e950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==82954==ABORTING
2019-04-26 15:59:40 +09:00
Urabe, Shyouhei 171a6ad1c1 print the disasm
It seems to be my fault to leave the variable disasm unused.
2019-04-26 15:59:40 +09:00
Urabe, Shyouhei b6ebbee5d6 suppress warning [ci skip] 2019-04-26 15:59:40 +09:00
k0kubun 088df9c8c2 Revert "GET_CFP and ec->cfp are different"
This reverts commit 30f71f4768.

I've also overlooked we're doing RESTORE_REGS()...

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67523 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-13 06:55:35 +00:00
k0kubun 30f71f4768 GET_CFP and ec->cfp are different
When reviewing r66565, I overlooked that `GET_ISEQ()` and `GET_EP()` are
NOT `ec->cfp->iseq` and `ec->cfp->ep` but `reg_cfp->iseq` and
`reg_cfp->ep`.

`vm_push_frame` updates `ec->cfp` and in this case we want to check the
callee's cfp and so `ec->cfp` should be checked instead.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67522 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-13 06:27:52 +00:00
svn 4b53f84326 * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67443 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-05 08:15:21 +00:00
ko1 2b5bb8a087 add definemethod/definesmethod insn.
* 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-04-05 08:15:11 +00:00
svn e590173547 * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67432 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-04 01:34:56 +00:00
k0kubun 22fd30e605 Revert "Introduce inline cache for invokesuper"
This reverts commit d147ad6231.

because failing on CI:
http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1916925

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67431 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-04 01:34:53 +00:00
k0kubun d147ad6231 Introduce inline cache for invokesuper
Looks good in micro benchmark:
```
$ benchmark-driver benchmark/vm2_super.yml -v --rbenv 'before;after'
before: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
after: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
last_commit=Introduce inline cache for invokesuper
Calculating -------------------------------------
                         before       after
           vm2_super    19.265M     31.280M i/s -      6.000M times in 0.311447s 0.191813s

Comparison:
                        vm2_super
               after:  31280464.2 i/s
              before:  19264906.2 i/s - 1.62x  slower
```

No significant impact to Optcarrot:
```
$ benchmark-driver benchmark.yml --rbenv='before;after' -v --output=all --repeat-count=12
before: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
after: ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
last_commit=Introduce inline cache for invokesuper
Calculating -------------------------------------
                                       before                 after
Optcarrot Lan_Master.nes    48.41126024010233     47.28027196127746 fps
                            49.49212664510990     48.75072555488074
                            49.51485564376117     49.20650895701073
                            49.58351773328487     49.24563592659139
                            49.64022392458479     49.26292753046641
                            49.92566235019630     49.44496216868009
                            50.18022198879376     49.45467429762771
                            50.33038373991723     49.52003367348857
                            50.43202877523305     49.69190055704068
                            50.61368587766504     49.79856204866324
                            50.77975014460643     50.27764769510704
                            50.89807360753746     50.35785776505005
```

A little improvement to k0kubun/railsbench?:
```
$ rbenv shell before; RUBYOPT="-v" WARMUP=1 BENCHMARK=30000 bin/bench
ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
Warmup: 1 requests
Benchmark: 30000 requests

Request per second: 897.1 [#/s] (mean)

Percentage of the requests served within a certain time (ms)
  50%    1.01
  66%    1.02
  75%    1.03
  80%    1.04
  90%    1.08
  95%    1.23
  98%    2.10
  99%    5.52
 100%   13.26

$ rbenv shell after; RUBYOPT="-v" WARMUP=1 BENCHMARK=30000 bin/bench
ruby 2.7.0dev (2019-04-03 trunk 67428) [x86_64-linux]
last_commit=Introduce inline cache for invokesuper
Warmup: 1 requests
Benchmark: 30000 requests

Request per second: 913.0 [#/s] (mean)

Percentage of the requests served within a certain time (ms)
  50%    0.99
  66%    1.00
  75%    1.01
  80%    1.02
  90%    1.06
  95%    1.20
  98%    2.12
  99%    5.57
 100%   12.39
```

No significant impact to discourse:
```
* before
categories_admin:
  50: 54
  75: 60
  90: 70
  99: 86
home_admin:
  50: 56
  75: 65
  90: 71
  99: 122
topic_admin:
  50: 64
  75: 73
  90: 79
  99: 117
categories:
  50: 32
  75: 33
  90: 46
  99: 61
home:
  50: 34
  75: 36
  90: 48
  99: 56
topic:
  50: 40
  75: 42
  90: 55
  99: 83

* after
categories_admin:
  50: 59
  75: 66
  90: 80
  99: 149
home_admin:
  50: 54
  75: 58
  90: 70
  99: 96
topic_admin:
  50: 63
  75: 66
  90: 79
  99: 115
categories:
  50: 31
  75: 32
  90: 45
  99: 65
home:
  50: 34
  75: 35
  90: 49
  99: 58
topic:
  50: 40
  75: 42
  90: 55
  99: 78
```

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67429 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-04-03 16:06:03 +00:00
k0kubun c92c0a5935 Prefer using vm_base_ptr rather than cfp->bp
in MJIT implementation.

This allows us to drop cfp->bp by just modifying vm_base_ptr in the
future.

No performance impact:

$ benchmark-driver benchmark.yml --rbenv='before::before --disable-gems --jit;bp_::after --disable-gems --jit;vm_env_ptr::ruby-svn --disable-gems --jit' -v --output=all --repeat-count=12
before: ruby 2.7.0dev (2019-03-24 trunk 67341) +JIT [x86_64-linux]
bp_: ruby 2.7.0dev (2019-03-24 trunk 67342) +JIT [x86_64-linux]
vm_env_ptr: ruby 2.7.0dev (2019-03-25 trunk 67343) +JIT [x86_64-linux]
last_commit=Prefer using vm_base_ptr rather than cfp->bp
Calculating -------------------------------------
                                       before                   bp_            vm_env_ptr
Optcarrot Lan_Master.nes    77.15059205092646     70.18873044267853     69.62171387083328 fps
                            78.75767783870441     77.49867689173411     75.43496867709587
                            79.60102690369321     77.78037687683523     79.36688927929428
                            80.25144236638835     78.74729849101701     80.42363742291455
                            82.22375417165489     80.44265482494045     80.90287243299306
                            82.29166786292619     80.51740049420938     81.81153053252902
                            83.35386925305345     80.91054205210609     81.93562989125176
                            83.39770634366975     81.34550754145043     82.24544621470430
                            83.88523450309972     81.60698516017347     82.76801860263230
                            84.17553130135879     82.69615943446324     83.02530407910871
                            84.42132328119858     83.00969158037691     83.19968539409922
                            84.60731429793329     83.32703363300098     83.81352746019631

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67344 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-25 14:26:11 +00:00
ko1 8dd0fb9039 use cfp->bp more.
cfp->bp was (re-)introduced by Kokubun san, but VM doesn't use it
because I (ko1) want to remove it in a future. But using it make
leave instruction fast because of sp consisntency check.
So now VM uses cfp->bp.

To use cfp->bp, I checked the value and I found that it is not a
"initial value of sp" but a "initial value of ep". Fix this problem
and fix all bp references (this is why bp is renamed to bp_).


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67342 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-25 06:58:50 +00:00
ko1 c671f836b4 add debug counters to count call cache fastpath.
Add counters to count ccf (call cache fastpath) usage.
These counters will help which kind of method dispatch
is important to optimize.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67336 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-22 07:57:26 +00:00
svn a433f2c51b * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67334 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-22 00:21:43 +00:00
ko1 79ddbe9dee optimize method dispatch for lead/kw params.
similar idea to r67315, provide the following optimization
for method dispatch with lead and kw parameters.

(1) add a special branch to check passing kw arguments to
    a method which has lead and kw parameters.
    ex) def foo(x, k:1); end; foo(0, k:1)
(2) add a special branch to check passing no-kw arguments to
    a method which has lead and kw parameters.
    ex) def foo(x, k:1); end; foo(0)

For (1) and (2) cases, provide special dispatchers. For (2) case,
this patch only use the special dispatcher if all default
kw parameters are literal values (nil, 1, and so on. In other case,
kw->default_values does not contains Qundef) (and no required kw
parameters becaseu they don't pass any keyword parameters).

Passing keyword arguments with a hash object is not a scope of
this patch.

Without this patch, (1) and (2) cases use `setup_parameters_complex()`.
Especially, (2) seems frequent case for methods which extend a normal
usecase with keyword parameters (like: `exception: true`).

We can measure the performance with benchmark-driver:
  With methods: def kw k1:1, k2:2; end
                def m; end
  With the following binaries:
    clean-miniruby: unmodified trunk.
    opt_miniruby1: use special branches for lead/kw parameters.
    opt_miniruby2: use special dispatchers for lead/kw parameters.
    opt_cc_miniruby: apply step (2).
  Result with benchmark-driver:

                              m
     opt_miniruby2:  75222278.0 i/s
    clean-miniruby:  73177896.5 i/s - 1.03x  slower
     opt_miniruby1:  62466783.3 i/s - 1.20x  slower

                             kw
     opt_miniruby2:  52044504.4 i/s
     opt_miniruby1:  29142025.7 i/s - 1.79x  slower
    clean-miniruby:  20515235.4 i/s - 2.54x  slower

                      kw k1: 10
     opt_miniruby2:  26492219.5 i/s
     opt_miniruby1:  25409484.9 i/s - 1.04x  slower
    clean-miniruby:  20235113.7 i/s - 1.31x  slower

              kw k1: 10, k2: 20
     opt_miniruby1:  24159534.0 i/s
     opt_miniruby2:  23470527.5 i/s - 1.03x  slower
    clean-miniruby:  17822621.5 i/s - 1.36x  slower


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67333 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-22 00:21:41 +00:00
k0kubun 52bd8f6f68 Share vm_call_iseq_optimizable_p to reduce copy-paste
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67329 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-21 06:25:09 +00:00
k0kubun a8695d5022 Make rb_iseq_only_optparam_p static
because it's not used outside vm*.c, and also having non-static function
without MJIT_STATIC is harmful for mswin JIT system.

I hope this fix mswin test failure starting from r67315.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67328 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-21 05:59:57 +00:00
ko1 e8e1f72d8f remove redundant check.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67319 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-20 20:37:03 +00:00
ko1 df2af1147f fix a type error with a cast for clang.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67318 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-20 20:26:21 +00:00
svn 5c439ebfb0 * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67316 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-20 19:57:43 +00:00
ko1 24e03d7e26 optimize method dispatch for lead/opt params.
There is a special optimization for "only lead parameters"
method dispatch using specialized dispatcher functions
`vm_call_iseq_setup_normal_0start...`.
Other cases (opt, rest, post, ...) we don't use specialized
dispatcher and call with `setup_parameters_complex` to
satisfy Ruby's complex parameter specification.

This commit introduce a specialize dispatcher for
methods which use only lead and optional parameters.

Two step improvements:
(1) prepare "lead/opt" only check pass.
    It is to skip the `setup_parameters_complex` function.
(2) introduce specialized dispatcher for only "lead/opt"
    parameters methods (vm_call_iseq_setup_normal_opt_start).

With these improvements, we achieved good micro-benchmark
results:
  With a method: `def opt2 a, b=nil; end`
  With the following binaries:
    clean-miniruby: unmodified trunk.
    opt_miniruby: apply step (1).
    opt_cc_miniruby: apply step (2).
  Result with benchmark-driver:

                        opt2(1)
   opt_cc_miniruby:  42269409.1 i/s
      opt_miniruby:  36304428.3 i/s - 1.16x  slower
    clean-miniruby:  25897409.5 i/s - 1.63x  slower

                     opt2(1, 2)
   opt_cc_miniruby:  45935145.7 i/s
      opt_miniruby:  40513196.9 i/s - 1.13x  slower
    clean-miniruby:  29976057.6 i/s - 1.53x  slower

This improvement may be trivial (difficult to improve practical
cases). However, this is enough small patch so I decide to
introduce it.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-03-20 19:57:39 +00:00
ko1 b1c1ee7183 change `cfunc->invoker` type for opt.
* 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-02-22 07:25:51 +00:00
shyouhei 232f31ca12 on-smash canary detection
In addition to detect dead canary, we try to detect the very moment
when we smash the stack top.  Requested by k0kubun:
https://twitter.com/k0kubun/status/1085180749899194368


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-02-01 07:26:39 +00:00
k0kubun 4840771afb vm_insnhelper.c: make VM helpers inline
In r66597, both VM and JIT seem to be made slower:

```
$ benchmark-driver benchmark.yml --rbenv 'r66596::before --disable-gems;r66597::after --disable-gems;r66596+JIT::before --disable-gems --jit;r66597+JIT::after --disable-gems --jit' -v --repeat-count 24
r66596: ruby 2.7.0dev (2018-12-28 trunk 66596) [x86_64-linux]
r66597: ruby 2.7.0dev (2018-12-28 trunk 66597) [x86_64-linux]
r66596+JIT: ruby 2.7.0dev (2018-12-28 trunk 66596) +JIT [x86_64-linux]
r66597+JIT: ruby 2.7.0dev (2018-12-28 trunk 66597) +JIT [x86_64-linux]
Calculating -------------------------------------
                             r66596      r66597  r66596+JIT  r66597+JIT
Optcarrot Lan_Master.nes     55.174      54.620      88.011      85.326 fps

Comparison:
             Optcarrot Lan_Master.nes
              r66596+JIT:        88.0 fps
              r66597+JIT:        85.3 fps - 1.03x  slower
                  r66596:        55.2 fps - 1.60x  slower
                  r66597:        54.6 fps - 1.61x  slower
```

This commit makes JIT's situation a little better. But in 2.7 we seem to
have some other regressions after that, and this can't still resurrect the
2.6.0's performance.

```
$ benchmark-driver benchmark.yml --rbenv 'before::before --disable-gems;after::after --disable-gems;before+JIT::before --disable-gems --jit;after+JIT::after --disable-gems --jit' -v --repeat-count 24
before: ruby 2.7.0dev (2019-01-13 trunk 66808) [x86_64-linux]
after: ruby 2.7.0dev (2019-01-13 trunk 66808) [x86_64-linux]
last_commit=vm_insnhelper.c: make VM helpers inline
before+JIT: ruby 2.7.0dev (2019-01-13 trunk 66808) +JIT [x86_64-linux]
after+JIT: ruby 2.7.0dev (2019-01-13 trunk 66808) +JIT [x86_64-linux]
last_commit=vm_insnhelper.c: make VM helpers inline
Calculating -------------------------------------
                             before       after  before+JIT   after+JIT
Optcarrot Lan_Master.nes     51.710      51.535      83.629      85.486 fps

Comparison:
             Optcarrot Lan_Master.nes
               after+JIT:        85.5 fps
              before+JIT:        83.6 fps - 1.02x  slower
                  before:        51.7 fps - 1.65x  slower
                   after:        51.5 fps - 1.66x  slower
```

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66809 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-14 04:49:28 +00:00
k0kubun 56bf732aaf mjit.c: use boolean type for boolean variables
and functions to clarify the intention and make sure it's not used in a
surprising way (like using 2, 3, ... other than 0, 1 even while it seems
to be a boolean).

This is a retry of r66775. It included some typos...

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66778 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-10 14:31:18 +00:00
k0kubun efd99b5331 Revert "mjit.c: use boolean type for boolean variables"
This reverts commit bb1a1aeab0.

We hit something on ci.rvm.jp, reverting until investigation is done.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-10 13:29:29 +00:00
k0kubun bb1a1aeab0 mjit.c: use boolean type for boolean variables
and functions to clarify the intention and make sure it's not used in a
surprising way (like using 2, 3, ... other than 0, 1 even while it seems
to be a boolean).

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66775 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2019-01-10 13:21:58 +00:00
shyouhei 91dfdf840b vm_insnhelper.c: USE_FLONUM is always defined
This changeset should fix the 32bit failures.
See also: https://travis-ci.org/ruby/ruby/jobs/472855470


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66601 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-28 03:42:11 +00:00
shyouhei 24b1b433c5 vm_insnhelper.c: delete unused macros
- FIXNUM_2_P: moved to vm_insnhelper.c because that is the only
  place this macro is used.

- FLONUM_2_P: ditto.

- FLOAT_HEAP_P: not used anywhere.

- FLOAT_INSTANCE_P: ditto.

- GET_TOS: ditto.

- USE_IC_FOR_SPECIALIZED_METHOD: ditto.

- rb_obj_hidden_p: ditto.

- REG_A: ditto.

- REG_B: ditto.

- GET_CONST_INLINE_CACHE: ditto.

- vm_regan_regtype: moved inside of VM_COLLECT_USAGE_DETAILS
  because that os the only place this enum is used.

- vm_regan_acttype: ditto.

- GET_GLOBAL: used only once.  Removed with replacing that usage.

- SET_GLOBAL: ditto.

- rb_method_definition_create: declaration moved to
  vm_insnhelper.c because that is the only place this declaration
  makes sense.

- rb_method_definition_set: ditto.

- rb_method_definition_eq: ditto.

- rb_make_no_method_exception: ditto.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66597 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-28 01:06:04 +00:00
svn 70398311d0 * expand tabs.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66566 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-26 00:59:40 +00:00
shyouhei d46ab95376 insns.def: refactor to avoid CALL_METHOD macro
These send and its variant instructions are the most frequently called
paths in the entire process.  Reducing macro expansions to make them
dedicated function called vm_sendish() is the main goal of this
changeset.  It reduces the size of vm_exec_coref from 25,552 bytes to
23,728 bytes on my machine.

I see no significant slowdown.

Fix: [GH-2056]

vanilla: ruby 2.6.0dev (2018-12-19 trunk 66449) [x86_64-darwin15]
ours: ruby 2.6.0dev (2018-12-19 refactor-send 66449) [x86_64-darwin15]
last_commit=insns.def: refactor to avoid CALL_METHOD macro
Calculating -------------------------------------
                         vanilla        ours
   vm2_defined_method     2.645M      2.823M i/s -      6.000M times in 5.109888s 4.783254s
           vm2_method     8.553M      8.873M i/s -      6.000M times in 1.579892s 1.524026s
   vm2_method_missing     3.772M      3.858M i/s -      6.000M times in 3.579482s 3.499220s
vm2_method_with_block     8.494M      8.944M i/s -      6.000M times in 1.589774s 1.509463s
      vm2_poly_method      0.571       0.607 i/s -       1.000 times in 3.947570s 3.733528s
   vm2_poly_method_ov      5.514       5.168 i/s -       1.000 times in 0.408156s 0.436169s
 vm3_clearmethodcache      2.875       2.837 i/s -       1.000 times in 0.783018s 0.793493s

Comparison:
                vm2_defined_method
                 ours:   2822555.4 i/s
              vanilla:   2644878.1 i/s - 1.07x  slower

                        vm2_method
                 ours:   8872947.8 i/s
              vanilla:   8553433.1 i/s - 1.04x  slower

                vm2_method_missing
                 ours:   3858192.3 i/s
              vanilla:   3772296.3 i/s - 1.02x  slower

             vm2_method_with_block
                 ours:   8943825.1 i/s
              vanilla:   8493955.0 i/s - 1.05x  slower

                   vm2_poly_method
                 ours:         0.6 i/s
              vanilla:         0.6 i/s - 1.06x  slower

                vm2_poly_method_ov
              vanilla:         5.5 i/s
                 ours:         5.2 i/s - 1.07x  slower

              vm3_clearmethodcache
              vanilla:         2.9 i/s
                 ours:         2.8 i/s - 1.01x  slower



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66565 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2018-12-26 00:59:37 +00:00