Commit graph

196 commits

Author SHA1 Message Date
Étienne Barrié
12be40ae6b Implement chilled strings
[Feature #20205]

As a path toward enabling frozen string literals by default in the future,
this commit introduce "chilled strings". From a user perspective chilled
strings pretend to be frozen, but on the first attempt to mutate them,
they lose their frozen status and emit a warning rather than to raise a
`FrozenError`.

Implementation wise, `rb_compile_option_struct.frozen_string_literal` is
no longer a boolean but a tri-state of `enabled/disabled/unset`.

When code is compiled with frozen string literals neither explictly enabled
or disabled, string literals are compiled with a new `putchilledstring`
instruction. This instruction is identical to `putstring` except it marks
the String with the `STR_CHILLED (FL_USER3)` and `FL_FREEZE` flags.

Chilled strings have the `FL_FREEZE` flag as to minimize the need to check
for chilled strings across the codebase, and to improve compatibility with
C extensions.

Notes:
  - `String#freeze`: clears the chilled flag.
  - `String#-@`: acts as if the string was mutable.
  - `String#+@`: acts as if the string was mutable.
  - `String#clone`: copies the chilled flag.

Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2024-03-19 09:26:49 +01:00
Alan Wu
802e857ae6
YJIT: Support arity=-2 cfuncs (#10268)
This type of cfuncs shows up as consume a lot of cycles in profiles of
the lobsters benchmark, even though in the stats they don't happen that
frequently. Might be a bug in the profiling, but these calls are not
too bad to support, so might as well do it.

Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
2024-03-18 16:02:22 +00:00
Jean Boussier
09d8c99cdc Ensure test suite is compatible with --frozen-string-literal
As preparation for https://bugs.ruby-lang.org/issues/20205
making sure the test suite is compatible with frozen string
literals is making things easier.
2024-03-14 17:56:15 +01:00
Takashi Kokubun
5891c70b38
YJIT: Support inlining putself (#10137) 2024-02-29 11:08:57 -05:00
Alan Wu
558b58d330 YJIT: Reject keywords hash in -1 arity cfunc splat support
`test_keyword.rb` caught this issue. Just need to run with `threshold=1`
2024-02-28 15:00:26 -05:00
Alan Wu
11f121364a
YJIT: Support splat with C methods with -1 arity
Usually we deal with splats by speculating that they're of a specific
size. In this case, the C method takes a pointer and a length, so
we can support changing sizes just fine.
2024-02-27 17:50:38 +00:00
Takashi Kokubun
8a6740c70e
YJIT: Lazily push a frame for specialized C funcs (#10080)
* YJIT: Lazily push a frame for specialized C funcs

Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>

* Fix a comment on pc_to_cfunc

* Rename rb_yjit_check_pc to rb_yjit_lazy_push_frame

* Rename it to jit_prepare_lazy_frame_call

* Fix a typo

* Optimize String#getbyte as well

* Optimize String#byteslice as well

---------

Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
2024-02-23 19:08:09 +00:00
Alan Wu
35fdf1a624 YJIT: Remove duplicate test 2024-02-20 16:53:36 -05:00
Alan Wu
8e1090487e YJIT: Fix calling leaf builtins with empty splat and kw_splat
These don't pass anything and just need to be popped off the stack.

2178009528 (step):13:104
2024-02-20 16:53:36 -05:00
Takashi Kokubun
9216a2ac43
YJIT: Verify the assumption of leaf C calls (#10002) 2024-02-20 13:42:29 -08:00
Alan Wu
c4e30d2865 YJIT: Support **nil
This adds YJIT support for VM_CALL_KW_SPLAT with nil, specifically for
when we already know from the context that it's done with a nil. This is
enough to support forwarding with `...` when there no keyword arguments
are present.

Amend the kw_rest support to propagate the type of the parameter to help
with this. Test interactions with splat, since the splat array sits
lower on the stack when a kw_splat argument is present.
2024-02-16 15:27:49 -05:00
Alan Wu
fdaef7a72e YJIT: Fixup kwrest stack base
I was a little rushed and didn't notice that it was still using the
final stack size even though we don't grow the stack before kwrest
handling anymore. Oh well, we got a new test out of it.

Fix: cbdabd5890
2024-02-13 12:16:36 -05:00
Alan Wu
44f0dc622a YJIT: Allow popping before falling back
Popping but not generating any code before returning `None` was allowed
before fallbacks were introduced so this is restoring that support in
the same way. The included test used to trip an assert due to popping
too much.
2024-02-06 16:17:54 -05:00
Alan Wu
bae3e5b29a YJIT: No need to reject splat+zsuper
There is nothing special about argument handling when it comes to zsuper
if you look around in the VM. Everything passes removing these fallback
reasons. It was ~16% on `railsbench`.
2024-02-05 16:13:22 -05:00
Takashi Kokubun
09427f51a2
YJIT: Add codegen for Float arithmetics (#9774)
* YJIT: Add codegen for Float arithmetics

* Add Flonum and Fixnum tests
2024-01-31 17:58:47 +00:00
Takashi Kokubun
c1f8d974a8
YJIT: Specialize splatkw on T_HASH (#9764)
* YJIT: Specialize splatkw on T_HASH

* Fix a typo

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>

* Fix a few more comments

---------

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2024-01-30 14:59:53 -05:00
Maxime Chevalier-Boisvert
fe5590e464
YJIT: add specialized codegen for fixnum XOR (#9763) 2024-01-30 14:57:13 -05:00
Takashi Kokubun
7567e4e1e1
YJIT: Fix exits on splatkw instruction (#9711) 2024-01-26 00:22:27 +00:00
Takashi Kokubun
2034e6ad5a
YJIT: Support concattoarray and pushtoarray (#9708) 2024-01-25 21:45:58 +00:00
Alan Wu
ac1e9e443a YJIT: Fix ruby2_keywords splat+rest and drop bogus checks
YJIT didn't guard for ruby2_keywords hash in case of splat calls that
land in methods with a rest parameter, creating incorrect results.

The compile-time checks didn't correspond to any actual effects of
ruby2_keywords, so it was masking this bug and YJIT was needlessly
refusing to compile some code. About 16% of fallback reasons in
`lobsters` was due to the ISeq check.

We already handle the tagging part with
exit_if_supplying_kw_and_has_no_kw() and should now have a dynamic guard
for all splat cases.

Note for backporting: You also need 7f51959ff1.

[Bug #20195]
2024-01-23 19:22:57 -05:00
Peter Zhu
7ac74f5c77 Revert "Skip a failing test for Prism"
This reverts commit 557b69e83b.
2024-01-23 15:23:48 -05:00
Takashi Kokubun
557b69e83b Skip a failing test for Prism
This should be reverted once https://github.com/ruby/prism/issues/2249
is closed.
2024-01-23 11:00:05 -08:00
Alan Wu
7f51959ff1 YJIT: Move guard up for a case of splat+rest
Previously, YJIT put the guard for having enough items to extract from
splat array at a place where the side exit is invalid, so if the guard
fails, YJIT could raise something other than ArgumentError. Move the
guard up to a place before any stack manipulation.

[Bug #20204]
2024-01-23 11:04:16 -05:00
Alan Wu
703eee7745
YJIT: Drop extra arguments passed by yield (#9596)
Support dropping extra arguments passed by `yield` in blocks. For
example `10.times { work }` drops the count argument. This is common
enough that it's about 3% of fallback reasons in `lobsters`.

Only support simple cases where the surplus arguments are at the top of
the stack, that way they just need to be popped, which takes no work.
2024-01-22 11:55:44 -05:00
Takashi Kokubun
3c9290173a
YJIT: Optimize defined?(yield) (#9599)
* YJIT: Optimize defined?(yield)

* Remove an irrelevant comment

* s/get/gen/
2024-01-19 11:00:46 -05:00
Alan Wu
bbd249e351 YJIT: Properly reject keyword splat with yield
We don't have support for keyword splat anywhere, but we tried to
compile these anyways in case of `invokeblock`. This led to bad things
happening such as passing the wrong value and passing a hash into
rb_yjit_array_len(), which raised in the middle of compilation.

[Bug #20192]
2024-01-18 20:22:40 -05:00
Maxime Chevalier-Boisvert
afba09d30f
YJIT: specialized codegen for integer right shift (#9564)
* YJIT: specialized codegen for integer right shift

Used in optcarrot. May also be used to write pure-Ruby gems.
No overflow check or fixnum untagging required.

* Update yjit/src/codegen.rs

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

---------

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2024-01-17 10:35:48 -05:00
Takashi Kokubun
5e61cc26c9
YJIT: Optimize Integer#succ (#9519) 2024-01-15 10:32:48 -05:00
ywenc
16624ef463
YJIT: expandarray for non-arrays (#9495)
* YJIT: expandarray for non-arrays

Co-authored-by: John Hawthorn <john@hawthorn.email>

* Skip the new test on RJIT

* Increment counter for to_ary exit

---------

Co-authored-by: John Hawthorn <john@hawthorn.email>
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2024-01-12 15:41:58 +00:00
Hiroshi SHIBATA
863ded45a1
Typofix under bootstraptest, spec and yjit directories 2023-12-25 13:50:23 +09:00
Takashi Kokubun
78b27ce62a RJIT: Streamline RJIT enablement check
in bootstrap tests so that `make btest-bruby` skips the right tests.
2023-12-21 14:32:03 -08:00
Alan Wu
d4bbee7475
YJIT: Fix off-by-one in Kernel#send type handling (#9212)
Previously, if the method ID argument happens to be on one below the top
of the stack, we didn't overwrite the type of the stack slot, which
leaves an incorrect type for the stack slot. The included script tripped
asserts both with and without --yjit-verify-ctx.
2023-12-12 22:10:14 +00:00
Alan Wu
4eca329d29 Skip a YJIT test on RJIT 2023-12-11 19:21:08 -05:00
Alan Wu
9cb0ad863c YJIT: Fix missing arity check for splat calls to methods with optionals
Previously, for splat callsites that land in methods with optional
parameters, we didn't reject the case where the caller supplies too many
arguments. Accepting those calls previously caused YJIT to construct
corrupted control frames, which leads to crashes if the callee uses
certain stack walking methods such as Kernel#raise and String#gsub (for
setting up the frame-local `$~`).

Example crash in a debug build:

    Assertion Failed: ../vm_core.h:1375:VM_ENV_FLAGS:FIXNUM_P(flags)
2023-12-11 19:21:08 -05:00
Takashi Kokubun
a439fc2f17
YJIT: Avoid register allocation conflict with a higher stack_idx (#9143)
YJIT: Avoid register allocation conflict

with a higher stack_idx
2023-12-06 15:19:43 -05:00
Alan Wu
b5a62eb9ab
YJIT: Mark and update stubs in invalidated blocks (#9104)
Like in the example given in delayed_deallocation(), stubs can be hit
even if the block housing it is invalidated. Mark them so we don't
work with invalidate ISeqs when hitting these stubs.
2023-12-04 10:13:40 -05:00
Takashi Kokubun
926bfc3bc0
YJIT: Avoid a register spill on arm64 (#9014) 2023-11-22 15:13:32 -08:00
Maxime Chevalier-Boisvert
7a93bee4f8
YJIT: add an extra btest for shape too complex (#9013)
Following Jean Boussier's comment that some shape bugs were not
caught by our tests, I'm trying to improve our test coverage a
tiny bit.
2023-11-22 19:06:37 +00:00
Takashi Kokubun
9877f3ada8
YJIT: Inline basic Ruby methods (#8855)
* YJIT: Inline basic Ruby methods

* YJIT: Fix "InsnOut operand made it past register allocation"

checktype should not generate a useless instruction.
2023-11-07 10:54:33 -05:00
Alan Wu
0bf1749e9f
YJIT: Fix argument clobbering in some block_arg+rest_param calls (#8647)
Previously, for block argument callsites with some specific argument
count and callee local variable count combinations, YJIT ended up
writing over arguments that are supposed to be collected into a rest
parameter array unmodified.

Detect when clobbering would happen and avoid it. Also, place the block
handler after the stack overflow check, since it writes to new stack
space.

Reported-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-10-13 10:41:53 -04:00
Takashi Kokubun
0b67e3fd3e
YJIT: Chain-guard opt_mult overflow (#8554)
* YJIT: Chain-guard opt_mult overflow

* YJIT: Support regenerating Jo after Mul
2023-09-29 21:55:48 -04:00
Alan Wu
7cec7d14c3
YJIT: Fix object movement bug in iseq guard for invokeblock
Since the compile-time iseq used in the guard was not marked and updated
during compaction, a runtime value reusing the address could falsely pass
the guard.

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-09-15 19:03:48 -04:00
Ian Candy
78233e8352
Add String#getbyte YJIT implementation (#8397)
* Add getbyte JIT implementation

Adds an implementation for String#getbyte for YJIT, along with a
bootstrap test. This should be helpful for pure Ruby implementations
and to avoid unneeded allocations.

Co-authored-by: John Hawthorn <jhawthorn@github.com>

* Skip the getbyte test for RJIT for now

---------

Co-authored-by: John Hawthorn <jhawthorn@github.com>
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2023-09-07 23:15:24 -04:00
Alan Wu
23c83d172c YJIT: Remove Type::CArray and limit use of Type::CString
These types are essentially claims about what `RBASIC_CLASS(obj)`
returns. The field changes with singleton class creation, but we didn't
consider so previously and elided guards where we actually needed them.

Found running ruby/spec with --yjit-verify-ctx. The assertion interface
makes extensive use of singleton classes.
2023-08-28 17:14:33 -04:00
Alan Wu
4524aeba2f YJIT: Fix return type of Integer#/ with T_FIXNUM inputs
Issue found by running ruby/spec with `--yjit-verify-ctx`. Thanks!
2023-08-18 12:17:37 -04:00
Maxime Chevalier-Boisvert
314eed8a5e
YJIT: implement fast path for integer multiplication in opt_mult (#8204)
* YJIT: implement fast path for integer multiplication in opt_mult

* Update yjit/src/codegen.rs

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>

* Implement mul with overflow checking on arm64

* Fix missing semicolon

* Add arm splitting for lshift, rshift, urshift

---------

Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2023-08-18 10:05:32 -04:00
Alan Wu
5d48825d55 YJIT: Fix String#<< return type
We previously falsely asserted that String#<< always returns a ::String
instance. Issue was discovered on CI with `--yjit-verify-ctx`.

1598600253
2023-08-17 17:17:31 -04:00
Alan Wu
9acc73d7c5
YJIT: Optional parameter rework and bugfix (#8220)
* YJIT: Fix splatting empty array with rest param

* YJIT: Rework optional parameter handling to fix corner case

The old code had a few unintuitive parts. The starting PC of the callee
was set in different places; `num_param`, which one would assume to be
static for a particular callee seemingly tallied to different amounts
depending on the what the caller passed; `opts_filled_with_splat` was
greater than zero even when the opts were not filled by items in the
splat array. Functionally, the bits that lets the callee know which
keyword parameters are unspecified were not passed properly when there
are optional parameters and a rest parameter, and then optional
parameters are all filled.

Make `num_param` non-mut and use parameter information in the callee
iseq as-is. Move local variable nil fill and placing of the rest array
out of `gen_push_frame()` as they are only ever relevant for iseq calls.
Always place the rest array at `lead_num + opt_num` to fix the
previously buggy situation.

* YJIT: Compile splat calls to iseqs with rest params

Test interactions with optional parameters.
2023-08-15 10:08:48 -04:00
Takashi Kokubun
02e5095108
YJIT: Implement GET_BLOCK_HANDLER() for invokesuper (#8206) 2023-08-11 13:07:16 -07: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