Age | Commit message (Collapse) | Author |
|
|
|
Co-authored-by: Aaron Patterson <[email protected]>
|
|
|
|
|
|
|
|
These instructions are marked as not leaf in insns.def, which indicate
that they could raise exceptions and/or call Ruby methods.
|
|
Adds yjit support for setting global variables.
Co-authored-by: Aaron Patterson <[email protected]>
Co-authored-by: John Hawthorn <[email protected]>
|
|
Adds getglobal to yjit and a test for it.
Co-authored-by: Aaron Patterson <[email protected]>
|
|
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.
|
|
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
|
|
|
|
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.
|
|
Otherwise you can end up not implicitly calling `to_ary`, which if it has side-effects will result in different behavior.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Basically the same thing as opt_mod, but for multiplying.
|
|
|
|
|
|
This adds guards
|
|
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.
|
|
|
|
|
|
|
|
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.
|
|
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().
|
|
The added test fails with SystemStackError with --yjit-call-threshold=1.
|
|
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.
|
|
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.
|
|
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.
|
|
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 <[email protected]>
Co-authored-by: Noah Gibbs <[email protected]>
|
|
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).
|
|
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).
|
|
|
|
This commit implements the topn instruction
Co-Authored-By: Maxime Chevalier-Boisvert <[email protected]>
Co-Authored-By: Noah Gibbs <[email protected]>
|
|
|
|
|
|
|
|
|
|
|
|
This extracts the generation code from getlocal_wc1, since this is the
same just with more loops inside vm_get_ep.
|
|
|
|
|
|
Also added a comment when inlining a leaf builtin
|
|
* 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 <[email protected]>
|
|
* Add ETYPE_TRUE and ETYPE_FALSE
* Implement checktype
* Implement concatstrings
* Update deps
|