Vectorcall for builtin functions (PEP 590). Avoids `prepend_arg` O(n) shift by building args with self at front.
(
zelf_obj: &PyObject,
args: Vec<PyObjectRef>,
nargs: usize,
kwnames: Option<&[PyObjectRef]>,
vm: &VirtualMachine,
)
| 229 | /// Vectorcall for builtin functions (PEP 590). |
| 230 | /// Avoids `prepend_arg` O(n) shift by building args with self at front. |
| 231 | fn vectorcall_native_function( |
| 232 | zelf_obj: &PyObject, |
| 233 | args: Vec<PyObjectRef>, |
| 234 | nargs: usize, |
| 235 | kwnames: Option<&[PyObjectRef]>, |
| 236 | vm: &VirtualMachine, |
| 237 | ) -> PyResult { |
| 238 | let zelf: &Py<PyNativeFunction> = zelf_obj.downcast_ref().unwrap(); |
| 239 | |
| 240 | // Build FuncArgs with self already at position 0 (no insert(0) needed) |
| 241 | let needs_self = zelf |
| 242 | .zelf |
| 243 | .as_ref() |
| 244 | .is_some_and(|_| !zelf.value.flags.contains(PyMethodFlags::STATIC)); |
| 245 | |
| 246 | let func_args = if needs_self { |
| 247 | let self_obj = zelf.zelf.as_ref().unwrap().clone(); |
| 248 | let mut all_args = Vec::with_capacity(args.len() + 1); |
| 249 | all_args.push(self_obj); |
| 250 | all_args.extend(args); |
| 251 | FuncArgs::from_vectorcall(&all_args, nargs + 1, kwnames) |
| 252 | } else { |
| 253 | FuncArgs::from_vectorcall(&args, nargs, kwnames) |
| 254 | }; |
| 255 | |
| 256 | (zelf.value.func)(vm, func_args) |
| 257 | } |
| 258 | |
| 259 | pub fn init(context: &'static Context) { |
| 260 | PyNativeFunction::extend_class(context, context.types.builtin_function_or_method_type); |