Commit graph

276 commits

Author SHA1 Message Date
eileencodes
d2e8b99b5b Implement tostring instruction for yjit
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2021-10-20 18:19:38 -04:00
John Hawthorn
6c80150d40 Introduce ctx_{get,set}_opnd_mapping 2021-10-20 18:19:38 -04:00
John Hawthorn
4ea69e5c0b Rename to ctx_upgrade_opnd_type 2021-10-20 18:19:38 -04:00
John Hawthorn
53079ca585 Return if fixnums impossible 2021-10-20 18:19:38 -04:00
Alan Wu
f4f940e5a6 Save PC and SP before accessing globals
These instructions are marked as not leaf in insns.def, which indicate
that they could raise exceptions and/or call Ruby methods.
2021-10-20 18:19:38 -04:00
eileencodes
b91078ea74 Add setglobal to yjit
Adds yjit support for setting global variables.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Co-authored-by: John Hawthorn <john@hawthorn.email>
2021-10-20 18:19:38 -04:00
eileencodes
50029fb127 Add getglobal to yjit
Adds getglobal to yjit and a test for it.

Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2021-10-20 18:19:38 -04:00
Aaron Patterson
84a1e04e58 Change register definitions to match the entry point calling convention
The JIT entry point passes the CFP as RSI and the EC as RDI.  Lets match
that so we don't have to shuffle registers around.
2021-10-20 18:19:38 -04:00
Aaron Patterson
05b5a7f011 Add a guard that we start executing on the first PC
Methods with optional parameters don't always start executing at the
first PC, but we compile all methods assuming that they do.  This commit
adds a guard to ensure that we're actually starting at the first PC for
methods with optional params
2021-10-20 18:19:37 -04:00
Aaron Patterson
0fdcdd267f fix alignment 2021-10-20 18:19:37 -04:00
Aaron Patterson
d0174d99c6 Always use ret to return to the interpreter
Always using `ret` to return to the interpreter means that we never have
to check the VM_FRAME_FLAG_FINISH flag.

In the case that we return `Qundef`, the interpreter will execute the
cfp.  We can take advantage of this by setting the PC to the instruction
we can't handle, and let the interpreter pick up the ball from there.

If we return a value other than Qundef, the interpreter will take that
value as the "return value" from the JIT and push that to the SP of the
caller

The leave instruction puts the return value on the top of the calling
frame's stack.  YJIT does the same thing for leave instructions.
However, when we're returning back to the interpreter, the leave
instruction _should not_ put the return value on the top of the stack,
but put it in RAX and use RET.  This commit pops the last value from the
stack pointer and puts it in RAX so that the interpreter is happy with
SP.
2021-10-20 18:19:37 -04:00
Kevin Newton
9a436da064 Ensure we guard the value before we return
Otherwise you can end up not implicitly calling `to_ary`, which if it has side-effects will result in different behavior.
2021-10-20 18:19:37 -04:00
Kevin Newton
341d5bdcb2 Code review for expandarray and tests 2021-10-20 18:19:37 -04:00
Kevin Newton
97025db90e Convert jumps to cmov 2021-10-20 18:19:37 -04:00
Kevin Deisz
bfde30c326 Implement expandarray 2021-10-20 18:19:37 -04:00
Kevin Newton
be648e0940 Implement splatarray 2021-10-20 18:19:37 -04:00
John Hawthorn
dc8aca1883 Use push and pop in jit_rb_obj_not to avoid corrupting types 2021-10-20 18:19:37 -04:00
John Hawthorn
0c390e9965 Add assertions of types in jit_guard_known_klass 2021-10-20 18:19:37 -04:00
Kevin Deisz
ba9aa1f8ef Implement opt_div 2021-10-20 18:19:37 -04:00
Kevin Deisz
b0ae4fdcfb Implement opt_mult
Basically the same thing as opt_mod, but for multiplying.
2021-10-20 18:19:37 -04:00
Maxime Chevalier-Boisvert
6cb4edd73f Implement swap instruction 2021-10-20 18:19:37 -04:00
John Hawthorn
9e0a56fb24 Add FLONUM detection 2021-10-20 18:19:37 -04:00
John Hawthorn
dfc5e5e35b Support guards against symbols and integers
This adds guards
2021-10-20 18:19:37 -04:00
John Hawthorn
c3f264b62c Allow chaining on immediate guard
In jit_guard_known_klass whenever we encounter a new class should
recompile the current instruction.

