@@ -380,6 +380,14 @@ impl LocalsPlus {
380380 data. swap ( base + a, base + b) ;
381381 }
382382
383+ /// Truncate the stack to `new_len` elements, dropping excess values.
384+ fn stack_truncate ( & mut self , new_len : usize ) {
385+ debug_assert ! ( new_len <= self . stack_top as usize ) ;
386+ while self . stack_top as usize > new_len {
387+ let _ = self . stack_pop ( ) ;
388+ }
389+ }
390+
383391 /// Clear the stack, dropping all values.
384392 fn stack_clear ( & mut self ) {
385393 while self . stack_top > 0 {
@@ -6050,13 +6058,15 @@ impl ExecutingFrame<'_> {
60506058 #[ inline]
60516059 fn execute_call_vectorcall ( & mut self , nargs : u32 , vm : & VirtualMachine ) -> FrameResult {
60526060 let nargs_usize = nargs as usize ;
6053- let stack_len = self . stack . len ( ) ;
6061+ let stack_len = self . localsplus . stack_len ( ) ;
60546062 let callable_idx = stack_len - nargs_usize - 2 ;
60556063 let self_or_null_idx = stack_len - nargs_usize - 1 ;
60566064 let args_start = stack_len - nargs_usize;
60576065
60586066 // Check if callable has vectorcall slot
6059- let has_vectorcall = self . stack [ callable_idx]
6067+ let has_vectorcall = self
6068+ . localsplus
6069+ . stack_index ( callable_idx)
60606070 . as_ref ( )
60616071 . is_some_and ( |sr| sr. as_object ( ) . class ( ) . slots . vectorcall . load ( ) . is_some ( ) ) ;
60626072
@@ -6067,7 +6077,9 @@ impl ExecutingFrame<'_> {
60676077 }
60686078
60696079 // Build args slice: [self_or_null?, arg1, ..., argN]
6070- let self_or_null = self . stack [ self_or_null_idx]
6080+ let self_or_null = self
6081+ . localsplus
6082+ . stack_index_mut ( self_or_null_idx)
60716083 . take ( )
60726084 . map ( |sr| sr. to_pyobj ( ) ) ;
60736085 let has_self = self_or_null. is_some ( ) ;
@@ -6082,12 +6094,12 @@ impl ExecutingFrame<'_> {
60826094 args_vec. push ( self_val) ;
60836095 }
60846096 for stack_idx in args_start..stack_len {
6085- let val = self . stack [ stack_idx] . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6097+ let val = self . localsplus . stack_index_mut ( stack_idx) . take ( ) . unwrap ( ) . to_pyobj ( ) ;
60866098 args_vec. push ( val) ;
60876099 }
60886100
6089- let callable_obj = self . stack [ callable_idx] . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6090- self . stack . truncate ( callable_idx) ;
6101+ let callable_obj = self . localsplus . stack_index_mut ( callable_idx) . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6102+ self . localsplus . stack_truncate ( callable_idx) ;
60916103
60926104 let result = callable_obj. vectorcall ( args_vec, effective_nargs, None , vm) ?;
60936105 self . push_value ( result) ;
@@ -6106,13 +6118,15 @@ impl ExecutingFrame<'_> {
61066118 . expect ( "kwarg names should be tuple" ) ;
61076119 let kw_count = kwarg_names_tuple. len ( ) ;
61086120
6109- let stack_len = self . stack . len ( ) ;
6121+ let stack_len = self . localsplus . stack_len ( ) ;
61106122 let callable_idx = stack_len - nargs_usize - 2 ;
61116123 let self_or_null_idx = stack_len - nargs_usize - 1 ;
61126124 let args_start = stack_len - nargs_usize;
61136125
61146126 // Check if callable has vectorcall slot
6115- let has_vectorcall = self . stack [ callable_idx]
6127+ let has_vectorcall = self
6128+ . localsplus
6129+ . stack_index ( callable_idx)
61166130 . as_ref ( )
61176131 . is_some_and ( |sr| sr. as_object ( ) . class ( ) . slots . vectorcall . load ( ) . is_some ( ) ) ;
61186132
@@ -6143,7 +6157,9 @@ impl ExecutingFrame<'_> {
61436157 }
61446158
61456159 // Build args: [self?, pos_arg1, ..., pos_argM, kw_val1, ..., kw_valK]
6146- let self_or_null = self . stack [ self_or_null_idx]
6160+ let self_or_null = self
6161+ . localsplus
6162+ . stack_index_mut ( self_or_null_idx)
61476163 . take ( )
61486164 . map ( |sr| sr. to_pyobj ( ) ) ;
61496165 let has_self = self_or_null. is_some ( ) ;
@@ -6158,12 +6174,12 @@ impl ExecutingFrame<'_> {
61586174 args_vec. push ( self_val) ;
61596175 }
61606176 for stack_idx in args_start..stack_len {
6161- let val = self . stack [ stack_idx] . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6177+ let val = self . localsplus . stack_index_mut ( stack_idx) . take ( ) . unwrap ( ) . to_pyobj ( ) ;
61626178 args_vec. push ( val) ;
61636179 }
61646180
6165- let callable_obj = self . stack [ callable_idx] . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6166- self . stack . truncate ( callable_idx) ;
6181+ let callable_obj = self . localsplus . stack_index_mut ( callable_idx) . take ( ) . unwrap ( ) . to_pyobj ( ) ;
6182+ self . localsplus . stack_truncate ( callable_idx) ;
61676183
61686184 let kwnames = kwarg_names_tuple. as_slice ( ) ;
61696185 let result = callable_obj. vectorcall ( args_vec, effective_nargs, Some ( kwnames) , vm) ?;
0 commit comments