Commit graph

20692 commits

Author SHA1 Message Date
Kevin Newton
9bd5995b40 [PRISM] Remove duplicated tests
These tests are flaky and are duplicative of other tests that are
run in CI when parser=prism.
2024-06-20 09:24:19 -04:00
David Rodríguez
0a9f1ecc37 [rubygems/rubygems] Add a regression test for previous bundler update --bundler fix
c392593dc3
2024-06-20 09:26:33 +00:00
Nobuyoshi Nakada
92ab2dac22 [rubygems/rubygems] Check if failed with the expected error
3f22e9df8d
2024-06-20 07:16:56 +00:00
Nobuyoshi Nakada
e345970707 [rubygems/rubygems] Revert "Workaround for TruffleRuby that set nil to LIBRUBY_RELATIVE"
This reverts commit 06fd399973, for a
bug that is fixed by 0148cce153.

907e51e521
2024-06-20 07:16:55 +00:00
Jean Boussier
83f57ca3d2 String.new(capacity:) don't substract termlen
[Bug #20585]

This was changed in 36a06efdd9 because
`String.new(1024)` would end up allocating `1025` bytes, but the problem
with this change is that the caller may be trying to right size a String.

So instead, we should just better document the behavior of `capacity:`.
2024-06-19 15:11:07 +02:00
Nobuyoshi Nakada
321ed86e93 [rubygems/rubygems] Do not set previously unset value
0148cce153
2024-06-19 11:42:35 +00:00
Nobuyoshi Nakada
57e15074fe [rubygems/rubygems] Workaround for TruffleRuby that set nil to LIBRUBY_RELATIVE
06fd399973
2024-06-19 11:42:35 +00:00
Nobuyoshi Nakada
378e65af9a [rubygems/rubygems] Dump RbConfig elements to escape special characters
Naively embed strings do not work if special characters (newline,
backslahes and so on) are contained.

ac2c4c4af1
2024-06-19 11:42:34 +00:00
Kevin Newton
dfb67a4433 [ruby/prism] (parser) Print when token tests are now passing
9e4fb665ee
2024-06-18 21:18:39 -04:00
Kevin Newton
24f48382bc [ruby/prism] (parser) Fix up tokens for empty symbol
5985ab7687
2024-06-18 21:18:39 -04:00
Peter Zhu
eb215c8dc6 Fix flaky TestWeakMap#test_inspect_garbage
If a GC is ran before the assert_match, then the WeakMap would be empty
and would not have any objects, so the regular expression match would
fail. This changes the regular expression to work even if the WeakMap
is empty.
2024-06-18 14:21:37 -04:00
Aaron Patterson
cfc5646cdc fix allocation assertions 2024-06-18 09:28:25 -07:00
Aaron Patterson
cdf33ed5f3 Optimized forwarding callers and callees
This patch optimizes forwarding callers and callees. It only optimizes methods that only take `...` as their parameter, and then pass `...` to other calls.

Calls it optimizes look like this:

```ruby
def bar(a) = a
def foo(...) = bar(...) # optimized
foo(123)
```

```ruby
def bar(a) = a
def foo(...) = bar(1, 2, ...) # optimized
foo(123)
```

```ruby
def bar(*a) = a

def foo(...)
  list = [1, 2]
  bar(*list, ...) # optimized
end
foo(123)
```

All variants of the above but using `super` are also optimized, including a bare super like this:

```ruby
def foo(...)
  super
end
```

This patch eliminates intermediate allocations made when calling methods that accept `...`.
We can observe allocation elimination like this:

```ruby
def m
  x = GC.stat(:total_allocated_objects)
  yield
  GC.stat(:total_allocated_objects) - x
end

def bar(a) = a
def foo(...) = bar(...)

def test
  m { foo(123) }
end

test
p test # allocates 1 object on master, but 0 objects with this patch
```

```ruby
def bar(a, b:) = a + b
def foo(...) = bar(...)

def test
  m { foo(1, b: 2) }
end

test
p test # allocates 2 objects on master, but 0 objects with this patch
```

How does it work?
-----------------

This patch works by using a dynamic stack size when passing forwarded parameters to callees.
The caller's info object (known as the "CI") contains the stack size of the
parameters, so we pass the CI object itself as a parameter to the callee.
When forwarding parameters, the forwarding ISeq uses the caller's CI to determine how much stack to copy, then copies the caller's stack before calling the callee.
The CI at the forwarded call site is adjusted using information from the caller's CI.

I think this description is kind of confusing, so let's walk through an example with code.

```ruby
def delegatee(a, b) = a + b

def delegator(...)
  delegatee(...)  # CI2 (FORWARDING)
end

def caller
  delegator(1, 2) # CI1 (argc: 2)
end
```

Before we call the delegator method, the stack looks like this:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
              4|   #                                   |
              5|   delegatee(...)  # CI2 (FORWARDING)  |
              6| end                                   |
              7|                                       |
              8| def caller                            |
          ->  9|   delegator(1, 2) # CI1 (argc: 2)     |
             10| end                                   |
```

The ISeq for `delegator` is tagged as "forwardable", so when `caller` calls in
to `delegator`, it writes `CI1` on to the stack as a local variable for the
`delegator` method.  The `delegator` method has a special local called `...`
that holds the caller's CI object.

Here is the ISeq disasm fo `delegator`:

```
== disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] "..."@0
0000 putself                                                          (   1)[LiCa]
0001 getlocal_WC_0                          "..."@0
0003 send                                   <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil
0006 leave                                  [Re]
```

The local called `...` will contain the caller's CI: CI1.

Here is the stack when we enter `delegator`:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
           -> 4|   #                                   | CI1 (argc: 2)
              5|   delegatee(...)  # CI2 (FORWARDING)  | cref_or_me
              6| end                                   | specval
              7|                                       | type
              8| def caller                            |
              9|   delegator(1, 2) # CI1 (argc: 2)     |
             10| end                                   |
```

