I also compared different PUC Lua versions in an earlier measurement (see http://software.rochus-keller.ch/are-we-fast-yet_lua_results...) and found similar significant differences between versions.
And here is a repository with a compiler backend to generate LuaJIT bytecode and other useful tools: https://github.com/rochus-keller/ljtools/
The reason why I switched from generating Lua source code to LuaJIT bytecode in 2019 was mostly the higher flexibility. I could better avoid operations not yet supported by the tracer, and some language features of Oberon+ didn't match well to Lua. And adding line information for debugging was much easier. And it was a fun project and the bytecode was well documented. It's certainly also a bit faster, but I haven't done specific measurements.
My goals are:
Deep copy value passing semantics by default (with outs for hotpath and some optimization).
Persistence by default using SQLite. (Again, opt out for hot paths).
Lua tables, but callable. Also every object is a continuation. Optimizations for js are float64 arrays with the 0 index holding some meta stuff - but semantically just objects and messages.
No variables, just fields.
Fields can be thought of as canned message responses. Fallthrough is “call”.
I guess in my head, I really liked the idea of the simplicity and size of Lua/luajit - but maybe for people like me, who have no hope of designing competitive JITs, the future is just to spit out JavaScript.
Your work has been an inspiration to me for quite a long time but the way.