@@ -240,33 +240,45 @@ impl LuaVM {
240240 /// Main execution loop - interprets bytecode instructions
241241 /// Returns the final return value from the chunk
242242 fn run ( & mut self ) -> LuaResult < LuaValue > {
243+ // OPTIMIZATION: Cache chunk pointer across instructions to avoid RefCell::borrow() overhead
244+ // This is safe because chunk doesn't change during function execution
245+ let mut cached_chunk_ptr: Option < * const Chunk > = None ;
246+ let mut cached_func_ptr: Option < * const RefCell < LuaFunction > > = None ;
247+
243248 loop {
244249 // Check if we have any frames to execute
245250 if self . frames . is_empty ( ) {
246251 // Execution finished
247252 return Ok ( self . return_values . first ( ) . copied ( ) . unwrap_or ( LuaValue :: nil ( ) ) ) ;
248253 }
249254
250- // Get current frame and chunk
255+ // Get current frame
251256 let frame = self . current_frame ( ) ;
252257 let func_ptr = match frame. get_function_ptr ( ) {
253258 Some ( ptr) => ptr,
254259 None => return Err ( LuaError :: RuntimeError ( "Not a Lua function" . to_string ( ) ) ) ,
255260 } ;
256261
257- // Safety: func_ptr is valid as long as the function exists in object_pool
258- let func = unsafe { & * func_ptr } ;
259- let func_ref = func. borrow ( ) ;
260- let chunk = & func_ref. chunk ;
262+ // OPTIMIZATION: Cache chunk pointer to avoid repeated RefCell::borrow()
263+ // Only update cache when function changes
264+ let chunk_ptr = if Some ( func_ptr) == cached_func_ptr {
265+ unsafe { cached_chunk_ptr. unwrap_unchecked ( ) }
266+ } else {
267+ // Function changed (call/return), update cache
268+ let func = unsafe { & * func_ptr } ;
269+ let func_ref = func. borrow ( ) ;
270+ let chunk_ptr = Rc :: as_ptr ( & func_ref. chunk ) ;
271+ drop ( func_ref) ;
272+ cached_func_ptr = Some ( func_ptr) ;
273+ cached_chunk_ptr = Some ( chunk_ptr) ;
274+ chunk_ptr
275+ } ;
261276
262- // OPTIMIZATION: Use unsafe for unchecked instruction fetch (hot path )
263- // Safety: PC bounds are checked by bytecode compiler and instruction execution
277+ // OPTIMIZATION: Use cached chunk pointer directly (zero overhead )
278+ let chunk = unsafe { & * chunk_ptr } ;
264279 let pc = frame. pc ;
265280 let instr = unsafe { * chunk. code . get_unchecked ( pc) } ;
266281
267- // Drop borrows before executing instruction
268- drop ( func_ref) ;
269-
270282 // Increment PC before dispatching (standard for most instructions)
271283 // Some instructions (JMP, FORLOOP, etc.) will override this
272284 self . current_frame_mut ( ) . pc += 1 ;
0 commit comments