Just thought I'd share a simple application-specific optimization I'm using.
For those that don't know, fasttms (that is TM_INDEX through TM_EQ) can be checked for existence via a flag in the metatable.
Eg, if (mt->flags & (1u<<TM_INDEX)) then TM_INDEX is known not to exist inside the metatable.
If the bit is not set, then an ordinary rawget is performed to find the key inside the table.
A simple optimization for those with lots of metamethods (eg oo people), is to change this system a bit:
If (mt->flags & (1u<<TM_INDEX)) then the __index value is stored inside an event cache array, removing the need for a rawget.
A few points come to mind:
(1) As the gc does not resize tables, this event cache can be a simple array of *values for speed and simplicity.
(2) The invalidating of the cache is very quick, merely clear all bits of the flag but bit in (3)(3) So that the size of tables is not increased, one bit in the flags can define whether or not the event cache has been mallocd. This allows storing the event cache as a negative offset of the array component.
(4) This "fastertm" is best limited to just TM_INDEX and TM_NEWINDEX, and any other fasttms that tables with metatables usually have defined. Eg, TM_PROXY or TM_USEDINDEX if you have those. Regular fasttm should be used in cases where the result is usually nil, as it saves an array lookup.
Just thought I'd get comments before posting a patch, if anyone desires it.