However, previously once jit_guard_known_klass had guarded for a heap
object it would not recompile for  any immediate (special const) objects
arriving afterwards and would take a plain side-exit instead of a chain
guard.

This commit uses jit_chain_guard inside jit_guard_known_klass instead of
the plain side exit, so that we can recompile for any special constants
arriving afterwards.
2021-10-20 18:19:37 -04:00
John Hawthorn
94cb5a6b1e Implement opt_neq 2021-10-20 18:19:36 -04:00
Alan Wu
3996e0ab07 Add tests, comments, and an assert for invokesuper 2021-10-20 18:19:36 -04:00
John Hawthorn
71560f8804 Add opt_size and opt_length 2021-10-20 18:19:36 -04:00
John Hawthorn
e4bf905a28 Use an st_table for optimized method codegen
We recently added the ability to optimize a known cfunc with custom code
generation for it.

Previously we performed this lookup with a switch statement on the
address of the c function being called. This commit swaps that out for a
hash lookup on the method definition. For now I've kept this limited
this to cfuncs, but it wouldn't take significant changes to make this
work for other method types.

This implemenation is similar to how the interpreter keeps track of
which BOPs (basic operations) are redefined

This has a few advantages:
- Doesn't the C function's symbol to be exported (they're often static)
- This could support VM_METHOD_TYPE_OPTIMIZED in the future.
- This could support VM_METHOD_TYPE_ISEQ in the future. Kernel#class
  would be a good candidate for this since to yjit it will just be a
  constant push as we already know the class through BBV.
- Slightly cleaner to declare
- Less tightly coupled to each method's implementation

And a couple minor trade-offs:
- The looser coupling could be seen as a disadvantage (I don't think so,
- If a cfunc is defined multiple times we would need to declare it on
  each definition. ex. BasicObject#== and BasicObject#equal?. This is
  rare compared to using an alias.
2021-10-20 18:19:36 -04:00
Alan Wu
0cd3b97e02 Handle non-material empty singleton class properly
As an optimization, multiple objects could share the same singleton
class. The optimization introduced in 6698e433934d810b16ee3636b63974c0a75c07f0
wasn't handling this correctly so was generating guards that never pass
for the inputs we defer compilation to wait for. After generating
identical code multiple times and failing, the call site is falsely
recognized as megamorphic and it side exits. See disassembly for the
following before this commit:

    def foo(obj)
      obj.itself
    end

    o = Object.new.singleton_class
    foo(o)
    puts YJIT.disasm(method(:foo))

See also: comment in rb_singleton_class_clone_and_attach().
2021-10-20 18:19:36 -04:00
Alan Wu
89110590a3 Disable invokesuper codegen for now. Add test
The added test fails with SystemStackError with --yjit-call-threshold=1.
2021-10-20 18:19:36 -04:00
Alan Wu
da20ff1644 Fix bug in generic case for gen_checktype
When checking for T_HASH, which is Qnil and when the type check succeeds
we were outputting to the stack a Qnil instead of a Qtrue.
2021-10-20 18:19:36 -04:00
John Hawthorn
7d252186fe Simplify known class check for singletons
Singleton classes should only ever be attached to one object. This means
that checking for the object should be the same as checking for the
class. This should be slightly faster by avoiding one memory acccess as
well as allowing us to skip checking if the receiver is a heap object.

This will be most common for calling class methods.
2021-10-20 18:19:36 -04:00
Alan Wu
8c68f112d8 Delay and be selective about when to discard local types
jit_rb_obj_not() wants to access the type information of the receiver,
but we were discarding type info of locals before jit_rb_obj_not() runs
unncessarily.

There are also cases we are unncessarily discarding local type info. For
example, ivar reader and setter methods can never change local
variables.
2021-10-20 18:19:36 -04:00
Alan Wu
936ee55562 Improve opt_not by expanding cfunc codegen
This commit improves opt_not by making it correct when TrueClass#!
and/or FalseClass#! is defined and genearting better code when the
receiver is a heap object.

guard_known_class() can now handle true, false, and nil, and we
introduce a codegen function reimplementing rb_obj_not(), used when we
know we are calling into rb_obj_not().

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
Co-authored-by: Noah Gibbs <the.codefolio.guy@gmail.com>
2021-10-20 18:19:36 -04:00
John Hawthorn
78f64d14d4 Add invokebuiltin_delegate_leave
invokebuiltin_delegate can be run in place of
invokebuiltin_delegate_leave because there is always a leave instruction
afterwards (the interpreter takes advantage of this as well when
rewriting iseqs for tracing).
2021-10-20 18:19:36 -04:00
John Hawthorn
b93f59ced0 Implement invokebuiltin_delegate
invokebuiltin_delegate is a special version of invokebuiltin used for
sending a contiguous subset of the current method's locals.

In some cases YJIT would already handle this for trivial cases it could
be inlined, implementing this OP allows it to work when the method isn't
inlinable (not marked as 'inline', does more than just call, not called
from yjit, etc).
2021-10-20 18:19:36 -04:00
Maxime Chevalier-Boisvert
364cdda0f1 Fix compiler warning 2021-10-20 18:19:36 -04:00
Aaron Patterson
9043ad3d74 Implement topn instruction
This commit implements the topn instruction

Co-Authored-By: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
Co-Authored-By: Noah Gibbs <noah.gibbs@shopify.com>
2021-10-20 18:19:36 -04:00
John Hawthorn
986b9b47d1 Better comments 2021-10-20 18:19:36 -04:00
John Hawthorn
0a3ee8b2e3 Avoid looping on invokesuper on module included multiple times 2021-10-20 18:19:36 -04:00
John Hawthorn
3fedf8329d Check for refinements in gen_invokesuper 2021-10-20 18:19:36 -04:00
John Hawthorn
0fb2926097 Guard against implicitly forwarded block 2021-10-20 18:19:36 -04:00
John Hawthorn
83c7f27ade Add invokesuper 2021-10-20 18:19:35 -04:00
John Hawthorn
67c2cdc59a Implement gen_getlocal
This extracts the generation code from getlocal_wc1, since this is the
same just with more loops inside vm_get_ep.
2021-10-20 18:19:35 -04:00
Maxime Chevalier-Boisvert
5432f46f6a Can't add comments to the outlined code block 2021-10-20 18:19:35 -04:00
John Hawthorn
ed636b59ed Add duparray to YJIT codegen 2021-10-20 18:19:35 -04:00
John Hawthorn
d77c989ac7 Fix check for leaf invokebuiltin
Also added a comment when inlining a leaf builtin
2021-10-20 18:19:35 -04:00
Maxime Chevalier-Boisvert
860589c7fa Use builtin_inline_p to avoid pushing a frame for primitive C methods (#63)
* Use builtin_inline_p to skip a frame of C methods

* Fix bugs in primitive cfunc call code

* Remove if (push_frame) {}

* Remove if (push_frame) {}

* Push Aaron's fix to avoid hardcoding insn lengths

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
2021-10-20 18:19:35 -04:00
John Hawthorn
ea33b0a9ba Add concatstrings to yjit codegen (#58)
* Add ETYPE_TRUE and ETYPE_FALSE

* Implement checktype

* Implement concatstrings

* Update deps
2021-10-20 18:19:35 -04:00
John Hawthorn
eb6e5be038 Add newhash and newarray instructions to yjit codegen (#48)
* Implement gen_newarray

* Implement newhash for n=0

* Add yjit tests for newhash/newarray

* Fix integer size warning on clang

* Save PC and SP in newhash and newarray

Co-authored-by: Maxime Chevalier-Boisvert <maximechevalierb@gmail.com>
2021-10-20 18:19:35 -04:00