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