diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:23:21 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-29 11:23:21 +0200 |
commit | 05921ccb8205a4dcf1897dd8be9aa30a09e9a379 (patch) | |
tree | 9bb3c3139fbdf1ca8b409163877f6a3f69a81260 /src | |
parent | 6b836d54fdbea502f47c546f8f04c347eba46d5c (diff) | |
download | lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.tar.gz lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.tar.bz2 lanes-05921ccb8205a4dcf1897dd8be9aa30a09e9a379.zip |
PushDeepProxy internal change
Diffstat (limited to 'src')
-rw-r--r-- | src/deep.cpp | 87 | ||||
-rw-r--r-- | src/deep.h | 2 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 9 | ||||
-rw-r--r-- | src/lanes.cpp | 12 |
4 files changed, 48 insertions, 62 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index a39e0f8..dfa3579 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -177,28 +177,29 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Push a proxy userdata on the stack. | 179 | * Push a proxy userdata on the stack. |
180 | * returns nullptr if ok, else some error string related to bad factory behavior or module require problem | 180 | * raises an error in case of problem (error cannot happen with mode_ == LookupMode::ToKeeper) |
181 | * (error cannot happen with mode_ == LookupMode::ToKeeper) | ||
182 | * | 181 | * |
183 | * Initializes necessary structures if it's the first time 'factory' is being | 182 | * Initializes necessary structures if it's the first time 'factory' is being used in |
184 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 183 | * this Lua state (metatable, registring it). Otherwise, increments the reference count. |
185 | * reference count. | ||
186 | */ | 184 | */ |
187 | std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_) | 185 | void DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int nuv_, LookupMode mode_, lua_State* errL_) |
188 | { | 186 | { |
189 | // Check if a proxy already exists | 187 | STACK_CHECK_START_REL(L_, 0); |
190 | kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC | 188 | kDeepProxyCacheRegKey.getSubTableMode(L_, "v"); // L_: DPC |
189 | |||
190 | // Check if a proxy already exists | ||
191 | lua_pushlightuserdata(L_, prelude_); // L_: DPC deep | 191 | lua_pushlightuserdata(L_, prelude_); // L_: DPC deep |
192 | lua_rawget(L_, -2); // L_: DPC proxy | 192 | lua_rawget(L_, -2); // L_: DPC proxy |
193 | if (!lua_isnil(L_, -1)) { | 193 | if (!lua_isnil(L_, -1)) { |
194 | lua_remove(L_, -2); // L_: proxy | 194 | lua_remove(L_, -2); // L_: proxy |
195 | return std::string_view{}; | 195 | STACK_CHECK(L_, 1); |
196 | return; | ||
196 | } else { | 197 | } else { |
197 | lua_pop(L_, 1); // L_: DPC | 198 | lua_pop(L_, 1); // L_: DPC |
198 | } | 199 | } |
200 | STACK_CHECK(L_, 1); | ||
199 | 201 | ||
200 | STACK_GROW(L_, 7); | 202 | STACK_GROW(L_, 7); |
201 | STACK_CHECK_START_REL(L_, 0); | ||
202 | 203 | ||
203 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 204 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
204 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy | 205 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy |
@@ -219,9 +220,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
219 | factory.createMetatable(L_); // L_: DPC proxy metatable | 220 | factory.createMetatable(L_); // L_: DPC proxy metatable |
220 | if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { | 221 | if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { |
221 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! | 222 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! |
222 | lua_settop(L_, _oldtop); // L_: DPC proxy X | 223 | raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); |
223 | lua_pop(L_, 3); // L_: | ||
224 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; | ||
225 | } | 224 | } |
226 | // if the metatable contains a __gc, we will call it from our own | 225 | // if the metatable contains a __gc, we will call it from our own |
227 | std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc | 226 | std::ignore = luaG_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc |
@@ -248,40 +247,42 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
248 | // L.registry._LOADED exists without having registered the 'package' library. | 247 | // L.registry._LOADED exists without having registered the 'package' library. |
249 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() | 248 | lua_getglobal(L_, "require"); // L_: DPC proxy metatable require() |
250 | // check that the module is already loaded (or being loaded, we are happy either way) | 249 | // check that the module is already loaded (or being loaded, we are happy either way) |
251 | if (lua_isfunction(L_, -1)) { | 250 | if (!lua_isfunction(L_, -1)) { // a module name, but no require() function :-( |
252 | std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" | 251 | raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library"); |
253 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) == LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED | 252 | } |
254 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" | 253 | |
255 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module | 254 | std::ignore = lua_pushstringview(L_, _modname); // L_: DPC proxy metatable require() "module" |
256 | int const _alreadyloaded{ lua_toboolean(L_, -1) }; | 255 | if (luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED |
257 | if (!_alreadyloaded) { // not loaded | 256 | // no L.registry._LOADED; can this ever happen? |
258 | lua_pop(L_, 2); // L_: DPC proxy metatable require() "module" | 257 | lua_pop(L_, 6); // L_: |
259 | // require "modname" | 258 | raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName"); |
260 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | 259 | } |
261 | if (_require_result != LuaError::OK) { | 260 | |
262 | // failed, return the error message | 261 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" |
263 | lua_pushfstring(L_, "error while requiring '" STRINGVIEW_FMT "' identified by DeepFactory::moduleName: ", _modname.size(), _modname.data()); | 262 | lua_rawget(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED module |
264 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error | 263 | int const _alreadyloaded{ lua_toboolean(L_, -1) }; |
265 | lua_concat(L_, 2); // L_: DPC proxy metatable error | 264 | if (!_alreadyloaded) { // not loaded |
266 | return lua_tostringview(L_, -1); | 265 | lua_pop(L_, 2); // L_: DPC proxy metatable require() "module" |
267 | } | 266 | // require "modname". in case of error, raise it in errL_ |
268 | } else { // already loaded, we are happy | 267 | if (L_ == errL_) { |
269 | lua_pop(L_, 4); // L_: DPC proxy metatable | 268 | lua_call(L_, 1, 0); // L_: DPC proxy metatable module |
269 | } else { | ||
270 | LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? | ||
271 | if (_require_result != LuaError::OK) { | ||
272 | // failed, raise the error in the proper state | ||
273 | std::ignore = lua_pushstringview(errL_, lua_tostringview(L_, -1)); | ||
274 | raise_lua_error(errL_); | ||
270 | } | 275 | } |
271 | } else { // no L.registry._LOADED; can this ever happen? | ||
272 | lua_pop(L_, 6); // L_: | ||
273 | return std::string_view{ "unexpected error while requiring a module identified by DeepFactory::moduleName" }; | ||
274 | } | 276 | } |
275 | } else { // a module name, but no require() function :-( | 277 | } else { // already loaded, we are happy |
276 | lua_pop(L_, 4); // L_: | 278 | lua_pop(L_, 4); // L_: DPC proxy metatable |
277 | return std::string_view{ "lanes receiving deep userdata should register the 'package' library" }; | ||
278 | } | 279 | } |
279 | } | 280 | } |
280 | } | 281 | } |
281 | STACK_CHECK(L_, 2); // DPC proxy metatable | 282 | STACK_CHECK(L_, 3); // DPC proxy metatable |
282 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); | 283 | LUA_ASSERT(L_, lua_type_as_enum(L_, -2) == LuaType::USERDATA); |
283 | LUA_ASSERT(L_, lua_istable(L_, -1)); | 284 | LUA_ASSERT(L_, lua_istable(L_, -1)); |
284 | lua_setmetatable(L_, -2); // DPC proxy | 285 | lua_setmetatable(L_, -2); // DPC proxy |
285 | 286 | ||
286 | // If we're here, we obviously had to create a new proxy, so cache it. | 287 | // If we're here, we obviously had to create a new proxy, so cache it. |
287 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep | 288 | lua_pushlightuserdata(L_, prelude_); // L_: DPC proxy deep |
@@ -289,8 +290,7 @@ std::string_view DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, | |||
289 | lua_rawset(L_, -4); // L_: DPC proxy | 290 | lua_rawset(L_, -4); // L_: DPC proxy |
290 | lua_remove(L_, -2); // L_: proxy | 291 | lua_remove(L_, -2); // L_: proxy |
291 | LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); | 292 | LUA_ASSERT(L_, lua_type_as_enum(L_, -1) == LuaType::USERDATA); |
292 | STACK_CHECK(L_, 0); | 293 | STACK_CHECK(L_, 1); |
293 | return std::string_view{}; | ||
294 | } | 294 | } |
295 | 295 | ||
296 | // ################################################################################################# | 296 | // ################################################################################################# |
@@ -335,10 +335,7 @@ int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const | |||
335 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); | 335 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); |
336 | } | 336 | } |
337 | 337 | ||
338 | std::string_view const _err{ DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody) }; // proxy | 338 | DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody, L_); // proxy |
339 | if (!_err.empty()) { | ||
340 | raise_luaL_error(L_, _err.data()); | ||
341 | } | ||
342 | STACK_CHECK(L_, 1); | 339 | STACK_CHECK(L_, 1); |
343 | return 1; | 340 | return 1; |
344 | } | 341 | } |
@@ -75,7 +75,7 @@ class DeepFactory | |||
75 | [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; | 75 | [[nodiscard]] int pushDeepUserdata(DestState L_, int nuv_) const; |
76 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; | 76 | [[nodiscard]] DeepPrelude* toDeep(lua_State* L_, int index_) const; |
77 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); | 77 | static void DeleteDeepObject(lua_State* L_, DeepPrelude* o_); |
78 | [[nodiscard]] static std::string_view PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_); | 78 | static void PushDeepProxy(DestState L_, DeepPrelude* o_, int nuv_, LookupMode mode_, lua_State* errL_); |
79 | }; | 79 | }; |
80 | 80 | ||
81 | // ################################################################################################# | 81 | // ################################################################################################# |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 978a69b..8058838 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -731,7 +731,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
731 | STACK_CHECK_START_REL(L2, 0); | 731 | STACK_CHECK_START_REL(L2, 0); |
732 | 732 | ||
733 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail | 733 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
734 | int _nuv = 0; | 734 | int _nuv{ 0 }; |
735 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil | 735 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil |
736 | ++_nuv; | 736 | ++_nuv; |
737 | } | 737 | } |
@@ -739,11 +739,8 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
739 | lua_pop(L1, 1); // L1: ... u [uv]* | 739 | lua_pop(L1, 1); // L1: ... u [uv]* |
740 | STACK_CHECK(L1, _nuv); | 740 | STACK_CHECK(L1, _nuv); |
741 | 741 | ||
742 | DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 742 | DeepPrelude* const _u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
743 | std::string_view const errmsg{ DeepFactory::PushDeepProxy(L2, u, _nuv, mode) }; // L1: ... u [uv]* L2: u | 743 | DeepFactory::PushDeepProxy(L2, _u, _nuv, mode, getErrL()); // L1: ... u [uv]* L2: u |
744 | if (!errmsg.empty()) { | ||
745 | raise_luaL_error(getErrL(), errmsg.data()); | ||
746 | } | ||
747 | 744 | ||
748 | // transfer all uservalues of the source in the destination | 745 | // transfer all uservalues of the source in the destination |
749 | { | 746 | { |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 109fba4..bd5f69e 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -701,16 +701,8 @@ LUAG_FUNC(configure) | |||
701 | } | 701 | } |
702 | 702 | ||
703 | STACK_CHECK(L_, 2); | 703 | STACK_CHECK(L_, 2); |
704 | 704 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda | |
705 | { | 705 | lua_setfield(L_, -2, "timer_gateway"); // L_: settings M |
706 | std::string_view const _errmsg{ | ||
707 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody) | ||
708 | }; // L_: settings M timerLinda | ||
709 | if (!_errmsg.empty()) { | ||
710 | raise_luaL_error(L_, _errmsg.data()); | ||
711 | } | ||
712 | lua_setfield(L_, -2, "timer_gateway"); // L_: settings M | ||
713 | } | ||
714 | STACK_CHECK(L_, 2); | 706 | STACK_CHECK(L_, 2); |
715 | 707 | ||
716 | // prepare the metatable for threads | 708 | // prepare the metatable for threads |