From 0c060e6e4b9f99dc887b5dfebdae76fcde9524f1 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Mon, 25 Mar 2024 10:43:25 +0100 Subject: C++ migration: revamped stack checking macros --- src/deep.cpp | 41 ++++---- src/keeper.cpp | 46 ++++----- src/lanes.cpp | 107 ++++++++++----------- src/lanes_private.h | 7 +- src/linda.cpp | 16 ++-- src/macros_and_utils.h | 116 +++++++++++++++-------- src/state.cpp | 76 +++++++-------- src/tools.cpp | 252 ++++++++++++++++++++++++------------------------- src/universe.cpp | 18 ++-- 9 files changed, 359 insertions(+), 320 deletions(-) (limited to 'src') diff --git a/src/deep.cpp b/src/deep.cpp index 1aab6ed..cd5a844 100644 --- a/src/deep.cpp +++ b/src/deep.cpp @@ -74,16 +74,16 @@ static constexpr UniqueKey DEEP_PROXY_CACHE_KEY{ 0x05773d6fc26be106ull }; static void set_deep_lookup( lua_State* L) { STACK_GROW( L, 3); - STACK_CHECK( L, 2); // a b + STACK_CHECK_START_REL(L, 2); // a b push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} - STACK_MID( L, 3); + STACK_CHECK( L, 3); lua_insert( L, -3); // {} a b lua_pushvalue( L, -1); // {} a b b lua_pushvalue( L,-3); // {} a b b a lua_rawset( L, -5); // {} a b lua_rawset( L, -3); // {} lua_pop( L, 1); // - STACK_END( L, 0); + STACK_CHECK( L, 0); } /* @@ -93,7 +93,7 @@ static void set_deep_lookup( lua_State* L) static void get_deep_lookup( lua_State* L) { STACK_GROW( L, 1); - STACK_CHECK( L, 1); // a + STACK_CHECK_START_REL(L, 1); // a DEEP_LOOKUP_KEY.query_registry(L); // a {} if( !lua_isnil( L, -1)) { @@ -101,7 +101,7 @@ static void get_deep_lookup( lua_State* L) lua_rawget( L, -2); // {} b } lua_remove( L, -2); // a|b - STACK_END( L, 1); + STACK_CHECK( L, 1); } /* @@ -122,9 +122,8 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database // it is the only way to ensure that the userdata is indeed a deep userdata! // of course, we could just trust the caller, but we won't - luaG_IdFunction* ret; STACK_GROW( L, 1); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); if( !lua_getmetatable( L, index)) // deep ... metatable? { @@ -134,9 +133,9 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m // replace metatable with the idfunc pointer, if it is actually a deep userdata get_deep_lookup( L); // deep ... idfunc|nil - ret = (luaG_IdFunction*) lua_touserdata( L, -1); // nullptr if not a userdata + luaG_IdFunction* const ret{ static_cast(lua_touserdata(L, -1)) }; // nullptr if not a userdata lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); return ret; } } @@ -228,7 +227,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in if( U) MUTEX_UNLOCK( &U->deep_lock); STACK_GROW( L, 7); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) proxy = (DeepPrelude**) lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy @@ -340,7 +339,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in } } } - STACK_MID( L, 2); // DPC proxy metatable + STACK_CHECK( L, 2); // DPC proxy metatable ASSERT_L( lua_isuserdata( L, -2)); ASSERT_L( lua_istable( L, -1)); lua_setmetatable( L, -2); // DPC proxy @@ -351,7 +350,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in lua_rawset( L, -4); // DPC proxy lua_remove( L, -2); // proxy ASSERT_L( lua_isuserdata( L, -1)); - STACK_END( L, 0); + STACK_CHECK( L, 0); return nullptr; } @@ -382,7 +381,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) char const* errmsg; STACK_GROW( L, 1); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); { int const oldtop = lua_gettop( L); DeepPrelude* prelude = (DeepPrelude*) idfunc( L, eDO_new); @@ -413,7 +412,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) return luaL_error( L, errmsg); } } - STACK_END( L, 1); + STACK_CHECK( L, 1); return 1; } @@ -428,7 +427,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction* idfunc, int index) { DeepPrelude** proxy; - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // ensure it is actually a deep userdata if( get_idfunc( L, index, eLM_LaneBody) != idfunc) { @@ -436,7 +435,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction* idfunc, int index) } proxy = (DeepPrelude**) lua_touserdata( L, index); - STACK_END( L, 0); + STACK_CHECK( L, 0); return *proxy; } @@ -460,8 +459,8 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L return false; // not a deep userdata } - STACK_CHECK( L, 0); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); + STACK_CHECK_START_REL(L2, 0); // extract all uservalues of the source while( lua_getiuservalue( L, i, nuv + 1) != LUA_TNONE) // ... u [uv]* nil @@ -470,7 +469,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L } // last call returned TNONE and pushed nil, that we don't need lua_pop( L, 1); // ... u [uv]* - STACK_MID( L, nuv); + STACK_CHECK( L, nuv); errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u @@ -487,8 +486,8 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L } } - STACK_END( L2, 1); - STACK_END( L, 0); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 0); if (errmsg != nullptr) { diff --git a/src/keeper.cpp b/src/keeper.cpp index 0cb1a94..19f6ae1 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp @@ -170,12 +170,12 @@ static constexpr UniqueKey FIFOS_KEY{ 0xdce50bbc351cd465ull }; static void push_table(lua_State* L, int idx_) { STACK_GROW(L, 4); - STACK_CHECK(L, 0); + STACK_CHECK_START_REL(L, 0); idx_ = lua_absindex(L, idx_); FIFOS_KEY.query_registry(L); // ud fifos lua_pushvalue(L, idx_); // ud fifos ud lua_rawget(L, -2); // ud fifos fifos[ud] - STACK_MID(L, 2); + STACK_CHECK(L, 2); if (lua_isnil(L, -1)) { lua_pop(L, 1); // ud fifos @@ -186,7 +186,7 @@ static void push_table(lua_State* L, int idx_) lua_rawset(L, -4); // ud fifos fifos[ud] } lua_remove(L, -2); // ud fifos[ud] - STACK_END(L, 1); + STACK_CHECK(L, 1); } // ################################################################################################## @@ -197,7 +197,7 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m lua_State* const KL = K ? K->L : nullptr; if( KL == nullptr) return 0; STACK_GROW(KL, 4); - STACK_CHECK(KL, 0); + STACK_CHECK_START_REL(KL, 0); FIFOS_KEY.query_registry(KL); // fifos lua_pushlightuserdata(KL, ptr_); // fifos ud lua_rawget(KL, -2); // fifos storage @@ -205,38 +205,38 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m if( !lua_istable(KL, -1)) { lua_pop(KL, 1); // - STACK_MID(KL, 0); + STACK_CHECK(KL, 0); return 0; } // move data from keeper to destination state KEEPER MAIN lua_pushnil(KL); // storage nil STACK_GROW(L, 5); - STACK_CHECK(L, 0); + STACK_CHECK_START_REL(L, 0); lua_newtable(L); // out while( lua_next(KL, -2)) // storage key fifo { keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifo lua_pushvalue(KL, -2); // storage key fifo key luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key - STACK_MID(L, 2); + STACK_CHECK(L, 2); lua_newtable(L); // out key keyout luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo lua_pushinteger(L, fifo->first); // out key keyout fifo first - STACK_MID(L, 5); + STACK_CHECK(L, 5); lua_setfield(L, -3, "first"); // out key keyout fifo lua_pushinteger(L, fifo->count); // out key keyout fifo count - STACK_MID(L, 5); + STACK_CHECK(L, 5); lua_setfield(L, -3, "count"); // out key keyout fifo lua_pushinteger(L, fifo->limit); // out key keyout fifo limit - STACK_MID(L, 5); + STACK_CHECK(L, 5); lua_setfield(L, -3, "limit"); // out key keyout fifo lua_setfield(L, -2, "fifo"); // out key keyout lua_rawset(L, -3); // out - STACK_MID(L, 1); + STACK_CHECK(L, 1); } - STACK_END(L, 1); + STACK_CHECK(L, 1); lua_pop(KL, 1); // - STACK_END(KL, 0); + STACK_CHECK(KL, 0); return 1; } @@ -246,13 +246,13 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m int keepercall_clear(lua_State* L) { STACK_GROW(L, 3); - STACK_CHECK(L, 0); + STACK_CHECK_START_REL(L, 0); FIFOS_KEY.query_registry(L); // ud fifos lua_pushvalue(L, 1); // ud fifos ud lua_pushnil(L); // ud fifos ud nil lua_rawset(L, -3); // ud fifos lua_pop(L, 1); // ud - STACK_END(L, 0); + STACK_CHECK(L, 0); return 0; } @@ -637,7 +637,7 @@ void close_keepers(Universe* U) */ void init_keepers(Universe* U, lua_State* L) { - STACK_CHECK(L, 0); // L K + STACK_CHECK_START_REL(L, 0); // L K lua_getfield(L, 1, "nb_keepers"); // nb_keepers int nb_keepers{ static_cast(lua_tointeger(L, -1)) }; lua_pop(L, 1); // @@ -677,19 +677,19 @@ void init_keepers(Universe* U, lua_State* L) // therefore, we need a recursive mutex. MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); - STACK_CHECK(K, 0); + STACK_CHECK_START_ABS(K, 0); // copy the universe pointer in the keeper itself universe_store(K, U); - STACK_MID(K, 0); + STACK_CHECK(K, 0); // make sure 'package' is initialized in keeper states, so that we have require() // this because this is needed when transferring deep userdata object luaL_requiref(K, "package", luaopen_package, 1); // package lua_pop(K, 1); // - STACK_MID(K, 0); + STACK_CHECK(K, 0); serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); - STACK_MID(K, 0); + STACK_CHECK(K, 0); // copy package.path and package.cpath from the source state lua_getglobal(L, "package"); // "..." keepersUD package @@ -705,7 +705,7 @@ void init_keepers(Universe* U, lua_State* L) } } lua_pop(L, 1); // - STACK_MID(L, 0); + STACK_CHECK(L, 0); // attempt to call on_state_create(), if we have one and it is a C function // (only support a C function because we can't transfer executable Lua code in keepers) @@ -717,9 +717,9 @@ void init_keepers(Universe* U, lua_State* L) lua_setglobal(K, "decoda_name"); // // create the fifos table in the keeper state FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); }); - STACK_END(K, 0); + STACK_CHECK(K, 0); } - STACK_END(L, 0); + STACK_CHECK(L, 0); } // ################################################################################################## diff --git a/src/lanes.cpp b/src/lanes.cpp index 38dd92c..6123766 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -113,7 +113,7 @@ THE SOFTWARE. // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed static void securize_debug_threadname( lua_State* L, Lane* s) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); STACK_GROW( L, 3); lua_getiuservalue( L, 1, 1); lua_newtable( L); @@ -122,7 +122,7 @@ static void securize_debug_threadname( lua_State* L, Lane* s) s->debug_name = lua_tostring( L, -1); lua_rawset( L, -3); lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); } #if ERROR_FULL_STACK @@ -155,12 +155,13 @@ struct s_Linda; static bool push_registry_table( lua_State* L, UniqueKey key, bool create) { STACK_GROW( L, 3); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); key.query_registry(L); // ? if( lua_isnil( L, -1)) // nil? { lua_pop( L, 1); // + STACK_CHECK(L, 0); if( !create) { @@ -170,7 +171,7 @@ static bool push_registry_table( lua_State* L, UniqueKey key, bool create) lua_newtable( L); // t key.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); } - STACK_END( L, 1); + STACK_CHECK( L, 1); return true; // table pushed } @@ -675,11 +676,8 @@ done: static int lane_error( lua_State* L) { - lua_Debug ar; - int n; - // error message (any type) - STACK_CHECK_ABS( L, 1); // some_error + STACK_CHECK_START_ABS(L, 1); // some_error // Don't do stack survey for cancelled lanes. // @@ -692,6 +690,7 @@ static int lane_error( lua_State* L) EXTENDED_STACKTRACE_REGKEY.query_registry(L); // some_error basic|extended bool const extended{ lua_toboolean(L, -1) ? true : false}; lua_pop( L, 1); // some_error + STACK_CHECK(L, 1); // Place stack trace at 'registry[STACKTRACE_REGKEY]' for the 'lua_pcall()' // caller to fetch. This bypasses the Lua 5.1 limitation of only one @@ -709,7 +708,8 @@ static int lane_error( lua_State* L) // and we don't get '.currentline' for that. It's okay - just keep level // and table index growing separate. --AKa 22-Jan-2009 // - for( n = 1; lua_getstack( L, n, &ar); ++ n) + lua_Debug ar; + for (int n = 1; lua_getstack(L, n, &ar); ++n) { lua_getinfo( L, extended ? "Sln" : "Sl", &ar); if( extended) @@ -745,8 +745,8 @@ static int lane_error( lua_State* L) // store the stack trace table in the registry STACKTRACE_REGKEY.set_registry(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error - STACK_END( L, 1); - return 1; // the untouched error value + STACK_CHECK(L, 1); + return 1; // the untouched error value } #endif // ERROR_FULL_STACK @@ -761,12 +761,12 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) case LUA_ERRRUN: // cancellation or a runtime error #if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // fetch the call stack table from the registry where the handler stored it STACK_GROW( L, 1); // yields nil if no stack was generated (in case of cancellation for example) STACKTRACE_REGKEY.query_registry(L); // err trace|nil - STACK_END( L, 1); + STACK_CHECK( L, 1); // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed // For other errors, the message can be whatever was thrown, and we should have a stack trace table @@ -793,16 +793,16 @@ LUAG_FUNC( set_debug_threadname) Lane* s = (Lane*) lua_touserdata( L, lua_upvalueindex( 1)); luaL_checktype( L, -1, LUA_TSTRING); // "name" lua_settop( L, 1); - STACK_CHECK_ABS( L, 1); + STACK_CHECK_START_ABS( L, 1); // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... hidden_regkey.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); - STACK_MID( L, 1); + STACK_CHECK( L, 1); s->debug_name = lua_tostring( L, -1); // keep a direct pointer on the string THREAD_SETNAME( s->debug_name); // to see VM name in Decoda debugger Virtual Machine window lua_setglobal( L, "decoda_name"); // - STACK_END( L, 0); + STACK_CHECK( L, 0); return 0; } @@ -990,7 +990,7 @@ LUAG_FUNC( require) char const* name = lua_tostring( L, 1); int const nargs = lua_gettop( L); DEBUGSPEW_CODE( Universe* U = universe_get( L)); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); lua_pushvalue( L, lua_upvalueindex(1)); // "name" require @@ -999,7 +999,7 @@ LUAG_FUNC( require) populate_func_lookup_table( L, -1, name); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); - STACK_END( L, 0); + STACK_CHECK( L, 0); return 1; } @@ -1015,13 +1015,13 @@ LUAG_FUNC( register) lua_settop( L, 2); luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); DEBUGSPEW_CODE( Universe* U = universe_get( L)); - STACK_CHECK( L, 0); // "name" mod_table + STACK_CHECK_START_REL(L, 0); // "name" mod_table DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); populate_func_lookup_table( L, -1, name); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); - STACK_END( L, 0); + STACK_CHECK( L, 0); return 0; } @@ -1075,10 +1075,10 @@ LUAG_FUNC( lane_new) L2 = luaG_newstate( U, L, libs_str); // L // L2 STACK_GROW( L2, nargs + 3); // - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L2, 0); STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...] - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // give a default "Lua" name to the thread to see VM name in Decoda debugger lua_pushfstring( L2, "Lane #%p", L2); // "..." @@ -1146,8 +1146,8 @@ LUAG_FUNC( lane_new) } // func libs priority globals package required gc_cb [... args ...] DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } - STACK_MID( L, 0); - STACK_MID( L2, 0); // + STACK_CHECK( L, 0); + STACK_CHECK( L2, 0); // // Appending the specified globals to the global environment // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... @@ -1175,8 +1175,8 @@ LUAG_FUNC( lane_new) DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } - STACK_MID( L, 0); - STACK_MID( L2, 0); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 0); // Lane main function if( lua_type( L, 1) == LUA_TFUNCTION) @@ -1200,8 +1200,8 @@ LUAG_FUNC( lane_new) return luaL_error( L, "error when parsing lane function code"); } } - STACK_MID( L, 0); - STACK_MID( L2, 1); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 1); ASSERT_L( lua_isfunction( L2, 1)); // revive arguments @@ -1217,10 +1217,10 @@ LUAG_FUNC( lane_new) return luaL_error( L, "tried to copy unsupported types"); } } - STACK_END( L, -nargs); + STACK_CHECK( L, -nargs); ASSERT_L( lua_gettop( L) == FIXED_ARGS); - STACK_CHECK( L, 0); - STACK_MID( L2, 1 + nargs); + STACK_CHECK_RESET_REL(L, 0); + STACK_CHECK( L2, 1 + nargs); // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) // @@ -1260,7 +1260,7 @@ LUAG_FUNC( lane_new) // lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane - STACK_MID( L, 1); + STACK_CHECK( L, 1); // Create uservalue for the userdata // (this is where lane body return values will be stored when the handle is indexed by a numeric key) @@ -1279,8 +1279,8 @@ LUAG_FUNC( lane_new) // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). CANCEL_TEST_KEY.set_registry(L2, [s](lua_State* L) { lua_pushlightuserdata(L, s); }); // func [... args ...] - STACK_END( L, 1); - STACK_END( L2, 1 + nargs); + STACK_CHECK( L, 1); + STACK_CHECK( L2, 1 + nargs); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); THREAD_CREATE( &s->thread, lane_main, s, priority); @@ -1436,7 +1436,7 @@ LUAG_FUNC( thread_join) return 2; } - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // Thread is DONE/ERROR_ST/CANCELLED; all ours now if (s->mstatus == ThreadStatus::Killed) // OS thread was killed if thread_cancel was forced @@ -1492,7 +1492,7 @@ LUAG_FUNC( thread_join) lua_close( L2); } s->L = 0; - STACK_END( L, ret); + STACK_CHECK( L, ret); return ret; } @@ -1723,7 +1723,7 @@ LUAG_FUNC( wakeup_conv ) // .yday (day of the year) // .isdst (daylight saving on/off) - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); @@ -1737,7 +1737,7 @@ LUAG_FUNC( wakeup_conv ) lua_getfield( L, 1, "isdst" ); isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; lua_pop(L,1); - STACK_END( L, 0); + STACK_CHECK( L, 0); t.tm_year= year-1900; t.tm_mon= month-1; // 0..11 @@ -1863,7 +1863,7 @@ LUAG_FUNC( configure) #endif // THREADAPI == THREADAPI_PTHREAD STACK_GROW( L, 4); - STACK_CHECK_ABS( L, 1); // settings + STACK_CHECK_START_ABS( L, 1); // settings DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); DEBUGSPEW_CODE( if( U) ++ U->debugspew_indent_depth); @@ -1900,13 +1900,13 @@ LUAG_FUNC( configure) initialize_allocator_function( U, L); initialize_on_state_create( U, L); init_keepers( U, L); - STACK_MID( L, 1); + STACK_CHECK( L, 1); // Initialize 'timer_deep'; a common Linda object shared by all states lua_pushcfunction( L, LG_linda); // settings lanes.linda lua_pushliteral( L, "lanes-timer"); // settings lanes.linda "lanes-timer" lua_call( L, 1, 1); // settings linda - STACK_MID( L, 2); + STACK_CHECK( L, 2); // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); @@ -1914,7 +1914,7 @@ LUAG_FUNC( configure) ++ U->timer_deep->refcount; lua_pop( L, 1); // settings } - STACK_MID( L, 1); + STACK_CHECK( L, 1); // Serialize calls to 'require' from now on, also in the primary state serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); @@ -1934,7 +1934,7 @@ LUAG_FUNC( configure) lua_setfield( L, -2, "threads"); // settings M } #endif // HAVE_LANE_TRACKING() - STACK_MID( L, 2); + STACK_CHECK( L, 2); { char const* errmsg; @@ -1945,7 +1945,7 @@ LUAG_FUNC( configure) } lua_setfield( L, -2, "timer_gateway"); // settings M } - STACK_MID( L, 2); + STACK_CHECK( L, 2); // prepare the metatable for threads // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } @@ -1992,16 +1992,16 @@ LUAG_FUNC( configure) CANCEL_ERROR.push(L); // settings M CANCEL_ERROR lua_setfield( L, -2, "cancel_error"); // settings M - STACK_MID( L, 2); // reference stack contains only the function argument 'settings' + STACK_CHECK( L, 2); // reference stack contains only the function argument 'settings' // we'll need this every time we transfer some C function from/to this state LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); // settings M - STACK_MID( L, 2); + STACK_CHECK( L, 2); // register all native functions found in that module in the transferable functions database // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) // for example in package.loaded["lanes.core"].* populate_func_lookup_table( L, -1, name); - STACK_MID( L, 2); + STACK_CHECK( L, 2); // record all existing C/JIT-fast functions // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack @@ -2018,7 +2018,7 @@ LUAG_FUNC( configure) // set _R[CONFIG_REGKEY] = settings CONFIG_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); - STACK_END( L, 1); + STACK_CHECK( L, 1); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); // Return the settings table @@ -2085,7 +2085,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) #endif // defined PLATFORM_WIN32 && !defined NDEBUG STACK_GROW( L, 4); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too lua_getglobal( L, "jit"); // {jit?} @@ -2097,6 +2097,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) return luaL_error( L, "Lanes is built for LuaJIT, don't run from PUC-Lua"); #endif lua_pop( L, 1); // + STACK_CHECK(L, 0); // Create main module interface table // we only have 1 closure, which must be called to configure Lanes @@ -2118,7 +2119,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) lua_setfield( L, -2, "configure"); // M } - STACK_END( L, 1); + STACK_CHECK( L, 1); return 1; } @@ -2135,12 +2136,12 @@ static int default_luaopen_lanes( lua_State* L) // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application LANES_API void luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core lua_pop( L, 1); // ... - STACK_MID( L, 0); + STACK_CHECK( L, 0); // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it luaL_requiref( L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes - STACK_END( L, 1); + STACK_CHECK( L, 1); } diff --git a/src/lanes_private.h b/src/lanes_private.h index 2fbbae9..b8d26d3 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h @@ -80,13 +80,12 @@ struct Lane static inline Lane* get_lane_from_registry( lua_State* L) { - Lane* s; STACK_GROW( L, 1); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); CANCEL_TEST_KEY.query_registry(L); - s = (Lane*) lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil + Lane* const s = static_cast(lua_touserdata(L, -1)); // lightuserdata (true 's_lane' pointer) / nil lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); return s; } diff --git a/src/linda.cpp b/src/linda.cpp index ff3d543..a6025ce 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -88,7 +88,7 @@ LUAG_FUNC( linda_protected_call) // acquire the keeper Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)); - lua_State* KL = K ? K->L : nullptr; // need to do this for 'STACK_CHECK' + lua_State* KL = K ? K->L : nullptr; if( KL == nullptr) return 0; // retrieve the actual function to be called and move it before the arguments @@ -168,10 +168,10 @@ LUAG_FUNC( linda_send) { Lane* const s = get_lane_from_registry( L); - Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); - lua_State* KL = K ? K->L : nullptr; // need to do this for 'STACK_CHECK' + Keeper* const K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); + lua_State* KL = K ? K->L : nullptr; if( KL == nullptr) return 0; - STACK_CHECK( KL, 0); + STACK_CHECK_START_REL(KL, 0); for(bool try_again{ true };;) { if( s != nullptr) @@ -186,7 +186,7 @@ LUAG_FUNC( linda_send) break; } - STACK_MID( KL, 0); + STACK_CHECK( KL, 0); pushed = keeper_call( linda->U, KL, KEEPER_API( send), L, linda, key_i); if( pushed < 0) { @@ -231,7 +231,7 @@ LUAG_FUNC( linda_send) } } } - STACK_END( KL, 0); + STACK_CHECK( KL, 0); } if( pushed < 0) @@ -839,7 +839,7 @@ static void* linda_id( lua_State* L, DeepOp op_) case eDO_metatable: { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); lua_newtable( L); // metatable is its own index lua_pushvalue( L, -1); @@ -904,7 +904,7 @@ static void* linda_id( lua_State* L, DeepOp op_) NIL_SENTINEL.push(L); lua_setfield( L, -2, "null"); - STACK_END( L, 1); + STACK_CHECK( L, 1); return nullptr; } diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 9982693..c549d72 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h @@ -10,6 +10,8 @@ extern "C" { } #endif // __cplusplus +#include + #define USE_DEBUG_SPEW() 0 #if USE_DEBUG_SPEW() extern char const* debugspew_indent; @@ -27,53 +29,89 @@ extern char const* debugspew_indent; #ifdef NDEBUG #define _ASSERT_L(lua,c) //nothing -#define STACK_CHECK(L,o) //nothing -#define STACK_CHECK_ABS(L,o) //nothing -#define STACK_MID(L,c) //nothing -#define STACK_END(L,c) //nothing #define STACK_DUMP(L) //nothing +#define STACK_CHECK_START_REL(L, offset_) +#define STACK_CHECK_START_ABS(L, offset_) +#define STACK_CHECK_RESET_REL(L, offset_) +#define STACK_CHECK_RESET_ABS(L, offset_) +#define STACK_CHECK(L, offset_) + #else // NDEBUG #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} +#define STACK_DUMP( L) luaG_dump( L) + +class StackChecker +{ + private: + lua_State* const m_L; + int m_oldtop; + + public: + struct Relative + { + int const m_offset; + + operator int() const { return m_offset; } + }; + + struct Absolute + { + int const m_offset; -#define STACK_CHECK( L, offset_) \ - { \ - int const L##_delta = offset_; \ - if( (L##_delta < 0) || (lua_gettop( L) < L##_delta)) \ - { \ - assert( false); \ - (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_delta, __FILE__, __LINE__); \ - } \ - int const L##_oldtop = lua_gettop( L) - L##_delta - -#define STACK_CHECK_ABS( L, offset_) \ - { \ - int const L##_pos = offset_; \ - if( lua_gettop( L) < L##_pos) \ - { \ - assert( false); \ - (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_pos, __FILE__, __LINE__); \ - } \ - int const L##_oldtop = 0 - -#define STACK_MID( L, change) \ - do if( change != LUA_MULTRET) \ - { \ - int stack_check_a = lua_gettop( L) - L##_oldtop; \ - int stack_check_b = (change); \ - if( stack_check_a != stack_check_b) \ - { \ - assert( false); \ - luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", stack_check_a, stack_check_b, __FILE__, __LINE__); \ - } \ - } while( 0) - -#define STACK_END( L, change) \ - STACK_MID( L, change); \ + operator int() const { return m_offset; } + }; + + StackChecker(lua_State* const L_, Relative offset_, char const* file_, size_t const line_) + : m_L{ L_ } + , m_oldtop{ lua_gettop(L_) - offset_ } + { + if ((offset_ < 0) || (m_oldtop < 0)) + { + assert(false); + (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), offset_, file_, line_); + } } -#define STACK_DUMP( L) luaG_dump( L) + StackChecker(lua_State* const L_, Absolute pos_, char const* file_, size_t const line_) + : m_L{ L_ } + , m_oldtop{ 0 } + { + if (lua_gettop(m_L) != pos_) + { + assert(false); + (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), pos_, file_, line_); + } + } + + StackChecker& operator=(StackChecker const& rhs_) + { + assert(m_L == rhs_.m_L); + m_oldtop = rhs_.m_oldtop; + return *this; + } + + // verify if the distance between the current top and the initial one is what we expect + void check(int expected_, char const* file_, size_t const line_) + { + if (expected_ != LUA_MULTRET) + { + int const actual{ lua_gettop(m_L) - m_oldtop }; + if (actual != expected_) + { + assert(false); + luaL_error(m_L, "STACK ASSERT failed (%d not %d): %s:%d", actual, expected_, file_, line_); + } + } + } +}; + +#define STACK_CHECK_START_REL(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__) +#define STACK_CHECK_START_ABS(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__) +#define STACK_CHECK_RESET_REL(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} +#define STACK_CHECK_RESET_ABS(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} +#define STACK_CHECK(L, offset_) stackChecker_##L.check(offset_, __FILE__, __LINE__) #endif // NDEBUG diff --git a/src/state.cpp b/src/state.cpp index f53d180..aa6b38a 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -91,28 +91,28 @@ static int luaG_new_require( lua_State* L) /* * Serialize calls to 'require', if it exists */ -void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) +void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) { - STACK_GROW( L, 1); - STACK_CHECK( L, 0); - DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); + STACK_GROW(L, 1); + STACK_CHECK_START_REL(L, 0); + DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); // Check 'require' is there and not already wrapped; if not, do nothing // - lua_getglobal( L, "require"); - if( lua_isfunction( L, -1) && lua_tocfunction( L, -1) != luaG_new_require) + lua_getglobal(L, "require"); + if (lua_isfunction(L, -1) && lua_tocfunction(L, -1) != luaG_new_require) { // [-1]: original 'require' function - lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/); - lua_setglobal( L, "require"); + lua_pushcclosure(L, luaG_new_require, 1 /*upvalues*/); + lua_setglobal(L, "require"); } else { // [-1]: nil - lua_pop( L, 1); + lua_pop(L, 1); } - STACK_END( L, 0); + STACK_CHECK(L, 0); } // ################################################################################################ @@ -176,7 +176,7 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con { bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) luaL_requiref( L, name_, libfunc, !isLanesCore); // lanes.core doesn't declare a global, so scan it here and now @@ -185,7 +185,7 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con populate_func_lookup_table( L, -1, name_); } lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); } break; } @@ -197,8 +197,8 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) { STACK_GROW( L, 2); - STACK_CHECK( L, 0); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); + STACK_CHECK_START_REL(L2, 0); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); @@ -211,31 +211,31 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) } // set L2:_R[CONFIG_REGKEY] = settings CONFIG_REGKEY.set_registry(L2, [](lua_State* L) { lua_insert(L, -2); }); // config - STACK_END( L2, 0); - STACK_END( L, 0); + STACK_CHECK( L2, 0); + STACK_CHECK( L, 0); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } void initialize_on_state_create( Universe* U, lua_State* L) { - STACK_CHECK( L, 0); - lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil - if( !lua_isnil( L, -1)) + STACK_CHECK_START_REL(L, 1); // settings + lua_getfield(L, -1, "on_state_create"); // settings on_state_create|nil + if( !lua_isnil(L, -1)) { // store C function pointer in an internal variable - U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create + U->on_state_create_func = lua_tocfunction(L, -1); // settings on_state_create if (U->on_state_create_func != nullptr) { // make sure the function doesn't have upvalues - char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? + char const* upname = lua_getupvalue(L, -1, 1); // settings on_state_create upval? if (upname != nullptr) // should be "" for C functions with upvalues if any { - (void) luaL_error( L, "on_state_create shouldn't have upvalues"); + (void) luaL_error(L, "on_state_create shouldn't have upvalues"); } // remove this C function from the config table so that it doesn't cause problems // when we transfer the config table in newly created Lua states - lua_pushnil( L); // settings on_state_create nil - lua_setfield( L, -3, "on_state_create"); // settings on_state_create + lua_pushnil(L); // settings on_state_create nil + lua_setfield(L, -3, "on_state_create"); // settings on_state_create } else { @@ -243,8 +243,8 @@ void initialize_on_state_create( Universe* U, lua_State* L) U->on_state_create_func = (lua_CFunction) initialize_on_state_create; } } - lua_pop( L, 1); // settings - STACK_END( L, 0); + lua_pop(L, 1); // settings + STACK_CHECK(L, 1); } lua_State* create_state( Universe* U, lua_State* from_) @@ -282,7 +282,7 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo { if (U->on_state_create_func != nullptr) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) { @@ -295,20 +295,21 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo { // if attempting to call in a keeper state, do nothing because the function doesn't exist there // this doesn't count as an error though + STACK_CHECK(L, 0); return; } CONFIG_REGKEY.query_registry(L); // {} - STACK_MID( L, 1); + STACK_CHECK( L, 1); lua_getfield( L, -1, "on_state_create"); // {} on_state_create() lua_remove( L, -2); // on_state_create() } - STACK_MID( L, 1); + STACK_CHECK( L, 1); // capture error and raise it in caller state if( lua_pcall( L, 0, 0, 0) != LUA_OK) { luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); } - STACK_END( L, 0); + STACK_CHECK( L, 0); } } @@ -330,16 +331,16 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) lua_State* L = create_state( U, from_); STACK_GROW( L, 2); - STACK_CHECK_ABS( L, 0); + STACK_CHECK_START_ABS(L, 0); // copy the universe as a light userdata (only the master state holds the full userdata) // that way, if Lanes is required in this new state, we'll know we are part of this universe universe_store( L, U); - STACK_MID( L, 0); + STACK_CHECK(L, 0); // we'll need this every time we transfer some C function from/to this state LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); - STACK_MID( L, 0); + STACK_CHECK(L, 0); // neither libs (not even 'base') nor special init func: we are done if (libs_ == nullptr && U->on_state_create_func == nullptr) @@ -386,7 +387,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) #endif // LUA_VERSION_NUM } } - STACK_END( L, 0); + STACK_CHECK(L, 0); // scan all libraries, open them one by one if( libs_) @@ -414,9 +415,10 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) // will raise an error in from_ in case of problem call_on_state_create( U, L, from_, eLM_LaneBody); - STACK_CHECK( L, 0); + STACK_CHECK(L, 0); // after all this, register everything we find in our name<->function database lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack + STACK_CHECK(L, 1); populate_func_lookup_table(L, -1, nullptr); #if 0 && USE_DEBUG_SPEW() @@ -436,7 +438,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) #endif // USE_DEBUG_SPEW() lua_pop( L, 1); - STACK_END( L, 0); - DEBUGSPEW_CODE( -- U->debugspew_indent_depth); + STACK_CHECK(L, 0); + DEBUGSPEW_CODE(--U->debugspew_indent_depth); return L; } diff --git a/src/tools.cpp b/src/tools.cpp index 5196e7e..1e38144 100644 --- a/src/tools.cpp +++ b/src/tools.cpp @@ -62,10 +62,10 @@ DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!-- void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) { STACK_GROW(L, 3); - STACK_CHECK(L, 0); + STACK_CHECK_START_REL(L, 0); key_.query_registry(L); // {}|nil - STACK_MID(L, 1); + STACK_CHECK(L, 1); if (lua_isnil(L, -1)) { @@ -73,7 +73,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode lua_newtable(L); // {} // _R[key_] = {} key_.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // {} - STACK_MID(L, 1); + STACK_CHECK(L, 1); // Set its metatable if requested if (mode_) @@ -85,7 +85,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode lua_setmetatable(L, -2); // {} } } - STACK_END(L, 1); + STACK_CHECK(L, 1); ASSERT_L(lua_istable(L, -1)); } @@ -125,7 +125,7 @@ void luaG_dump( lua_State* L) // Note: this requires 'tostring()' to be defined. If it is NOT, // enable it for more debugging. // - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); STACK_GROW( L, 2); lua_getglobal( L, "tostring"); @@ -146,7 +146,7 @@ void luaG_dump( lua_State* L) fprintf( stderr, "%s", lua_tostring( L, -1)); } lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); fprintf( stderr, "\n"); } fprintf( stderr, "\n"); @@ -193,7 +193,7 @@ static int luaG_provide_protected_allocator( lua_State* L) // Do I need to disable this when compiling for LuaJIT to prevent issues? void initialize_allocator_function( Universe* U, lua_State* L) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 1); // settings lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" if( !lua_isnil( L, -1)) { @@ -232,7 +232,7 @@ void initialize_allocator_function( Universe* U, lua_State* L) U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); } lua_pop( L, 1); // settings - STACK_MID(L, 0); + STACK_CHECK(L, 1); lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator" { @@ -248,7 +248,7 @@ void initialize_allocator_function( Universe* U, lua_State* L) } } lua_pop( L, 1); // settings - STACK_END( L, 0); + STACK_CHECK( L, 1); } void cleanup_allocator_function( Universe* U, lua_State* L) @@ -335,7 +335,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) { int i = 1; luaL_Buffer b; - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... luaL_buffinit( L, &b); // ... {} ... &b? for( ; i < last; ++ i) @@ -351,7 +351,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) } // &b is popped at that point (-> replaced by the result) luaL_pushresult( &b); // ... {} ... "" - STACK_END( L, 1); + STACK_CHECK( L, 1); return lua_tolstring( L, -1, length); } @@ -376,7 +376,7 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // first, raise an error if the function is already known lua_pushvalue( L, -1); // ... {bfc} k o o lua_rawget( L, dest); // ... {bfc} k o name? @@ -433,7 +433,7 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* lua_rawseti( L, fqn, _depth); // ... {bfc} k } -- _depth; - STACK_END( L, -1); + STACK_CHECK( L, -1); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } @@ -451,13 +451,13 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U STACK_GROW( L, 6); // slot _i contains a table where we search for functions (or a full userdata with a metatable) - STACK_CHECK( L, 0); // ... {_i} + STACK_CHECK_START_REL(L, 0); // ... {_i} // if object is a userdata, replace it by its metatable if( lua_type( L, _i) == LUA_TUSERDATA) { - lua_getmetatable( L, _i); // ... {_i} mt - lua_replace( L, _i); // ... {_i} + lua_getmetatable( L, _i); // ... {_i} mt + lua_replace( L, _i); // ... {_i} } // if table is already visited, we are done @@ -465,7 +465,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U lua_rawget( L, cache); // ... {_i} nil|n visit_count = lua_tointeger( L, -1); // 0 if nil, else n lua_pop( L, 1); // ... {_i} - STACK_MID( L, 0); + STACK_CHECK( L, 0); if( visit_count > 0) { DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); @@ -477,7 +477,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U lua_pushvalue( L, _i); // ... {_i} {} lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 lua_rawset( L, cache); // ... {_i} - STACK_MID( L, 0); + STACK_CHECK( L, 0); // this table is at breadth_first_cache index lua_newtable( L); // ... {_i} {bfc} @@ -515,7 +515,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U { lua_pop( L, 1); // ... {_i} {bfc} k } - STACK_MID( L, 2); + STACK_CHECK( L, 2); } // now process the tables we encountered at that depth ++ _depth; @@ -546,7 +546,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); lua_pop( L, 1); // ... {_i} {bfc} k - STACK_MID( L, 2); + STACK_CHECK( L, 2); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } // remove table name from fqn stack @@ -555,7 +555,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U -- _depth; // we are done with our cache lua_pop( L, 1); // ... {_i} - STACK_END( L, 0); + STACK_CHECK( L, 0); // we are done // ... {_i} {bfc} DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } @@ -572,9 +572,9 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); STACK_GROW( L, 3); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); LOOKUP_REGKEY.query_registry(L); // {} - STACK_MID( L, 1); + STACK_CHECK( L, 1); ASSERT_L( lua_istable( L, -1)); if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function { @@ -592,7 +592,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) lua_newtable( L); // {} {fqn} if( name_) { - STACK_MID( L, 2); + STACK_CHECK( L, 2); lua_pushstring( L, name_); // {} {fqn} "name" // generate a name, and if we already had one name, keep whichever is the shorter lua_pushvalue( L, in_base); // {} {fqn} "name" t @@ -600,7 +600,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) // don't forget to store the name at the bottom of the fqn stack ++ start_depth; lua_rawseti( L, -2, start_depth); // {} {fqn} - STACK_MID( L, 2); + STACK_CHECK( L, 2); } // retrieve the cache, create it if we haven't done it yet LOOKUPCACHE_REGKEY.query_registry(L); // {} {fqn} {cache}? @@ -609,7 +609,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) lua_pop( L, 1); // {} {fqn} lua_newtable( L); // {} {fqn} {cache} LOOKUPCACHE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); - STACK_MID( L, 3); + STACK_CHECK( L, 3); } // 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, ctx_base, in_base, start_depth); @@ -620,7 +620,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) lua_pop( L, 1); // (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); } - STACK_END( L, 0); + STACK_CHECK( L, 0); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } @@ -640,14 +640,14 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) STACK_GROW( L, 3); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID] lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} lua_rawget( L, -2); // ... _R[REG_MTID] mtk? id = lua_tointeger( L, -1); // 0 for nil lua_pop( L, 1); // ... _R[REG_MTID] - STACK_MID( L, 1); + STACK_CHECK( L, 1); if( id == 0) { @@ -667,7 +667,7 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) } lua_pop( L, 1); // ... - STACK_END( L, 0); + STACK_CHECK( L, 0); return id; } @@ -699,7 +699,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char DEBUGSPEW_CODE( Universe* const U = universe_get( L)); char const* fqn; ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); STACK_GROW( L, 3); // up to 3 slots are necessary on error if( mode_ == eLM_FromKeeper) { @@ -720,7 +720,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char { // fetch the name from the source state's lookup table LOOKUP_REGKEY.query_registry(L); // ... v ... {} - STACK_MID( L, 1); + STACK_CHECK( L, 1); ASSERT_L( lua_istable( L, -1)); lua_pushvalue( L, i); // ... v ... {} v lua_rawget( L, -2); // ... v ... {} "f.q.n" @@ -729,7 +729,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ... - STACK_MID( L, 0); + STACK_CHECK( L, 0); if (nullptr == fqn && !lua_istable(L, i)) // raise an error if we try to send an unknown function (but not for tables) { char const *from, *typewhat, *what, *gotchaA, *gotchaB; @@ -758,7 +758,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char *len_ = 0; return nullptr; } - STACK_END( L, 0); + STACK_CHECK( L, 0); return fqn; } @@ -776,7 +776,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c return false; } // push the equivalent table in the destination's stack, retrieved from the lookup table - STACK_CHECK( L2, 0); // L // L2 + STACK_CHECK_START_REL(L2, 0); // L // L2 STACK_GROW( L2, 3); // up to 3 slots are necessary on error switch( mode_) { @@ -793,7 +793,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c case eLM_LaneBody: case eLM_FromKeeper: LOOKUP_REGKEY.query_registry(L2); // {} - STACK_MID( L2, 1); + STACK_CHECK( L2, 1); ASSERT_L( lua_istable( L2, -1)); lua_pushlstring( L2, fqn, len); // {} "f.q.n" lua_rawget( L2, -2); // {} t @@ -802,7 +802,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody) { lua_pop( L2, 2); // - STACK_MID( L2, 0); + STACK_CHECK( L2, 0); return false; } else if( !lua_istable( L2, -1)) @@ -827,7 +827,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c lua_remove( L2, -2); // t break; } - STACK_END( L2, 1); + STACK_CHECK( L2, 1); return true; } @@ -849,7 +849,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i ASSERT_L( L2_cache_i != 0); STACK_GROW( L2, 3); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L2, 0); // We don't need to use the from state ('L') in ID since the life span // is only for the duration of a copy (both states are locked). @@ -868,7 +868,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i lua_pushvalue( L2, -2); // ... {} p {} lua_rawset( L2, L2_cache_i); // ... {} } - STACK_END( L2, 1); + STACK_CHECK( L2, 1); ASSERT_L( lua_istable( L2, -1)); return !not_found_in_cache; } @@ -889,7 +889,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) return shortest_; } STACK_GROW( L, 3); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // stack top contains the table to search in lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 @@ -910,14 +910,14 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) { //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : nullptr; // only for debugging //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging - STACK_MID( L, 2); + STACK_CHECK( L, 2); // append key name to fqn stack ++ depth_; lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v if( lua_rawequal( L, -1, what)) // is it what we are looking for? { - STACK_MID( L, 2); + STACK_CHECK( L, 2); // update shortest name if( depth_ < shortest_) { @@ -927,7 +927,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) } // no need to search further at this level lua_pop( L, 2); // o "r" {c} {fqn} ... {?} - STACK_MID( L, 0); + STACK_CHECK( L, 0); break; } switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v @@ -936,7 +936,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) break; case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {} - STACK_MID( L, 2); + STACK_CHECK( L, 2); shortest_ = discover_object_name_recur( L, shortest_, depth_); // search in the table's metatable too if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} @@ -953,7 +953,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) } lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {} } - STACK_MID( L, 2); + STACK_CHECK( L, 2); break; case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T @@ -961,7 +961,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) break; case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U - STACK_MID( L, 2); + STACK_CHECK( L, 2); // search in the object's metatable (some modules are built that way) if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt} { @@ -977,7 +977,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) } lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U } - STACK_MID( L, 2); + STACK_CHECK( L, 2); // search in the object's uservalues { int uvi = 1; @@ -999,7 +999,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U } - STACK_MID( L, 2); + STACK_CHECK( L, 2); break; } // make ready for next iteration @@ -1007,15 +1007,15 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) // remove name from fqn stack lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k - STACK_MID( L, 1); + STACK_CHECK( L, 1); -- depth_; } // o "r" {c} {fqn} ... {?} - STACK_MID( L, 0); + STACK_CHECK( L, 0); // remove the visited table from the cache, in case a shorter path to the searched object exists lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} - STACK_END( L, 0); + STACK_CHECK( L, 0); return shortest_; } @@ -1040,7 +1040,7 @@ int luaG_nameof( lua_State* L) } STACK_GROW( L, 4); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // this slot will contain the shortest name we found when we are done lua_pushnil( L); // o nil // push a cache that will contain all already visited tables @@ -1061,7 +1061,7 @@ int luaG_nameof( lua_State* L) (void) discover_object_name_recur( L, 6666, 1); } lua_pop( L, 3); // o "result" - STACK_END( L, 1); + STACK_CHECK( L, 1); lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type" lua_replace( L, -3); // "type" "result" return 2; @@ -1077,7 +1077,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo size_t len; char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); // push the equivalent function in the destination's stack, retrieved from the lookup table - STACK_CHECK( L2, 0); // L // L2 + STACK_CHECK_START_REL(L2, 0); // L // L2 STACK_GROW( L2, 3); // up to 3 slots are necessary on error switch( mode_) { @@ -1094,7 +1094,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo case eLM_LaneBody: case eLM_FromKeeper: LOOKUP_REGKEY.query_registry(L2); // {} - STACK_MID( L2, 1); + STACK_CHECK( L2, 1); ASSERT_L( lua_istable( L2, -1)); lua_pushlstring( L2, fqn, len); // {} "f.q.n" lua_rawget( L2, -2); // {} f @@ -1139,7 +1139,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo break; */ } - STACK_END( L2, 1); + STACK_CHECK( L2, 1); } @@ -1194,7 +1194,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, ASSERT_L( L2_cache_i != 0); // ... {cache} ... p STACK_GROW( L, 2); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); // 'lua_dump()' needs the function at top of stack @@ -1270,7 +1270,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, // cache[p] = function lua_rawset( L2, L2_cache_i); // ... {cache} ... function } - STACK_MID( L, 0); + STACK_CHECK( L, 0); /* push over any upvalues; references to this function will come from * cache so we don't end up in eternal loop. @@ -1311,7 +1311,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, } // L2: function + 'n' upvalues (>=0) - STACK_MID( L, 0); + STACK_CHECK( L, 0); // Set upvalues (originally set to 'nil' by 'lua_load') { @@ -1329,7 +1329,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, // with the function at the top of the stack // ... {cache} ... function } } - STACK_END( L, 0); + STACK_CHECK( L, 0); } /* @@ -1352,7 +1352,7 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta // L2_cache[id_str]= function // - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L2, 0); // We don't need to use the from state ('L') in ID since the life span // is only for the duration of a copy (both states are locked). @@ -1380,7 +1380,7 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta { lua_remove( L2, -2); // ... {cache} ... function } - STACK_END( L2, 1); + STACK_CHECK( L2, 1); ASSERT_L( lua_isfunction( L2, -1)); } else // function is native/LuaJIT: no need to cache @@ -1393,26 +1393,26 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); if( lua_getmetatable( L, i)) // ... mt { lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L2, 0); STACK_GROW( L2, 4); // do we already know this metatable? push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] lua_pushinteger( L2, mt_id); // _R[REG_MTID] id lua_rawget( L2, -2); // _R[REG_MTID] mt? - STACK_MID( L2, 2); + STACK_CHECK( L2, 2); if( lua_isnil( L2, -1)) { // L2 did not know the metatable lua_pop( L2, 1); // _R[REG_MTID] if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt { - STACK_MID( L2, 2); + STACK_CHECK( L2, 2); // mt_id -> metatable lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt @@ -1427,16 +1427,16 @@ static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lu { (void) luaL_error( L, "Error copying a metatable"); } - STACK_MID( L2, 2); + STACK_CHECK( L2, 2); } lua_remove( L2, -2); // mt lua_pop( L, 1); // ... - STACK_END( L2, 1); - STACK_MID( L, 0); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 0); return true; } - STACK_END( L, 0); + STACK_CHECK( L, 0); return false; } @@ -1515,27 +1515,27 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, void* const source = lua_touserdata( L, source_i_); source_i_ = lua_absindex( L, source_i_); - STACK_CHECK( L, 0); // L (source) // L2 (destination) - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) + STACK_CHECK_START_REL(L2, 0); // Check if the source was already cloned during this copy lua_pushlightuserdata( L2, source); // ... source lua_rawget( L2, L2_cache_i); // ... clone? if ( !lua_isnil( L2, -1)) { - STACK_MID( L2, 1); + STACK_CHECK( L2, 1); return true; } else { lua_pop( L2, 1); // ... } - STACK_MID( L2, 0); + STACK_CHECK( L2, 0); // no metatable? -> not clonable if( !lua_getmetatable( L, source_i_)) // ... mt? { - STACK_MID( L, 0); + STACK_CHECK( L, 0); return false; } @@ -1544,7 +1544,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, if( lua_isnil( L, -1)) { lua_pop( L, 2); // ... - STACK_MID( L, 0); + STACK_CHECK( L, 0); return false; } @@ -1578,7 +1578,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, ASSERT_L( lua_istable( L2, -1)); lua_setmetatable( L2, -2); // ... u } - STACK_MID( L2, 1); + STACK_CHECK( L2, 1); } else { @@ -1597,7 +1597,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, while( uvi > 0) { inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv - lua_pop( L, 1); // ... mt __lanesclone [uv]* + lua_pop( L, 1); // ... mt __lanesclone [uv]* // this pops the value from the stack lua_setiuservalue( L2, -2, uvi); // ... u -- uvi; @@ -1607,26 +1607,26 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, { lua_pop( L2, 1); // ... userdata_clone_sentinel } - STACK_MID( L2, 1); - STACK_MID( L, 2); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 2); // call cloning function in source state to perform the actual memory cloning lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source lua_pushinteger( L, userdata_size); // ... mt __lanesclone clone source size lua_call( L, 3, 0); // ... mt - STACK_MID( L, 1); + STACK_CHECK( L, 1); } - STACK_END( L2, 1); + STACK_CHECK( L2, 1); lua_pop( L, 1); // ... - STACK_END( L, 0); + STACK_CHECK( L, 0); return true; } static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) { - STACK_CHECK( L, 0); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); + STACK_CHECK_START_REL(L2, 0); if( vt == VT_KEY) { return false; @@ -1635,25 +1635,25 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_ // try clonable userdata first if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) { - STACK_MID( L, 0); - STACK_MID( L2, 1); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 1); return true; } - STACK_MID( L, 0); - STACK_MID( L2, 0); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 0); // Allow only deep userdata entities to be copied across DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) { - STACK_MID( L, 0); - STACK_MID( L2, 1); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 1); return true; } - STACK_MID( L, 0); - STACK_MID( L2, 0); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 0); // Not a deep or clonable full userdata if( U->demoteFullUserdata) // attempt demotion to light userdata @@ -1666,8 +1666,8 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_ (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); } - STACK_END( L2, 1); - STACK_END( L, 0); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 0); return true; } @@ -1678,8 +1678,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ return false; } - STACK_CHECK( L, 0); // L (source) // L2 (destination) - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) + STACK_CHECK_START_REL(L2, 0); DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper @@ -1697,8 +1697,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ if( !lua_isnil( L2, -1)) { lua_pop( L, 1); // ... - STACK_MID( L, 0); - STACK_MID( L2, 1); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 1); return true; } lua_pop( L2, 1); // ... @@ -1717,7 +1717,7 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now lua_pop( L, 1); // ... u [uv]* -- uvi; - STACK_MID( L, uvi + 1); + STACK_CHECK( L, uvi + 1); // create the clone userdata with the required number of uservalue slots clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u // add it in the cache @@ -1738,8 +1738,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ } // when we are done, all uservalues are popped from the stack, we can pop the source as well lua_pop( L, 1); // ... - STACK_MID( L, 0); - STACK_MID( L2, 2); // ... mt u + STACK_CHECK( L, 0); + STACK_CHECK( L2, 2); // ... mt u } // perform the custom cloning part lua_insert( L2, -2); // ... u mt @@ -1759,8 +1759,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f DEBUGSPEW_CODE( -- U->debugspew_indent_depth); } - STACK_END( L2, 1); - STACK_END( L, 0); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 0); return true; } @@ -1771,8 +1771,8 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta return false; } - STACK_CHECK( L, 0); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); + STACK_CHECK_START_REL(L2, 0); DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); /* @@ -1811,16 +1811,16 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); lua_pop( L, 1); // pop value (next round) } - STACK_MID( L, 0); - STACK_MID( L2, 1); + STACK_CHECK( L, 0); + STACK_CHECK( L2, 1); // Metatables are expected to be immutable, and copied only once. if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt? { lua_setmetatable( L2, -2); // ... t } - STACK_END( L2, 1); - STACK_END( L, 0); + STACK_CHECK( L2, 1); + STACK_CHECK( L, 0); return true; } @@ -1840,8 +1840,8 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in int val_type = lua_type( L, i); static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); STACK_GROW( L2, 1); - STACK_CHECK( L, 0); // L // L2 - STACK_CHECK( L2, 0); // L // L2 + STACK_CHECK_START_REL(L, 0); // L // L2 + STACK_CHECK_START_REL(L2, 0); // L // L2 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); @@ -1861,7 +1861,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in lua_pop( L, 2); // ... } } - STACK_MID( L, 0); + STACK_CHECK( L, 0); /* Lets push nil to L2 if the object should be ignored */ switch( val_type) @@ -1945,8 +1945,8 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in DEBUGSPEW_CODE( -- U->debugspew_indent_depth); - STACK_END( L2, ret ? 1 : 0); - STACK_END( L, 0); + STACK_CHECK( L2, ret ? 1 : 0); + STACK_CHECK( L, 0); return ret; } @@ -1977,7 +1977,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode return -1; } - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L2, 0); STACK_GROW( L2, n + 1); /* @@ -1987,7 +1987,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode */ lua_newtable( L2); // ... cache - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) { if( U->verboseErrors) @@ -2000,13 +2000,13 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode break; } } - STACK_END( L, 0); + STACK_CHECK( L, 0); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); if( copyok) { - STACK_MID( L2, n + 1); + STACK_CHECK( L2, n + 1); // Remove the cache table. Persistent caching would cause i.e. multiple // messages passed in the same table to use the same table also in receiving end. lua_remove( L2, top_L2 + 1); @@ -2015,7 +2015,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode // error -> pop everything from the target state stack lua_settop( L2, top_L2); - STACK_END( L2, 0); + STACK_CHECK( L2, 0); return -2; } @@ -2032,13 +2032,13 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); // package - STACK_CHECK( L, 0); - STACK_CHECK( L2, 0); + STACK_CHECK_START_REL(L, 0); + STACK_CHECK_START_REL(L2, 0); package_idx_ = lua_absindex( L, package_idx_); if( lua_type( L, package_idx_) != LUA_TTABLE) { lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); - STACK_MID( L, 1); + STACK_CHECK( L, 1); // raise the error when copying from lane to lane, else just leave it on the stack to be raised later return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1; } @@ -2073,8 +2073,8 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); } lua_pop( L2, 1); - STACK_END( L2, 0); - STACK_END( L, 0); + STACK_CHECK( L2, 0); + STACK_CHECK( L, 0); DEBUGSPEW_CODE( -- U->debugspew_indent_depth); return 0; } diff --git a/src/universe.cpp b/src/universe.cpp index 5d0d3b6..06c7313 100644 --- a/src/universe.cpp +++ b/src/universe.cpp @@ -41,35 +41,35 @@ static constexpr UniqueKey UNIVERSE_REGKEY{ 0x9f877b2cf078f17full }; // ################################################################################################ -Universe* universe_create( lua_State* L) +Universe* universe_create(lua_State* L) { Universe* U = (Universe*) lua_newuserdatauv( L, sizeof(Universe), 0); // universe memset( U, 0, sizeof( Universe)); - STACK_CHECK( L, 1); + STACK_CHECK_START_REL(L, 1); UNIVERSE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // universe - STACK_END( L, 1); + STACK_CHECK( L, 1); return U; } // ################################################################################################ -void universe_store( lua_State* L, Universe* U) +void universe_store(lua_State* L, Universe* U) { - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); UNIVERSE_REGKEY.set_registry(L, [U](lua_State* L) { U ? lua_pushlightuserdata( L, U) : lua_pushnil( L); }); - STACK_END( L, 0); + STACK_CHECK( L, 0); } // ################################################################################################ -Universe* universe_get( lua_State* L) +Universe* universe_get(lua_State* L) { Universe* universe; STACK_GROW( L, 2); - STACK_CHECK( L, 0); + STACK_CHECK_START_REL(L, 0); UNIVERSE_REGKEY.query_registry(L); universe = (Universe*) lua_touserdata( L, -1); // nullptr if nil lua_pop( L, 1); - STACK_END( L, 0); + STACK_CHECK( L, 0); return universe; } -- cgit v1.2.3-55-g6feb