YJIT: Fix obj.send(:call)

All the method call types need to handle argument shifting in case they're
called by `.send`, and we weren't handling that in `OPTIMIZED_METHOD_TYPE_CALL`.

Lack of shifting caused the stack size assertion in gen_leave() to fail.

Discovered by Rails CI: https://buildkite.com/rails/rails/builds/91705#018516c4-f8f8-469e-bc2d-ddeb25ca8317/1920-2067
Diagnosed with help from `@eileencodes` and `@k0kubun`.
This commit is contained in:
Alan Wu 2022-12-15 18:10:28 -05:00 committed by GitHub
parent e9ba3042e1
commit 14158f1f8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
Notes: git 2022-12-15 23:10:48 +00:00
Merged: https://github.com/ruby/ruby/pull/6943

Merged-By: XrXr
2 changed files with 12 additions and 1 deletions

View File

@ -1022,6 +1022,12 @@ class TestYJIT < Test::Unit::TestCase
RUBY
end
def test_send_to_call
assert_compiles(<<~'RUBY', result: :ok)
->{ :ok }.send(:call)
RUBY
end
private
def code_gc_helpers

View File

@ -5938,6 +5938,11 @@ fn gen_send_general(
return CantCompile;
}
// If this is a .send call we need to adjust the stack
if flags & VM_CALL_OPT_SEND != 0 {
handle_opt_send_shift_stack(asm, argc as i32, ctx);
}
// About to reset the SP, need to load this here
let recv_load = asm.load(recv);
@ -6309,7 +6314,7 @@ fn gen_leave(
ocb: &mut OutlinedCb,
) -> CodegenStatus {
// Only the return value should be on the stack
assert!(ctx.get_stack_size() == 1);
assert_eq!(1, ctx.get_stack_size());
// Create a side-exit to fall back to the interpreter
let side_exit = get_side_exit(jit, ocb, ctx);