diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2025-07-24 16:51:49 +0200 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2025-07-24 16:51:49 +0200 |
| commit | d8acb18ce8bf6e89a042d166f61b2934e8722cf0 (patch) | |
| tree | 69f5046056f4aa38b868b057055da8144e029846 /src/tools.cpp | |
| parent | eb997664a5a0a7890efa050982854a1447aec70f (diff) | |
| download | lanes-d8acb18ce8bf6e89a042d166f61b2934e8722cf0.tar.gz lanes-d8acb18ce8bf6e89a042d166f61b2934e8722cf0.tar.bz2 lanes-d8acb18ce8bf6e89a042d166f61b2934e8722cf0.zip | |
Rework function bytecode dumping to be Lua5.5-ready
* prepare the luaL_Buffer in the destination state instead of the source state to prevent stack issues when everything happens in the same state
Diffstat (limited to 'src/tools.cpp')
| -rw-r--r-- | src/tools.cpp | 31 |
1 files changed, 11 insertions, 20 deletions
diff --git a/src/tools.cpp b/src/tools.cpp index c6e9cc3..cd1c593 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -47,13 +47,9 @@ static constexpr RegistryUniqueKey kLookupCacheRegKey{ 0x9BF75F84E54B691Bull }; | |||
| 47 | 47 | ||
| 48 | namespace { | 48 | namespace { |
| 49 | namespace local { | 49 | namespace local { |
| 50 | static int buf_writer(lua_State* L_, void const* b_, size_t size_, void* ud_) | 50 | static int buf_writer([[maybe_unused]] lua_State* const L_, void const* b_, size_t size_, void* ud_) |
| 51 | { | 51 | { |
| 52 | auto* const _B{ static_cast<luaL_Buffer*>(ud_) }; | 52 | auto* const _B{ static_cast<luaL_Buffer*>(ud_) }; |
| 53 | if (!_B->L) { | ||
| 54 | luaL_buffinit(L_, _B); | ||
| 55 | } | ||
| 56 | // starting with Lua 5.5, the writer is called one last time with nullptr, 0 at the end | ||
| 57 | if (b_ && size_) { | 53 | if (b_ && size_) { |
| 58 | luaL_addlstring(_B, static_cast<char const*>(b_), size_); | 54 | luaL_addlstring(_B, static_cast<char const*>(b_), size_); |
| 59 | } | 55 | } |
| @@ -79,9 +75,7 @@ namespace { | |||
| 79 | * +-------------------+------------+----------+ | 75 | * +-------------------+------------+----------+ |
| 80 | * | bytecode | C function | JIT-fast | | 76 | * | bytecode | C function | JIT-fast | |
| 81 | * +-----------------+-------------------+------------+----------+ | 77 | * +-----------------+-------------------+------------+----------+ |
| 82 | * | lua_topointer | | | | | 78 | * | lua_tocfunction | nullptr | <some p> | nullptr | |
| 83 | * +-----------------+-------------------+------------+----------+ | ||
| 84 | * | lua_tocfunction | nullptr | | nullptr | | ||
| 85 | * +-----------------+-------------------+------------+----------+ | 79 | * +-----------------+-------------------+------------+----------+ |
| 86 | * | luaW_dump | kWriterReturnCode | 1 | 1 | | 80 | * | luaW_dump | kWriterReturnCode | 1 | 1 | |
| 87 | * +-----------------+-------------------+------------+----------+ | 81 | * +-----------------+-------------------+------------+----------+ |
| @@ -139,20 +133,17 @@ namespace tools { | |||
| 139 | 133 | ||
| 140 | // ############################################################################################# | 134 | // ############################################################################################# |
| 141 | 135 | ||
| 142 | [[nodiscard]] | 136 | void PushFunctionBytecode(SourceState const L1_, DestState const L2_, int const strip_) |
| 143 | int PushFunctionBytecode(lua_State* const L_, int const strip_) | ||
| 144 | { | 137 | { |
| 145 | luaL_Buffer B{}; | 138 | luaL_Buffer B{}; |
| 146 | // WORKAROUND FOR Lua 5.5 beta: lua_dump followed by luaL_pushresult pops the function from the stack before adding the bytecode string | 139 | STACK_CHECK_START_REL(L1_, 0); |
| 147 | // so I need to duplicate it so that I end up with the original stack and the bytecode string pushed on top | 140 | STACK_CHECK_START_REL(L2_, 0); |
| 148 | if constexpr (LUA_VERSION_NUM == 505) { | 141 | STACK_GROW(L2_, 2); |
| 149 | lua_pushvalue(L_, kIdxTop); | 142 | luaL_buffinit(L2_, &B); // L1_: ... f L2_: ... <B stuff> |
| 150 | } | 143 | luaW_dump(L1_, local::buf_writer, &B, strip_); |
| 151 | int const result_{ luaW_dump(L_, local::buf_writer, &B, strip_) }; | 144 | luaL_pushresult(&B); // L2_: ... "<bytecode>" |
| 152 | if (result_ == 0) { // documentation says it should always be the case (because our writer only ever returns 0), but better safe than sorry | 145 | STACK_CHECK(L2_, 1); |
| 153 | luaL_pushresult(&B); | 146 | STACK_CHECK(L1_, 0); |
| 154 | } | ||
| 155 | return result_; | ||
| 156 | } | 147 | } |
| 157 | } // namespace tools | 148 | } // namespace tools |
| 158 | 149 | ||
