From dd80d9b089e35729d585bae2f8866c845c48f3b7 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Wed, 8 Jan 2025 19:07:07 -0500 Subject: [PATCH] YJIT: Filter `&` calls from specialized C method codegen Evident with the crash reported in [Bug #20997], the C replacement codegen functions aren't authored to handle block arguments (nor should they because the extra code from the complexity defeats optimization). Filter sites with VM_CALL_ARGS_BLOCKARG. --- bootstraptest/test_yjit.rb | 8 ++++++++ yjit/src/codegen.rs | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 8c6171bd0a..b5bd883599 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -5347,3 +5347,11 @@ assert_equal '["x", "Y", "c", "A", "t", "A", "b", "C", "d"]', <<~'RUBY' Swap.new("xy").swap + Swap.new("cat").reverse_odd + Swap.new("abcd").reverse_even RUBY + +assert_normal_exit %{ + class Bug20997 + def foo(&) = self.class.name(&) + + new.foo + end +} diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index d04da48c6a..f68b1d8da2 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6894,11 +6894,12 @@ fn gen_send_cfunc( // Increment total cfunc send count gen_counter_incr(jit, asm, Counter::num_send_cfunc); - // Delegate to codegen for C methods if we have it. + // Delegate to codegen for C methods if we have it and the callsite is simple enough. if kw_arg.is_null() && !kw_splat && flags & VM_CALL_OPT_SEND == 0 && flags & VM_CALL_ARGS_SPLAT == 0 && + flags & VM_CALL_ARGS_BLOCKARG == 0 && (cfunc_argc == -1 || argc == cfunc_argc) { let expected_stack_after = asm.ctx.get_stack_size() as i32 - argc; if let Some(known_cfunc_codegen) = lookup_cfunc_codegen(unsafe { (*cme).def }) {