You used to have to be extremely careful to keep the JIT happy, but I think this has been partially solved in LuaJIT 2.1.
Calling C functions using the old stack API would cause the JIT to abort. In Garrysmod's case, that includes such simple operations as constructing and performing arithmetic on vectors.
So when I was building a high-performance voxel library for Garrysmod, I ended up splitting my hot code into chunks that the JIT compiler would usually be happy with. One fast loop to generate a mesh, then a slow loop to convert that into a mesh structure the engine wants. Very carefully designed methods for bit-packing trees of 12-bit integer voxel data into flat tables of floats.
It it still true that generating bindings for luajit is easier than with plain Lua? When I used it for a toy project that was the main reason I chose luajit, especially since the project was written in c++.
Writing bindings isn't something I have a lot of experience with. The main difference I'm aware of is the FFI system, which creates bindings from C headers, and will result in faster calls with good JIT support. I assume it introduces some extra security challenges if you care about that. You'll still probably need to write some wrappers, either C-side or Lua-side if you want a nice API. I know there are other tools for creating bindings, but again, not my area of expertise.
In my experience it very much is. Most of the LuaJIT code I write is just metatable classes around C libraries like SDL. Just being able to write C structs and lua functions is a dream. Having to manually deal with the stack from C-side is a PITA.
Alright, time to run some LuaJIT in my RISC-V emulator.