@@ -5,7 +5,7 @@ use super::LuaValue;
55use crate :: LuaVM ;
66
77/// Hash node - mimics Lua 5.4's Node structure
8- /// Contains key+value pair and next index for collision chaining
8+ /// Contains key+value pair
99#[ derive( Clone , Copy ) ]
1010struct Node {
1111 key : LuaValue ,
@@ -75,29 +75,26 @@ impl LuaTable {
7575 }
7676 }
7777
78- /// Hash function for LuaValue - matches Lua's hashing strategy
79- #[ inline]
78+ /// Hash function for LuaValue - optimized for speed
79+ #[ inline( always ) ]
8080 fn hash_key ( key : & LuaValue , size : usize ) -> usize {
8181 if size == 0 {
8282 return 0 ;
8383 }
8484
85- // Use Lua's approach: extract a numeric hash from the value
86- let hash = if let Some ( i) = key. as_integer ( ) {
87- i as u64
88- } else if let Some ( f) = key. as_float ( ) {
89- f. to_bits ( )
90- } else {
91- // For other types, use the primary value as hash
92- key. primary
93- } ;
85+ // Use XOR of both words for good distribution
86+ // This is faster than type-checking and works for all value types
87+ let raw = key. primary ^ key. secondary ;
88+
89+ // Simple but effective mixing (from FxHash)
90+ let hash = raw. wrapping_mul ( 0x517cc1b727220a95 ) ;
9491
95- // Simple modulo - Lua uses power-of-2 sizes for fast masking
92+ // Fast modulo using bitmask (size is power of 2)
9693 ( hash as usize ) & ( size - 1 )
9794 }
9895
9996 /// Find a node with the given key, returns Some(index) if found
100- #[ inline]
97+ #[ inline( always ) ]
10198 fn find_node ( & self , key : & LuaValue ) -> Option < usize > {
10299 let size = self . nodes . len ( ) ;
103100 if size == 0 {
@@ -107,23 +104,30 @@ impl LuaTable {
107104 let mut idx = Self :: hash_key ( key, size) ;
108105 let start_idx = idx;
109106
107+ // Fast path: check first slot (no collision case - most common)
108+ let node = unsafe { self . nodes . get_unchecked ( idx) } ;
109+ if node. is_empty ( ) {
110+ return None ;
111+ }
112+ if node. key == * key {
113+ return Some ( idx) ;
114+ }
115+
116+ // Collision path: linear probe
110117 loop {
111- let node = & self . nodes [ idx] ;
118+ idx = ( idx + 1 ) & ( size - 1 ) ;
119+
120+ if idx == start_idx {
121+ return None ;
122+ }
123+
124+ let node = unsafe { self . nodes . get_unchecked ( idx) } ;
112125 if node. is_empty ( ) {
113126 return None ;
114127 }
115-
116128 if node. key == * key {
117129 return Some ( idx) ;
118130 }
119-
120- // Linear probing
121- idx = ( idx + 1 ) & ( size - 1 ) ;
122-
123- // Avoid infinite loop
124- if idx == start_idx {
125- return None ;
126- }
127131 }
128132 }
129133
@@ -150,25 +154,28 @@ impl LuaTable {
150154 }
151155
152156 /// Simple insert using linear probing (no complex chaining)
157+ #[ inline]
153158 fn insert_node_simple ( & mut self , key : LuaValue , value : LuaValue ) {
154159 let size = self . nodes . len ( ) ;
155160 debug_assert ! ( size > 0 , "insert_node_simple called with empty nodes" ) ;
156161
157162 let mut idx = Self :: hash_key ( & key, size) ;
163+
164+ // Fast path: first slot is empty (common case)
165+ let node = unsafe { self . nodes . get_unchecked ( idx) } ;
166+ if node. is_empty ( ) {
167+ self . nodes [ idx] = Node { key, value } ;
168+ self . hash_size += 1 ;
169+ return ;
170+ }
171+ if node. key == key {
172+ self . nodes [ idx] . value = value;
173+ return ;
174+ }
175+
176+ // Collision path
158177 let start_idx = idx;
159-
160178 loop {
161- if self . nodes [ idx] . is_empty ( ) {
162- // New insertion
163- self . nodes [ idx] = Node { key, value } ;
164- self . hash_size += 1 ;
165- return ;
166- } else if self . nodes [ idx] . key == key {
167- // Update existing
168- self . nodes [ idx] . value = value;
169- return ;
170- }
171-
172179 idx = ( idx + 1 ) & ( size - 1 ) ;
173180
174181 if idx == start_idx {
@@ -178,6 +185,17 @@ impl LuaTable {
178185 size, self . hash_size, key
179186 ) ;
180187 }
188+
189+ let node = unsafe { self . nodes . get_unchecked ( idx) } ;
190+ if node. is_empty ( ) {
191+ self . nodes [ idx] = Node { key, value } ;
192+ self . hash_size += 1 ;
193+ return ;
194+ }
195+ if node. key == key {
196+ self . nodes [ idx] . value = value;
197+ return ;
198+ }
181199 }
182200 }
183201
0 commit comments