The `luaL_testudata` and `luaL_checkudata` functions correctly treat the
absence of a metatable for the type to check as the type not matching,
so there is no need to have the type's metatable in memory until an
object using it exists. Therefore we can defer the metatable's creation
until the first time an object of that type is created.
Saves some 4500 bytes of Lua heap RAM, at least if no such objects are
created. The created metatables are shared between all scripts, so there
is no increase in the total RAM usage if all objects are used. However,
there is some increased risk of heap fragmentation and unexpected
out-of-memory errors on rarely used code paths.
It would be nice to construct the object in the new utility function,
but it's not possible in C++ to take the address of a constructor.
Instead passing in a lambda is ugly, hardly any more efficient, and
screws up constructors which take parameters.
Also optimizes by using the generated userdata creators where possible,
and convincing the compiler to omit unnecessary checks.
add CRSF menu example
add scripted CRSF menu events
custom CRSFMenu helpers
play Beethoven's 5th on CRSF command
use native packed strings for CRSF menus and payloads
support CRSF submenus
Fix generator to skip generation of docs for generation methods that
don't exist, and to avoid generating Lua creation methods that couldn't
be called.
Co-authored-by: Thomas Watson <twatson52@icloud.com>
Move the string checks into the load functions to avoid duplicating it
for each binding.
Also sync up the return types to avoid an unnecessary conversion.
Saves ~1.5K.
The Lua stack is guaranteed to have at least LUA_MINSTACK (default 20)
slots upon entry to C. Check to see if we might need more than that
minimum and only in that case call the function to check and resize the
stack. In virtually all cases the check can then be optimized away.
Additionally remove the redundant "Out of stack" message. Lua already
says "stack overflow" and a null message is valid.
Saves ~330B.
Only create the binding object (singleton metatable/userdata or C
function reference) once the user first references a particular
singleton or userdata creation function. Once created, the object is
stored into the script's environment so it doesn't get recreated on the
next reference and there isn't any further overhead. The userdatas are
no longer shared between scripts which imposes a slight memory penalty
for multiple scripts using the same singleton but this avoids an
additional lookup time cost.
Userdata and ap_objects aren't eligible for this optimization as the C++
code might want a particular metatable at any time.
Saves ~9.3K Lua heap.
The global table is then used as the __index metamethod of each state's
environment table. Avoids the overhead of loading binding objects into
each state. The binding objects are immutable from Lua so sandboxing is
not violated.
Does have the slight downside that a script can no longer know all the
binding names by enumerating _ENV.
Saves ~700B of memory per loaded script.
The __call metamethod was set to the metatable itself. With __call not
present, Lua will try to call the metatable (and fail), which is the
same behavior as with the __call metamethod set to the metatable.
Saves ~2K Lua heap.
Passing -1 to the argument count for the `creation` tag (name does not
matter) will stop the generator from giving Lua a function to construct
that userdata. The C `new_<name>` function still works.