diff options
Diffstat (limited to 'src/deep.cpp')
-rw-r--r-- | src/deep.cpp | 64 |
1 files changed, 33 insertions, 31 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index e0c2a39..9474666 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -59,6 +59,8 @@ static constexpr RegistryUniqueKey kDeepLookupRegKey{ 0xC6788345703C6059ull }; | |||
59 | */ | 59 | */ |
60 | static constexpr RegistryUniqueKey kDeepProxyCacheRegKey{ 0xEBCD49AE1A3DD35Eull }; | 60 | static constexpr RegistryUniqueKey kDeepProxyCacheRegKey{ 0xEBCD49AE1A3DD35Eull }; |
61 | 61 | ||
62 | // ################################################################################################# | ||
63 | |||
62 | /* | 64 | /* |
63 | * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. | 65 | * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. |
64 | * Pops the both values off the stack. | 66 | * Pops the both values off the stack. |
@@ -106,9 +108,9 @@ static void LookupDeep(lua_State* L_) | |||
106 | { | 108 | { |
107 | // when looking inside a keeper, we are 100% sure the object is a deep userdata | 109 | // when looking inside a keeper, we are 100% sure the object is a deep userdata |
108 | if (mode_ == LookupMode::FromKeeper) { | 110 | if (mode_ == LookupMode::FromKeeper) { |
109 | DeepPrelude* const proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index_) }; | 111 | DeepPrelude* const _proxy{ *lua_tofulluserdata<DeepPrelude*>(L_, index_) }; |
110 | // we can (and must) cast and fetch the internally stored factory | 112 | // we can (and must) cast and fetch the internally stored factory |
111 | return &proxy->factory; | 113 | return &_proxy->factory; |
112 | } else { | 114 | } else { |
113 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/factory database | 115 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/factory database |
114 | // it is the only way to ensure that the userdata is indeed a deep userdata! | 116 | // it is the only way to ensure that the userdata is indeed a deep userdata! |
@@ -123,10 +125,10 @@ static void LookupDeep(lua_State* L_) | |||
123 | // replace metatable with the factory pointer, if it is actually a deep userdata | 125 | // replace metatable with the factory pointer, if it is actually a deep userdata |
124 | LookupDeep(L_); // L_: deep ... factory|nil | 126 | LookupDeep(L_); // L_: deep ... factory|nil |
125 | 127 | ||
126 | DeepFactory* const ret{ lua_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata | 128 | DeepFactory* const _ret{ lua_tolightuserdata<DeepFactory>(L_, -1) }; // nullptr if not a userdata |
127 | lua_pop(L_, 1); | 129 | lua_pop(L_, 1); |
128 | STACK_CHECK(L_, 0); | 130 | STACK_CHECK(L_, 0); |
129 | return ret; | 131 | return _ret; |
130 | } | 132 | } |
131 | } | 133 | } |
132 | 134 | ||
@@ -149,12 +151,12 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
149 | */ | 151 | */ |
150 | [[nodiscard]] static int deep_userdata_gc(lua_State* L_) | 152 | [[nodiscard]] static int deep_userdata_gc(lua_State* L_) |
151 | { | 153 | { |
152 | DeepPrelude* const* const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, 1) }; | 154 | DeepPrelude* const* const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, 1) }; |
153 | DeepPrelude* const p{ *proxy }; | 155 | DeepPrelude* const _p{ *_proxy }; |
154 | 156 | ||
155 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 157 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
156 | // in that case, we are not multithreaded and locking isn't necessary anyway | 158 | // in that case, we are not multithreaded and locking isn't necessary anyway |
157 | bool const isLastRef{ p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; | 159 | bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; |
158 | 160 | ||
159 | if (isLastRef) { | 161 | if (isLastRef) { |
160 | // retrieve wrapped __gc | 162 | // retrieve wrapped __gc |
@@ -166,7 +168,7 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) | |||
166 | // need an empty stack in case we are GC_ing from a Keeper, so that empty stack checks aren't triggered | 168 | // need an empty stack in case we are GC_ing from a Keeper, so that empty stack checks aren't triggered |
167 | lua_pop(L_, 2); // L_: | 169 | lua_pop(L_, 2); // L_: |
168 | } | 170 | } |
169 | DeepFactory::DeleteDeepObject(L_, p); | 171 | DeepFactory::DeleteDeepObject(L_, _p); |
170 | } | 172 | } |
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
@@ -219,9 +221,9 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int | |||
219 | STACK_CHECK_START_REL(L_, 0); | 221 | STACK_CHECK_START_REL(L_, 0); |
220 | 222 | ||
221 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 223 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
222 | DeepPrelude** const proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy | 224 | DeepPrelude** const _proxy{ lua_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy |
223 | LUA_ASSERT(L_, proxy); | 225 | LUA_ASSERT(L_, _proxy); |
224 | *proxy = prelude_; | 226 | *_proxy = prelude_; |
225 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data | 227 | prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data |
226 | 228 | ||
227 | // Get/create metatable for 'factory' (in this state) | 229 | // Get/create metatable for 'factory' (in this state) |
@@ -231,13 +233,13 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int | |||
231 | 233 | ||
232 | if (lua_isnil(L_, -1)) { // No metatable yet. | 234 | if (lua_isnil(L_, -1)) { // No metatable yet. |
233 | lua_pop(L_, 1); // L_: DPC proxy | 235 | lua_pop(L_, 1); // L_: DPC proxy |
234 | int const oldtop{ lua_gettop(L_) }; | 236 | int const _oldtop{ lua_gettop(L_) }; |
235 | // 1 - make one and register it | 237 | // 1 - make one and register it |
236 | if (mode_ != LookupMode::ToKeeper) { | 238 | if (mode_ != LookupMode::ToKeeper) { |
237 | factory.createMetatable(L_); // L_: DPC proxy metatable | 239 | factory.createMetatable(L_); // L_: DPC proxy metatable |
238 | if (lua_gettop(L_) - oldtop != 1 || !lua_istable(L_, -1)) { | 240 | if (lua_gettop(L_) - _oldtop != 1 || !lua_istable(L_, -1)) { |
239 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! | 241 | // factory didn't push exactly 1 value, or the value it pushed is not a table: ERROR! |
240 | lua_settop(L_, oldtop); // L_: DPC proxy X | 242 | lua_settop(L_, _oldtop); // L_: DPC proxy X |
241 | lua_pop(L_, 3); // L_: | 243 | lua_pop(L_, 3); // L_: |
242 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; | 244 | return "Bad DeepFactory::createMetatable overload: unexpected pushed value"; |
243 | } | 245 | } |
@@ -262,12 +264,12 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int | |||
262 | factory.storeDeepLookup(L_); | 264 | factory.storeDeepLookup(L_); |
263 | 265 | ||
264 | // 2 - cause the target state to require the module that exported the factory | 266 | // 2 - cause the target state to require the module that exported the factory |
265 | if (char const* const modname{ factory.moduleName() }; modname) { // we actually got a module name | 267 | if (char const* const _modname{ factory.moduleName() }; _modname) { // we actually got a module name |
266 | // L.registry._LOADED exists without having registered the 'package' library. | 268 | // L.registry._LOADED exists without having registered the 'package' library. |
267 | lua_getglobal(L_, "require"); // DPC proxy metatable require() | 269 | lua_getglobal(L_, "require"); // DPC proxy metatable require() |
268 | // check that the module is already loaded (or being loaded, we are happy either way) | 270 | // check that the module is already loaded (or being loaded, we are happy either way) |
269 | if (lua_isfunction(L_, -1)) { | 271 | if (lua_isfunction(L_, -1)) { |
270 | lua_pushstring(L_, modname); // L_: DPC proxy metatable require() "module" | 272 | lua_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module" |
271 | lua_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // L_: DPC proxy metatable require() "module" _R._LOADED | 273 | lua_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); // L_: DPC proxy metatable require() "module" _R._LOADED |
272 | if (lua_istable(L_, -1)) { | 274 | if (lua_istable(L_, -1)) { |
273 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" | 275 | lua_pushvalue(L_, -2); // L_: DPC proxy metatable require() "module" _R._LOADED "module" |
@@ -280,7 +282,7 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int | |||
280 | require_result = lua_pcall(L_, 1, 0, 0); // L_: DPC proxy metatable error? | 282 | require_result = lua_pcall(L_, 1, 0, 0); // L_: DPC proxy metatable error? |
281 | if (require_result != LUA_OK) { | 283 | if (require_result != LUA_OK) { |
282 | // failed, return the error message | 284 | // failed, return the error message |
283 | lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", modname); | 285 | lua_pushfstring(L_, "error while requiring '%s' identified by DeepFactory::moduleName: ", _modname); |
284 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error | 286 | lua_insert(L_, -2); // L_: DPC proxy metatable prefix error |
285 | lua_concat(L_, 2); // L_: DPC proxy metatable error | 287 | lua_concat(L_, 2); // L_: DPC proxy metatable error |
286 | return lua_tostring(L_, -1); | 288 | return lua_tostring(L_, -1); |
@@ -334,30 +336,30 @@ int DeepFactory::pushDeepUserdata(DestState L_, int nuv_) const | |||
334 | { | 336 | { |
335 | STACK_GROW(L_, 1); | 337 | STACK_GROW(L_, 1); |
336 | STACK_CHECK_START_REL(L_, 0); | 338 | STACK_CHECK_START_REL(L_, 0); |
337 | int const oldtop{ lua_gettop(L_) }; | 339 | int const _oldtop{ lua_gettop(L_) }; |
338 | DeepPrelude* const prelude{ newDeepObjectInternal(L_) }; | 340 | DeepPrelude* const _prelude{ newDeepObjectInternal(L_) }; |
339 | if (prelude == nullptr) { | 341 | if (_prelude == nullptr) { |
340 | raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); | 342 | raise_luaL_error(L_, "DeepFactory::newDeepObjectInternal failed to create deep userdata (out of memory)"); |
341 | } | 343 | } |
342 | 344 | ||
343 | if (prelude->magic != kDeepVersion) { | 345 | if (_prelude->magic != kDeepVersion) { |
344 | // just in case, don't leak the newly allocated deep userdata object | 346 | // just in case, don't leak the newly allocated deep userdata object |
345 | deleteDeepObjectInternal(L_, prelude); | 347 | deleteDeepObjectInternal(L_, _prelude); |
346 | raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); | 348 | raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); |
347 | } | 349 | } |
348 | 350 | ||
349 | LUA_ASSERT(L_, prelude->refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 | 351 | LUA_ASSERT(L_, _prelude->refcount.load(std::memory_order_relaxed) == 0); // 'DeepFactory::PushDeepProxy' will lift it to 1 |
350 | LUA_ASSERT(L_, &prelude->factory == this); | 352 | LUA_ASSERT(L_, &_prelude->factory == this); |
351 | 353 | ||
352 | if (lua_gettop(L_) - oldtop != 0) { | 354 | if (lua_gettop(L_) - _oldtop != 0) { |
353 | // just in case, don't leak the newly allocated deep userdata object | 355 | // just in case, don't leak the newly allocated deep userdata object |
354 | deleteDeepObjectInternal(L_, prelude); | 356 | deleteDeepObjectInternal(L_, _prelude); |
355 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); | 357 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); |
356 | } | 358 | } |
357 | 359 | ||
358 | char const* const errmsg{ DeepFactory::PushDeepProxy(L_, prelude, nuv_, LookupMode::LaneBody) }; // proxy | 360 | char const* const _err{ DeepFactory::PushDeepProxy(L_, _prelude, nuv_, LookupMode::LaneBody) }; // proxy |
359 | if (errmsg != nullptr) { | 361 | if (_err != nullptr) { |
360 | raise_luaL_error(L_, errmsg); | 362 | raise_luaL_error(L_, _err); |
361 | } | 363 | } |
362 | STACK_CHECK(L_, 1); | 364 | STACK_CHECK(L_, 1); |
363 | return 1; | 365 | return 1; |
@@ -380,6 +382,6 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const | |||
380 | } | 382 | } |
381 | STACK_CHECK(L_, 0); | 383 | STACK_CHECK(L_, 0); |
382 | 384 | ||
383 | DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; | 385 | DeepPrelude** const _proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; |
384 | return *proxy; | 386 | return *_proxy; |
385 | } | 387 | } |