diff options
| author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-16 12:46:14 +0200 |
|---|---|---|
| committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-16 12:46:14 +0200 |
| commit | d6f5a7795360e3c2a6fc2d424904b6daa1f2accd (patch) | |
| tree | 8ac5f6c7076de45ec837d3b669ffc61f72bd4f5a | |
| parent | e7276bee137b87a2323b125a6a8c792de73819eb (diff) | |
| download | lanes-d6f5a7795360e3c2a6fc2d424904b6daa1f2accd.tar.gz lanes-d6f5a7795360e3c2a6fc2d424904b6daa1f2accd.tar.bz2 lanes-d6f5a7795360e3c2a6fc2d424904b6daa1f2accd.zip | |
C++ migration: more conversion to InterCopyContext. debugspew indentation is managed by a scope object
| -rw-r--r-- | docs/index.html | 2 | ||||
| -rw-r--r-- | src/deep.h | 2 | ||||
| -rw-r--r-- | src/keeper.cpp | 59 | ||||
| -rw-r--r-- | src/lanes.cpp | 61 | ||||
| -rw-r--r-- | src/macros_and_utils.h | 7 | ||||
| -rw-r--r-- | src/state.cpp | 44 | ||||
| -rw-r--r-- | src/tools.cpp | 192 | ||||
| -rw-r--r-- | src/tools.h | 12 | ||||
| -rw-r--r-- | src/universe.h | 28 |
9 files changed, 231 insertions, 176 deletions
diff --git a/docs/index.html b/docs/index.html index 67eccd5..9b3e5e7 100644 --- a/docs/index.html +++ b/docs/index.html | |||
| @@ -1706,7 +1706,7 @@ static MyDeepFactory g_MyDeepFactory; | |||
| 1706 | Take a look at <tt>LindaFactory</tt> in <tt>linda.cpp</tt> or <tt>MyDeepFactory</tt> in <tt>deep_test.cpp</tt>. | 1706 | Take a look at <tt>LindaFactory</tt> in <tt>linda.cpp</tt> or <tt>MyDeepFactory</tt> in <tt>deep_test.cpp</tt>. |
| 1707 | </li> | 1707 | </li> |
| 1708 | <li>Include <tt>"deep.h"</tt> and either link against Lanes or statically compile <tt>compat.cpp deep.cpp tools.cpp universe.cpp</tt> into your module if you want to avoid a runtime dependency for users that will use your module without Lanes. | 1708 | <li>Include <tt>"deep.h"</tt> and either link against Lanes or statically compile <tt>compat.cpp deep.cpp tools.cpp universe.cpp</tt> into your module if you want to avoid a runtime dependency for users that will use your module without Lanes. |
| 1709 | <li>Instanciate your userdata using <tt>yourFactoryObject.pushDeepUserdata()()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given a <tt>factory</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li> | 1709 | <li>Instanciate your userdata using <tt>yourFactoryObject.pushDeepUserdata()</tt>, instead of the regular <tt>lua_newuserdata()</tt>. Given a <tt>factory</tt>, it sets up the support structures and returns a state-specific proxy userdata for accessing your data. This proxy can also be copied over to other lanes.</li> |
| 1710 | <li>Accessing the deep userdata from your C code, use <tt>yourFactoryObject.toDeep()</tt> instead of the regular <tt>lua_touserdata()</tt>.</li> | 1710 | <li>Accessing the deep userdata from your C code, use <tt>yourFactoryObject.toDeep()</tt> instead of the regular <tt>lua_touserdata()</tt>.</li> |
| 1711 | </ol> | 1711 | </ol> |
| 1712 | 1712 | ||
| @@ -23,7 +23,7 @@ class Universe; | |||
| 23 | 23 | ||
| 24 | enum class LookupMode | 24 | enum class LookupMode |
| 25 | { | 25 | { |
| 26 | LaneBody, // send the lane body directly from the source to the destination lane | 26 | LaneBody, // send the lane body directly from the source to the destination lane. keep this one first so that it's the value we get when we default-construct |
| 27 | ToKeeper, // send a function from a lane to a keeper state | 27 | ToKeeper, // send a function from a lane to a keeper state |
| 28 | FromKeeper // send a function from a keeper state to a lane | 28 | FromKeeper // send a function from a keeper state to a lane |
| 29 | }; | 29 | }; |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 650789b..3e26d5e 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
| @@ -226,18 +226,19 @@ int keeper_push_linda_storage(Universe* U, Dest L, void* ptr_, uintptr_t magic_) | |||
| 226 | return 0; | 226 | return 0; |
| 227 | } | 227 | } |
| 228 | // move data from keeper to destination state | 228 | // move data from keeper to destination state |
| 229 | lua_pushnil(KL); // storage nil | ||
| 230 | STACK_GROW(L, 5); | 229 | STACK_GROW(L, 5); |
| 231 | STACK_CHECK_START_REL(L, 0); | 230 | STACK_CHECK_START_REL(L, 0); |
| 232 | lua_newtable(L); // out | 231 | lua_newtable(L); // out |
| 232 | InterCopyContext c{ U, L, KL, {}, {}, {}, LookupMode::FromKeeper, {} }; | ||
| 233 | lua_pushnil(KL); // storage nil | ||
| 233 | while (lua_next(KL, -2)) // storage key fifo | 234 | while (lua_next(KL, -2)) // storage key fifo |
| 234 | { | 235 | { |
| 235 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl | 236 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifotbl |
| 236 | lua_pushvalue(KL, -2); // storage key fifotbl key | 237 | lua_pushvalue(KL, -2); // storage key fifotbl key |
| 237 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key fifotbl // out key | 238 | std::ignore = c.inter_move(1); // storage key fifotbl // out key |
| 238 | STACK_CHECK(L, 2); | 239 | STACK_CHECK(L, 2); |
| 239 | lua_newtable(L); // out key keyout | 240 | lua_newtable(L); // out key keyout |
| 240 | std::ignore = luaG_inter_move(U, KL, L, 1, LookupMode::FromKeeper); // storage key // out key keyout fifotbl | 241 | std::ignore = c.inter_move(1); // storage key // out key keyout fifotbl |
| 241 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first | 242 | lua_pushinteger(L, fifo->first); // out key keyout fifotbl first |
| 242 | STACK_CHECK(L, 5); | 243 | STACK_CHECK(L, 5); |
| 243 | lua_setfield(L, -3, "first"); // out key keyout fifotbl | 244 | lua_setfield(L, -3, "first"); // out key keyout fifotbl |
| @@ -646,23 +647,24 @@ void close_keepers(Universe* U) | |||
| 646 | * Note: Any problems would be design flaws; the created Lua state is left | 647 | * Note: Any problems would be design flaws; the created Lua state is left |
| 647 | * unclosed, because it does not really matter. In production code, this | 648 | * unclosed, because it does not really matter. In production code, this |
| 648 | * function never fails. | 649 | * function never fails. |
| 649 | * settings table is at position 1 on the stack | 650 | * settings table is expected at position 1 on the stack |
| 650 | */ | 651 | */ |
| 651 | void init_keepers(Universe* U, lua_State* L) | 652 | void init_keepers(Universe* U, lua_State* L) |
| 652 | { | 653 | { |
| 654 | ASSERT_L(lua_gettop(L) == 1 && lua_istable(L, 1)); | ||
| 653 | STACK_CHECK_START_REL(L, 0); // L K | 655 | STACK_CHECK_START_REL(L, 0); // L K |
| 654 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers | 656 | lua_getfield(L, 1, "nb_keepers"); // settings nb_keepers |
| 655 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; | 657 | int const nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; |
| 656 | lua_pop(L, 1); // | 658 | lua_pop(L, 1); // settings |
| 657 | if (nb_keepers < 1) | 659 | if (nb_keepers < 1) |
| 658 | { | 660 | { |
| 659 | luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return | 661 | luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return |
| 660 | } | 662 | } |
| 661 | STACK_CHECK(L, 0); | 663 | STACK_CHECK(L, 0); |
| 662 | 664 | ||
| 663 | lua_getfield(L, 1, "keepers_gc_threshold"); // keepers_gc_threshold | 665 | lua_getfield(L, 1, "keepers_gc_threshold"); // settings keepers_gc_threshold |
| 664 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; | 666 | int const keepers_gc_threshold{ static_cast<int>(lua_tointeger(L, -1)) }; |
| 665 | lua_pop(L, 1); // | 667 | lua_pop(L, 1); // settings |
| 666 | STACK_CHECK(L, 0); | 668 | STACK_CHECK(L, 0); |
| 667 | 669 | ||
| 668 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states | 670 | // Keepers contains an array of 1 Keeper, adjust for the actual number of keeper states |
| @@ -682,7 +684,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
| 682 | U->keepers->keeper_array[i].Keeper::Keeper(); | 684 | U->keepers->keeper_array[i].Keeper::Keeper(); |
| 683 | } | 685 | } |
| 684 | } | 686 | } |
| 685 | for (int i = 0; i < nb_keepers; ++i) // keepersUD | 687 | for (int i = 0; i < nb_keepers; ++i) // settings |
| 686 | { | 688 | { |
| 687 | // note that we will leak K if we raise an error later | 689 | // note that we will leak K if we raise an error later |
| 688 | lua_State* const K{ create_state(U, L) }; | 690 | lua_State* const K{ create_state(U, L) }; |
| @@ -706,26 +708,28 @@ void init_keepers(Universe* U, lua_State* L) | |||
| 706 | 708 | ||
| 707 | // make sure 'package' is initialized in keeper states, so that we have require() | 709 | // make sure 'package' is initialized in keeper states, so that we have require() |
| 708 | // this because this is needed when transferring deep userdata object | 710 | // this because this is needed when transferring deep userdata object |
| 709 | luaL_requiref(K, "package", luaopen_package, 1); // package | 711 | luaL_requiref(K, "package", luaopen_package, 1); // settings package |
| 710 | lua_pop(K, 1); // | 712 | lua_pop(K, 1); // settings |
| 711 | STACK_CHECK(K, 0); | 713 | STACK_CHECK(K, 0); |
| 712 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); | 714 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); |
| 713 | STACK_CHECK(K, 0); | 715 | STACK_CHECK(K, 0); |
| 714 | 716 | ||
| 715 | // copy package.path and package.cpath from the source state | 717 | // copy package.path and package.cpath from the source state (TODO: use _R._LOADED.package instead of _G.package) |
| 716 | lua_getglobal(L, "package"); // "..." keepersUD package | 718 | lua_getglobal(L, "package"); // settings package |
| 717 | if (!lua_isnil(L, -1)) | 719 | if (!lua_isnil(L, -1)) |
| 718 | { | 720 | { |
| 719 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately | 721 | // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately |
| 720 | if (luaG_inter_copy_package(U, Source{ L }, Dest{ K }, -1, LookupMode::ToKeeper) != InterCopyResult::Success) | 722 | InterCopyContext c{ U, Dest{ K }, Source{ L }, {}, SourceIndex{ lua_absindex(L, -1) }, {}, LookupMode::ToKeeper, {} }; |
| 723 | if (c.inter_copy_package() != InterCopyResult::Success) | ||
| 721 | { | 724 | { |
| 722 | // if something went wrong, the error message is at the top of the stack | 725 | // if something went wrong, the error message is at the top of the stack |
| 723 | lua_remove(L, -2); // error_msg | 726 | lua_remove(L, -2); // settings error_msg |
| 724 | raise_lua_error(L); | 727 | raise_lua_error(L); |
| 725 | } | 728 | } |
| 726 | } | 729 | } |
| 727 | lua_pop(L, 1); // | 730 | lua_pop(L, 1); // settings |
| 728 | STACK_CHECK(L, 0); | 731 | STACK_CHECK(L, 0); |
| 732 | STACK_CHECK(K, 0); | ||
| 729 | 733 | ||
| 730 | // attempt to call on_state_create(), if we have one and it is a C function | 734 | // attempt to call on_state_create(), if we have one and it is a C function |
| 731 | // (only support a C function because we can't transfer executable Lua code in keepers) | 735 | // (only support a C function because we can't transfer executable Lua code in keepers) |
| @@ -837,20 +841,23 @@ KeeperCallResult keeper_call(Universe* U, lua_State* K, keeper_api_t func_, lua_ | |||
| 837 | ASSERT_L(lua_gettop(K) == 0); | 841 | ASSERT_L(lua_gettop(K) == 0); |
| 838 | 842 | ||
| 839 | STACK_GROW(K, 2); | 843 | STACK_GROW(K, 2); |
| 840 | 844 | PUSH_KEEPER_FUNC(K, func_); // func_ | |
| 841 | PUSH_KEEPER_FUNC(K, func_); // func_ | 845 | lua_pushlightuserdata(K, linda); // func_ linda |
| 842 | 846 | if ( | |
| 843 | lua_pushlightuserdata(K, linda); // func_ linda | 847 | (args == 0) || |
| 844 | 848 | (InterCopyContext{ U, Dest{ K }, Source{ L }, {}, {}, {}, LookupMode::ToKeeper, {} }.inter_copy(args) == InterCopyResult::Success) | |
| 845 | if ((args == 0) || luaG_inter_copy(U, Source{ L }, Dest{ K }, args, LookupMode::ToKeeper) == InterCopyResult::Success) // func_ linda args... | 849 | ) |
| 846 | { | 850 | { // func_ linda args... |
| 847 | lua_call(K, 1 + args, LUA_MULTRET); // result... | 851 | lua_call(K, 1 + args, LUA_MULTRET); // result... |
| 848 | int const retvals{ lua_gettop(K) - top_K }; | 852 | int const retvals{ lua_gettop(K) - top_K }; |
| 849 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired | 853 | // note that this can raise a luaL_error while the keeper state (and its mutex) is acquired |
| 850 | // this may interrupt a lane, causing the destruction of the underlying OS thread | 854 | // this may interrupt a lane, causing the destruction of the underlying OS thread |
| 851 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function | 855 | // after this, another lane making use of this keeper can get an error code from the mutex-locking function |
| 852 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) | 856 | // when attempting to grab the mutex again (WINVER <= 0x400 does this, but locks just fine, I don't know about pthread) |
| 853 | if ((retvals == 0) || (luaG_inter_move(U, Source{ K }, Dest{ L }, retvals, LookupMode::FromKeeper) == InterCopyResult::Success)) // K->L | 857 | if ( |
| 858 | (retvals == 0) || | ||
| 859 | (InterCopyContext{ U, Dest{ L }, Source{ K }, {}, {}, {}, LookupMode::FromKeeper, {} }.inter_move(retvals) == InterCopyResult::Success) | ||
| 860 | ) // K->L | ||
| 854 | { | 861 | { |
| 855 | result.emplace(retvals); | 862 | result.emplace(retvals); |
| 856 | } | 863 | } |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 8b4410a..17d4f67 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
| @@ -946,13 +946,12 @@ LUAG_FUNC(require) | |||
| 946 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); | 946 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); |
| 947 | STACK_CHECK_START_REL(L, 0); | 947 | STACK_CHECK_START_REL(L, 0); |
| 948 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); | 948 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); |
| 949 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 949 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 950 | lua_pushvalue(L, lua_upvalueindex(1)); // "name" require | 950 | lua_pushvalue(L, lua_upvalueindex(1)); // "name" require |
| 951 | lua_insert(L, 1); // require "name" | 951 | lua_insert(L, 1); // require "name" |
| 952 | lua_call(L, nargs, 1); // module | 952 | lua_call(L, nargs, 1); // module |
| 953 | populate_func_lookup_table(L, -1, name); | 953 | populate_func_lookup_table(L, -1, name); |
| 954 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); | 954 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); |
| 955 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 956 | STACK_CHECK(L, 0); | 955 | STACK_CHECK(L, 0); |
| 957 | return 1; | 956 | return 1; |
| 958 | } | 957 | } |
| @@ -972,10 +971,9 @@ LUAG_FUNC(register) | |||
| 972 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); | 971 | DEBUGSPEW_CODE(Universe* U = universe_get(L)); |
| 973 | STACK_CHECK_START_REL(L, 0); // "name" mod_table | 972 | STACK_CHECK_START_REL(L, 0); // "name" mod_table |
| 974 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); | 973 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); |
| 975 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 974 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 976 | populate_func_lookup_table(L, -1, name); | 975 | populate_func_lookup_table(L, -1, name); |
| 977 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); | 976 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); |
| 978 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 979 | STACK_CHECK(L, 0); | 977 | STACK_CHECK(L, 0); |
| 980 | return 0; | 978 | return 0; |
| 981 | } | 979 | } |
| @@ -1022,7 +1020,6 @@ LUAG_FUNC(lane_new) | |||
| 1022 | 1020 | ||
| 1023 | /* --- Create and prepare the sub state --- */ | 1021 | /* --- Create and prepare the sub state --- */ |
| 1024 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END)); | 1022 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: setup\n" INDENT_END)); |
| 1025 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | ||
| 1026 | 1023 | ||
| 1027 | // populate with selected libraries at the same time | 1024 | // populate with selected libraries at the same time |
| 1028 | lua_State* const L2{ luaG_newstate(U, Source{ L }, libs_str) }; // L // L2 | 1025 | lua_State* const L2{ luaG_newstate(U, Source{ L }, libs_str) }; // L // L2 |
| @@ -1041,7 +1038,8 @@ LUAG_FUNC(lane_new) | |||
| 1041 | lua_State* const m_L; | 1038 | lua_State* const m_L; |
| 1042 | Lane* m_lane{ nullptr }; | 1039 | Lane* m_lane{ nullptr }; |
| 1043 | int const m_gc_cb_idx; | 1040 | int const m_gc_cb_idx; |
| 1044 | DEBUGSPEW_CODE(Universe* const U); // for DEBUGSPEW only (hence the absence of m_ prefix) | 1041 | DEBUGSPEW_CODE(Universe* const U); |
| 1042 | DEBUGSPEW_CODE(DebugSpewIndentScope m_scope); | ||
| 1045 | 1043 | ||
| 1046 | public: | 1044 | public: |
| 1047 | 1045 | ||
| @@ -1050,7 +1048,9 @@ LUAG_FUNC(lane_new) | |||
| 1050 | , m_lane{ lane_ } | 1048 | , m_lane{ lane_ } |
| 1051 | , m_gc_cb_idx{ gc_cb_idx_ } | 1049 | , m_gc_cb_idx{ gc_cb_idx_ } |
| 1052 | DEBUGSPEW_COMMA_PARAM(U{ U_ }) | 1050 | DEBUGSPEW_COMMA_PARAM(U{ U_ }) |
| 1053 | {} | 1051 | DEBUGSPEW_COMMA_PARAM(m_scope{ U_ }) |
| 1052 | { | ||
| 1053 | } | ||
| 1054 | 1054 | ||
| 1055 | ~OnExit() | 1055 | ~OnExit() |
| 1056 | { | 1056 | { |
| @@ -1132,7 +1132,8 @@ LUAG_FUNC(lane_new) | |||
| 1132 | { | 1132 | { |
| 1133 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END)); | 1133 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: update 'package'\n" INDENT_END)); |
| 1134 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack | 1134 | // when copying with mode LookupMode::LaneBody, should raise an error in case of problem, not leave it one the stack |
| 1135 | [[maybe_unused]] InterCopyResult const ret{ luaG_inter_copy_package(U, Source{ L }, Dest{ L2 }, package_idx, LookupMode::LaneBody) }; | 1135 | InterCopyContext c{ U, Dest{ L2 }, Source{ L }, {}, SourceIndex{ package_idx }, {}, {}, {} }; |
| 1136 | [[maybe_unused]] InterCopyResult const ret{ c.inter_copy_package() }; | ||
| 1136 | ASSERT_L(ret == InterCopyResult::Success); // either all went well, or we should not even get here | 1137 | ASSERT_L(ret == InterCopyResult::Success); // either all went well, or we should not even get here |
| 1137 | } | 1138 | } |
| 1138 | 1139 | ||
| @@ -1141,7 +1142,7 @@ LUAG_FUNC(lane_new) | |||
| 1141 | { | 1142 | { |
| 1142 | int nbRequired = 1; | 1143 | int nbRequired = 1; |
| 1143 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END)); | 1144 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require 'required' list\n" INDENT_END)); |
| 1144 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1145 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1145 | // should not happen, was checked in lanes.lua before calling lane_new() | 1146 | // should not happen, was checked in lanes.lua before calling lane_new() |
| 1146 | if (lua_type(L, required_idx) != LUA_TTABLE) | 1147 | if (lua_type(L, required_idx) != LUA_TTABLE) |
| 1147 | { | 1148 | { |
| @@ -1175,10 +1176,8 @@ LUAG_FUNC(lane_new) | |||
| 1175 | if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode | 1176 | if (lua_pcall( L2, 1, 1, 0) != LUA_OK) // ret/errcode |
| 1176 | { | 1177 | { |
| 1177 | // propagate error to main state if any | 1178 | // propagate error to main state if any |
| 1178 | std::ignore = luaG_inter_move(U | 1179 | InterCopyContext c{ U, Dest{ L }, Source{ L2 }, {}, {}, {}, {}, {} }; |
| 1179 | , Source{ L2 }, Dest{ L } | 1180 | std::ignore = c.inter_move(1); // func libs priority globals package required gc_cb [... args ...] n "modname" error |
| 1180 | , 1, LookupMode::LaneBody | ||
| 1181 | ); // func libs priority globals package required gc_cb [... args ...] n "modname" error | ||
| 1182 | raise_lua_error(L); | 1181 | raise_lua_error(L); |
| 1183 | } | 1182 | } |
| 1184 | // after requiring the module, register the functions it exported in our name<->function database | 1183 | // after requiring the module, register the functions it exported in our name<->function database |
| @@ -1189,7 +1188,6 @@ LUAG_FUNC(lane_new) | |||
| 1189 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n | 1188 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] n |
| 1190 | ++ nbRequired; | 1189 | ++ nbRequired; |
| 1191 | } // func libs priority globals package required gc_cb [... args ...] | 1190 | } // func libs priority globals package required gc_cb [... args ...] |
| 1192 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1193 | } | 1191 | } |
| 1194 | STACK_CHECK(L, 0); | 1192 | STACK_CHECK(L, 0); |
| 1195 | STACK_CHECK(L2, 0); // | 1193 | STACK_CHECK(L2, 0); // |
| @@ -1205,20 +1203,19 @@ LUAG_FUNC(lane_new) | |||
| 1205 | luaL_error(L, "Expected table, got %s", luaL_typename(L, globals_idx)); // doesn't return | 1203 | luaL_error(L, "Expected table, got %s", luaL_typename(L, globals_idx)); // doesn't return |
| 1206 | } | 1204 | } |
| 1207 | 1205 | ||
| 1208 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1206 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1209 | lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil | 1207 | lua_pushnil(L); // func libs priority globals package required gc_cb [... args ...] nil |
| 1210 | // Lua 5.2 wants us to push the globals table on the stack | 1208 | // Lua 5.2 wants us to push the globals table on the stack |
| 1211 | lua_pushglobaltable(L2); // _G | 1209 | InterCopyContext c{ U, Dest{ L2 }, Source{ L }, {}, {}, {}, {}, {} }; |
| 1210 | lua_pushglobaltable(L2); // _G | ||
| 1212 | while( lua_next(L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v | 1211 | while( lua_next(L, globals_idx)) // func libs priority globals package required gc_cb [... args ...] k v |
| 1213 | { | 1212 | { |
| 1214 | std::ignore = luaG_inter_copy(U, Source{ L }, Dest{ L2 }, 2, LookupMode::LaneBody); // _G k v | 1213 | std::ignore = c.inter_copy(2); // _G k v |
| 1215 | // assign it in L2's globals table | 1214 | // assign it in L2's globals table |
| 1216 | lua_rawset(L2, -3); // _G | 1215 | lua_rawset(L2, -3); // _G |
| 1217 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] k | 1216 | lua_pop(L, 1); // func libs priority globals package required gc_cb [... args ...] k |
| 1218 | } // func libs priority globals package required gc_cb [... args ...] | 1217 | } // func libs priority globals package required gc_cb [... args ...] |
| 1219 | lua_pop( L2, 1); // | 1218 | lua_pop( L2, 1); // |
| 1220 | |||
| 1221 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1222 | } | 1219 | } |
| 1223 | STACK_CHECK(L, 0); | 1220 | STACK_CHECK(L, 0); |
| 1224 | STACK_CHECK(L2, 0); | 1221 | STACK_CHECK(L2, 0); |
| @@ -1228,10 +1225,10 @@ LUAG_FUNC(lane_new) | |||
| 1228 | if (func_type == LuaType::FUNCTION) | 1225 | if (func_type == LuaType::FUNCTION) |
| 1229 | { | 1226 | { |
| 1230 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); | 1227 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane body\n" INDENT_END)); |
| 1231 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1228 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1232 | lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func | 1229 | lua_pushvalue(L, 1); // func libs priority globals package required gc_cb [... args ...] func |
| 1233 | InterCopyResult const res{ luaG_inter_move(U, Source{ L }, Dest{ L2 }, 1, LookupMode::LaneBody) }; // func libs priority globals package required gc_cb [... args ...] // func | 1230 | InterCopyContext c{ U, Dest{ L2 }, Source{ L }, {}, {}, {}, {}, {} }; |
| 1234 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | 1231 | InterCopyResult const res{ c.inter_move(1) }; // func libs priority globals package required gc_cb [... args ...] // func |
| 1235 | if (res != InterCopyResult::Success) | 1232 | if (res != InterCopyResult::Success) |
| 1236 | { | 1233 | { |
| 1237 | luaL_error(L, "tried to copy unsupported types"); // doesn't return | 1234 | luaL_error(L, "tried to copy unsupported types"); // doesn't return |
| @@ -1258,9 +1255,9 @@ LUAG_FUNC(lane_new) | |||
| 1258 | if (nargs > 0) | 1255 | if (nargs > 0) |
| 1259 | { | 1256 | { |
| 1260 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); | 1257 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "lane_new: transfer lane arguments\n" INDENT_END)); |
| 1261 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1258 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1262 | InterCopyResult const res{ luaG_inter_move(U, Source{ L }, Dest{ L2 }, nargs, LookupMode::LaneBody) }; // func libs priority globals package required gc_cb // func [... args ...] | 1259 | InterCopyContext c{ U, Dest{ L2 }, Source{ L }, {}, {}, {}, {}, {} }; |
| 1263 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | 1260 | InterCopyResult const res{ c.inter_move(nargs) }; // func libs priority globals package required gc_cb // func [... args ...] |
| 1264 | if (res != InterCopyResult::Success) | 1261 | if (res != InterCopyResult::Success) |
| 1265 | { | 1262 | { |
| 1266 | luaL_error(L, "tried to copy unsupported types"); // doesn't return | 1263 | luaL_error(L, "tried to copy unsupported types"); // doesn't return |
| @@ -1278,7 +1275,6 @@ LUAG_FUNC(lane_new) | |||
| 1278 | onExit.success(); | 1275 | onExit.success(); |
| 1279 | // we should have the lane userdata on top of the stack | 1276 | // we should have the lane userdata on top of the stack |
| 1280 | STACK_CHECK(L, 1); | 1277 | STACK_CHECK(L, 1); |
| 1281 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1282 | return 1; | 1278 | return 1; |
| 1283 | } | 1279 | } |
| 1284 | 1280 | ||
| @@ -1423,7 +1419,10 @@ LUAG_FUNC(thread_join) | |||
| 1423 | case Lane::Done: | 1419 | case Lane::Done: |
| 1424 | { | 1420 | { |
| 1425 | int const n{ lua_gettop(L2) }; // whole L2 stack | 1421 | int const n{ lua_gettop(L2) }; // whole L2 stack |
| 1426 | if ((n > 0) && (luaG_inter_move(U, Source{ L2 }, Dest{ L }, n, LookupMode::LaneBody) != InterCopyResult::Success)) | 1422 | if ( |
| 1423 | (n > 0) && | ||
| 1424 | (InterCopyContext{ U, Dest{ L }, Source{ L2 }, {}, {}, {}, {}, {} }.inter_move(n) != InterCopyResult::Success) | ||
| 1425 | ) | ||
| 1427 | { | 1426 | { |
| 1428 | luaL_error(L, "tried to copy unsupported types"); // doesn't return | 1427 | luaL_error(L, "tried to copy unsupported types"); // doesn't return |
| 1429 | } | 1428 | } |
| @@ -1437,7 +1436,8 @@ LUAG_FUNC(thread_join) | |||
| 1437 | STACK_GROW(L, 3); | 1436 | STACK_GROW(L, 3); |
| 1438 | lua_pushnil(L); | 1437 | lua_pushnil(L); |
| 1439 | // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... | 1438 | // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... |
| 1440 | if (luaG_inter_move(U, Source{ L2 }, Dest{ L }, n, LookupMode::LaneBody) != InterCopyResult::Success) // nil "err" [trace] | 1439 | InterCopyContext c{ U, Dest{ L }, Source{ L2 }, {}, {}, {}, {}, {} }; |
| 1440 | if (c.inter_move(n) != InterCopyResult::Success) // nil "err" [trace] | ||
| 1441 | { | 1441 | { |
| 1442 | luaL_error(L, "tried to copy unsupported types: %s", lua_tostring(L, -n)); // doesn't return | 1442 | luaL_error(L, "tried to copy unsupported types: %s", lua_tostring(L, -n)); // doesn't return |
| 1443 | } | 1443 | } |
| @@ -1772,12 +1772,12 @@ LUAG_FUNC(configure) | |||
| 1772 | STACK_CHECK_START_ABS(L, 1); // settings | 1772 | STACK_CHECK_START_ABS(L, 1); // settings |
| 1773 | 1773 | ||
| 1774 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); | 1774 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); |
| 1775 | DEBUGSPEW_CODE(if (U) U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1775 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1776 | 1776 | ||
| 1777 | if (U == nullptr) | 1777 | if (U == nullptr) |
| 1778 | { | 1778 | { |
| 1779 | U = universe_create(L); // settings universe | 1779 | U = universe_create(L); // settings universe |
| 1780 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1780 | DEBUGSPEW_CODE(DebugSpewIndentScope scope2{ U }); |
| 1781 | lua_newtable( L); // settings universe mt | 1781 | lua_newtable( L); // settings universe mt |
| 1782 | lua_getfield(L, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout | 1782 | lua_getfield(L, 1, "shutdown_timeout"); // settings universe mt shutdown_timeout |
| 1783 | lua_getfield(L, 1, "shutdown_mode"); // settings universe mt shutdown_timeout shutdown_mode | 1783 | lua_getfield(L, 1, "shutdown_mode"); // settings universe mt shutdown_timeout shutdown_mode |
| @@ -1920,7 +1920,6 @@ LUAG_FUNC(configure) | |||
| 1920 | CONFIG_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 1920 | CONFIG_REGKEY.setValue(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
| 1921 | STACK_CHECK(L, 1); | 1921 | STACK_CHECK(L, 1); |
| 1922 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | 1922 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); |
| 1923 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1924 | // Return the settings table | 1923 | // Return the settings table |
| 1925 | return 1; | 1924 | return 1; |
| 1926 | } | 1925 | } |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 77bcfe2..073e940 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
| @@ -19,9 +19,8 @@ using namespace std::chrono_literals; | |||
| 19 | 19 | ||
| 20 | #define USE_DEBUG_SPEW() 0 | 20 | #define USE_DEBUG_SPEW() 0 |
| 21 | #if USE_DEBUG_SPEW() | 21 | #if USE_DEBUG_SPEW() |
| 22 | extern char const* debugspew_indent; | ||
| 23 | #define INDENT_BEGIN "%.*s " | 22 | #define INDENT_BEGIN "%.*s " |
| 24 | #define INDENT_END , (U ? U->debugspew_indent_depth.load(std::memory_order_relaxed) : 0), debugspew_indent | 23 | #define INDENT_END , (U ? U->debugspew_indent_depth.load(std::memory_order_relaxed) : 0), DebugSpewIndentScope::debugspew_indent |
| 25 | #define DEBUGSPEW_CODE(_code) _code | 24 | #define DEBUGSPEW_CODE(_code) _code |
| 26 | #define DEBUGSPEW_OR_NOT(a_, b_) a_ | 25 | #define DEBUGSPEW_OR_NOT(a_, b_) a_ |
| 27 | #define DEBUGSPEW_PARAM_COMMA(param_) param_, | 26 | #define DEBUGSPEW_PARAM_COMMA(param_) param_, |
| @@ -114,8 +113,8 @@ class StackChecker | |||
| 114 | } | 113 | } |
| 115 | }; | 114 | }; |
| 116 | 115 | ||
| 117 | #define STACK_CHECK_START_REL(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__) | 116 | #define STACK_CHECK_START_REL(L, offset_) StackChecker stackChecker_##L{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} |
| 118 | #define STACK_CHECK_START_ABS(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__) | 117 | #define STACK_CHECK_START_ABS(L, offset_) StackChecker stackChecker_##L{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} |
| 119 | #define STACK_CHECK_RESET_REL(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} | 118 | #define STACK_CHECK_RESET_REL(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} |
| 120 | #define STACK_CHECK_RESET_ABS(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} | 119 | #define STACK_CHECK_RESET_ABS(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} |
| 121 | #define STACK_CHECK(L, offset_) stackChecker_##L.check(offset_, __FILE__, __LINE__) | 120 | #define STACK_CHECK(L, offset_) stackChecker_##L.check(offset_, __FILE__, __LINE__) |
diff --git a/src/state.cpp b/src/state.cpp index 4a5f995..1ba5a77 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
| @@ -191,26 +191,27 @@ static void open1lib(DEBUGSPEW_PARAM_COMMA(Universe* U) lua_State* L, char const | |||
| 191 | // ################################################################################################# | 191 | // ################################################################################################# |
| 192 | 192 | ||
| 193 | // just like lua_xmove, args are (from, to) | 193 | // just like lua_xmove, args are (from, to) |
| 194 | static void copy_one_time_settings(Universe* U, Source L, Dest L2) | 194 | static void copy_one_time_settings(Universe* U, Source L1, Dest L2) |
| 195 | { | 195 | { |
| 196 | STACK_GROW(L, 2); | 196 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 197 | STACK_CHECK_START_REL(L, 0); | 197 | |
| 198 | STACK_GROW(L1, 2); | ||
| 199 | STACK_CHECK_START_REL(L1, 0); | ||
| 198 | STACK_CHECK_START_REL(L2, 0); | 200 | STACK_CHECK_START_REL(L2, 0); |
| 199 | 201 | ||
| 200 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 202 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
| 201 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | ||
| 202 | 203 | ||
| 203 | CONFIG_REGKEY.pushValue(L); // config | 204 | CONFIG_REGKEY.pushValue(L1); // config |
| 204 | // copy settings from from source to destination registry | 205 | // copy settings from from source to destination registry |
| 205 | if (luaG_inter_move(U, L, L2, 1, LookupMode::LaneBody) != InterCopyResult::Success) // // config | 206 | InterCopyContext c{ U, L2, L1, {}, {}, {}, {}, {} }; |
| 207 | if (c.inter_move(1) != InterCopyResult::Success) // // config | ||
| 206 | { | 208 | { |
| 207 | luaL_error( L, "failed to copy settings when loading lanes.core"); // doesn't return | 209 | luaL_error(L1, "failed to copy settings when loading lanes.core"); // doesn't return |
| 208 | } | 210 | } |
| 209 | // set L2:_R[CONFIG_REGKEY] = settings | 211 | // set L2:_R[CONFIG_REGKEY] = settings |
| 210 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config | 212 | CONFIG_REGKEY.setValue(L2, [](lua_State* L) { lua_insert(L, -2); }); // config |
| 211 | STACK_CHECK(L2, 0); | 213 | STACK_CHECK(L2, 0); |
| 212 | STACK_CHECK(L, 0); | 214 | STACK_CHECK(L1, 0); |
| 213 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 214 | } | 215 | } |
| 215 | 216 | ||
| 216 | // ################################################################################################# | 217 | // ################################################################################################# |
| @@ -355,7 +356,7 @@ lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) | |||
| 355 | } | 356 | } |
| 356 | 357 | ||
| 357 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 358 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
| 358 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 359 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 359 | 360 | ||
| 360 | // copy settings (for example because it may contain a Lua on_state_create function) | 361 | // copy settings (for example because it may contain a Lua on_state_create function) |
| 361 | copy_one_time_settings( U, from_, L); | 362 | copy_one_time_settings( U, from_, L); |
| @@ -426,24 +427,23 @@ lua_State* luaG_newstate(Universe* U, Source from_, char const* libs_) | |||
| 426 | STACK_CHECK(L, 1); | 427 | STACK_CHECK(L, 1); |
| 427 | populate_func_lookup_table(L, -1, nullptr); | 428 | populate_func_lookup_table(L, -1, nullptr); |
| 428 | 429 | ||
| 429 | #if 0 && USE_DEBUG_SPEW() | 430 | #if 1 && USE_DEBUG_SPEW() |
| 430 | // dump the lookup database contents | 431 | // dump the lookup database contents |
| 431 | lua_getfield(L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 432 | LOOKUP_REGKEY.pushValue(L); // {} |
| 432 | lua_pushnil(L); // {} nil | 433 | lua_pushnil(L); // {} nil |
| 433 | while (lua_next(L, -2)) // {} k v | 434 | while (lua_next(L, -2)) // {} k v |
| 434 | { | 435 | { |
| 435 | lua_getglobal(L, "print"); // {} k v print | 436 | lua_getglobal(L, "print"); // {} k v print |
| 436 | lua_pushlstring(L, debugspew_indent, U->debugspew_indent_depth.load(std::memory_order_relaxed)); // {} k v print " " | 437 | lua_pushlstring(L, DebugSpewIndentScope::debugspew_indent, U->debugspew_indent_depth.load(std::memory_order_relaxed)); // {} k v print " " |
| 437 | lua_pushvalue(L, -4); // {} k v print " " k | 438 | lua_pushvalue(L, -4); // {} k v print " " k |
| 438 | lua_pushvalue(L, -4); // {} k v print " " k v | 439 | lua_pushvalue(L, -4); // {} k v print " " k v |
| 439 | lua_call(L, 3, 0); // {} k v | 440 | lua_call(L, 3, 0); // {} k v |
| 440 | lua_pop(L, 1); // {} k | 441 | lua_pop(L, 1); // {} k |
| 441 | } | 442 | } |
| 442 | lua_pop(L, 1); // {} | 443 | lua_pop(L, 1); // {} |
| 443 | #endif // USE_DEBUG_SPEW() | 444 | #endif // USE_DEBUG_SPEW() |
| 444 | 445 | ||
| 445 | lua_pop(L, 1); | 446 | lua_pop(L, 1); |
| 446 | STACK_CHECK(L, 0); | 447 | STACK_CHECK(L, 0); |
| 447 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 448 | return L; | 448 | return L; |
| 449 | } | 449 | } |
diff --git a/src/tools.cpp b/src/tools.cpp index c995fdd..ad706be 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
| @@ -38,7 +38,7 @@ THE SOFTWARE. | |||
| 38 | // functions implemented in deep.c | 38 | // functions implemented in deep.c |
| 39 | extern void push_registry_subtable( lua_State* L, UniqueKey key_); | 39 | extern void push_registry_subtable( lua_State* L, UniqueKey key_); |
| 40 | 40 | ||
| 41 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 41 | DEBUGSPEW_CODE(char const* const DebugSpewIndentScope::debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | // ################################################################################################ | 44 | // ################################################################################################ |
| @@ -348,7 +348,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L | |||
| 348 | char const* prevName; | 348 | char const* prevName; |
| 349 | DEBUGSPEW_CODE(char const *newName); | 349 | DEBUGSPEW_CODE(char const *newName); |
| 350 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); | 350 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); |
| 351 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 351 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 352 | 352 | ||
| 353 | STACK_CHECK_START_REL(L, 0); | 353 | STACK_CHECK_START_REL(L, 0); |
| 354 | // first, raise an error if the function is already known | 354 | // first, raise an error if the function is already known |
| @@ -408,7 +408,6 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L | |||
| 408 | } | 408 | } |
| 409 | -- _depth; | 409 | -- _depth; |
| 410 | STACK_CHECK(L, -1); | 410 | STACK_CHECK(L, -1); |
| 411 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 412 | } | 411 | } |
| 413 | 412 | ||
| 414 | // ################################################################################################# | 413 | // ################################################################################################# |
| @@ -423,7 +422,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
| 423 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 422 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
| 424 | int const breadth_first_cache = lua_gettop( L) + 1; | 423 | int const breadth_first_cache = lua_gettop( L) + 1; |
| 425 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); | 424 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); |
| 426 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 425 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 427 | 426 | ||
| 428 | STACK_GROW( L, 6); | 427 | STACK_GROW( L, 6); |
| 429 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 428 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
| @@ -445,7 +444,6 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
| 445 | if( visit_count > 0) | 444 | if( visit_count > 0) |
| 446 | { | 445 | { |
| 447 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); | 446 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); |
| 448 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 449 | return; | 447 | return; |
| 450 | } | 448 | } |
| 451 | 449 | ||
| @@ -500,7 +498,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
| 500 | { | 498 | { |
| 501 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); | 499 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); |
| 502 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); | 500 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); |
| 503 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 501 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 504 | // un-visit this table in case we do need to process it | 502 | // un-visit this table in case we do need to process it |
| 505 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 503 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} |
| 506 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n | 504 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n |
| @@ -523,7 +521,6 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
| 523 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); | 521 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); |
| 524 | lua_pop( L, 1); // ... {_i} {bfc} k | 522 | lua_pop( L, 1); // ... {_i} {bfc} k |
| 525 | STACK_CHECK( L, 2); | 523 | STACK_CHECK( L, 2); |
| 526 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 527 | } | 524 | } |
| 528 | // remove table name from fqn stack | 525 | // remove table name from fqn stack |
| 529 | lua_pushnil( L); // ... {_i} {bfc} nil | 526 | lua_pushnil( L); // ... {_i} {bfc} nil |
| @@ -533,7 +530,6 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U) | |||
| 533 | lua_pop( L, 1); // ... {_i} | 530 | lua_pop( L, 1); // ... {_i} |
| 534 | STACK_CHECK( L, 0); | 531 | STACK_CHECK( L, 0); |
| 535 | // we are done // ... {_i} {bfc} | 532 | // we are done // ... {_i} {bfc} |
| 536 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 537 | } | 533 | } |
| 538 | 534 | ||
| 539 | // ################################################################################################# | 535 | // ################################################################################################# |
| @@ -548,8 +544,8 @@ void populate_func_lookup_table(lua_State* L, int i_, char const* name_) | |||
| 548 | int start_depth = 0; | 544 | int start_depth = 0; |
| 549 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 545 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
| 550 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); | 546 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); |
| 551 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 547 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 552 | STACK_GROW( L, 3); | 548 | STACK_GROW(L, 3); |
| 553 | STACK_CHECK_START_REL(L, 0); | 549 | STACK_CHECK_START_REL(L, 0); |
| 554 | LOOKUP_REGKEY.pushValue(L); // {} | 550 | LOOKUP_REGKEY.pushValue(L); // {} |
| 555 | STACK_CHECK( L, 1); | 551 | STACK_CHECK( L, 1); |
| @@ -599,7 +595,6 @@ void populate_func_lookup_table(lua_State* L, int i_, char const* name_) | |||
| 599 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); | 595 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); |
| 600 | } | 596 | } |
| 601 | STACK_CHECK( L, 0); | 597 | STACK_CHECK( L, 0); |
| 602 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 603 | } | 598 | } |
| 604 | 599 | ||
| 605 | // ################################################################################################# | 600 | // ################################################################################################# |
| @@ -1782,9 +1777,8 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 1782 | else // regular function | 1777 | else // regular function |
| 1783 | { | 1778 | { |
| 1784 | DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", name)); | 1779 | DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", name)); |
| 1785 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1780 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1786 | copy_cached_func(); // ... f | 1781 | copy_cached_func(); // ... f |
| 1787 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1788 | } | 1782 | } |
| 1789 | STACK_CHECK(L2, 1); | 1783 | STACK_CHECK(L2, 1); |
| 1790 | STACK_CHECK(L1, 0); | 1784 | STACK_CHECK(L1, 0); |
| @@ -1872,13 +1866,14 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 1872 | STACK_CHECK_START_REL(L1, 0); // L1 // L2 | 1866 | STACK_CHECK_START_REL(L1, 0); // L1 // L2 |
| 1873 | STACK_CHECK_START_REL(L2, 0); // L1 // L2 | 1867 | STACK_CHECK_START_REL(L2, 0); // L1 // L2 |
| 1874 | 1868 | ||
| 1875 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); | 1869 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); |
| 1876 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1870 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1877 | DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt)])); | ||
| 1878 | 1871 | ||
| 1879 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } | ||
| 1880 | LuaType val_type{ lua_type_as_enum(L1, L1_i) }; | 1872 | LuaType val_type{ lua_type_as_enum(L1, L1_i) }; |
| 1881 | if( ((1 << static_cast<int>(val_type)) & pod_mask) == 0) | 1873 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[static_cast<int>(val_type)], vt_names[static_cast<int>(vt)])); |
| 1874 | |||
| 1875 | // Non-POD can be skipped if its metatable contains { __lanesignore = true } | ||
| 1876 | if (((1 << static_cast<int>(val_type)) & pod_mask) == 0) | ||
| 1882 | { | 1877 | { |
| 1883 | if (lua_getmetatable(L1, L1_i)) // ... mt | 1878 | if (lua_getmetatable(L1, L1_i)) // ... mt |
| 1884 | { | 1879 | { |
| @@ -1974,8 +1969,6 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 1974 | break; | 1969 | break; |
| 1975 | } | 1970 | } |
| 1976 | 1971 | ||
| 1977 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 1978 | |||
| 1979 | STACK_CHECK(L2, ret ? 1 : 0); | 1972 | STACK_CHECK(L2, ret ? 1 : 0); |
| 1980 | STACK_CHECK(L1, 0); | 1973 | STACK_CHECK(L1, 0); |
| 1981 | return ret; | 1974 | return ret; |
| @@ -1983,30 +1976,25 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 1983 | 1976 | ||
| 1984 | // ################################################################################################# | 1977 | // ################################################################################################# |
| 1985 | 1978 | ||
| 1986 | /* | 1979 | // Akin to 'lua_xmove' but copies values between _any_ Lua states. |
| 1987 | * Akin to 'lua_xmove' but copies values between _any_ Lua states. | 1980 | // NOTE: Both the states must be solely in the current OS thread's possession. |
| 1988 | * | 1981 | [[nodiscard]] InterCopyResult InterCopyContext::inter_copy(int n_) const |
| 1989 | * NOTE: Both the states must be solely in the current OS thread's posession. | ||
| 1990 | * | ||
| 1991 | * Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. | ||
| 1992 | */ | ||
| 1993 | [[nodiscard]] InterCopyResult luaG_inter_copy(Universe* U, Source L, Dest L2, int n, LookupMode mode_) | ||
| 1994 | { | 1982 | { |
| 1995 | int const top_L{ lua_gettop(L) }; // ... {}n | 1983 | _ASSERT_L(L1, vt == VT::NORMAL); |
| 1996 | 1984 | ||
| 1997 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END)); | 1985 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy()\n" INDENT_END)); |
| 1998 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 1986 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 1999 | 1987 | ||
| 2000 | if (n > top_L) | 1988 | int const top_L1{ lua_gettop(L1) }; |
| 1989 | if (n_ > top_L1) | ||
| 2001 | { | 1990 | { |
| 2002 | // requesting to copy more than is available? | 1991 | // requesting to copy more than is available? |
| 2003 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); | 1992 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); |
| 2004 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 2005 | return InterCopyResult::NotEnoughValues; | 1993 | return InterCopyResult::NotEnoughValues; |
| 2006 | } | 1994 | } |
| 2007 | 1995 | ||
| 2008 | STACK_CHECK_START_REL(L2, 0); | 1996 | STACK_CHECK_START_REL(L2, 0); |
| 2009 | STACK_GROW(L2, n + 1); | 1997 | STACK_GROW(L2, n_ + 1); |
| 2010 | 1998 | ||
| 2011 | /* | 1999 | /* |
| 2012 | * Make a cache table for the duration of this copy. Collects tables and | 2000 | * Make a cache table for the duration of this copy. Collects tables and |
| @@ -2018,10 +2006,10 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 2018 | 2006 | ||
| 2019 | char tmpBuf[16]; | 2007 | char tmpBuf[16]; |
| 2020 | char const* const pBuf{ U->verboseErrors ? tmpBuf : "?" }; | 2008 | char const* const pBuf{ U->verboseErrors ? tmpBuf : "?" }; |
| 2021 | InterCopyContext c{ U, L2, L, CacheIndex{ top_L2 + 1 }, {}, VT::NORMAL, mode_, pBuf }; | 2009 | InterCopyContext c{ U, L2, L1, CacheIndex{ top_L2 + 1 }, {}, VT::NORMAL, mode, pBuf }; |
| 2022 | bool copyok{ true }; | 2010 | bool copyok{ true }; |
| 2023 | STACK_CHECK_START_REL(L, 0); | 2011 | STACK_CHECK_START_REL(L1, 0); |
| 2024 | for (int i = top_L - n + 1, j = 1; i <= top_L; ++i, ++j) | 2012 | for (int i{ top_L1 - n_ + 1 }, j{ 1 }; i <= top_L1; ++i, ++j) |
| 2025 | { | 2013 | { |
| 2026 | if (U->verboseErrors) | 2014 | if (U->verboseErrors) |
| 2027 | { | 2015 | { |
| @@ -2034,13 +2022,11 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 2034 | break; | 2022 | break; |
| 2035 | } | 2023 | } |
| 2036 | } | 2024 | } |
| 2037 | STACK_CHECK(L, 0); | 2025 | STACK_CHECK(L1, 0); |
| 2038 | |||
| 2039 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 2040 | 2026 | ||
| 2041 | if (copyok) | 2027 | if (copyok) |
| 2042 | { | 2028 | { |
| 2043 | STACK_CHECK(L2, n + 1); | 2029 | STACK_CHECK(L2, n_ + 1); |
| 2044 | // Remove the cache table. Persistent caching would cause i.e. multiple | 2030 | // Remove the cache table. Persistent caching would cause i.e. multiple |
| 2045 | // messages passed in the same table to use the same table also in receiving end. | 2031 | // messages passed in the same table to use the same table also in receiving end. |
| 2046 | lua_remove(L2, top_L2 + 1); | 2032 | lua_remove(L2, top_L2 + 1); |
| @@ -2055,74 +2041,108 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; | |||
| 2055 | 2041 | ||
| 2056 | // ################################################################################################# | 2042 | // ################################################################################################# |
| 2057 | 2043 | ||
| 2058 | [[nodiscard]] InterCopyResult luaG_inter_move(Universe* U, Source L, Dest L2, int n_, LookupMode mode_) | 2044 | [[nodiscard]] InterCopyResult InterCopyContext::inter_move(int n_) const |
| 2059 | { | 2045 | { |
| 2060 | InterCopyResult const ret{ luaG_inter_copy(U, L, L2, n_, mode_) }; | 2046 | InterCopyResult const ret{ inter_copy(n_) }; |
| 2061 | lua_pop( L, n_); | 2047 | lua_pop( L1, n_); |
| 2062 | return ret; | 2048 | return ret; |
| 2063 | } | 2049 | } |
| 2064 | 2050 | ||
| 2065 | // ################################################################################################# | 2051 | // ################################################################################################# |
| 2066 | 2052 | ||
| 2067 | // transfers stuff from L->_G["package"] to L2->_G["package"] | 2053 | // transfers stuff from L1->_G["package"] to L2->_G["package"] |
| 2068 | // returns InterCopyResult::Success if everything is fine | 2054 | // returns InterCopyResult::Success if everything is fine |
| 2069 | // returns InterCopyResult::Error if pushed an error message in L | 2055 | // returns InterCopyResult::Error if pushed an error message in L1 |
| 2070 | // else raise an error in L | 2056 | // else raise an error in L1 |
| 2071 | [[nodiscard]] InterCopyResult luaG_inter_copy_package(Universe* U, Source L, Dest L2, int package_idx_, LookupMode mode_) | 2057 | [[nodiscard]] InterCopyResult InterCopyContext::inter_copy_package() const |
| 2072 | { | 2058 | { |
| 2073 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 2059 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "InterCopyContext::inter_copy_package()\n" INDENT_END)); |
| 2074 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 2060 | |
| 2075 | // package | 2061 | class OnExit |
| 2076 | STACK_CHECK_START_REL(L, 0); | ||
| 2077 | STACK_CHECK_START_REL(L2, 0); | ||
| 2078 | package_idx_ = lua_absindex(L, package_idx_); | ||
| 2079 | if (lua_type(L, package_idx_) != LUA_TTABLE) | ||
| 2080 | { | 2062 | { |
| 2081 | lua_pushfstring(L, "expected package as table, got %s", luaL_typename(L, package_idx_)); | 2063 | private: |
| 2082 | STACK_CHECK(L, 1); | 2064 | |
| 2065 | lua_State* const L2; | ||
| 2066 | int const top_L2; | ||
| 2067 | DEBUGSPEW_CODE(DebugSpewIndentScope m_scope); | ||
| 2068 | |||
| 2069 | public: | ||
| 2070 | |||
| 2071 | OnExit(Universe* U_, lua_State* L2_) | ||
| 2072 | : L2{ L2_ } | ||
| 2073 | , top_L2{ lua_gettop(L2) } | ||
| 2074 | DEBUGSPEW_COMMA_PARAM(m_scope{ U_ }) | ||
| 2075 | { | ||
| 2076 | } | ||
| 2077 | |||
| 2078 | ~OnExit() | ||
| 2079 | { | ||
| 2080 | lua_settop(L2, top_L2); | ||
| 2081 | } | ||
| 2082 | } onExit{ U, L2 }; | ||
| 2083 | |||
| 2084 | STACK_CHECK_START_REL(L1, 0); | ||
| 2085 | if (lua_type_as_enum(L1, L1_i) != LuaType::TABLE) | ||
| 2086 | { | ||
| 2087 | lua_pushfstring(L1, "expected package as table, got %s", luaL_typename(L1, L1_i)); | ||
| 2088 | STACK_CHECK(L1, 1); | ||
| 2083 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 2089 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 2084 | if (mode_ == LookupMode::LaneBody) | 2090 | if (mode == LookupMode::LaneBody) |
| 2085 | { | 2091 | { |
| 2086 | lua_error(L); // doesn't return | 2092 | lua_error(L1); // doesn't return |
| 2087 | } | 2093 | } |
| 2088 | return InterCopyResult::Error; | 2094 | return InterCopyResult::Error; |
| 2089 | } | 2095 | } |
| 2090 | lua_getglobal(L2, "package"); | 2096 | lua_getglobal(L2, "package"); // TODO: use _R._LOADED.package instead of _G.package |
| 2091 | if (!lua_isnil(L2, -1)) // package library not loaded: do nothing | 2097 | if (lua_isnil(L2, -1)) // package library not loaded: do nothing |
| 2092 | { | 2098 | { |
| 2093 | // package.loaders is renamed package.searchers in Lua 5.2 | 2099 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); |
| 2094 | // but don't copy it anyway, as the function names change depending on the slot index! | 2100 | STACK_CHECK(L1, 0); |
| 2095 | // users should provide an on_state_create function to setup custom loaders instead | 2101 | return InterCopyResult::Success; |
| 2096 | // don't copy package.preload in keeper states (they don't know how to translate functions) | 2102 | } |
| 2097 | char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; | 2103 | |
| 2098 | for (char const* const entry : entries) | 2104 | InterCopyResult result{ InterCopyResult::Success }; |
| 2105 | // package.loaders is renamed package.searchers in Lua 5.2 | ||
| 2106 | // but don't copy it anyway, as the function names change depending on the slot index! | ||
| 2107 | // users should provide an on_state_create function to setup custom loaders instead | ||
| 2108 | // don't copy package.preload in keeper states (they don't know how to translate functions) | ||
| 2109 | char const* entries[] = { "path", "cpath", (mode == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; | ||
| 2110 | for (char const* const entry : entries) | ||
| 2111 | { | ||
| 2112 | if (!entry) | ||
| 2113 | { | ||
| 2114 | continue; | ||
| 2115 | } | ||
| 2116 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entry)); | ||
| 2117 | lua_getfield(L1, L1_i, entry); | ||
| 2118 | if (lua_isnil(L1, -1)) | ||
| 2119 | { | ||
| 2120 | lua_pop(L1, 1); | ||
| 2121 | } | ||
| 2122 | else | ||
| 2099 | { | 2123 | { |
| 2100 | if (!entry) | ||
| 2101 | { | 2124 | { |
| 2102 | continue; | 2125 | DEBUGSPEW_CODE(DebugSpewIndentScope scope{ U }); |
| 2126 | result = inter_move(1); // moves the entry to L2 | ||
| 2127 | STACK_CHECK(L1, 0); | ||
| 2103 | } | 2128 | } |
| 2104 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entry)); | 2129 | if (result == InterCopyResult::Success) |
| 2105 | lua_getfield(L, package_idx_, entry); | ||
| 2106 | if (lua_isnil(L, -1)) | ||
| 2107 | { | 2130 | { |
| 2108 | lua_pop(L, 1); | 2131 | lua_setfield(L2, -2, entry); // set package[entry] |
| 2109 | } | 2132 | } |
| 2110 | else | 2133 | else |
| 2111 | { | 2134 | { |
| 2112 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); | 2135 | lua_pushfstring(L1, "failed to copy package entry %s", entry); |
| 2113 | std::ignore = luaG_inter_move(U, L, L2, 1, mode_); // moves the entry to L2 | 2136 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
| 2114 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | 2137 | if (mode == LookupMode::LaneBody) |
| 2115 | lua_setfield(L2, -2, entry); // set package[entry] | 2138 | { |
| 2139 | lua_error(L1); // doesn't return | ||
| 2140 | } | ||
| 2141 | lua_pop(L1, 1); | ||
| 2142 | break; | ||
| 2116 | } | 2143 | } |
| 2117 | } | 2144 | } |
| 2118 | } | 2145 | } |
| 2119 | else | 2146 | STACK_CHECK(L1, 0); |
| 2120 | { | 2147 | return result; |
| 2121 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); | ||
| 2122 | } | ||
| 2123 | lua_pop(L2, 1); | ||
| 2124 | STACK_CHECK(L2, 0); | ||
| 2125 | STACK_CHECK(L, 0); | ||
| 2126 | DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); | ||
| 2127 | return InterCopyResult::Success; | ||
| 2128 | } | 2148 | } |
diff --git a/src/tools.h b/src/tools.h index e14ac65..06646d3 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -19,7 +19,7 @@ void push_registry_subtable(lua_State* L, UniqueKey key_); | |||
| 19 | 19 | ||
| 20 | enum class VT | 20 | enum class VT |
| 21 | { | 21 | { |
| 22 | NORMAL, | 22 | NORMAL, // keep this one first so that it's the value we get when we default-construct |
| 23 | KEY, | 23 | KEY, |
| 24 | METATABLE | 24 | METATABLE |
| 25 | }; | 25 | }; |
| @@ -60,14 +60,16 @@ struct InterCopyContext | |||
| 60 | void copy_func() const; | 60 | void copy_func() const; |
| 61 | void copy_cached_func() const; | 61 | void copy_cached_func() const; |
| 62 | void inter_copy_keyvaluepair() const; | 62 | void inter_copy_keyvaluepair() const; |
| 63 | |||
| 64 | public: | ||
| 65 | |||
| 66 | [[nodiscard]] InterCopyResult inter_copy_package() const; | ||
| 67 | [[nodiscard]] InterCopyResult inter_copy(int n_) const; | ||
| 68 | [[nodiscard]] InterCopyResult inter_move(int n_) const; | ||
| 63 | }; | 69 | }; |
| 64 | 70 | ||
| 65 | // ################################################################################################ | 71 | // ################################################################################################ |
| 66 | 72 | ||
| 67 | [[nodiscard]] InterCopyResult luaG_inter_copy_package(Universe* U, Source L, Dest L2, int package_idx_, LookupMode mode_); | ||
| 68 | [[nodiscard]] InterCopyResult luaG_inter_copy(Universe* U, Source L, Dest L2, int n, LookupMode mode_); | ||
| 69 | [[nodiscard]] InterCopyResult luaG_inter_move(Universe* U, Source L, Dest L2, int n, LookupMode mode_); | ||
| 70 | |||
| 71 | [[nodiscard]] int luaG_nameof(lua_State* L); | 73 | [[nodiscard]] int luaG_nameof(lua_State* L); |
| 72 | 74 | ||
| 73 | void populate_func_lookup_table(lua_State* L, int _i, char const* _name); | 75 | void populate_func_lookup_table(lua_State* L, int _i, char const* _name); |
diff --git a/src/universe.h b/src/universe.h index 113ed21..eb85133 100644 --- a/src/universe.h +++ b/src/universe.h | |||
| @@ -188,3 +188,31 @@ class Universe | |||
| 188 | [[nodiscard]] Universe* universe_get(lua_State* L); | 188 | [[nodiscard]] Universe* universe_get(lua_State* L); |
| 189 | [[nodiscard]] Universe* universe_create(lua_State* L); | 189 | [[nodiscard]] Universe* universe_create(lua_State* L); |
| 190 | void universe_store(lua_State* L, Universe* U); | 190 | void universe_store(lua_State* L, Universe* U); |
| 191 | |||
| 192 | // ################################################################################################ | ||
| 193 | |||
| 194 | #if USE_DEBUG_SPEW() | ||
| 195 | class DebugSpewIndentScope | ||
| 196 | { | ||
| 197 | private: | ||
| 198 | |||
| 199 | Universe* const U; | ||
| 200 | |||
| 201 | public: | ||
| 202 | |||
| 203 | static char const* const debugspew_indent; | ||
| 204 | |||
| 205 | DebugSpewIndentScope(Universe* U_) | ||
| 206 | : U{ U_ } | ||
| 207 | { | ||
| 208 | if (U) | ||
| 209 | U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed); | ||
| 210 | } | ||
| 211 | |||
| 212 | ~DebugSpewIndentScope() | ||
| 213 | { | ||
| 214 | if (U) | ||
| 215 | U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed); | ||
| 216 | } | ||
| 217 | }; | ||
| 218 | #endif // USE_DEBUG_SPEW() | ||
