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

1141 Коммитов

Автор SHA1 Сообщение Дата
Takashi Kokubun 5808999d30
YJIT: Fallback opt_getconstant_path for const_missing (#8623)
* YJIT: Fallback opt_getconstant_path for const_missing

* Fix a comment [ci skip]

* Remove a wrapper function
2023-10-13 08:52:23 -07:00
Adam Hess 8b236e0c66 [Bug #19896]
fix memory leak in vm_method

This introduces a unified reference_count to clarify who is referencing a method.
This also allows us to treat the refinement method as the def owner since it counts itself as a reference

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-09-22 09:44:58 -04:00
Alan Wu 1961c5bb76
YJIT: Plug native stack overflow
Previously, TestStack#test_machine_stack_size failed pretty consistently
on ARM64 macOS, with Rust code and part of the interpreter used for
per-instruction fallback (rb_vm_invokeblock() and friends) touching the
stack guard page and crashing with SEGV. I've also seen the same test
fail on x64 Linux, though with a different symptom.
2023-09-14 17:18:45 -04:00
Maxime Chevalier-Boisvert 30a5b94517
YJIT: implement side chain fallback for setlocal to avoid exiting (#8227)
* YJIT: implement side chain fallback for setlocal to avoid exiting

* Update yjit/src/codegen.rs

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>

---------

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-08-17 10:11:17 -04:00
Takashi Kokubun 654b648223
YJIT: Implement checkmatch instruction (#8203) 2023-08-10 23:08:29 -04:00
Takashi Kokubun cd8d20cd1f
YJIT: Compile exception handlers (#8171)
Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
2023-08-08 16:06:22 -07:00
Koichi Sasada d68c01fd31 support `rescue` event for TracePoint
fix [Feature #19572]
2023-08-01 22:46:17 +09:00
Koichi Sasada cfd7729ce7 use inline cache for refinements
From Ruby 3.0, refined method invocations are slow because
resolved methods are not cached by inline cache because of
conservertive strategy. However, `using` clears all caches
so that it seems safe to cache resolved method entries.

This patch caches resolved method entries in inline cache
and clear all of inline method caches when `using` is called.

fix [Bug #18572]

```ruby
 # without refinements

class C
  def foo = :C
end

N = 1_000_000

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}

_END__
              user     system      total        real
master    0.362859   0.002544   0.365403 (  0.365424)
modified  0.357251   0.000000   0.357251 (  0.357258)
```

```ruby
 # with refinment but without using

class C
  def foo = :C
end

module R
  refine C do
    def foo = :R
  end
end

N = 1_000_000

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}
__END__
               user     system      total        real
master     0.957182   0.000000   0.957182 (  0.957212)
modified   0.359228   0.000000   0.359228 (  0.359238)
```

```ruby
 # with using

class C
  def foo = :C
end

module R
  refine C do
    def foo = :R
  end
end

N = 1_000_000

using R

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}
2023-07-31 17:13:43 +09:00
Koichi Sasada 280419d0e0 `calling->cd` instead of `calling->ci`
`struct rb_calling_info::cd` is introduced and `rb_calling_info::ci`
is replaced with it to manipulate the inline cache of iseq while
method invocation process. So that `ci` can be acessed with
`calling->cd->ci`. It adds one indirection but it can be justified
by the following points:

1) `vm_search_method_fastpath()` doesn't need `ci` and also
`vm_call_iseq_setup_normal()` doesn't need `ci`. It means
reducing `cd->ci` access in `vm_sendish()` can make it faster.

2) most of method types need to access `ci` once in theory
so that 1 additional indirection doesn't matter.
2023-07-31 17:13:43 +09:00
Koichi Sasada 36023d5cb7 mark `cc->cme_` if it is for `super`
`vm_search_super_method()` makes orphan CCs (they are not connected
from ccs) and `cc->cme_` can be collected before without marking.
2023-07-31 14:04:31 +09:00
ywenc 8ca399d640
Implement `opt_aref_with` instruction (#8118)
Implement gen_opt_aref_with

Vm opt_aref_with is available

Test opt_aref_with

Stats for opt_aref_with

Co-authored-by: jhawthorn <jhawthorn@github.com>
2023-07-26 10:38:59 -04:00
Takashi Kokubun cef60e93e6
YJIT: Fallback send instructions to vm_sendish (#8106) 2023-07-24 13:51:46 -07:00
Alan Wu f302e725e1
Remove __bp__ and speed-up bmethod calls (#8060)
Remove rb_control_frame_t::__bp__ and optimize bmethod calls

This commit removes the __bp__ field from rb_control_frame_t. It was
introduced to help MJIT, but since MJIT was replaced by RJIT, we can use
vm_base_ptr() to compute it from the SP of the previous control frame
instead. Removing the field avoids needing to set it up when pushing new
frames.

Simply removing __bp__ would cause crashes since RJIT and YJIT used a
slightly different stack layout for bmethod calls than the interpreter.
At the moment of the call, the two layouts looked as follows:

                   ┌────────────┐    ┌────────────┐
                   │ frame_base │    │ frame_base │
                   ├────────────┤    ├────────────┤
                   │    ...     │    │    ...     │
                   ├────────────┤    ├────────────┤
                   │    args    │    │    args    │
                   ├────────────┤    └────────────┘<─prev_frame_sp
                   │  receiver  │
    prev_frame_sp─>└────────────┘
                     RJIT & YJIT      interpreter

Essentially, vm_base_ptr() needs to compute the address to frame_base
given prev_frame_sp in the diagrams. The presence of the receiver
created an off-by-one situation.

Make the interpreter use the layout the JITs use for iseq-to-iseq
bmethod calls. Doing so removes unnecessary argument shifting and
vm_exec_core() re-entry from the interpreter, yielding a speed
improvement visible through `benchmark/vm_defined_method.yml`:

     patched:   7578743.1 i/s
      master:   4796596.3 i/s - 1.58x  slower

C-to-iseq bmethod calls now store one more VALUE than before, but that
should have negligible impact on overall performance.

Note that re-entering vm_exec_core() used to be necessary for firing
TracePoint events, but that's no longer the case since
9121e57a5f.

Closes ruby/ruby#6428
2023-07-17 13:57:58 -04:00
Peter Zhu 3223181284 Remove RARRAY_CONST_PTR_TRANSIENT
RARRAY_CONST_PTR now does the same things as RARRAY_CONST_PTR_TRANSIENT.
2023-07-13 14:48:14 -04:00
Nobuyoshi Nakada 913e01e80e
Stop allocating unused backref strings at `defined?` 2023-06-27 23:14:10 +09:00
eileencodes 135a5eb716 Add missing write barrier
We were missing the write barrier for class_value to cref. This should
fix the segv we were seeing in http://ci.rvm.jp/logfiles/brlog.trunk-gc-asserts.20230601-165052

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-06-05 11:11:12 -07:00
eileencodes 40f090f433 Revert "Revert "Fix cvar caching when class is cloned""
This reverts commit 10621f7cb9.

This was reverted because the gc integrity build started failing. We
have figured out a fix so I'm reopening the PR.

Original commit message:

Fix cvar caching when class is cloned

The class variable cache that was added in
ruby#4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.

This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.

To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.

This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.

We also added a marking function which was missing.

Fixes [Bug #19379]

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-06-05 11:11:12 -07:00
Aaron Patterson 10621f7cb9
Revert "Fix cvar caching when class is cloned"
This reverts commit 77d1b08247.
2023-06-01 14:55:36 -07:00
eileencodes 77d1b08247 Fix cvar caching when class is cloned
The class variable cache that was added in
https://github.com/ruby/ruby/pull/4544 changed the behavior of class
variables on cloned classes. As reported when a class is cloned AND a
class variable was set, and the class variable was read from the
original class, reading a class variable from the cloned class would
return the value from the original class.

This was happening because the IC (inline cache) is stored on the ISEQ
which is shared between the original and cloned class, therefore they
share the cache too.

To fix this we are now storing the `cref` in the cache so that we can
check if it's equal to the current `cref`. If it's different we don't
want to read from the cache. If it's the same we do. Cloned classes
don't share the same cref with their original class.

This will need to be backported to 3.1 in addition to 3.2 since the bug
exists in both versions.

We also added a marking function which was missing.

Fixes [Bug #19379]

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2023-06-01 08:52:48 -07:00
Nobuyoshi Nakada 8d242a33af
`rb_bug` prints a newline after the message 2023-05-20 21:43:30 +09:00
Samuel Williams 2df5a697e2
Add Fiber#kill, similar to Thread#kill. (#7823) 2023-05-18 23:33:42 +09:00
Gary Tou 96a2e27185 `klass == (VALUE)NULL` --> `!klass`
Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
2023-04-26 10:21:20 -04:00
Gary Tou 1883dc5bde defined zsuper: Handle NULL superclass for `BasicObject`
Prior to this commit, a segmentation fault occurred in `vm_defined`'s
`zsuper` implementation after NULL is returned as `BasicObject`'s superclass.
This fix returns false from `vm_defined` if the superclass is NULL.

For example, the following code resulted in a segfault.
```ruby
class BasicObject
  def seg_fault
    defined?(super)
  end
end

seg_fault
```
2023-04-26 10:21:20 -04:00
Jeremy Evans a82a24ed57 Optimize method_missing calls
CALLER_ARG_SPLAT is not necessary for method_missing.  We just need
to unshift the method name into the arguments.

This optimizes all method_missing calls:

* mm(recv) ~9%
* mm(recv, *args) ~215% for args.length == 200
* mm(recv, *args, **kw) ~55% for args.length == 200
* mm(recv, **kw) ~22%
* mm(recv, kw: 1) ~100%

Note that empty argument splats do get slower with this approach,
by about 30-40%.  Other than non-empty argument splats, other
argument splats are faster, with the speedup depending on the
number of arguments.
2023-04-25 08:06:16 -07:00
Jeremy Evans 583e9d24d4 Optimize symproc calls
Similar to the bmethod/send optimization, this avoids using
CALLER_ARG_SPLAT if not necessary.  As long as the receiver argument
can be shifted off, other arguments are passed through as-is.

This optimizes the following types of calls:

* symproc.(recv) ~5%
* symproc.(recv, *args) ~65% for args.length == 200
* symproc.(recv, *args, **kw) ~45% for args.length == 200
* symproc.(recv, **kw) ~30%
* symproc.(recv, kw: 1) ~100%

Note that empty argument splats do get slower with this approach,
by about 2-3%.  This is probably because iseq argument setup is
slower for empty argument splats than CALLER_SETUP_ARG is. Other
than non-empty argument splats, other argument splats are faster,
with the speedup depending on the number of arguments.

The following types of calls are not optimized:

* symproc.(*args)
* symproc.(*args, **kw)

This is because the you cannot shift the receiver argument off
without first splatting the arg.
2023-04-25 08:06:16 -07:00
Jeremy Evans 9b4bf02aa8 Optimize send calls
Similar to the bmethod optimization, this avoids using
CALLER_ARG_SPLAT if not necessary.  As long as the method argument
can be shifted off, other arguments are passed through as-is.

This optimizes the following types of calls:

* send(meth, arg) ~5%
* send(meth, *args) ~75% for args.length == 200
* send(meth, *args, **kw) ~50% for args.length == 200
* send(meth, **kw) ~25%
* send(meth, kw: 1) ~115%

Note that empty argument splats do get slower with this approach,
by about 20%.  This is probably because iseq argument setup is
slower for empty argument splats than CALLER_SETUP_ARG is. Other
than non-empty argument splats, other argument splats are faster,
with the speedup depending on the number of arguments.

The following types of calls are not optimized:

* send(*args)
* send(*args, **kw)

This is because the you cannot shift the method argument off
without first splatting the arg.
2023-04-25 08:06:16 -07:00
Jeremy Evans af2da6419a Optimize cfunc calls for f(*a) and f(*a, **kw) if kw is empty
This optimizes the following calls:

* ~10-15% for f(*a) when a does not end with a flagged keywords hash
* ~10-15% for f(*a) when a ends with an empty flagged keywords hash
* ~35-40% for f(*a, **kw) if kw is empty

This still copies the array contents to the VM stack, but avoids some
overhead. It would be faster to use the array pointer directly,
but that could cause problems if the array was modified during
the call to the function. You could do that optimization for frozen
arrays, but as splatting frozen arrays is uncommon, and the speedup
is minimal (<5%), it doesn't seem worth it.

The vm_send_cfunc benchmark has been updated to test additional cfunc
call types, and the numbers above were taken from the benchmark results.
2023-04-25 08:06:16 -07:00
Jeremy Evans f6254f77f7 Speed up calling iseq bmethods
Currently, bmethod arguments are copied from the VM stack to the
C stack in vm_call_bmethod, then copied from the C stack to the VM
stack later in invoke_iseq_block_from_c.  This is inefficient.

This adds vm_call_iseq_bmethod and vm_call_noniseq_bmethod.
vm_call_iseq_bmethod is an optimized method that skips stack
copies (though there is one copy to remove the receiver from
the stack), and avoids calling vm_call_bmethod_body,
rb_vm_invoke_bmethod, invoke_block_from_c_proc,
invoke_iseq_block_from_c, and vm_yield_setup_args.

Th vm_call_iseq_bmethod argument handling is similar to the
way normal iseq methods are called, and allows for similar
performance optimizations when using splats or keywords.
However, even in the no argument case it's still significantly
faster.

A benchmark is added for bmethod calling.  In my environment,
it improves bmethod calling performance by 38-59% for simple
bmethod calls, and up to 180% for bmethod calls passing
literal keywords on both sides.

```

./miniruby-iseq-bmethod:  18159792.6 i/s
          ./miniruby-m:  13174419.1 i/s - 1.38x  slower

                   bmethod_simple_1
./miniruby-iseq-bmethod:  15890745.4 i/s
          ./miniruby-m:  10008972.7 i/s - 1.59x  slower

             bmethod_simple_0_splat
./miniruby-iseq-bmethod:  13142804.3 i/s
          ./miniruby-m:  11168595.2 i/s - 1.18x  slower

             bmethod_simple_1_splat
./miniruby-iseq-bmethod:  12375791.0 i/s
          ./miniruby-m:   8491140.1 i/s - 1.46x  slower

                   bmethod_no_splat
./miniruby-iseq-bmethod:  10151258.8 i/s
          ./miniruby-m:   8716664.1 i/s - 1.16x  slower

                    bmethod_0_splat
./miniruby-iseq-bmethod:   8138802.5 i/s
          ./miniruby-m:   7515600.2 i/s - 1.08x  slower

                    bmethod_1_splat
./miniruby-iseq-bmethod:   8028372.7 i/s
          ./miniruby-m:   5947658.6 i/s - 1.35x  slower

                   bmethod_10_splat
./miniruby-iseq-bmethod:   6953514.1 i/s
          ./miniruby-m:   4840132.9 i/s - 1.44x  slower

                  bmethod_100_splat
./miniruby-iseq-bmethod:   5287288.4 i/s
          ./miniruby-m:   2243218.4 i/s - 2.36x  slower

                         bmethod_kw
./miniruby-iseq-bmethod:   8931358.2 i/s
          ./miniruby-m:   3185818.6 i/s - 2.80x  slower

                      bmethod_no_kw
./miniruby-iseq-bmethod:  12281287.4 i/s
          ./miniruby-m:  10041727.9 i/s - 1.22x  slower

                   bmethod_kw_splat
./miniruby-iseq-bmethod:   5618956.8 i/s
          ./miniruby-m:   3657549.5 i/s - 1.54x  slower
```
2023-04-25 08:06:16 -07:00
Jeremy Evans 99c6d19e50 Generalize cfunc large array splat fix to fix many additional cases raising SystemStackError
Originally, when 2e7bceb34e fixed cfuncs to no
longer use the VM stack for large array splats, it was thought to have fully
fixed Bug #4040, since the issue was fixed for methods defined in Ruby (iseqs)
back in Ruby 2.2.

After additional research, I determined that same issue affects almost all
types of method calls, not just iseq and cfunc calls.  There were two main
types of remaining issues, important cases (where large array splat should
work) and pedantic cases (where large array splat raised SystemStackError
instead of ArgumentError).

Important cases:

```ruby
define_method(:a){|*a|}
a(*1380888.times)

def b(*a); end
send(:b, *1380888.times)

:b.to_proc.call(self, *1380888.times)

def d; yield(*1380888.times) end
d(&method(:b))

def self.method_missing(*a); end
not_a_method(*1380888.times)

```

Pedantic cases:

```ruby
def a; end
a(*1380888.times)
def b(_); end
b(*1380888.times)
def c(_=nil); end
c(*1380888.times)

c = Class.new do
  attr_accessor :a
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)

c = Struct.new(:a) do
  alias b a=
end.new
c.a(*1380888.times)
c.b(*1380888.times)
```

This patch fixes all usage of CALLER_SETUP_ARG with splatting a large
number of arguments, and required similar fixes to use a temporary
hidden array in three other cases where the VM would use the VM stack
for handling a large number of arguments.  However, it is possible
there may be additional cases where splatting a large number
of arguments still causes a SystemStackError.

This has a measurable performance impact, as it requires additional
checks for a large number of arguments in many additional cases.

This change is fairly invasive, as there were many different VM
functions that needed to be modified to support this. To avoid
too much API change, I modified struct rb_calling_info to add a
heap_argv member for storing the array, so I would not have to
thread it through many functions.  This struct is always stack
allocated, which helps ensure sure GC doesn't collect it early.

Because of how invasive the changes are, and how rarely large
arrays are actually splatted in Ruby code, the existing test/spec
suites are not great at testing for correct behavior.  To try to
find and fix all issues, I tested this in CI with
VM_ARGC_STACK_MAX to -1, ensuring that a temporary array is used
for all array splat method calls.  This was very helpful in
finding breaking cases, especially ones involving flagged keyword
hashes.

Fixes [Bug #4040]

Co-authored-by: Jimmy Miller <jimmy.miller@shopify.com>
2023-04-25 08:06:16 -07:00
Aaron Patterson b816ea8772 Implement opt_newarray_send in YJIT
This commit implements opt_newarray_send along with min / max / hash for
stack allocated arrays
2023-04-18 17:16:22 -07:00
Aaron Patterson c5fc1ce975 Emit special instruction for array literal + .(hash|min|max)
This commit introduces a new instruction `opt_newarray_send` which is
used when there is an array literal followed by either the `hash`,
`min`, or `max` method.

```
[a, b, c].hash
```

Will emit an `opt_newarray_send` instruction.  This instruction falls
back to a method call if the "interested" method has been monkey
patched.

Here are some examples of the instructions generated:

```
$ ./miniruby --dump=insns -e '[@a, @b].max'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE)
0000 getinstancevariable                    :@a, <is:0>               (   1)[Li]
0003 getinstancevariable                    :@b, <is:1>
0006 opt_newarray_send                      2, :max
0009 leave
$ ./miniruby --dump=insns -e '[@a, @b].min'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE)
0000 getinstancevariable                    :@a, <is:0>               (   1)[Li]
0003 getinstancevariable                    :@b, <is:1>
0006 opt_newarray_send                      2, :min
0009 leave
$ ./miniruby --dump=insns -e '[@a, @b].hash'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE)
0000 getinstancevariable                    :@a, <is:0>               (   1)[Li]
0003 getinstancevariable                    :@b, <is:1>
0006 opt_newarray_send                      2, :hash
0009 leave
```

[Feature #18897] [ruby-core:109147]

Co-authored-by: John Hawthorn <jhawthorn@github.com>
2023-04-18 17:16:22 -07:00
Peter Zhu ad3d4e87d7 Move RCLASS_CLONED to rb_classext_struct
This commit moves RCLASS_CLONED from the flags to the
rb_classext_struct. This frees the FL_USER1 bit.
2023-04-16 11:06:31 -04:00
Koichi Sasada c9fd81b860 `vm_call_single_noarg_inline_builtin`
If the iseq only contains `opt_invokebuiltin_delegate_leave` insn and
the builtin-function (bf) is inline-able, the caller doesn't need to
build a method frame.

`vm_call_single_noarg_inline_builtin` is fast path for such cases.
2023-03-23 14:03:12 +09:00
Aaron Patterson 54dbd8bea8 Use an st table for "too complex" objects
st tables will maintain insertion order so we can marshal dump / load
objects with instance variables in the same order they were set on that
particular instance

[ruby-core:112926] [Bug #19535]

Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
2023-03-20 13:54:18 -07:00
Takashi Kokubun 9a43c63d43
YJIT: Implement throw instruction (#7491)
* Break up jit_exec from vm_sendish

* YJIT: Implement throw instruction

* YJIT: Explain what rb_vm_throw does [ci skip]
2023-03-14 13:39:06 -07:00
Takashi Kokubun 94da5f7c36 Rename builtin attr :inline to :leaf 2023-03-11 14:25:12 -08:00
Takashi Kokubun 0c0c88d383 Support multiple attributes with Primitive.attr! 2023-03-11 14:19:46 -08:00
Ole Friis Østergaard 1a3f8e1c9f Add defined_ivar instruction
This is a variation of the `defined` instruction, for use when we
are checking for an instance variable. Splitting this out as a
separate instruction lets us skip some checks, and it also allows
us to use an instance variable cache, letting shape analysis
speed up the operation further.
2023-03-08 09:34:31 -08:00
Takashi Kokubun 23ec248e48 s/mjit/rjit/ 2023-03-06 23:44:01 -08:00
Takashi Kokubun 2e875549a9 s/MJIT/RJIT/ 2023-03-06 23:44:01 -08:00
Takashi Kokubun 290e26c729 Remove obsoleted MJIT_HEADER macro 2023-03-06 22:29:35 -08:00
Takashi Kokubun 7fb36a0054 Remove obsoleted MJIT_STATIC macro 2023-03-06 22:29:35 -08:00
Takashi Kokubun 233ddfac54 Stop exporting symbols for MJIT 2023-03-06 21:59:23 -08:00
Takashi Kokubun feb60f6f51 Invalidate blocks on constant IC updates 2023-03-05 23:28:59 -08:00
Takashi Kokubun e4a824f769 Fix broken rebase 2023-03-05 22:11:20 -08:00
Koichi Sasada e87d088291 Change bytecode of `f(*a, **kw)`
`f(*a, **kw)` is compiled to `f([*a, kw])` but it makes an dummy
array, so change it to pass two arguments `a` and `kw` with calling
flags.

```
ruby 3.2.0 (2022-12-29 revision a7d467a792) [x86_64-linux]
Calculating -------------------------------------
               foo()     15.354M (± 4.2%) i/s -     77.295M in   5.043650s
              dele()     13.439M (± 3.9%) i/s -     67.109M in   5.001974s
             dele(*)      6.265M (± 4.5%) i/s -     31.730M in   5.075649s
            dele(*a)      6.286M (± 3.3%) i/s -     31.719M in   5.051516s
      dele(*a, **kw)      1.926M (± 4.5%) i/s -      9.753M in   5.076487s
         dele(*, **)      1.927M (± 4.2%) i/s -      9.710M in   5.048224s
           dele(...)      5.871M (± 3.9%) i/s -     29.471M in   5.028023s
         forwardable      4.969M (± 4.1%) i/s -     25.233M in   5.087498s

ruby 3.3.0dev (2023-01-13T01:28:00Z master 7e8802fa5b) [x86_64-linux]
Calculating -------------------------------------
               foo()     16.354M (± 4.7%) i/s -     81.799M in   5.014561s
              dele()     14.256M (± 3.5%) i/s -     71.656M in   5.032883s
             dele(*)      6.701M (± 3.8%) i/s -     33.948M in   5.074938s
            dele(*a)      6.681M (± 3.3%) i/s -     33.578M in   5.031720s
      dele(*a, **kw)      4.200M (± 4.4%) i/s -     21.258M in   5.072583s
         dele(*, **)      4.197M (± 5.3%) i/s -     21.322M in   5.096684s
           dele(...)      6.039M (± 6.8%) i/s -     30.355M in   5.052662s
         forwardable      4.788M (± 3.2%) i/s -     24.033M in   5.024875s
```
2023-03-06 15:03:06 +09:00
Peter Zhu 62c2082f1f [Bug #19469] Fix crash when resizing generic iv list
The following script can sometimes trigger a crash:

```ruby
GC.stress = true

class Array
  def foo(bool)
    if bool
      @a = 1
      @b = 2
      @c = 1
    else
      @c = 1
    end
  end
end

obj = []
obj.foo(true)

obj2 = []
obj2.foo(false)

obj3 = []
obj3.foo(true)
```

This is because vm_setivar_default calls rb_ensure_generic_iv_list_size
to resize the iv list. However, the call to gen_ivtbl_resize reallocs
the iv list, and then inserts into the generic iv table. If the
st_insert triggers a GC then the old iv list will be read during
marking, causing a use-after-free bug.

Co-Authored-By: Jemma Issroff <jemmaissroff@gmail.com>
2023-03-03 16:12:03 -05:00
Peter Zhu 0700d0fd1c Fix indentation in vm_setivar_default 2023-03-03 16:12:03 -05:00
Aaron Patterson ae2340c9d7 Refactor / document instance variable debug counters
This commit is refactoring and documenting the debug counters related to
instance variables.
2023-02-15 08:47:26 -08:00
Takashi Kokubun 3d20740881 Remove unneeded repetitions 2023-02-04 13:46:46 -08:00