The CI at `delegatee` on line 5 is tagged as "FORWARDING", so it knows to
memcopy the caller's stack before calling `delegatee`.  In this case, it will
memcopy self, 1, and 2 to the stack before calling `delegatee`.  It knows how much
memory to copy from the caller because `CI1` contains stack size information
(argc: 2).

Before executing the `send` instruction, we push `...` on the stack.  The
`send` instruction pops `...`, and because it is tagged with `FORWARDING`, it
knows to memcopy (using the information in the CI it just popped):

```
== disasm: #<ISeq:delegator@-e:1 (1,0)-(1,39)>
local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 1] "..."@0
0000 putself                                                          (   1)[LiCa]
0001 getlocal_WC_0                          "..."@0
0003 send                                   <calldata!mid:delegatee, argc:0, FCALL|FORWARDING>, nil
0006 leave                                  [Re]
```

Instruction 001 puts the caller's CI on the stack.  `send` is tagged with
FORWARDING, so it reads the CI and _copies_ the callers stack to this stack:

```
Executing Line | Code                                  | Stack
---------------+---------------------------------------+--------
              1| def delegatee(a, b) = a + b           | self
              2|                                       | 1
              3| def delegator(...)                    | 2
              4|   #                                   | CI1 (argc: 2)
           -> 5|   delegatee(...)  # CI2 (FORWARDING)  | cref_or_me
              6| end                                   | specval
              7|                                       | type
              8| def caller                            | self
              9|   delegator(1, 2) # CI1 (argc: 2)     | 1
             10| end                                   | 2
```

The "FORWARDING" call site combines information from CI1 with CI2 in order
to support passing other values in addition to the `...` value, as well as
perfectly forward splat args, kwargs, etc.

Since we're able to copy the stack from `caller` in to `delegator`'s stack, we
can avoid allocating objects.

I want to do this to eliminate object allocations for delegate methods.
My long term goal is to implement `Class#new` in Ruby and it uses `...`.

