Fast path for calling a simple function with exact positional args. Skips FuncArgs allocation, prepend_arg, and fill_locals_from_args. Only valid when: CO_OPTIMIZED, no VARARGS, no VARKEYWORDS, no kwonlyargs, and nargs == co_argcount.
(&self, args: Vec<PyObjectRef>, vm: &VirtualMachine)
| 726 | /// Only valid when: CO_OPTIMIZED, no VARARGS, no VARKEYWORDS, no kwonlyargs, |
| 727 | /// and nargs == co_argcount. |
| 728 | pub fn invoke_exact_args(&self, args: Vec<PyObjectRef>, vm: &VirtualMachine) -> PyResult { |
| 729 | let code: PyRef<PyCode> = (*self.code).to_owned(); |
| 730 | |
| 731 | debug_assert_eq!(args.len(), code.arg_count as usize); |
| 732 | debug_assert!(code.flags.contains(bytecode::CodeFlags::OPTIMIZED)); |
| 733 | debug_assert!( |
| 734 | !code |
| 735 | .flags |
| 736 | .intersects(bytecode::CodeFlags::VARARGS | bytecode::CodeFlags::VARKEYWORDS) |
| 737 | ); |
| 738 | debug_assert_eq!(code.kwonlyarg_count, 0); |
| 739 | |
| 740 | // Generator/coroutine code objects are SIMPLE_FUNCTION in call |
| 741 | // specialization classification, but their call path must still |
| 742 | // go through invoke() to produce generator/coroutine objects. |
| 743 | if code |
| 744 | .flags |
| 745 | .intersects(bytecode::CodeFlags::GENERATOR | bytecode::CodeFlags::COROUTINE) |
| 746 | { |
| 747 | return self.invoke(FuncArgs::from(args), vm); |
| 748 | } |
| 749 | let frame = self.prepare_exact_args_frame(args, vm); |
| 750 | |
| 751 | let result = vm.run_frame(frame.clone()); |
| 752 | unsafe { |
| 753 | if let Some(base) = frame.materialize_localsplus() { |
| 754 | vm.datastack_pop(base); |
| 755 | } |
| 756 | } |
| 757 | result |
| 758 | } |
| 759 | } |
| 760 | |
| 761 | pub(crate) fn datastack_frame_size_bytes_for_code(code: &Py<PyCode>) -> Option<usize> { |
no test coverage detected