diff options
-rw-r--r-- | deep_test/deep_test.args.json | 8 | ||||
-rw-r--r-- | deep_test/deep_test.vcxproj.user | 4 | ||||
-rw-r--r-- | src/compat.cpp | 28 | ||||
-rw-r--r-- | src/compat.h | 4 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 36 |
5 files changed, 47 insertions, 33 deletions
diff --git a/deep_test/deep_test.args.json b/deep_test/deep_test.args.json index fbef41c..a1654a6 100644 --- a/deep_test/deep_test.args.json +++ b/deep_test/deep_test.args.json | |||
@@ -7,6 +7,14 @@ | |||
7 | "Command": "DeepTest", | 7 | "Command": "DeepTest", |
8 | "Items": [ | 8 | "Items": [ |
9 | { | 9 | { |
10 | "Id": "d762af99-3873-4084-a9a1-ae42f57802a0", | ||
11 | "Command": "deeptest.lua" | ||
12 | }, | ||
13 | { | ||
14 | "Id": "a8d142a9-be5f-459d-8b80-61c7f3a263a1", | ||
15 | "Command": "-e \"REPEAT=1000, SIZE=1000\" -i deeptest.lua" | ||
16 | }, | ||
17 | { | ||
10 | "Id": "10e30bb2-dc23-4882-b918-b5939c14e588", | 18 | "Id": "10e30bb2-dc23-4882-b918-b5939c14e588", |
11 | "Command": "-e \"REPEAT=1000, SIZE=1000 DEEP='stack_abuser'\" -i deeptest.lua" | 19 | "Command": "-e \"REPEAT=1000, SIZE=1000 DEEP='stack_abuser'\" -i deeptest.lua" |
12 | } | 20 | } |
diff --git a/deep_test/deep_test.vcxproj.user b/deep_test/deep_test.vcxproj.user index ed75184..257d4e9 100644 --- a/deep_test/deep_test.vcxproj.user +++ b/deep_test/deep_test.vcxproj.user | |||
@@ -36,9 +36,9 @@ | |||
36 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> | 36 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> |
37 | <LocalDebuggerCommand>$(SolutionDir)..\framework\lua54.exe</LocalDebuggerCommand> | 37 | <LocalDebuggerCommand>$(SolutionDir)..\framework\lua54.exe</LocalDebuggerCommand> |
38 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> | 38 | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> |
39 | <LocalDebuggerCommandArguments>-e "REPEAT=1000, SIZE=1000" -i deeptest.lua</LocalDebuggerCommandArguments> | 39 | <LocalDebuggerCommandArguments>deeptest.lua</LocalDebuggerCommandArguments> |
40 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> | 40 | <LocalDebuggerWorkingDirectory>$(SolutionDir)Lanes\lanes\deep_test\</LocalDebuggerWorkingDirectory> |
41 | <RemoteDebuggerCommandArguments>-e "REPEAT=1000, SIZE=1000" -i deeptest.lua</RemoteDebuggerCommandArguments> | 41 | <RemoteDebuggerCommandArguments>deeptest.lua</RemoteDebuggerCommandArguments> |
42 | </PropertyGroup> | 42 | </PropertyGroup> |
43 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug MoonJIT|x64'"> | 43 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug MoonJIT|x64'"> |
44 | <LocalDebuggerCommand>$(SolutionDir)..\MoonJIT\bin\$(Platform)\moonjit.exe</LocalDebuggerCommand> | 44 | <LocalDebuggerCommand>$(SolutionDir)..\MoonJIT\bin\$(Platform)\moonjit.exe</LocalDebuggerCommand> |
diff --git a/src/compat.cpp b/src/compat.cpp index f0a3685..e1e7488 100644 --- a/src/compat.cpp +++ b/src/compat.cpp | |||
@@ -3,25 +3,37 @@ | |||
3 | 3 | ||
4 | #include "macros_and_utils.h" | 4 | #include "macros_and_utils.h" |
5 | 5 | ||
6 | |||
7 | // ################################################################################################# | ||
8 | // ###################################### Lua 5.1 / 5.2 / 5.3 ###################################### | ||
9 | // ################################################################################################# | 6 | // ################################################################################################# |
10 | 7 | ||
8 | int luaG_getalluservalues(lua_State* const L_, int const idx_) | ||
9 | { | ||
10 | STACK_CHECK_START_REL(L_, 0); | ||
11 | int const _idx{ luaG_absindex(L_, idx_) }; | ||
12 | int _nuv{ 0 }; | ||
13 | do { | ||
14 | // we don't know how many uservalues we are going to extract, there might be a lot... | ||
15 | STACK_GROW(L_, 1); | ||
16 | } while (lua_getiuservalue(L_, _idx, ++_nuv) != LUA_TNONE); // L_: ... [uv]* nil | ||
17 | // last call returned TNONE and pushed nil, that we don't need | ||
18 | lua_pop(L_, 1); // L_: ... [uv]* | ||
19 | --_nuv; | ||
20 | STACK_CHECK(L_, _nuv); | ||
21 | return _nuv; | ||
22 | } | ||
11 | 23 | ||
12 | // ################################################################################################# | 24 | // ################################################################################################# |
13 | 25 | ||
14 | // a small helper to obtain a module's table from the registry instead of relying on the presence of _G["<name>"] | 26 | // a small helper to obtain a module's table from the registry instead of relying on the presence of _G["<name>"] |
15 | LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_) | 27 | LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) |
16 | { | 28 | { |
17 | STACK_CHECK_START_REL(L_, 0); | 29 | STACK_CHECK_START_REL(L_, 0); |
18 | LuaType _type{ luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil | 30 | LuaType _type{ luaG_getfield(L_, LUA_REGISTRYINDEX, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil |
19 | if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil | 31 | if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil |
20 | STACK_CHECK(L_, 1); | 32 | STACK_CHECK(L_, 1); |
21 | return _type; | 33 | return _type; |
22 | } | 34 | } |
23 | _type = luaG_getfield(L_, -1, name_); // L_: _R._LOADED {module}|nil | 35 | _type = luaG_getfield(L_, -1, name_); // L_: _R._LOADED {module}|nil |
24 | lua_remove(L_, -2); // L_: {module}|nil | 36 | lua_remove(L_, -2); // L_: {module}|nil |
25 | STACK_CHECK(L_, 1); | 37 | STACK_CHECK(L_, 1); |
26 | return _type; | 38 | return _type; |
27 | } | 39 | } |
diff --git a/src/compat.h b/src/compat.h index 8963ef7..d84447b 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -292,6 +292,10 @@ inline int luaG_dump(lua_State* L_, lua_Writer writer_, void* data_, int strip_) | |||
292 | 292 | ||
293 | // ------------------------------------------------------------------------------------------------- | 293 | // ------------------------------------------------------------------------------------------------- |
294 | 294 | ||
295 | int luaG_getalluservalues(lua_State* L_, int idx_); | ||
296 | |||
297 | // ------------------------------------------------------------------------------------------------- | ||
298 | |||
295 | LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); | 299 | LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); |
296 | 300 | ||
297 | // ------------------------------------------------------------------------------------------------- | 301 | // ------------------------------------------------------------------------------------------------- |
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 8142b6a..b2eda83 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -653,13 +653,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
653 | int const _mt{ luaG_absindex(L1, -2) }; // L1: ... mt __lanesclone | 653 | int const _mt{ luaG_absindex(L1, -2) }; // L1: ... mt __lanesclone |
654 | size_t const userdata_size{ lua_rawlen(L1, _L1_i) }; | 654 | size_t const userdata_size{ lua_rawlen(L1, _L1_i) }; |
655 | // extract all the uservalues, but don't transfer them yet | 655 | // extract all the uservalues, but don't transfer them yet |
656 | int _uvi{ 0 }; | 656 | int const _nuv{ luaG_getalluservalues(L1, _L1_i) }; // L1: ... mt __lanesclone [uv]* |
657 | while (lua_getiuservalue(L1, _L1_i, ++_uvi) != LUA_TNONE) {} // L1: ... mt __lanesclone [uv]+ nil | ||
658 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now | ||
659 | lua_pop(L1, 1); // L1: ... mt __lanesclone [uv]+ | ||
660 | --_uvi; | ||
661 | // create the clone userdata with the required number of uservalue slots | 657 | // create the clone userdata with the required number of uservalue slots |
662 | void* const _clone{ lua_newuserdatauv(L2, userdata_size, _uvi) }; // L2: ... u | 658 | void* const _clone{ lua_newuserdatauv(L2, userdata_size, _nuv) }; // L2: ... u |
663 | // copy the metatable in the target state, and give it to the clone we put there | 659 | // copy the metatable in the target state, and give it to the clone we put there |
664 | InterCopyContext _c{ U, L2, L1, L2_cache_i, SourceIndex{ _mt }, VT::NORMAL, mode, name }; | 660 | InterCopyContext _c{ U, L2, L1, L2_cache_i, SourceIndex{ _mt }, VT::NORMAL, mode, name }; |
665 | if (_c.inter_copy_one()) { // L2: ... u mt|sentinel | 661 | if (_c.inter_copy_one()) { // L2: ... u mt|sentinel |
@@ -687,6 +683,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
687 | lua_getupvalue(L2, -1, 2); // L2: ... userdata_clone_sentinel u | 683 | lua_getupvalue(L2, -1, 2); // L2: ... userdata_clone_sentinel u |
688 | } | 684 | } |
689 | // assign uservalues | 685 | // assign uservalues |
686 | int _uvi{ _nuv }; | ||
690 | while (_uvi > 0) { | 687 | while (_uvi > 0) { |
691 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 688 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; |
692 | if (!_c.inter_copy_one()) { // L2: ... u uv | 689 | if (!_c.inter_copy_one()) { // L2: ... u uv |
@@ -732,12 +729,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
732 | STACK_CHECK_START_REL(L2, 0); | 729 | STACK_CHECK_START_REL(L2, 0); |
733 | 730 | ||
734 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail | 731 | // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail |
735 | int _nuv{ 0 }; | 732 | int const _nuv{ luaG_getalluservalues(L1, L1_i) }; // L1: ... deep ... [uv]* |
736 | while (lua_getiuservalue(L1, L1_i, _nuv + 1) != LUA_TNONE) { // L1: ... deep ... [uv]* nil | ||
737 | ++_nuv; | ||
738 | } | ||
739 | // last call returned TNONE and pushed nil, that we don't need | ||
740 | lua_pop(L1, 1); // L1: ... deep ... [uv]* | ||
741 | STACK_CHECK(L1, _nuv); | 733 | STACK_CHECK(L1, _nuv); |
742 | 734 | ||
743 | DeepPrelude* const _deep{ *luaG_tofulluserdata<DeepPrelude*>(L1, L1_i) }; | 735 | DeepPrelude* const _deep{ *luaG_tofulluserdata<DeepPrelude*>(L1, L1_i) }; |
@@ -747,16 +739,17 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
747 | { | 739 | { |
748 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; | 740 | InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name }; |
749 | int const _clone_i{ lua_gettop(L2) }; | 741 | int const _clone_i{ lua_gettop(L2) }; |
750 | // TODO: STACK_GROW(L2, _nuv), and same for L1 above and everywhere we use lua_getiuservalue | 742 | STACK_GROW(L2, _nuv); |
751 | while (_nuv) { | 743 | int _uvi{ _nuv }; |
744 | while (_uvi) { | ||
752 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 745 | _c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; |
753 | if (!_c.inter_copy_one()) { // L1: ... deep ... [uv]* L2: deep uv | 746 | if (!_c.inter_copy_one()) { // L1: ... deep ... [uv]* L2: deep uv |
754 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); | 747 | raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); |
755 | } | 748 | } |
756 | lua_pop(L1, 1); // L1: ... deep ... [uv]* | 749 | lua_pop(L1, 1); // L1: ... deep ... [uv]* |
757 | // this pops the value from the stack | 750 | // this pops the value from the stack |
758 | lua_setiuservalue(L2, _clone_i, _nuv); // L2: deep | 751 | lua_setiuservalue(L2, _clone_i, _uvi); // L2: deep |
759 | --_nuv; | 752 | --_uvi; |
760 | } // loop done: no uv remains on L1 stack // L1: ... deep ... | 753 | } // loop done: no uv remains on L1 stack // L1: ... deep ... |
761 | } | 754 | } |
762 | 755 | ||
@@ -818,14 +811,10 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
818 | size_t const userdata_size{ lua_rawlen(L1, -1) }; | 811 | size_t const userdata_size{ lua_rawlen(L1, -1) }; |
819 | { | 812 | { |
820 | // extract uservalues (don't transfer them yet) | 813 | // extract uservalues (don't transfer them yet) |
821 | int _uvi = 0; | 814 | int const _nuv{ luaG_getalluservalues(L1, source_i) }; // L1: ... u [uv]* |
822 | while (lua_getiuservalue(L1, source_i, ++_uvi) != LUA_TNONE) {} // L1: ... u uv | 815 | STACK_CHECK(L1, _nuv + 1); |
823 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now | ||
824 | lua_pop(L1, 1); // L1: ... u [uv]* | ||
825 | --_uvi; | ||
826 | STACK_CHECK(L1, _uvi + 1); | ||
827 | // create the clone userdata with the required number of uservalue slots | 816 | // create the clone userdata with the required number of uservalue slots |
828 | _clone = lua_newuserdatauv(L2, userdata_size, _uvi); // L2: ... mt u | 817 | _clone = lua_newuserdatauv(L2, userdata_size, _nuv); // L2: ... mt u |
829 | // add it in the cache | 818 | // add it in the cache |
830 | lua_pushlightuserdata(L2, _source); // L2: ... mt u source | 819 | lua_pushlightuserdata(L2, _source); // L2: ... mt u source |
831 | lua_pushvalue(L2, -2); // L2: ... mt u source u | 820 | lua_pushvalue(L2, -2); // L2: ... mt u source u |
@@ -835,6 +824,7 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
835 | lua_setmetatable(L2, -2); // L2: ... mt u | 824 | lua_setmetatable(L2, -2); // L2: ... mt u |
836 | // transfer and assign uservalues | 825 | // transfer and assign uservalues |
837 | InterCopyContext c{ *this }; | 826 | InterCopyContext c{ *this }; |
827 | int _uvi{ _nuv }; | ||
838 | while (_uvi > 0) { | 828 | while (_uvi > 0) { |
839 | c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; | 829 | c.L1_i = SourceIndex{ luaG_absindex(L1, -1) }; |
840 | if (!c.inter_copy_one()) { // L2: ... mt u uv | 830 | if (!c.inter_copy_one()) { // L2: ... mt u uv |