@@ -18,7 +18,7 @@ pub fn exec_return(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
1818 let base_ptr = vm. current_frame ( ) . base_ptr ;
1919 vm. close_upvalues_from ( base_ptr) ;
2020
21- let Some ( frame) = vm. frames . pop ( ) else {
21+ let Some ( frame) = vm. pop_frame ( ) else {
2222 return Err ( vm. error ( "RETURN with no frame on stack" . to_string ( ) ) ) ;
2323 } ;
2424
@@ -36,7 +36,7 @@ pub fn exec_return(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
3636 // === 零拷贝返回值优化 ===
3737 // 关键:返回值需要写回 caller 的 R[result_reg]
3838 // 而不是写到 caller 的栈顶
39- if !vm. frames . is_empty ( ) {
39+ if !vm. frames_is_empty ( ) {
4040 let caller_frame = vm. current_frame ( ) ;
4141 let caller_base = caller_frame. base_ptr ;
4242
@@ -127,7 +127,7 @@ pub fn exec_return(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
127127
128128 // CRITICAL: If frames are now empty, we're done - return control to caller
129129 // This prevents run() loop from trying to access empty frame
130- if vm. frames . is_empty ( ) {
130+ if vm. frames_is_empty ( ) {
131131 // Save return values before exiting
132132 vm. return_values . clear ( ) ;
133133 for i in 0 ..return_count {
@@ -840,20 +840,17 @@ fn exec_call_lua_function(
840840 }
841841 }
842842
843- // Create and push new frame - inline to avoid call overhead
844- let frame_id = vm. next_frame_id ;
845- vm. next_frame_id += 1 ;
846-
843+ // Create and push new frame - use frames.len() as frame_id to avoid counter
847844 let new_frame = LuaCallFrame :: new_lua_function (
848- frame_id ,
845+ vm . frames . len ( ) , // Use len as frame_id
849846 func,
850847 code_ptr,
851848 new_base,
852849 arg_count,
853850 a,
854851 return_count,
855852 ) ;
856- vm. frames . push ( new_frame) ;
853+ vm. push_frame ( new_frame) ;
857854 return Ok ( ( ) ) ;
858855 }
859856
@@ -919,7 +916,7 @@ fn exec_call_lua_function(
919916 return_count,
920917 ) ;
921918
922- vm. frames . push ( new_frame) ;
919+ vm. push_frame ( new_frame) ;
923920 Ok ( ( ) )
924921}
925922
@@ -987,21 +984,21 @@ fn exec_call_cfunction(
987984 actual_arg_count + 1 ,
988985 ) ;
989986
990- vm. frames . push ( temp_frame) ;
987+ vm. push_frame ( temp_frame) ;
991988
992989 // Call C function
993990 let result = match cfunc ( vm) {
994991 Ok ( r) => r,
995992 Err ( LuaError :: Yield ) => {
996- vm. frames . pop ( ) ;
993+ vm. pop_frame_discard ( ) ;
997994 return Err ( LuaError :: Yield ) ;
998995 }
999996 Err ( e) => {
1000- vm. frames . pop ( ) ;
997+ vm. pop_frame_discard ( ) ;
1001998 return Err ( e) ;
1002999 }
10031000 } ;
1004- vm. frames . pop ( ) ;
1001+ vm. pop_frame_discard ( ) ;
10051002
10061003 // Copy return values
10071004 let values = result. all_values ( ) ;
@@ -1097,7 +1094,7 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
10971094 // Pop current frame (tail call optimization)
10981095 let old_base = base; // Already extracted
10991096 // return_count already extracted
1100- vm. frames . pop ( ) ;
1097+ vm. pop_frame_discard ( ) ;
11011098
11021099 // Create new frame at same location
11031100 let frame_id = vm. next_frame_id ;
@@ -1119,7 +1116,7 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
11191116 result_reg, // result_reg from the CALLER (not 0!)
11201117 return_count,
11211118 ) ;
1122- vm. frames . push ( new_frame) ;
1119+ vm. push_frame ( new_frame) ;
11231120
11241121 Ok ( ( ) )
11251122 }
@@ -1157,16 +1154,16 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
11571154 LuaCallFrame :: new_c_function ( frame_id, function_value, pc, call_base, args_len + 1 ) ;
11581155
11591156 // Push temp frame and call C function
1160- vm. frames . push ( temp_frame) ;
1157+ vm. push_frame ( temp_frame) ;
11611158 let result = c_func ( vm) ?;
1162- vm. frames . pop ( ) ; // Pop temp frame
1159+ vm. pop_frame_discard ( ) ; // Pop temp frame
11631160
11641161 // NOW pop the tail-calling function's frame
1165- vm. frames . pop ( ) ;
1162+ vm. pop_frame_discard ( ) ;
11661163
11671164 // Write return values to PARENT frame
11681165 // CRITICAL: result_reg is relative to PARENT's base_ptr!
1169- if !vm. frames . is_empty ( ) {
1166+ if !vm. frames_is_empty ( ) {
11701167 let parent_base = vm. current_frame ( ) . base_ptr ;
11711168 let vals = result. all_values ( ) ;
11721169 let count = if return_count == usize:: MAX {
@@ -1203,26 +1200,32 @@ pub fn exec_tailcall(vm: &mut LuaVM, instr: u32) -> LuaResult<()> {
12031200/// OPTIMIZED: Use frame_ptr directly
12041201#[ inline( always) ]
12051202pub fn exec_return0 ( vm : & mut LuaVM , _instr : u32 , frame_ptr : * mut LuaCallFrame ) -> LuaResult < ( ) > {
1206- // FAST PATH: Use passed frame_ptr directly
1207- let base_ptr = unsafe { ( * frame_ptr) . base_ptr } ;
1203+ // FAST PATH: Use passed frame_ptr directly - get all info BEFORE popping
1204+ let ( base_ptr, result_reg, num_results) = unsafe {
1205+ (
1206+ ( * frame_ptr) . base_ptr ,
1207+ ( * frame_ptr) . get_result_reg ( ) ,
1208+ ( * frame_ptr) . get_num_results ( ) ,
1209+ )
1210+ } ;
12081211
12091212 // Only close upvalues if there are any
12101213 if !vm. open_upvalues . is_empty ( ) {
12111214 vm. close_upvalues_from ( base_ptr) ;
12121215 }
12131216
1214- let frame = unsafe { vm. frames . pop ( ) . unwrap_unchecked ( ) } ;
1217+ vm. pop_frame_discard ( ) ;
12151218
12161219 vm. return_values . clear ( ) ;
12171220
12181221 // FAST PATH: Check if we have a caller frame
1219- if let Some ( caller_frame ) = vm. frames . last_mut ( ) {
1220- let result_reg = frame . get_result_reg ( ) ;
1221- let num_results = frame . get_num_results ( ) ;
1222+ if ! vm. frames_is_empty ( ) {
1223+ // Get caller's base_ptr first without holding borrow
1224+ let caller_base = vm . current_frame ( ) . base_ptr ;
12221225
12231226 // Fill expected return values with nil
12241227 if num_results != usize:: MAX && num_results > 0 {
1225- let dest_base = caller_frame . base_ptr + result_reg;
1228+ let dest_base = caller_base + result_reg;
12261229 unsafe {
12271230 let reg_ptr = vm. register_stack . as_mut_ptr ( ) ;
12281231 let nil_val = LuaValue :: nil ( ) ;
@@ -1233,7 +1236,7 @@ pub fn exec_return0(vm: &mut LuaVM, _instr: u32, frame_ptr: *mut LuaCallFrame) -
12331236 }
12341237
12351238 // Update caller's top
1236- caller_frame . top = result_reg;
1239+ vm . current_frame_mut ( ) . top = result_reg;
12371240 Ok ( ( ) )
12381241 } else {
12391242 Err ( LuaError :: Exit )
@@ -1263,22 +1266,25 @@ pub fn exec_return1(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame) ->
12631266 } ;
12641267
12651268 // Pop frame - we already have all info we need from frame_ptr
1266- unsafe { vm. frames . pop ( ) . unwrap_unchecked ( ) } ;
1269+ vm. pop_frame_discard ( ) ;
12671270
12681271 // CRITICAL: Always set return_values for call_function_internal compatibility
12691272 vm. return_values . clear ( ) ;
12701273 vm. return_values . push ( return_value) ;
12711274
12721275 // Check if there's a caller frame
1273- if let Some ( caller_frame) = vm. frames . last_mut ( ) {
1276+ if !vm. frames_is_empty ( ) {
1277+ // Get caller's base_ptr first without holding mutable borrow
1278+ let caller_base = vm. current_frame ( ) . base_ptr ;
1279+ let dest_pos = caller_base + result_reg;
1280+
12741281 // Write to caller's result register
1275- let dest_pos = caller_frame. base_ptr + result_reg;
12761282 if dest_pos < vm. register_stack . len ( ) {
12771283 vm. register_stack [ dest_pos] = return_value;
12781284 }
12791285
12801286 // Update top
1281- caller_frame . top = result_reg + 1 ;
1287+ vm . current_frame_mut ( ) . top = result_reg + 1 ;
12821288
12831289 Ok ( ( ) )
12841290 } else {
0 commit comments