aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2025-07-22 15:36:56 +0200
committerBenoit Germain <bnt.germain@gmail.com>2025-07-22 15:36:56 +0200
commitc67c7bb2cde0d418f72c8ac1ef57f15669b8a2bf (patch)
tree74dfb12958087ddb04a6e856a6c04d6f17bab590 /src
parent9eb852e50c62f5e67266e0055e5899ef61e611d3 (diff)
downloadlanes-c67c7bb2cde0d418f72c8ac1ef57f15669b8a2bf.tar.gz
lanes-c67c7bb2cde0d418f72c8ac1ef57f15669b8a2bf.tar.bz2
lanes-c67c7bb2cde0d418f72c8ac1ef57f15669b8a2bf.zip
New helper to push function bytecode (to facilitate Lua 5.5 support)
Diffstat (limited to 'src')
-rw-r--r--src/intercopycontext.cpp38
-rw-r--r--src/tools.cpp51
-rw-r--r--src/tools.hpp2
3 files changed, 53 insertions, 38 deletions
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index 7be1326..653eeb6 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -36,23 +36,6 @@ THE SOFTWARE.
36 36
37// ################################################################################################# 37// #################################################################################################
38 38
39// Lua 5.4.3 style of dumping (see lstrlib.c)
40// we have to do it that way because we can't unbalance the stack between buffer operations
41// namely, this means we can't push a function on top of the stack *after* we initialize the buffer!
42// luckily, this also works with earlier Lua versions
43[[nodiscard]]
44static int buf_writer(lua_State* L_, void const* b_, size_t size_, void* ud_)
45{
46 luaL_Buffer* const _B{ static_cast<luaL_Buffer*>(ud_) };
47 if (!_B->L) {
48 luaL_buffinit(L_, _B);
49 }
50 luaL_addlstring(_B, static_cast<char const*>(b_), size_);
51 return 0;
52}
53
54// #################################################################################################
55
56// function sentinel used to transfer native functions from/to keeper states 39// function sentinel used to transfer native functions from/to keeper states
57[[nodiscard]] 40[[nodiscard]]
58static int func_lookup_sentinel(lua_State* const L_) 41static int func_lookup_sentinel(lua_State* const L_)
@@ -211,19 +194,18 @@ void InterCopyContext::copyFunction() const
211 // to the writer" (and we only return 0) 194 // to the writer" (and we only return 0)
212 // not sure this could ever fail but for memory shortage reasons 195 // not sure this could ever fail but for memory shortage reasons
213 // last argument is Lua 5.4-specific (no stripping) 196 // last argument is Lua 5.4-specific (no stripping)
214 luaL_Buffer B{}; 197 if (tools::PushFunctionBytecode(L1, U->stripFunctions) != 0) { // L1: ... f "<bytecode>"
215 if (luaW_dump(L1, buf_writer, &B, U->stripFunctions) != 0) {
216 raise_luaL_error(getErrL(), "internal error: function dump failed."); 198 raise_luaL_error(getErrL(), "internal error: function dump failed.");
217 } 199 }
218 200
219 // pushes dumped string on 'L1' 201 // if pushed, we need to pop
220 luaL_pushresult(&B); // L1: ... f b
221
222 // if not pushed, no need to pop
223 if (_needToPush) { 202 if (_needToPush) {
224 lua_remove(L1, -2); // L1: ... b 203 lua_remove(L1, -2); // L1: ... "<bytecode>"
225 } 204 }
226 205
206 // When we are done, the stack should be the original one, with the bytecode string added on top
207 STACK_CHECK(L1, 1);
208
227 // transfer the bytecode, then the upvalues, to create a similar closure 209 // transfer the bytecode, then the upvalues, to create a similar closure
228 { 210 {
229 char const* _fname{}; 211 char const* _fname{};
@@ -231,16 +213,16 @@ void InterCopyContext::copyFunction() const
231 if constexpr (LOG_FUNC_INFO) 213 if constexpr (LOG_FUNC_INFO)
232 { 214 {
233 lua_Debug _ar; 215 lua_Debug _ar;
234 lua_pushvalue(L1, L1_i); // L1: ... b f 216 lua_pushvalue(L1, L1_i); // L1: ... "<bytecode>" f
235 // "To get information about a function you push it onto the stack and start the what string with the character '>'." 217 // "To get information about a function you push it onto the stack and start the what string with the character '>'."
236 // fills 'fname' 'namewhat' and 'linedefined', pops function 218 // fills 'fname' 'namewhat' and 'linedefined', pops function
237 lua_getinfo(L1, ">nS", &_ar); // L1: ... b 219 lua_getinfo(L1, ">nS", &_ar); // L1: ... "<bytecode>"
238 _fname = _ar.namewhat; 220 _fname = _ar.namewhat;
239 DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl); 221 DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl);
240 } 222 }
241 223
242 { 224 {
243 std::string_view const _bytecode{ luaW_tostring(L1, kIdxTop) }; // L1: ... b 225 std::string_view const _bytecode{ luaW_tostring(L1, kIdxTop) }; // L1: ... "<bytecode>"
244 LUA_ASSERT(L1, !_bytecode.empty()); 226 LUA_ASSERT(L1, !_bytecode.empty());
245 STACK_GROW(L2, 2); 227 STACK_GROW(L2, 2);
246 // Note: Line numbers seem to be taken precisely from the 228 // Note: Line numbers seem to be taken precisely from the
@@ -257,7 +239,7 @@ void InterCopyContext::copyFunction() const
257 raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, -1)); 239 raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, -1));
258 } 240 }
259 // remove the dumped string 241 // remove the dumped string
260 lua_pop(L1, 1); // ... 242 lua_pop(L1, 1); // L1: ...
261 // now set the cache as soon as we can. 243 // now set the cache as soon as we can.
262 // this is necessary if one of the function's upvalues references it indirectly 244 // this is necessary if one of the function's upvalues references it indirectly
263 // we need to find it in the cache even if it isn't fully transfered yet 245 // we need to find it in the cache even if it isn't fully transfered yet
diff --git a/src/tools.cpp b/src/tools.cpp
index 25949e4..aafb9e8 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -45,13 +45,33 @@ static constexpr RegistryUniqueKey kLookupCacheRegKey{ 0x9BF75F84E54B691Bull };
45 45
46// ################################################################################################# 46// #################################################################################################
47 47
48static constexpr int kWriterReturnCode{ 666 }; 48namespace {
49[[nodiscard]] 49 namespace local {
50static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_) 50 static int buf_writer(lua_State* L_, void const* b_, size_t size_, void* ud_)
51{ 51 {
52 // always fail with this code 52 auto* const _B{ static_cast<luaL_Buffer*>(ud_) };
53 return kWriterReturnCode; 53 if (!_B->L) {
54} 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_) {
58 luaL_addlstring(_B, static_cast<char const*>(b_), size_);
59 }
60 return 0;
61 }
62
63 static constexpr int kWriterReturnCode{ 666 };
64 [[nodiscard]]
65 static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_)
66 {
67 // always fail with this code
68 return kWriterReturnCode;
69 }
70
71 } // namespace local
72} // namespace
73
74// #################################################################################################
55 75
56/* 76/*
57 * differentiation between C, bytecode and JIT-fast functions 77 * differentiation between C, bytecode and JIT-fast functions
@@ -77,11 +97,11 @@ FuncSubType luaW_getfuncsubtype(lua_State* const L_, StackIndex const i_)
77 // luaW_dump expects the function at the top of the stack 97 // luaW_dump expects the function at the top of the stack
78 int const _popCount{ (luaW_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) }; 98 int const _popCount{ (luaW_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) };
79 // here we either have a Lua bytecode or a LuaJIT-compiled function 99 // here we either have a Lua bytecode or a LuaJIT-compiled function
80 int const _dumpres{ luaW_dump(L_, dummy_writer, nullptr, 0) }; 100 int const _dumpres{ luaW_dump(L_, local::dummy_writer, nullptr, 0) };
81 if (_popCount > 0) { 101 if (_popCount > 0) {
82 lua_pop(L_, _popCount); 102 lua_pop(L_, _popCount);
83 } 103 }
84 if (_dumpres == kWriterReturnCode) { 104 if (_dumpres == local::kWriterReturnCode) {
85 // anytime we get kWriterReturnCode, this means that luaW_dump() attempted a dump 105 // anytime we get kWriterReturnCode, this means that luaW_dump() attempted a dump
86 return FuncSubType::Bytecode; 106 return FuncSubType::Bytecode;
87 } 107 }
@@ -92,7 +112,6 @@ FuncSubType luaW_getfuncsubtype(lua_State* const L_, StackIndex const i_)
92// ################################################################################################# 112// #################################################################################################
93 113
94namespace tools { 114namespace tools {
95
96 // inspired from tconcat() in ltablib.c 115 // inspired from tconcat() in ltablib.c
97 [[nodiscard]] 116 [[nodiscard]]
98 std::string_view PushFQN(lua_State* const L_, StackIndex const t_) 117 std::string_view PushFQN(lua_State* const L_, StackIndex const t_)
@@ -118,6 +137,18 @@ namespace tools {
118 return luaW_tostring(L_, kIdxTop); 137 return luaW_tostring(L_, kIdxTop);
119 } 138 }
120 139
140 // #############################################################################################
141
142 [[nodiscard]]
143 int PushFunctionBytecode(lua_State* const L_, int const strip_)
144 {
145 luaL_Buffer B{};
146 int const result_{ luaW_dump(L_, local::buf_writer, &B, strip_) };
147 if (result_ == 0) { // documentation says it should always be the case (because our writer only ever returns 0), but better safe than sorry
148 luaL_pushresult(&B);
149 }
150 return result_;
151 }
121} // namespace tools 152} // namespace tools
122 153
123// ################################################################################################# 154// #################################################################################################
diff --git a/src/tools.hpp b/src/tools.hpp
index 14f9855..51cbb9b 100644
--- a/src/tools.hpp
+++ b/src/tools.hpp
@@ -37,5 +37,7 @@ namespace tools {
37 void PopulateFuncLookupTable(lua_State* L_, StackIndex i_, std::string_view const& name_); 37 void PopulateFuncLookupTable(lua_State* L_, StackIndex i_, std::string_view const& name_);
38 [[nodiscard]] 38 [[nodiscard]]
39 std::string_view PushFQN(lua_State* L_, StackIndex t_); 39 std::string_view PushFQN(lua_State* L_, StackIndex t_);
40 [[nodiscard]]
41 int PushFunctionBytecode(lua_State* L_, int strip_);
40 void SerializeRequire(lua_State* L_); 42 void SerializeRequire(lua_State* L_);
41} // namespace tools 43} // namespace tools