|
6 | 6 | #![allow(clippy::if_same_then_else)] |
7 | 7 | #![allow(clippy::match_like_matches_macro)] |
8 | 8 | use crate::{ |
| 9 | + backend::lir::C_ARG_OPNDS, |
9 | 10 | cast::IntoUsize, codegen::local_idx_to_ep_offset, cruby::*, payload::{get_or_create_iseq_payload, IseqPayload}, options::{debug, get_option, DumpHIR}, state::ZJITState, json::Json |
10 | 11 | }; |
11 | 12 | use std::{ |
@@ -2699,19 +2700,30 @@ impl Function { |
2699 | 2700 | } |
2700 | 2701 |
|
2701 | 2702 | let kwarg = unsafe { rb_vm_ci_kwarg(ci) }; |
2702 | | - let processed_args = if !kwarg.is_null() { |
| 2703 | + let (send_state, processed_args) = if !kwarg.is_null() { |
2703 | 2704 | match self.reorder_keyword_arguments(&args, kwarg, iseq) { |
2704 | | - Ok(reordered) => reordered, |
| 2705 | + Ok(reordered) => { |
| 2706 | + // Only use reordered state if args fit in C registers. |
| 2707 | + // Fallback to interpreter needs original order for kwarg handling. |
| 2708 | + // NOTE: This needs to match with the condition in codegen.rs. |
| 2709 | + if reordered.len() + 1 <= C_ARG_OPNDS.len() { |
| 2710 | + let new_state = self.frame_state(state).with_reordered_args(&reordered); |
| 2711 | + let snapshot = self.push_insn(block, Insn::Snapshot { state: new_state }); |
| 2712 | + (snapshot, reordered) |
| 2713 | + } else { |
| 2714 | + (state, reordered) |
| 2715 | + } |
| 2716 | + } |
2705 | 2717 | Err(reason) => { |
2706 | 2718 | self.set_dynamic_send_reason(insn_id, reason); |
2707 | 2719 | self.push_insn_id(block, insn_id); continue; |
2708 | 2720 | } |
2709 | 2721 | } |
2710 | 2722 | } else { |
2711 | | - args.clone() |
| 2723 | + (state, args.clone()) |
2712 | 2724 | }; |
2713 | 2725 |
|
2714 | | - let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { recv, cd, cme, iseq, args: processed_args, state }); |
| 2726 | + let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { recv, cd, cme, iseq, args: processed_args, state: send_state }); |
2715 | 2727 | self.make_equal_to(insn_id, send_direct); |
2716 | 2728 | } else if def_type == VM_METHOD_TYPE_BMETHOD { |
2717 | 2729 | let procv = unsafe { rb_get_def_bmethod_proc((*cme).def) }; |
@@ -2748,19 +2760,30 @@ impl Function { |
2748 | 2760 | } |
2749 | 2761 |
|
2750 | 2762 | let kwarg = unsafe { rb_vm_ci_kwarg(ci) }; |
2751 | | - let processed_args = if !kwarg.is_null() { |
| 2763 | + let (send_state, processed_args) = if !kwarg.is_null() { |
2752 | 2764 | match self.reorder_keyword_arguments(&args, kwarg, iseq) { |
2753 | | - Ok(reordered) => reordered, |
| 2765 | + Ok(reordered) => { |
| 2766 | + // Only use reordered state if args fit in C registers. |
| 2767 | + // Fallback to interpreter needs original order for kwarg handling. |
| 2768 | + // NOTE: This needs to match with the condition in codegen.rs. |
| 2769 | + if reordered.len() + 1 <= C_ARG_OPNDS.len() { |
| 2770 | + let new_state = self.frame_state(state).with_reordered_args(&reordered); |
| 2771 | + let snapshot = self.push_insn(block, Insn::Snapshot { state: new_state }); |
| 2772 | + (snapshot, reordered) |
| 2773 | + } else { |
| 2774 | + (state, reordered) |
| 2775 | + } |
| 2776 | + } |
2754 | 2777 | Err(reason) => { |
2755 | 2778 | self.set_dynamic_send_reason(insn_id, reason); |
2756 | 2779 | self.push_insn_id(block, insn_id); continue; |
2757 | 2780 | } |
2758 | 2781 | } |
2759 | 2782 | } else { |
2760 | | - args.clone() |
| 2783 | + (state, args.clone()) |
2761 | 2784 | }; |
2762 | 2785 |
|
2763 | | - let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { recv, cd, cme, iseq, args: processed_args, state }); |
| 2786 | + let send_direct = self.push_insn(block, Insn::SendWithoutBlockDirect { recv, cd, cme, iseq, args: processed_args, state: send_state }); |
2764 | 2787 | self.make_equal_to(insn_id, send_direct); |
2765 | 2788 | } else if def_type == VM_METHOD_TYPE_IVAR && args.is_empty() { |
2766 | 2789 | // Check if we're accessing ivars of a Class or Module object as they require single-ractor mode. |
@@ -5045,6 +5068,15 @@ impl FrameState { |
5045 | 5068 | state.stack.clear(); |
5046 | 5069 | state |
5047 | 5070 | } |
| 5071 | + |
| 5072 | + /// Return itself with send args reordered. Used when kwargs are reordered for callee. |
| 5073 | + fn with_reordered_args(&self, reordered_args: &[InsnId]) -> Self { |
| 5074 | + let mut state = self.clone(); |
| 5075 | + let args_start = state.stack.len() - reordered_args.len(); |
| 5076 | + state.stack.truncate(args_start); |
| 5077 | + state.stack.extend_from_slice(reordered_args); |
| 5078 | + state |
| 5079 | + } |
5048 | 5080 | } |
5049 | 5081 |
|
5050 | 5082 | /// Print adaptor for [`FrameState`]. See [`PtrPrintMap`]. |
|
0 commit comments