@@ -736,6 +736,62 @@ impl Py<PyFunction> {
736736 frame
737737 }
738738
739+ pub ( crate ) fn prepare_exact_args_frame (
740+ & self ,
741+ mut args : Vec < PyObjectRef > ,
742+ vm : & VirtualMachine ,
743+ ) -> FrameRef {
744+ let code: PyRef < PyCode > = ( * self . code ) . to_owned ( ) ;
745+
746+ debug_assert_eq ! ( args. len( ) , code. arg_count as usize ) ;
747+ debug_assert ! ( code. flags. contains( bytecode:: CodeFlags :: OPTIMIZED ) ) ;
748+ debug_assert ! (
749+ !code
750+ . flags
751+ . intersects( bytecode:: CodeFlags :: VARARGS | bytecode:: CodeFlags :: VARKEYWORDS )
752+ ) ;
753+ debug_assert_eq ! ( code. kwonlyarg_count, 0 ) ;
754+ debug_assert ! (
755+ !code
756+ . flags
757+ . intersects( bytecode:: CodeFlags :: GENERATOR | bytecode:: CodeFlags :: COROUTINE )
758+ ) ;
759+
760+ let locals = if code. flags . contains ( bytecode:: CodeFlags :: NEWLOCALS ) {
761+ None
762+ } else {
763+ Some ( ArgMapping :: from_dict_exact ( self . globals . clone ( ) ) )
764+ } ;
765+
766+ let frame = Frame :: new (
767+ code. clone ( ) ,
768+ Scope :: new ( locals, self . globals . clone ( ) ) ,
769+ self . builtins . clone ( ) ,
770+ self . closure . as_ref ( ) . map_or ( & [ ] , |c| c. as_slice ( ) ) ,
771+ Some ( self . to_owned ( ) . into ( ) ) ,
772+ true , // Exact-args fast path is only used for non-gen/coro functions.
773+ vm,
774+ )
775+ . into_ref ( & vm. ctx ) ;
776+
777+ {
778+ let fastlocals = unsafe { frame. fastlocals_mut ( ) } ;
779+ for ( slot, arg) in fastlocals. iter_mut ( ) . zip ( args. drain ( ..) ) {
780+ * slot = Some ( arg) ;
781+ }
782+ }
783+
784+ if let Some ( cell2arg) = code. cell2arg . as_deref ( ) {
785+ let fastlocals = unsafe { frame. fastlocals_mut ( ) } ;
786+ for ( cell_idx, arg_idx) in cell2arg. iter ( ) . enumerate ( ) . filter ( |( _, i) | * * i != -1 ) {
787+ let x = fastlocals[ * arg_idx as usize ] . take ( ) ;
788+ frame. set_cell_contents ( cell_idx, x) ;
789+ }
790+ }
791+
792+ frame
793+ }
794+
739795 /// Fast path for calling a simple function with exact positional args.
740796 /// Skips FuncArgs allocation, prepend_arg, and fill_locals_from_args.
741797 /// Only valid when: CO_OPTIMIZED, no VARARGS, no VARKEYWORDS, no kwonlyargs,
0 commit comments