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

797 Коммитов

Автор SHA1 Сообщение Дата
Jeremy Evans dd2068ac8d Add rb_adjust_argv_kw_splat to internal.h
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.
2019-09-26 15:30:51 -07: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
Jeremy Evans 80b5a0ff2a
Make rb_scan_args handle keywords more similar to Ruby methods (#2460)
Cfuncs that use rb_scan_args with the : entry suffer similar keyword
argument separation issues that Ruby methods suffer if the cfuncs
accept optional or variable arguments.

This makes the following changes to : handling.

* Treats as **kw, prompting keyword argument separation warnings
  if called with a positional hash.

* Do not look for an option hash if empty keywords are provided.
  For backwards compatibility, treat an empty keyword splat as a empty
  mandatory positional hash argument, but emit a a warning, as this
  behavior will be removed in Ruby 3.  The argument number check
  needs to be moved lower so it can correctly handle an empty
  positional argument being added.

* If the last argument is nil and it is necessary to treat it as an option
  hash in order to make sure all arguments are processed, continue to
  treat the last argument as the option hash. Emit a warning in this case,
  as this behavior will be removed in Ruby 3.

* If splitting the keyword hash into two hashes, issue a warning, as we
  will not be splitting hashes in Ruby 3.

* If the keyword argument is required to fill a mandatory positional
  argument, continue to do so, but emit a warning as this behavior will
  be going away in Ruby 3.

* If keyword arguments are provided and the last argument is not a hash,
  that indicates something wrong. This can happen if a cfunc is calling
  rb_scan_args multiple times, and providing arguments that were not
  passed to it from Ruby.  Callers need to switch to the new
  rb_scan_args_kw function, which allows passing of whether keywords
  were provided.

This commit fixes all warnings caused by the changes above.

It switches some function calls to *_kw versions with appropriate
kw_splat flags. If delegating arguments, RB_PASS_CALLED_KEYWORDS
is used.  If creating new arguments, RB_PASS_KEYWORDS is used if
the last argument is a hash to be treated as keywords.

In open_key_args in io.c, use rb_scan_args_kw.
In this case, the arguments provided come from another C
function, not Ruby.  The last argument may or may not be a hash,
so we can't set keyword argument mode.  However, if it is a
hash, we don't want to warn when treating it as keywords.

In Ruby files, make sure to appropriately use keyword splats
or literal keywords when calling Cfuncs that now issue keyword
argument separation warnings through rb_scan_args.  Also, make
sure not to pass nil in place of an option hash.

Work around Kernel#warn warnings due to problems in the Rubygems
override of the method.  There is an open pull request to fix
these issues in Rubygems, but part of the Rubygems tests for
their override fail on ruby-head due to rb_scan_args not
recognizing empty keyword splats, which this commit fixes.

Implementation wise, adding rb_scan_args_kw is kind of a pain,
because rb_scan_args takes a variable number of arguments.
In order to not duplicate all the code, the function internals need
to be split into two functions taking a va_list, and to avoid passing
in a ton of arguments, a single struct argument is used to handle
the variables previously local to the function.
2019-09-25 11:18:49 -07:00
Yusuke Endoh 28eefb33c8 variable.c: Rename rb_st_copy to rb_iv_tbl_copy
This function was created as a variant of st_copy with firing write
barrier.
It should have more explicit name, such as st_copy_with_write_barrier.
But because it is used only for copying iv_tbl, so I rename it to
rb_iv_tbl_copy now.  If we face other use case than iv_tbl, we may want
to rename it to more general name.
2019-09-22 16:21:26 +09:00
Jeremy Evans c9f2b790ad Handle keyword argument separation for Enumerator#size
When Object#to_enum is passed a block, the block is called to get
a size with the arguments given to to_enum.  This calls the block
with the same keyword flag as to_enum is called with.

This requires adding rb_check_funcall_kw and
rb_check_funcall_default_kw to handle keyword flags.
2019-09-20 07:45:18 -07:00
Jeremy Evans 27b6746872 Make passing empty keywords to dig pass empty keywords to next dig method
If defined in Ruby, dig would be defined as def dig(arg, *rest) end,
it would not use keywords.  If the last dig argument was an empty
hash, it could be treated as keyword arguments by the next dig
method.  Allow dig to pass along the empty keyword flag if called
with an empty keyword, to suppress the previous behavior and force
treating the hash as a positional argument and not keywords.

Also handle the case where dig calls method_missing, passing the
empty keyword flag to that as well.

This requires adding rb_check_funcall_with_hook_kw functions, so
that dig can specify how arguments are treated.  It also adds
kw_splat arguments to a couple static functions.
2019-09-20 07:45:11 -07: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
Jeremy Evans 3cfbfa9628 Consolidate empty keyword handling
Remove rb_add_empty_keyword, and instead of calling that every
place you need to add empty keyword hashes, run that code in
a single static function in vm_eval.c.

Add 4 defines to include/ruby/ruby.h, these are to be used as
int kw_splat values when calling the various rb_*_kw functions:

RB_NO_KEYWORDS :: Do not pass keywords
RB_PASS_KEYWORDS :: Pass final argument (which should be hash) as keywords
RB_PASS_EMPTY_KEYWORDS :: Add an empty hash to arguments and pass as keywords
RB_PASS_CALLED_KEYWORDS :: Passes same keyword type as current method was
                           called with (for method delegation)

rb_empty_keyword_given_p needs to stay.  It is required if argument
delegation is done but delayed to a later point, which Enumerator
does.

Use RB_PASS_CALLED_KEYWORDS in rb_call_super to correctly
delegate keyword arguments to super method.
2019-09-13 16:42:27 -07:00
Nobuyoshi Nakada df1721c668
Fixed GCC version for diagnostic-pragmas
"GCC diagnostic push/pop" seems appeared at gcc 4.6.
2019-09-10 14:37:17 +09: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
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
卜部昌平 dd2b9d4a96 hide rb_funcallv_with_cc from public
Requested by ko1.  Also, because now that this function is internal
use only, why not just directly use struct rb_call_cache to purge
the ZALLOC.
2019-09-05 12:13:07 +09:00
Jeremy Evans afae8555da Set symbol export for rb_hash_stlike_foreach
This fixes MJIT after rb_hash_stlike_foreach used vm_args.c.
2019-08-30 12:39:31 -07:00
Jeremy Evans 334b41a46b Allow ** syntax to be used for calling methods that do not accept keywords
Treat the ** syntax as passing a copy of the hash as the last
positional argument.  If the hash being double splatted is empty, do
not add a positional argument.

Remove rb_no_keyword_hash, no longer needed.
2019-08-30 12:39:31 -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
卜部昌平 19b6678132 rb_uninterruptible now free from ANYARGS
After 5e86b005c0, I now think ANYARGS is
dangerous and should be extinct.  This function has only one call site
so adding appropriate prototype is trivial.
2019-08-27 15:52:26 +09:00
卜部昌平 bd8dc2561d struct MEMO now free from ANYARGS
After 5e86b005c0, I now think ANYARGS is
dangerous and should be extinct.  There is only one usage of
MEMO::u3::func in load.c (where void Init_Foobar(vodi) is registered)
so why not just be explicit.
2019-08-27 15:52:26 +09:00
卜部昌平 50f5a0a8d6 rb_hash_foreach now free from ANYARGS
After 5e86b005c0, I now think ANYARGS is
dangerous and should be extinct.  This commit adds function prototypes
for rb_hash_foreach / st_foreach_safe.  Also fixes some prototype
mismatches.
2019-08-27 15:52:26 +09:00
卜部昌平 703783324c rb_ensure now free from ANYARGS
After 5e86b005c0, I now think ANYARGS is
dangerous and should be extinct.  This commit deletes ANYARGS from
rb_ensure, which also revealed many arity / type mismatches.
2019-08-27 15:52:26 +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
卜部昌平 6007c7c366 delete rb_method_defined_by declaration.
Ko1 missed this in d5893b91fa.
2019-08-27 15:52:26 +09:00
Koichi Sasada 88b1f2dac4
`rp(obj)` shows func, file and line. (#2394)
rp() macro for debug also shows file location and function name
such as:

  [OBJ_INFO:rb_call_inits@inits.c:73] 0x000056147741b248 ...
2019-08-21 01:04:08 +09:00
Nobuyoshi Nakada 0c2d81dada
Renamed ruby_finalize_{0,1}
And pass rb_execution_context_t as an argument.
2019-08-13 09:47:08 +09:00
Nobuyoshi Nakada d69ffa4d93
Expanded f_quo 2019-08-10 14:38:30 +09:00
Koichi Sasada 6bf8db9a07 add rp() and bp() in internal.h.
debug utility macro rp() (rp_m()) and bp() are introduced.
* rp(obj) shows obj information w/o any side-effect to STDERR.
* rp_m(m, obj) is similar to rp(obj), but show m before.
* bp() is alias of ruby_debug_breakpoint(), which is registered
  as a breakpoint in run.gdb (used by `make gdb` or make gdb-ruby`).
2019-08-09 14:01:15 +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
卜部昌平 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
Nobuyoshi Nakada f9a0492b76
Expanded f_ceil 2019-08-02 11:26:58 +09:00
Koichi Sasada 3a6f51ee35 introduce ar_hint_t.
Hash hint for ar_array is 1 byte (unsigned char). This patch introduce
ar_hint_t which represents hint type.
2019-08-01 16:06:43 +09:00
Koichi Sasada 312879693f move macro to internal.h for documentation.
13e84d5c0a changes enum to macro, but the flags usage information
are lost in internal.h. It should be same place with other flags
information.
2019-07-31 11:32:14 +09:00
Nobuyoshi Nakada 13e84d5c0a
Moved RHASH_LEV_MASK and turned into a macro
Get rid of "ISO C restricts enumerator values to range of 'int'"
error.
2019-07-31 11:08:05 +09:00
Koichi Sasada 72825c35b0 Use 1 byte hint for ar_table [Feature #15602]
On ar_table, Do not keep a full-length hash value (FLHV, 8 bytes)
but keep a 1 byte hint from a FLHV (lowest byte of FLHV).
An ar_table only contains at least 8 entries, so hints consumes
8 bytes at most. We can store hints in RHash::ar_hint.

On 32bit CPU, we use 4 entries ar_table.

The advantages:
* We don't need to keep FLHV so ar_table only consumes
  16 bytes (VALUEs of key and value) * 8 entries = 128 bytes.
* We don't need to scan ar_table, but only need to check hints
  in many cases. Especially we don't need to access ar_table
  if there is no match entries (in many cases).
  It will increase memory cache locality.

The disadvantages:
* This technique can increase `#eql?` time because hints can
  conflicts (in theory, it conflicts once in 256 times).
  It can introduce incompatibility if there is a object x where
  x.eql? returns true even if hash values are different.
  I believe we don't need to care such irregular case.
* We need to re-calculate FLHV if we need to switch from ar_table
  to st_table (e.g. exceeds 8 entries).
  It also can introduce incompatibility, on mutating key objects.
  I believe we don't need to care such irregular case too.

Add new debug counters to measure the performance:
* artable_hint_hit - hint is matched and eql?#=>true
* artable_hint_miss - hint is not matched but eql?#=>false
* artable_hint_notfound - lookup counts
2019-07-31 09:52:03 +09:00
Koichi Sasada ebd398ac5a remove RHash::iter_lev.
iter_lev is used to detect the hash is iterating or not.
Usually, iter_lev should be very small number (1 or 2) so
`int` is overkill.

This patch introduce iter_lev in flags (7 bits, FL13 to FL19)
and if iter_lev exceeds this range, save it in hidden attribute.
We can get 1 word in RHash.

We can't modify frozen objects. Therefore I added new internal API
`rb_ivar_set_internal()` which allows us to set an attribute
even if the target object is frozen
if the name is hidden ivar (the name without `@` prefix).
2019-07-31 09:44:23 +09:00
Nobuyoshi Nakada 1d1f98d49c
Reuse match data
* string.c (rb_str_split_m): reuse occupied match data.  [Bug #16024]
2019-07-28 07:33:21 +09:00
Koichi Sasada 1feda1c2b0 constify again.
Same as last commit, make some fields `const`.

include/ruby/ruby.h:
* Rasic::klass
* RArray::heap::aux::shared_root
* RRegexp::src
internal.h:
* rb_classext_struct::origin_, redefined_class
* vm_svar::cref_or_me, lastline, backref, others
* vm_throw_data::throw_obj
* vm_ifunc::data
* MEMO::v1, v2, u3::value

While modifying this patch, I found write-barrier miss on
rb_classext_struct::redefined_class.

Also vm_throw_data::throw_state is only `int` so change the type.
2019-07-22 17:53:10 +09:00
Koichi Sasada f75561b8d4 constify RHash::ifnone.
RHash::ifnone should be protected by write-barriers so this field
should be const. However, to introduce GC.compact, the const was
removed. This commit revert this removing `const` and modify
gc.c `TYPED_UPDATE_IF_MOVED` to remove `const` forcely by a type cast.
2019-07-22 17:01:31 +09:00
Nobuyoshi Nakada e988048e25
Moved the check for `exception` to rb_execarg_addopt
Check for `exception` option in rb_execarg_addopt, as well as
other options.  And then raise a particular ArgumentError if it is
not allowed.
2019-07-16 18:57:08 +09:00
Nobuyoshi Nakada ca524bcd49
Expanded f_numerator 2019-07-16 08:15:05 +09:00
Nobuyoshi Nakada 34019a22eb
Expanded f_denominator 2019-07-16 07:59:30 +09:00
Koichi Sasada c23e597674 respect RUBY_DEBUG.
see RUBY_DEBUG for each debug options.
2019-07-15 11:30:34 +09:00
Tanaka Akira 4900a10689 socket: use frozen string buffer when releasing GVL
Thanks for the patch by normalperson (Eric Wong) [Bug #14204].
2019-07-14 20:46:51 +09:00
Nobuyoshi Nakada 3e7d002118
Check exception flag as a bool [Bug #15987] 2019-07-11 20:04:29 +09:00
Nobuyoshi Nakada bdddaa9f56
Use rb_ident_hash_new instead of rb_hash_new_compare_by_id
The latter is same as the former, removed the duplicate function.
2019-07-03 02:09:01 +09:00
Nobuyoshi Nakada 5b7cc63d11
Turned `recur` into `int` [Feature #15777] 2019-06-21 17:28:37 +09:00
Jean Boussier fb85a42860
Add an optional `inherit` argument to Module#autoload?
[Feature #15777]

Closes: https://github.com/ruby/ruby/pull/2173
2019-06-21 17:28:37 +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
Kazuhiro NISHIYAMA aee36bf149
Fix Possible Control flow issues (DEADCODE)
Coverity Scan says `Execution cannot reach this statement: "poison_object(v);"`,
so do nothing when `ptr` is always 0 without address_sanitizer.
2019-05-29 13:16:05 +09:00
Kazuhiro NISHIYAMA 54d5b599e8
Fix typos [ci skip] 2019-05-24 14:32:30 +09:00