Commit graph

244 commits

Author SHA1 Message Date
Eileen M. Uchitelle
459f9e3df8
Add setclassvariable to yjit (#5127)
Implements setclassvariable in yjit. Note that this version is not
faster than the standard version because we aren't handling the inline
cache in assembly. This is still important to implement because it will
prevent yjit from exiting in methods that call both a cvar setter and
other code that yjit can compile.

Co-authored-by: Aaron Patterson tenderlove@ruby-lang.org
2021-11-23 14:09:24 -05:00
Alan Wu
13d1ded253 YJIT: Make block invalidation more robust
This commit adds an entry_exit field to block_t for use in
invalidate_block_version(). By patching the start of the block while
invalidating it, invalidate_block_version() can function correctly
while there is no executable memory left for new branch stubs.

This change additionally fixes correctness for situations where we
cannot patch incoming jumps to the invalidated block. In situations
such as Shopify/yjit#226, the address to the start of the block
is saved and used later, possibly after the block is invalidated.

The assume_* family of function now generate block->entry_exit before
remembering blocks for invalidation.

RubyVM::YJIT.simulate_oom! is introduced for testing out of memory
conditions. The test for it is disabled for now because OOM triggers
other failure conditions not addressed by this commit.

Fixes Shopify/yjit#226
2021-11-22 18:23:28 -05:00
Adam Hess
73388aff5e
Add YJIT codegen for objtostring (#5149)
This is the minimal correct objtostring implementation in YJIT.
For correctness, it is important that to_string not get called on strings or subclasses of string.
There is a new test for this behavior.

A follow up should implement an optimized version for other types as performed in `vm_objtostring`.

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

Co-authored-by: John Hawthorn <jhawthorn@github.com>
2021-11-19 16:57:09 -05:00
Jeremy Evans
b08dacfea3
Optimize dynamic string interpolation for symbol/true/false/nil/0-9
This provides a significant speedup for symbol, true, false,
nil, and 0-9, class/module, and a small speedup in most other cases.

Speedups (using included benchmarks):
:symbol        :: 60%
0-9            :: 50%
Class/Module   :: 50%
nil/true/false :: 20%
integer        :: 10%
[]             :: 10%
""             :: 3%

One reason this approach is faster is it reduces the number of
VM instructions for each interpolated value.

Initial idea, approach, and benchmarks from Eric Wong. I applied
the same approach against the master branch, updating it to handle
the significant internal changes since this was first proposed 4
years ago (such as CALL_INFO/CALL_CACHE -> CALL_DATA). I also
expanded it to optimize true/false/nil/0-9/class/module, and added
handling of missing methods, refined methods, and RUBY_DEBUG.

This renames the tostring insn to anytostring, and adds an
objtostring insn that implements the optimization. This requires
making a few functions non-static, and adding some non-static
functions.

This disables 4 YJIT tests.  Those tests should be reenabled after
YJIT optimizes the new objtostring insn.

Implements [Feature #13715]

Co-authored-by: Eric Wong <e@80x24.org>
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
Co-authored-by: Yusuke Endoh <mame@ruby-lang.org>
Co-authored-by: Koichi Sasada <ko1@atdot.net>
2021-11-18 15:10:20 -08:00
Eileen M. Uchitelle
ec574ab345
Refactor getclassvariable (#5137)
* Refactor getclassvariable

We only need the cref when we have a cache miss so don't look it up until we
need it. This speeds up class variable reads in the interpreter but
also simplifies the jit code.

Benchmarks for master vs this branch (without yjit):

Before:

```
Warming up --------------------------------------
         read a cvar     1.276M i/100ms
Calculating -------------------------------------
         read a cvar     12.596M (± 1.7%) i/s -     63.781M in   5.064902s
```

After:

```
Warming up --------------------------------------
         read a cvar     1.336M i/100ms
Calculating -------------------------------------
         read a cvar     13.114M (± 3.6%) i/s -     65.488M in   5.000584s
```

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>

* Clean up function signatures / remove dead code

rb_vm_getclassvariable signature has changed and we don't need
rb_vm_get_cref.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2021-11-18 12:11:53 -05:00
John Hawthorn
fbd6cc5856
YJIT: Support iseq sends with mixed kwargs (#5082)
* YJIT: Support iseq sends with mixed kwargs

Co-authored-by: Kevin Newton <kddnewton@gmail.com>

* Add additional comments to iseq sends

Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2021-11-05 17:01:07 -04:00
John Hawthorn
9cc2c74b83
YJIT: Implement checkkeyword (#5083)
Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>

Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
2021-11-05 16:54:23 -04:00
Maxime Chevalier-Boisvert
2421527d6e
YJIT code pages refactoring for code GC (#5073)
* New code page allocation logic

* Fix leaked globals

* Fix leaked symbols, yjit asm tests

* Make COUNTED_EXIT take a jit argument, so we can eliminate global ocb

* Remove extra whitespace

* Change block start_pos/end_pos to be pointers instead of uint32_t

* Change branch end_pos and start_pos to end_addr, start_addr
2021-11-04 16:05:41 -04:00
John Hawthorn
2fa51c7068
YJIT: Support kwargs sends with all defaults (#5067)
* YJIT: Support kwargs sends with all defaults

Previously keyword argument methods were only compiled by YJIT when all
keywords were specified in the caller.

This adds support for calling methods with keyword arguments when no
keyword arguments are specified and all are filled with the defaults.

* Remove unused send_iseq_kwargs_none_passed
2021-11-01 10:54:59 -04:00
Maxime Chevalier-Boisvert
2e14fb7df7
Add comments about send method types (#5059) 2021-10-29 14:58:49 -04:00
Yusuke Endoh
c1228f833c vm_core.h: Avoid unaligned access to ic_serial on 32-bit machine
This caused Bus error on 32 bit Solaris
2021-10-29 10:57:46 +09:00
John Hawthorn
a6104b392a
YJIT: Support newhash with values (#5029)
* YJIT: Implement newhash with values

* YJIT: Add test of duphash

* Fix compilation on macos/clang
2021-10-27 10:55:43 -04:00
Ian C. Anderson
e943511455
YJIT: Implement duphash (#5009)
`duphash` showed up in the top-20 most frequent exit ops for @jhawthorn's benchmark that renders github.com/about

The implementation was almost exactly the same as `duparray`

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

Co-authored-by: John Hawthorn <john@hawthorn.email>
2021-10-25 10:40:33 -04:00
Alan Wu
bdfc23cba9
YJIT: don't compile attr_accessor methods when tracing (#4998)
2d98593bf5 made it so that
attr_accessor methods fire C method tracing events.
Previously, we weren't checking for whether we are tracing before
compiling, leading to missed events.

Since global invalidation invalidates all code, and that attr_accessor
methods can never enable tracing while running, events are only dropped
when YJIT tries to compile when tracing is already enabled.

Factor out the code for checking tracing and check it before generating
code for attr_accessor methods.

This change fixes TestSetTraceFunc#test_tracepoint_attr when it's
ran in isolation.
2021-10-21 15:07:32 -04:00
Alan Wu
00be5846e4 Fix non RUBY_DEBUG build warnings
On non RUBY_DEBUG builds, assert() compiles to nothing and the compiler
warns about uninitialized variables in those code paths. Replace
those asserts with rb_bug() to fix the warnings and do the assert in
all builds. Since yjit_asm_tests.c compiles outside of Ruby, it needed
a distinct version of rb_bug().

Also put YJIT_STATS check for function delcaration that is only defined
in YJIT_STATS builds.
2021-10-20 18:19:43 -04:00
Alan Wu
cffa116275 Do kwarg shuffle after checking for interrupts
Previously, we were shuffling keyword arguments before checking for
interrupts. In the case that we side exit in the interrupt check,
we left the interpreter with an already-shuffled argument list for
the call, resulting in a double shuffle, leaving the locals in the
wrong order for the callee.

Do keyword shuffling after all the possible side exits.

Co-authored-by: Kevin Newton <kddnewton@gmail.com>
2021-10-20 18:19:43 -04:00
Alan Wu
b74d6563a6 Extract yjit_force_iv_index and make it work when object is frozen
In an effort to simplify the logic YJIT generates for accessing instance
variable, YJIT ensures that a given name-to-index mapping exists at
compile time. In the case that the mapping doesn't exist, it was created
by using rb_ivar_set() with Qundef on the sample object we see at
compile time. This hack isn't fine if the sample object happens to be
frozen, in which case YJIT would raise a FrozenError unexpectedly.

To deal with this, make a new function that only reserves the mapping
but doesn't touch the object. This is rb_obj_ensure_iv_index_mapping().
This new function superceeds the functionality of rb_iv_index_tbl_lookup()
so it was removed.

Reported by and includes a test case from John Hawthorn <john@hawthorn.email>

Fixes: GH-282
2021-10-20 18:19:43 -04:00
Alan Wu
454fbe1046 Expand tabs 2021-10-20 18:19:43 -04:00
eileencodes
4cad893080 Add String#bytesize
Fixes: https://github.com/Shopify/yjit/issues/258

Co-authored-by: Aaron Patterson tenderlove@ruby-lang.org
2021-10-20 18:19:43 -04:00
Alan Wu
32b5125c5e else if style 2021-10-20 18:19:43 -04:00
Maxime Chevalier-Boisvert
35b37c5873 Update yjit_codegen.c
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2021-10-20 18:19:43 -04:00
Maxime Chevalier-Boisvert
201721b713 Update yjit_codegen.c
Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2021-10-20 18:19:43 -04:00
Kevin Newton
56b1b93a0c Feedback, tests, and rebase for kwargs 2021-10-20 18:19:43 -04:00
Kevin Newton
c5acbd0208 Bail out if passing keyword arguments to only positional and/or optional methods 2021-10-20 18:19:43 -04:00
Kevin Newton
06a826b8c8 Set up the callee stack pointer properly taking into account the bits object 2021-10-20 18:19:43 -04:00
Kevin Newton
5759d840c3 Correct for positional required arguments 2021-10-20 18:19:43 -04:00
Kevin Newton
266e12ac22 Push the unspecified_bits_value onto the stack 2021-10-20 18:19:42 -04:00
Kevin Newton
9aed5809e1 Reuse stack swapping logic 2021-10-20 18:19:42 -04:00
Kevin Newton
2c0891be20 Get kwargs reordering working 2021-10-20 18:19:42 -04:00
Kevin Newton
885bb972bf Get kwargs working for all passed in the correct order 2021-10-20 18:19:42 -04:00
Alan Wu
f6da559d5b Put YJIT into a single compilation unit
For upstreaming, we want functions we export either prefixed with "rb_"
or made static. Historically we haven't been following this rule, so we
were "leaking" a lot of symbols as `make leak-globals` would tell us.

This change unifies everything YJIT into a single compilation unit,
yjit.o, and makes everything unprefixed static to pass `make leak-globals`.
This manual "unified build" setup is similar to that of vm.o.

Having everything in one compilation unit allows static functions to
be visible across YJIT files and removes the need for declarations in
headers in some cases. Unnecessary declarations were removed.

Other changes of note:
  - switched to MJIT_SYMBOL_EXPORT_BEGIN which indicates stuff as being
    off limits for native extensions
  - the first include of each YJIT file is change to be "internal.h"
  - undefined MAP_STACK before explicitly redefining it since it
    collide's with a definition in system headers. Consider renaming?
2021-10-20 18:19:42 -04:00
Alan Wu
7eea96c780 Fix gen_getclassvariable
We need to reconstruct interpreter state before calling into the
routines to be able to raise exceptions. I'm getting a crash in
debug build with:
    make test-all 'TESTS=test/ruby/variable.rb' RUN_OPTS='--yjit-call-threshold=1 --yjit-max-versions=1'
2021-10-20 18:19:42 -04:00
Maxime Chevalier-Boisvert
70c5bbf84b Fix counter names for getblockparamproxy. Print in --yjit-stats. 2021-10-20 18:19:42 -04:00
eileencodes
c8e157bb5c Implement getclassvariable in yjit
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2021-10-20 18:19:42 -04:00
eileencodes
f911e264a1 Add counted side exit to getblockparamproxy
This is so we know the specific reason we're exiting this instruction.

Co-authored-by: Aaron Patterson tenderlove@ruby-lang.org
2021-10-20 18:19:42 -04:00
Noah Gibbs
be06112d48 Fix changes from rebase 2021-10-20 18:19:42 -04:00
Alan Wu
f36a5a98c0 style: line break before "else" 2021-10-20 18:19:41 -04:00
Alan Wu
ec4998bd69 style: switch statements indent
Case labels get half an indent and the opening brace is on the same line
as "switch".
2021-10-20 18:19:41 -04:00
Alan Wu
a10cf74e5c style: align pointer "*" to the right 2021-10-20 18:19:41 -04:00
John Hawthorn
5b68d14c2f Add optimized Thread.current 2021-10-20 18:19:41 -04:00
Alan Wu
5c15850ea6 Use jit_guard_known_klass() for hashes in opt_aref
The old heap object check is not as efficient as the one in
jit_guard_known_klass(). Also, the old code saves cfp->sp after popping
the operands off the stack, which might cause the operands to be not
marked by the GC in some circumstances.
2021-10-20 18:19:41 -04:00
Alan Wu
9dce2d5132 Also do String#str 2021-10-20 18:19:41 -04:00
Alan Wu
1a5109cb5f Comment edits and moving functions around in the file 2021-10-20 18:19:41 -04:00
Alan Wu
a09adac2d7 Add specialization for String#to_s on plain strings
When calling "to_s" on an instance of String, the method simply returns
self. In this situation most of the work comes from setting up the
method call. It turns out that both railsbench and liquid-render do this
a lot.

When generating code for opt_send_without_block, we already generate a
known class guard, so we can detect when the receiver is a String
instance. Since gen_send_cfunc() is also used for gen_invokesuper(), and
gen_invokesuper() doesn't generate a known class guard, a new nullable
parameter for specialized codegen function is added.

Closes GH-245
2021-10-20 18:19:41 -04:00
Maxime Chevalier-Boisvert
79015926eb Try to get getblockparamproxy to support level > 0 2021-10-20 18:19:41 -04:00
Alan Wu
8edb29e5a0 Reconstruct interpreter state before calling rb_ivar_get()
It could raise ractor exceptions. The included test didn't run properly
before this change.
2021-10-20 18:19:41 -04:00
Alan Wu
d0a213b30d Remove a memory load in gen_send_iseq
Instead of loading from meory for REG_SP, do a register rename instead.
It's cheaper.
2021-10-20 18:19:41 -04:00
Alan Wu
0a108601ef Add counters for version invalidation reasons
I noticed that there were two st_table iterators that do exactly the
same thing so I merged them into one.
2021-10-20 18:19:41 -04:00
Noah Gibbs
e48fc07d11 Fix counter names 2021-10-20 18:19:41 -04:00
Noah Gibbs
7704a6990a Fix typo in comment 2021-10-20 18:19:41 -04:00