@@ -75,21 +75,22 @@ pub fn exec_gettable(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, b
7575 ( table, key)
7676 } ;
7777
78- // FAST PATH: Direct table access for common case (integer key, no metatable)
78+ // FAST PATH: Direct table access for common case
7979 if let Some ( table_id) = table_value. as_table_id ( ) {
8080 // SAFETY: table_id is valid because it came from as_table_id()
8181 let lua_table = unsafe { vm. object_pool . get_table_unchecked ( table_id) } ;
8282
83- // Try integer key fast path first
84- if let Some ( i) = key_value. as_integer ( ) {
85- if let Some ( val) = lua_table. get_int ( i) {
86- unsafe { * vm. register_stack . get_unchecked_mut ( * base_ptr + a) = val } ;
87- return Ok ( ( ) ) ;
88- }
89- }
83+ // Check key type to choose optimal path
84+ // Integer keys may be in array part, other keys are in hash part
85+ let result = if let Some ( i) = key_value. as_integer ( ) {
86+ // Integer key: try array first, then hash
87+ lua_table. get_int ( i) . or_else ( || lua_table. get_from_hash ( & key_value) )
88+ } else {
89+ // Non-integer key: direct hash lookup (most common for string keys)
90+ lua_table. get_from_hash ( & key_value)
91+ } ;
9092
91- // Try hash lookup
92- if let Some ( val) = lua_table. get_from_hash ( & key_value) {
93+ if let Some ( val) = result {
9394 if !val. is_nil ( ) {
9495 unsafe { * vm. register_stack . get_unchecked_mut ( * base_ptr + a) = val } ;
9596 return Ok ( ( ) ) ;
@@ -259,44 +260,35 @@ pub fn exec_seti(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, base_
259260
260261/// GETFIELD A B C
261262/// R[A] := R[B][K[C]:string]
263+ /// OPTIMIZED: Uses cached constants_ptr for direct constant access
262264#[ inline( always) ]
263265pub fn exec_getfield ( vm : & mut LuaVM , instr : u32 , frame_ptr : * mut LuaCallFrame , base_ptr : & mut usize ) -> LuaResult < ( ) > {
264266 let a = Instruction :: get_a ( instr) as usize ;
265267 let b = Instruction :: get_b ( instr) as usize ;
266268 let c = Instruction :: get_c ( instr) as usize ;
267269
268- let func_value = unsafe { ( * frame_ptr) . function_value } ;
269-
270- // Get key constant using new API
271- let Some ( func_id) = func_value. as_function_id ( ) else {
272- return Err ( vm. error ( "Not a Lua function" . to_string ( ) ) ) ;
273- } ;
274- let Some ( func_ref) = vm. object_pool . get_function ( func_id) else {
275- return Err ( vm. error ( "Invalid function ID" . to_string ( ) ) ) ;
276- } ;
277- let Some ( key_value) = func_ref. chunk . constants . get ( c) . copied ( ) else {
278- return Err ( vm. error ( format ! ( "Invalid constant index: {}" , c) ) ) ;
279- } ;
280-
281- let table_value = vm. register_stack [ * base_ptr + b] ;
270+ // FAST PATH: Direct constant access via cached pointer (like GETTABUP)
271+ let key_value = unsafe { * ( * frame_ptr) . constants_ptr . add ( c) } ;
272+ let table_value = unsafe { * vm. register_stack . get_unchecked ( * base_ptr + b) } ;
282273
283274 // FAST PATH: Direct hash access for tables without metatable
284275 if let Some ( table_id) = table_value. as_table_id ( ) {
285- if let Some ( table_ref) = vm. object_pool . get_table ( table_id) {
286- // Use optimized hash-only lookup (GETFIELD always uses string keys, never integers)
287- if let Some ( val) = table_ref. get_from_hash ( & key_value) {
288- if !val. is_nil ( ) {
289- vm. register_stack [ * base_ptr + a] = val;
290- return Ok ( ( ) ) ;
291- }
292- }
276+ // OPTIMIZED: Use unchecked table access
277+ let table_ref = unsafe { vm. object_pool . get_table_unchecked ( table_id) } ;
293278
294- // Check if no metatable - can return nil directly
295- if table_ref. get_metatable ( ) . is_none ( ) {
296- vm. register_stack [ * base_ptr + a] = LuaValue :: nil ( ) ;
279+ // GETFIELD always uses string keys - direct hash lookup
280+ if let Some ( val) = table_ref. get_from_hash ( & key_value) {
281+ if !val. is_nil ( ) {
282+ unsafe { * vm. register_stack . get_unchecked_mut ( * base_ptr + a) = val } ;
297283 return Ok ( ( ) ) ;
298284 }
299285 }
286+
287+ // Check if no metatable - can return nil directly
288+ if table_ref. get_metatable ( ) . is_none ( ) {
289+ unsafe { * vm. register_stack . get_unchecked_mut ( * base_ptr + a) = LuaValue :: nil ( ) } ;
290+ return Ok ( ( ) ) ;
291+ }
300292 }
301293
302294 // Slow path: Use metamethod handling
@@ -306,61 +298,44 @@ pub fn exec_getfield(vm: &mut LuaVM, instr: u32, frame_ptr: *mut LuaCallFrame, b
306298
307299 // IMPORTANT: Re-read base_ptr after metamethod call in case frames changed
308300 * base_ptr = unsafe { ( * frame_ptr) . base_ptr } ;
309- vm. register_stack [ * base_ptr + a] = value;
301+ unsafe { * vm. register_stack . get_unchecked_mut ( * base_ptr + a) = value } ;
310302
311303 Ok ( ( ) )
312304}
313305
314306/// SETFIELD A B C k
315307/// R[A][K[B]:string] := RK(C)
308+ /// OPTIMIZED: Uses cached constants_ptr for direct constant access
316309#[ inline( always) ]
317310pub fn exec_setfield ( vm : & mut LuaVM , instr : u32 , frame_ptr : * mut LuaCallFrame , base_ptr : & mut usize ) -> LuaResult < ( ) > {
318311 let a = Instruction :: get_a ( instr) as usize ;
319312 let b = Instruction :: get_b ( instr) as usize ;
320313 let c = Instruction :: get_c ( instr) as usize ;
321314 let k = Instruction :: get_k ( instr) ;
322315
323- // CRITICAL: Read all values BEFORE any metamethod calls
324- // because metamethods can modify the register stack
316+ // FAST PATH: Direct access via cached pointers
325317 let ( table_value, key_value, set_value) = unsafe {
326- let func_value = ( * frame_ptr) . function_value ;
327-
328- // Get key constant using new API
329- let Some ( func_id) = func_value. as_function_id ( ) else {
330- return Err ( vm. error ( "Not a Lua function" . to_string ( ) ) ) ;
331- } ;
332- let Some ( func_ref) = vm. object_pool . get_function ( func_id) else {
333- return Err ( vm. error ( "Invalid function ID" . to_string ( ) ) ) ;
334- } ;
335- let Some ( key) = func_ref. chunk . constants . get ( b) . copied ( ) else {
336- return Err ( vm. error ( format ! ( "Invalid constant index: {}" , b) ) ) ;
337- } ;
338-
339- let table = vm. register_stack [ * base_ptr + a] ;
340-
318+ let table = * vm. register_stack . get_unchecked ( * base_ptr + a) ;
319+ let key = * ( * frame_ptr) . constants_ptr . add ( b) ;
341320 let value = if k {
342- let Some ( constant) = func_ref. chunk . constants . get ( c) . copied ( ) else {
343- return Err ( vm. error ( format ! ( "Invalid constant index: {}" , c) ) ) ;
344- } ;
345- constant
321+ * ( * frame_ptr) . constants_ptr . add ( c)
346322 } else {
347- vm. register_stack [ * base_ptr + c]
323+ * vm. register_stack . get_unchecked ( * base_ptr + c)
348324 } ;
349-
350325 ( table, key, value)
351326 } ;
352327
353328 // FAST PATH: Direct table access without metamethod check for common case
354329 if let Some ( table_id) = table_value. as_table_id ( ) {
355- if let Some ( table_ref) = vm. object_pool . get_table_mut ( table_id) {
356- // Quick check: no metatable means no __newindex to worry about
357- if table_ref. get_metatable ( ) . is_none ( ) {
358- // Ultra-fast path: direct set without any metamethod checks
359- table_ref. raw_set ( key_value. clone ( ) , set_value. clone ( ) ) ;
330+ // OPTIMIZED: Use unchecked access
331+ let table_ref = unsafe { vm. object_pool . get_table_unchecked ( table_id) } ;
360332
361- // Note: GC barrier is handled lazily during collection
362- return Ok ( ( ) ) ;
363- }
333+ // Quick check: no metatable means no __newindex to worry about
334+ if table_ref. get_metatable ( ) . is_none ( ) {
335+ let table_ref = unsafe { vm. object_pool . get_table_mut_unchecked ( table_id) } ;
336+ // Ultra-fast path: direct set without any metamethod checks
337+ table_ref. raw_set ( key_value, set_value) ;
338+ return Ok ( ( ) ) ;
364339 }
365340 }
366341
0 commit comments