I was able to implement `Class#new` in Ruby
[here](https://github.com/ruby/ruby/pull/9289).
If we adopt the technique in this patch, then we can optimize allocating
objects that take keyword parameters for `initialize`.

For example, this code will allocate 2 objects: one for `SomeObject`, and one
for the kwargs:

```ruby
SomeObject.new(foo: 1)
```

If we combine this technique, plus implement `Class#new` in Ruby, then we can
reduce allocations for this common operation.

Co-Authored-By: John Hawthorn <john@hawthorn.email>
Co-Authored-By: Alan Wu <XrXr@users.noreply.github.com>
2024-06-18 09:28:25 -07:00
Stan Lo
921f22e563 [ruby/irb] Improve how command calls' return value is handled
(https://github.com/ruby/irb/pull/972)

In #934, we changed command calls to return nil only. This PR improves
the behaviour even further by:

- Not echoing the `nil` returned by command calls
- Not overriding previous return value stored in `_` with the
  `nil` from commands

c844176842
2024-06-18 15:15:23 +00:00
tomoya ishida
c2e2c5975d [ruby/reline] Fix vi_yank or vi_delete_meta copies nil bug
(https://github.com/ruby/reline/pull/726)

46b30b07c9
2024-06-18 14:57:19 +00:00
Alexey Schepin
a3930db275 [rubygems/rubygems] Delete extra spaces left after rubocop autofix
a552732bed
2024-06-18 01:52:04 +00:00
Yuta Saito
97a23db5ac [rubygems/rubygems] Disable install_extension_in_lib when cross-compiling
643e154f32
2024-06-18 00:59:36 +00:00
Yuta Saito
273d41b9e3 [rubygems/rubygems] Add --target-rbconfig option to gem install and gem update commands
This patch adds `--target-rbconfig` option to specify the rbconfig.rb file
for the deployment target platform. This is useful when cross-compiling
gems. At the moment, this option is only available for `extconf.rb`-based
extensions.

cf2843f7a2
2024-06-18 00:59:35 +00:00
Kevin Newton
7529591df1 [ruby/prism] Ensure ranges are non-associative
f59295938b
2024-06-14 19:22:54 +00:00
Nobuyoshi Nakada
a1f72a563b [Bug #20579] ripper: Dispatch spaces at END-OF-INPUT without newline 2024-06-14 17:54:02 +09:00
David Rodríguez
62fc473224 [rubygems/rubygems] Never remove executables that may belong to a default gem
ed585f2fca
2024-06-14 08:02:38 +00:00
David Rodríguez
7767b60ff2 [rubygems/rubygems] Reuse write_file helper
339f099870
2024-06-14 08:02:38 +00:00
Nobuyoshi Nakada
2e59cf00cc [Bug #20578] ripper: Fix dispatching part at invalid escapes 2024-06-14 15:02:15 +09:00
Kevin Newton
0321f2c8fe [ruby/prism] Handle implicit array precedence
When an implicit array is used in a write, is causes the whole
expression to become a statement. For example:

```ruby
a = *b
a = 1, 2, 3
```

Even though these expressions are exactly equivalent to their
explicit array counterparts:

```ruby
a = [*b]
a = [1, 2, 3]
```

As such, these expressions cannot be joined with other expressions
by operators or modifiers except if, unless, while, until, or
rescue.

7cd2407272
2024-06-13 18:46:02 +00:00
tompng
04467218ce Add rb_str_resize coderange test 2024-06-13 18:27:02 +02:00
David Rodríguez
5c573b7652 [rubygems/rubygems] Fix default gem priority when sorting specs
8dbe1dbdc7

Co-authored-by: MSP-Greg <Greg.mpls@gmail.com>
2024-06-13 14:25:14 +00:00
Koichi Sasada
fc33559c40 clear kw_flag if given hash is nil
https://bugs.ruby-lang.org/issues/20570 is caused I missed to
clear the `kw_flag` even if `keyword_hash` is nil.
2024-06-13 13:52:39 +09:00
Aaron Patterson
85190d4130 Add regression test for Bug #20573
Just a regression test to ensure behavior remains the same
2024-06-12 10:25:57 -07:00
tomoya ishida
783eaf70f8 [ruby/irb] Invalid encoding symbol now raises SyntaxError also in
3.3
(https://github.com/ruby/irb/pull/969)

bad7492ab0
2024-06-12 16:57:55 +00:00
Nobuyoshi Nakada
32a555ea53
[Bug #20572] Abandon if replacing destination is the same 2024-06-12 19:57:50 +09:00
tomoya ishida
c56d0adfa6 [ruby/irb] Cleanup irbrc generator cache always at teardown
(https://github.com/ruby/irb/pull/968)

905184ff9c
2024-06-12 07:48:03 +00:00
gartens
c735f4947e [ruby/openssl] Pass through nil as digest when signing certificates
(https://github.com/ruby/openssl/pull/761)

In order to sign certificates with Ed25519 keys, NULL must be passed
as md to X509_sign.  This NULL is then passed
(via ASN1_item_sign_ex) as type to EVP_DigestSignInit.  The
documentation[1] of EVP_DigestSignInit states that type must be NULL
for various key types, including Ed25519.

[1]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html

b0fc100091
2024-06-11 17:12:28 +00:00
Kevin Newton
47322b592a [ruby/prism] Match CRuby error message for unknown regexp options
73669b59f6
2024-06-11 12:34:00 +00:00
Jean Boussier
f0001a4fa7 compile.c: use putspecialobject for RubyVM::FrozenCore
[Bug #20569]

`putobject RubyVM::FrozenCore`, is not serializable, we
have to use `putspecialobject VM_SPECIAL_OBJECT_VMCORE`.
2024-06-11 09:08:48 +02:00
Kevin Newton
d827d32527 [ruby/prism] Provide ability to lock encoding while parsing
f7faedfb3f
2024-06-10 17:21:32 -04:00
Peter Zhu
556bbf64e0 Don't skip test_inspect_under_gc_compact_stress
Commit 1471a16 seems to have fixed this flaky test, so we don't need to
skip it for YJIT or RJIT anymore.
2024-06-10 12:36:25 -04:00
Kevin Newton
21e06e57af [ruby/prism] Allow block exits in loop predicates
f09db18e46
2024-06-10 13:42:40 +00:00
Stan Lo
2959e1b5ea [ruby/irb] Suppress Ruby warnings in certain backtrace filtering
tests
(https://github.com/ruby/irb/pull/966)

Since they're sensitive to the warnings, and the warnings are
not relevant to the tests, we can suppress them to keep the tests
simple.

ad642795da
2024-06-09 20:22:34 +00:00
Samuel Giddins
0b92929e52 [ruby/openssl] Add X509::Certificate#tbs_bytes
Ref https://github.com/ruby/openssl/issues/519

This makes verifying embedded certificate transparency signatures
significantly easier, as otherwise the alternative was manipulating the
ASN1 sequence, as in
656d992fa8

99128bea5d
2024-06-08 10:57:02 +00:00
Kevin Newton
41a36b6853 [ruby/prism] Handle chomped bytesize with lines without newlines
1528d3c019
2024-06-07 19:46:27 +00:00
Kevin Newton
94e059797a [ruby/prism] Document that nested heredocs are not properly parsed for parser
d218e65561
2024-06-07 19:46:24 +00:00
Kevin Newton
79e9dea8de [ruby/prism] Ensure inner heredoc nodes have the correct location
100340bc6b
2024-06-07 19:46:20 +00:00
Kevin Newton
ce0a352e34 [ruby/prism] Use correct newlines for heredoc inner lines
4a9a7a62af

Co-authored-by: Jason Kim <jasonkim@github.com>
Co-authored-by: Adam Hess <HParker@github.com>
2024-06-07 19:46:16 +00:00
Kevin Newton
792e9c46a4 Remove prism compiler warning 2024-06-07 12:24:05 -04:00
Peter Zhu
caac56584c Don't use SEGV signal when timeout in test_gc_compact
Using a SEGV signal for timeout makes it difficult to tell if it's a real
SEGV or if it timed out, so we should just use the default signals.
2024-06-07 11:55:38 -04:00
Yusuke Endoh
43cf0f99f9 TestRequire#test_loading_fifo_threading_success: Extend the timeout limit 2024-06-07 23:44:29 +09:00
Yusuke Endoh
239378613b TestRegexp#test_match_cache_positive_look_behind: Extend the timeout limit 2024-06-07 23:29:59 +09:00
Yusuke Endoh
36b3fea0ff TestRegexp#test_timeout_shorter_than_global: Extend the timeout limit 2024-06-07 23:11:10 +09:00
Yusuke Endoh
b9b207f388 TestRequire#test_loading_fifo_fd_leak: Extend the timeout limit 2024-06-07 23:03:49 +09:00
Yusuke Endoh
7944710ed4 TestGc#test_thrashing_for_young_objects: extend the timeout limit 2024-06-07 22:39:21 +09:00