From 4995040204ca27b13ed4e52ad01d76111ae6b081 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Fri, 3 May 2024 11:25:07 +0200 Subject: Some code factorization --- src/compat.cpp | 12 +++++----- src/compat.h | 3 ++- src/deep.cpp | 24 ++++++++++++++++++-- src/keeper.cpp | 2 +- src/lanes.cpp | 70 ++++++++++++++++++++++----------------------------------- src/state.cpp | 2 +- src/tools.cpp | 56 ++++----------------------------------------- src/tools.h | 3 --- src/uniquekey.h | 22 ++++++++++++++++-- 9 files changed, 83 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/compat.cpp b/src/compat.cpp index 6ceed8f..1d38917 100644 --- a/src/compat.cpp +++ b/src/compat.cpp @@ -7,17 +7,17 @@ // ################################################################################################# -// a small helper to obtain the "package" module table from the registry instead of relying on the presence of _G.package -int luaG_getpackage(lua_State* L_) +// a small helper to obtain a module's table from the registry instead of relying on the presence of _G[""] +LuaType luaG_getmodule(lua_State* L_, char const* name_) { STACK_CHECK_START_REL(L_, 0); - int type{ lua503_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil - if (type != LUA_TTABLE) { // L_: _R._LOADED|nil + LuaType type{ static_cast(lua503_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE)) };// L_: _R._LOADED|nil + if (type != LuaType::TABLE) { // L_: _R._LOADED|nil STACK_CHECK(L_, 1); return type; } - type = lua503_getfield(L_, -1, LUA_LOADLIBNAME); // L_: _R._LOADED package|nil - lua_remove(L_, -2); // L_: package|nil + type = static_cast(lua503_getfield(L_, -1, name_)); // L_: _R._LOADED {module}|nil + lua_remove(L_, -2); // L_: {module}|nil STACK_CHECK(L_, 1); return type; } diff --git a/src/compat.h b/src/compat.h index f98e142..3a61268 100644 --- a/src/compat.h +++ b/src/compat.h @@ -21,6 +21,7 @@ extern "C" #endif // 64 bits #else // LUA_JITLIBNAME #define LUAJIT_FLAVOR() 0 +#define LUA_JITLIBNAME "jit" #endif // LUA_JITLIBNAME // code is now preferring Lua 5.4 API @@ -219,4 +220,4 @@ inline char const* lua_typename(lua_State* L_, LuaType t_) return lua_typename(L_, static_cast(t_)); } -int luaG_getpackage(lua_State* L_); +LuaType luaG_getmodule(lua_State* L_, char const* name_); diff --git a/src/deep.cpp b/src/deep.cpp index 735a14c..6570e55 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -71,7 +71,7 @@ void DeepFactory::storeDeepLookup(lua_State* L_) const // the deep metatable is at the top of the stack // L_: mt STACK_GROW(L_, 3); STACK_CHECK_START_REL(L_, 0); // L_: mt - push_registry_subtable(L_, kDeepLookupRegKey); // L_: mt {} + std::ignore = kDeepLookupRegKey.getSubTable(L_, 0, 0); // L_: mt {} lua_pushvalue(L_, -2); // L_: mt {} mt lua_pushlightuserdata(L_, std::bit_cast(this)); // L_: mt {} mt factory lua_rawset(L_, -3); // L_: mt {} @@ -176,6 +176,26 @@ void DeepFactory::DeleteDeepObject(lua_State* L_, DeepPrelude* o_) // ################################################################################################# +// TODO: convert to UniqueKey::getSubTableMode +static void push_registry_subtable_mode(lua_State* L_, RegistryUniqueKey key_, const char* mode_) +{ + STACK_GROW(L_, 4); + STACK_CHECK_START_REL(L_, 0); + if (!key_.getSubTable(L_, 0, 0)) { // L_: {} + // Set its metatable if requested + if (mode_) { + lua_createtable(L_, 0, 1); // L_: {} mt + lua_pushliteral(L_, "__mode"); // L_: {} mt "__mode" + lua_pushstring(L_, mode_); // L_: {} mt "__mode" mode + lua_rawset(L_, -3); // L_: {} mt + lua_setmetatable(L_, -2); // L_: {} + } + } + STACK_CHECK(L_, 1); +} + +// ################################################################################################# + /* * Push a proxy userdata on the stack. * returns nullptr if ok, else some error string related to bad factory behavior or module require problem @@ -228,7 +248,7 @@ char const* DeepFactory::PushDeepProxy(DestState L_, DeepPrelude* prelude_, int lua_getfield(L_, -1, "__gc"); // L_: DPC proxy metatable __gc } else { // keepers need a minimal metatable that only contains our own __gc - lua_newtable(L_); // L_: DPC proxy metatable + lua_createtable(L_, 0, 1); // L_: DPC proxy metatable lua_pushnil(L_); // L_: DPC proxy metatable nil } if (lua_isnil(L_, -1)) { diff --git a/src/keeper.cpp b/src/keeper.cpp index 8e76247..bb510f4 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -658,7 +658,7 @@ void init_keepers(Universe* U_, lua_State* L_) STACK_CHECK(K, 0); // copy package.path and package.cpath from the source state - if (luaG_getpackage(L_) != LUA_TNIL) { // L_: settings package K: + if (luaG_getmodule(L_, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package K: // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately InterCopyContext c{ U_, DestState{ K }, SourceState{ L_ }, {}, SourceIndex{ lua_absindex(L_, -1) }, {}, LookupMode::ToKeeper, {} }; if (c.inter_copy_package() != InterCopyResult::Success) { // L_: settings ... error_msg K: diff --git a/src/lanes.cpp b/src/lanes.cpp index d027cff..87edb02 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -206,13 +206,16 @@ static void securize_debug_threadname(lua_State* L_, Lane* lane_) { STACK_CHECK_START_REL(L_, 0); STACK_GROW(L_, 3); - lua_getiuservalue(L_, 1, 1); - lua_newtable(L_); + // a Lane's uservalue should be a table + lua_getiuservalue(L_, 1, 1); // L_: lane ... {uv} + LUA_ASSERT(L_, lua_istable(L_, -1)); + // we don't care about the actual key, so long as it's unique and can't collide with anything. + lua_newtable(L_); // L_: lane ... {uv} {} // Lua 5.1 can't do 'lane_->debugName = lua_pushstring(L_, lane_->debugName);' - lua_pushstring(L_, lane_->debugName); + lua_pushstring(L_, lane_->debugName); // L_: lane ... {uv} {} name lane_->debugName = lua_tostring(L_, -1); - lua_rawset(L_, -3); - lua_pop(L_, 1); + lua_rawset(L_, -3); // L_: lane ... {uv} + lua_pop(L_, 1); // L_: lane STACK_CHECK(L_, 0); } @@ -253,25 +256,6 @@ Lane::~Lane() // ########################################## Finalizer ############################################ // ################################################################################################# -// Push the finalizers table on the stack. -// If there is no existing table, create ti. -static void push_finalizers_table(lua_State* L_) -{ - STACK_GROW(L_, 3); - STACK_CHECK_START_REL(L_, 0); - - kFinalizerRegKey.pushValue(L_); // L_: ? - if (lua_isnil(L_, -1)) { // L_: nil? - lua_pop(L_, 1); // L_: - // store a newly created table in the registry, but leave it on the stack too - lua_newtable(L_); // L_: t - kFinalizerRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); // L_: t - } - STACK_CHECK(L_, 1); -} - -// ################################################################################################# - // void= finalizer( finalizer_func ) // // finalizer_func( [err, stack_tbl] ) @@ -283,13 +267,14 @@ LUAG_FUNC(set_finalizer) { luaL_argcheck(L_, lua_isfunction(L_, 1), 1, "finalizer should be a function"); luaL_argcheck(L_, lua_gettop(L_) == 1, 1, "too many arguments"); + STACK_GROW(L_, 3); // Get the current finalizer table (if any), create one if it doesn't exist - push_finalizers_table(L_); // L_: finalizer {finalisers} - STACK_GROW(L_, 2); - lua_pushinteger(L_, lua_rawlen(L_, -1) + 1); // L_: finalizer {finalisers} idx - lua_pushvalue(L_, 1); // L_: finalizer {finalisers} idx finalizer - lua_rawset(L_, -3); // L_: finalizer {finalisers} - lua_pop(L_, 2); // L_: + std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} + // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. + int const idx{ static_cast(lua_rawlen(L_, -1) + 1) }; + lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer + lua_rawseti(L_, -2, idx); // L_: finalizer {finalisers} + // no need to adjust the stack, Lua does this for us return 0; } @@ -1020,13 +1005,13 @@ LUAG_FUNC(lane_new) // Create uservalue for the userdata // (this is where lane body return values will be stored when the handle is indexed by a numeric key) - lua_newtable(m_L); // m_L: ... lane uv + lua_newtable(m_L); // m_L: ... lane {uv} // Store the gc_cb callback in the uservalue if (m_gc_cb_idx > 0) { - kLaneGC.pushKey(m_L); // m_L: ... lane uv k - lua_pushvalue(m_L, m_gc_cb_idx); // m_L: ... lane uv k gc_cb - lua_rawset(m_L, -3); // m_L: ... lane uv + kLaneGC.pushKey(m_L); // m_L: ... lane {uv} k + lua_pushvalue(m_L, m_gc_cb_idx); // m_L: ... lane {uv} k gc_cb + lua_rawset(m_L, -3); // m_L: ... lane {uv} } lua_setiuservalue(m_L, -2, 1); // m_L: ... lane @@ -1515,7 +1500,7 @@ LUAG_FUNC(threads) lua_newtable(L_); // L_: {} while (lane != TRACKING_END) { // insert a { name, status } tuple, so that several lanes with the same name can't clobber each other - lua_newtable(L_); // L_: {} {} + lua_createtable(L_, 0, 2); // L_: {} {} lua_pushstring(L_, lane->debugName); // L_: {} {} "name" lua_setfield(L_, -2, "name"); // L_: {} {} lane->pushThreadStatus(L_); // L_: {} {} "status" @@ -1648,11 +1633,11 @@ LUAG_FUNC(configure) if (U == nullptr) { U = universe_create(L_); // L_: settings universe DEBUGSPEW_CODE(DebugSpewIndentScope scope2{ U }); - lua_newtable(L_); // L_: settings universe mt - lua_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe mt shutdown_timeout - lua_getfield(L_, 1, "shutdown_mode"); // L_: settings universe mt shutdown_timeout shutdown_mode - lua_pushcclosure(L_, universe_gc, 2); // L_: settings universe mt universe_gc - lua_setfield(L_, -2, "__gc"); // L_: settings universe mt + lua_createtable(L_, 0, 1); // L_: settings universe {mt} + lua_getfield(L_, 1, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout + lua_getfield(L_, 1, "shutdown_mode"); // L_: settings universe {mt} shutdown_timeout shutdown_mode + lua_pushcclosure(L_, universe_gc, 2); // L_: settings universe {mt} universe_gc + lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} lua_setmetatable(L_, -2); // L_: settings universe lua_pop(L_, 1); // L_: settings lua_getfield(L_, 1, "verbose_errors"); // L_: settings verbose_errors @@ -1862,12 +1847,11 @@ LANES_API int luaopen_lanes_core(lua_State* L_) STACK_CHECK_START_REL(L_, 0); // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too - lua_getglobal(L_, "jit"); // L_: {jit?} #if LUAJIT_FLAVOR() == 0 - if (!lua_isnil(L_, -1)) + if (luaG_getmodule(L_, LUA_JITLIBNAME) != LuaType::NIL) raise_luaL_error(L_, "Lanes is built for PUC-Lua, don't run from LuaJIT"); #else - if (lua_isnil(L_, -1)) + if (luaG_getmodule(L_, LUA_JITLIBNAME) == LuaType::NIL) raise_luaL_error(L_, "Lanes is built for LuaJIT, don't run from PUC-Lua"); #endif lua_pop(L_, 1); // L_: diff --git a/src/state.cpp b/src/state.cpp index 2893907..a3dfbcd 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -233,7 +233,7 @@ void initializeOnStateCreate(Universe* U_, lua_State* L_) // ################################################################################################# -lua_State* create_state(Universe* U_, lua_State* from_) +lua_State* create_state([[maybe_unused]] Universe* U_, lua_State* from_) { lua_State* L; #if LUAJIT_FLAVOR() == 64 diff --git a/src/tools.cpp b/src/tools.cpp index 049a065..302d4cc 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -42,48 +42,6 @@ static constexpr RegistryUniqueKey kLookupCacheRegKey{ 0x9BF75F84E54B691Bull }; // ################################################################################################# -// does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it -void push_registry_subtable_mode(lua_State* L_, RegistryUniqueKey key_, const char* mode_) -{ - STACK_GROW(L_, 3); - STACK_CHECK_START_REL(L_, 0); - - key_.pushValue(L_); // L_: {}|nil - STACK_CHECK(L_, 1); - - if (lua_isnil(L_, -1)) { - lua_pop(L_, 1); // L_: - lua_newtable(L_); // L_: {} - // _R[key_] = {} - key_.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); // L_: {} - STACK_CHECK(L_, 1); - - // Set its metatable if requested - if (mode_) { - lua_newtable(L_); // L_: {} mt - lua_pushliteral(L_, "__mode"); // L_: {} mt "__mode" - lua_pushstring(L_, mode_); // L_: {} mt "__mode" mode - lua_rawset(L_, -3); // L_: {} mt - lua_setmetatable(L_, -2); // L_: {} - } - } - STACK_CHECK(L_, 1); - LUA_ASSERT(L_, lua_istable(L_, -1)); -} - -// ################################################################################################# - -/* - * Push a registry subtable (keyed by unique 'key_') onto the stack. - * If the subtable does not exist, it is created and chained. - */ -void push_registry_subtable(lua_State* L_, RegistryUniqueKey key_) -{ - push_registry_subtable_mode(L_, key_, nullptr); -} - -// ################################################################################################# - // same as PUC-Lua l_alloc extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) { @@ -459,13 +417,7 @@ void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) STACK_CHECK(L_, 2); } // retrieve the cache, create it if we haven't done it yet - kLookupCacheRegKey.pushValue(L_); // L_: {} {fqn} {cache}? - if (lua_isnil(L_, -1)) { - lua_pop(L_, 1); // L_: {} {fqn} - lua_newtable(L_); // L_: {} {fqn} {cache} - kLookupCacheRegKey.setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); - STACK_CHECK(L_, 3); - } + std::ignore = kLookupCacheRegKey.getSubTable(L_, 0, 0); // L_: {} {fqn} {cache} // process everything we find in that table, filling in lookup data for all functions and tables we see there populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(U) L_, dbIdx, in_base, startDepth); lua_pop(L_, 3); // L_: @@ -491,7 +443,7 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull }; STACK_GROW(L_, 3); STACK_CHECK_START_REL(L_, 0); - push_registry_subtable(L_, kMtIdRegKey); // L_: ... _R[kMtIdRegKey] + std::ignore = kMtIdRegKey.getSubTable(L_, 0, 0); // L_: ... _R[kMtIdRegKey] lua_pushvalue(L_, idx_); // L_: ... _R[kMtIdRegKey] {mt} lua_rawget(L_, -2); // L_: ... _R[kMtIdRegKey] mtk? @@ -1186,7 +1138,7 @@ void InterCopyContext::copy_cached_func() const STACK_CHECK_START_REL(L2, 0); STACK_GROW(L2, 4); // do we already know this metatable? - push_registry_subtable(L2, kMtIdRegKey); // L2: _R[kMtIdRegKey] + std::ignore = kMtIdRegKey.getSubTable(L2, 0, 0); // L2: _R[kMtIdRegKey] lua_pushinteger(L2, mt_id); // L2: _R[kMtIdRegKey] id lua_rawget(L2, -2); // L2: _R[kMtIdRegKey] mt|nil STACK_CHECK(L2, 2); @@ -1830,7 +1782,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const } return InterCopyResult::Error; } - if (luaG_getpackage(L2) == LUA_TNIL) { // package library not loaded: do nothing + if (luaG_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END(U))); STACK_CHECK(L1, 0); return InterCopyResult::Success; diff --git a/src/tools.h b/src/tools.h index 9d4ed4c..53d3a99 100644 --- a/src/tools.h +++ b/src/tools.h @@ -8,9 +8,6 @@ class Universe; // ################################################################################################# -void push_registry_subtable_mode(lua_State* L_, RegistryUniqueKey key_, const char* mode_); -void push_registry_subtable(lua_State* L_, RegistryUniqueKey key_); - enum class VT { NORMAL, // keep this one first so that it's the value we get when we default-construct diff --git a/src/uniquekey.h b/src/uniquekey.h index da699b0..6265a56 100644 --- a/src/uniquekey.h +++ b/src/uniquekey.h @@ -68,7 +68,7 @@ class RegistryUniqueKey } // --------------------------------------------------------------------------------------------- template - T* readLightUserDataValue(lua_State* const L_) const + [[nodiscard]] T* readLightUserDataValue(lua_State* const L_) const { STACK_GROW(L_, 1); STACK_CHECK_START_REL(L_, 0); @@ -79,7 +79,7 @@ class RegistryUniqueKey return value; } // --------------------------------------------------------------------------------------------- - bool readBoolValue(lua_State* const L_) const + [[nodiscard]] bool readBoolValue(lua_State* const L_) const { STACK_GROW(L_, 1); STACK_CHECK_START_REL(L_, 0); @@ -89,6 +89,24 @@ class RegistryUniqueKey STACK_CHECK(L_, 0); return value; } + // --------------------------------------------------------------------------------------------- + // equivalent to luaL_getsubtable + [[nodiscard]] bool getSubTable(lua_State* const L_, int narr_, int nrec_) const + { + STACK_CHECK_START_REL(L_, 0); + pushValue(L_); // L_: {}|nil + if (!lua_isnil(L_, -1)) { + LUA_ASSERT(L_, lua_istable(L_, -1)); + STACK_CHECK(L_, 1); + return true; // table already exists + } + lua_pop(L_, 1); // L_: + // store a newly created table in the registry, but leave it on the stack too + lua_createtable(L_, narr_, nrec_); // L_: {} + setValue(L_, [](lua_State* L_) { lua_pushvalue(L_, -2); }); // L_: {} + STACK_CHECK(L_, 1); + return false; + } }; // ################################################################################################# -- cgit v1.2.3-55-g6feb