(&mut self, nargs: u32, vm: &VirtualMachine)
| 6606 | /// Vectorcall dispatch for Instruction::CallKw (positional + keyword args). |
| 6607 | #[inline] |
| 6608 | fn execute_call_kw_vectorcall(&mut self, nargs: u32, vm: &VirtualMachine) -> FrameResult { |
| 6609 | let nargs_usize = nargs as usize; |
| 6610 | |
| 6611 | // Pop kwarg_names tuple from top of stack |
| 6612 | let kwarg_names_obj = self.pop_value(); |
| 6613 | let kwarg_names_tuple = kwarg_names_obj |
| 6614 | .downcast_ref::<PyTuple>() |
| 6615 | .expect("kwarg names should be tuple"); |
| 6616 | let kw_count = kwarg_names_tuple.len(); |
| 6617 | debug_assert!(kw_count <= nargs_usize, "CALL_KW kw_count exceeds nargs"); |
| 6618 | |
| 6619 | let stack_len = self.localsplus.stack_len(); |
| 6620 | debug_assert!( |
| 6621 | stack_len >= nargs_usize + 2, |
| 6622 | "CALL_KW stack underflow: need callable + self_or_null + {nargs_usize} args, have {stack_len}" |
| 6623 | ); |
| 6624 | let callable_idx = stack_len - nargs_usize - 2; |
| 6625 | let self_or_null_idx = stack_len - nargs_usize - 1; |
| 6626 | let args_start = stack_len - nargs_usize; |
| 6627 | |
| 6628 | // Build args: [self?, pos_arg1, ..., pos_argM, kw_val1, ..., kw_valK] |
| 6629 | let self_or_null = self |
| 6630 | .localsplus |
| 6631 | .stack_index_mut(self_or_null_idx) |
| 6632 | .take() |
| 6633 | .map(|sr| sr.to_pyobj()); |
| 6634 | let has_self = self_or_null.is_some(); |
| 6635 | |
| 6636 | let pos_count = nargs_usize |
| 6637 | .checked_sub(kw_count) |
| 6638 | .expect("CALL_KW: kw_count exceeds nargs"); |
| 6639 | let effective_nargs = if has_self { pos_count + 1 } else { pos_count }; |
| 6640 | |
| 6641 | // Build the full args slice: positional (including self) + kwarg values |
| 6642 | let total_args = effective_nargs + kw_count; |
| 6643 | let mut args_vec = Vec::with_capacity(total_args); |
| 6644 | if let Some(self_val) = self_or_null { |
| 6645 | args_vec.push(self_val); |
| 6646 | } |
| 6647 | for stack_idx in args_start..stack_len { |
| 6648 | let val = self |
| 6649 | .localsplus |
| 6650 | .stack_index_mut(stack_idx) |
| 6651 | .take() |
| 6652 | .unwrap() |
| 6653 | .to_pyobj(); |
| 6654 | args_vec.push(val); |
| 6655 | } |
| 6656 | |
| 6657 | let callable_obj = self |
| 6658 | .localsplus |
| 6659 | .stack_index_mut(callable_idx) |
| 6660 | .take() |
| 6661 | .unwrap() |
| 6662 | .to_pyobj(); |
| 6663 | self.localsplus.stack_truncate(callable_idx); |
| 6664 | |
| 6665 | // invoke_vectorcall falls back to FuncArgs if no vectorcall slot |
no test coverage detected