aboutsummaryrefslogtreecommitdiff
path: root/src/tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.cpp')
-rw-r--r--src/tools.cpp691
1 files changed, 348 insertions, 343 deletions
diff --git a/src/tools.cpp b/src/tools.cpp
index df7602e..a0a3018 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -31,24 +31,12 @@ THE SOFTWARE.
31=============================================================================== 31===============================================================================
32*/ 32*/
33 33
34#include <stdio.h>
35#include <assert.h>
36#include <string.h>
37#include <ctype.h>
38#include <stdlib.h>
39#if !defined(__APPLE__)
40#include <malloc.h>
41#endif // __APPLE__
42
43#include "tools.h" 34#include "tools.h"
44#include "compat.h" 35
45#include "universe.h" 36#include "universe.h"
46#include "keeper.h"
47#include "lanes.h"
48#include "uniquekey.h"
49 37
50// functions implemented in deep.c 38// functions implemented in deep.c
51extern bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_); 39extern bool copydeep(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode mode_, char const* upName_);
52extern void push_registry_subtable( lua_State* L, UniqueKey key_); 40extern void push_registry_subtable( lua_State* L, UniqueKey key_);
53 41
54DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); 42DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+");
@@ -116,7 +104,7 @@ void luaG_dump( lua_State* L)
116 104
117 for( i = 1; i <= top; ++ i) 105 for( i = 1; i <= top; ++ i)
118 { 106 {
119 int type = lua_type( L, i); 107 LuaType type{ lua_type_as_enum(L, i) };
120 108
121 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type)); 109 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type));
122 110
@@ -156,7 +144,7 @@ void luaG_dump( lua_State* L)
156// ################################################################################################ 144// ################################################################################################
157 145
158// same as PUC-Lua l_alloc 146// same as PUC-Lua l_alloc
159extern "C" static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_) 147extern "C" [[nodiscard]] static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused]] void* ptr_, [[maybe_unused]] size_t osize_, size_t nsize_)
160{ 148{
161 if (nsize_ == 0) 149 if (nsize_ == 0)
162 { 150 {
@@ -171,7 +159,7 @@ extern "C" static void* libc_lua_Alloc([[maybe_unused]] void* ud, [[maybe_unused
171 159
172// ################################################################################################# 160// #################################################################################################
173 161
174static int luaG_provide_protected_allocator(lua_State* L) 162[[nodiscard]] static int luaG_provide_protected_allocator(lua_State* L)
175{ 163{
176 Universe* const U{ universe_get(L) }; 164 Universe* const U{ universe_get(L) };
177 // push a new full userdata on the stack, giving access to the universe's protected allocator 165 // push a new full userdata on the stack, giving access to the universe's protected allocator
@@ -246,7 +234,7 @@ void initialize_allocator_function(Universe* U, lua_State* L)
246 234
247// ################################################################################################ 235// ################################################################################################
248 236
249static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud) 237[[nodiscard]] static int dummy_writer(lua_State* L, void const* p, size_t sz, void* ud)
250{ 238{
251 (void)L; (void)p; (void)sz; (void) ud; // unused 239 (void)L; (void)p; (void)sz; (void) ud; // unused
252 return 666; 240 return 666;
@@ -303,7 +291,7 @@ FuncSubType luaG_getfuncsubtype( lua_State *L, int _i)
303 291
304// ################################################################################################# 292// #################################################################################################
305 293
306static lua_CFunction luaG_tocfunction(lua_State* L, int _i, FuncSubType* _out) 294[[nodiscard]] static lua_CFunction luaG_tocfunction(lua_State* L, int _i, FuncSubType* _out)
307{ 295{
308 lua_CFunction p = lua_tocfunction( L, _i); 296 lua_CFunction p = lua_tocfunction( L, _i);
309 *_out = luaG_getfuncsubtype( L, _i); 297 *_out = luaG_getfuncsubtype( L, _i);
@@ -316,7 +304,7 @@ static constexpr UniqueKey LOOKUPCACHE_REGKEY{ 0x837a68dfc6fcb716ull };
316// ################################################################################################# 304// #################################################################################################
317 305
318// inspired from tconcat() in ltablib.c 306// inspired from tconcat() in ltablib.c
319static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) 307[[nodiscard]] static char const* luaG_pushFQN(lua_State* L, int t, int last, size_t* length)
320{ 308{
321 int i = 1; 309 int i = 1;
322 luaL_Buffer b; 310 luaL_Buffer b;
@@ -350,7 +338,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length)
350 * if we already had an entry of type [o] = ..., replace the name if the new one is shorter 338 * if we already had an entry of type [o] = ..., replace the name if the new one is shorter
351 * pops the processed object from the stack 339 * pops the processed object from the stack
352 */ 340 */
353static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth) 341static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth)
354{ 342{
355 // slot 1 in the stack contains the table that receives everything we found 343 // slot 1 in the stack contains the table that receives everything we found
356 int const dest = _ctx_base; 344 int const dest = _ctx_base;
@@ -359,9 +347,9 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State*
359 347
360 size_t prevNameLength, newNameLength; 348 size_t prevNameLength, newNameLength;
361 char const* prevName; 349 char const* prevName;
362 DEBUGSPEW_CODE( char const *newName); 350 DEBUGSPEW_CODE(char const *newName);
363 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); 351 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END));
364 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 352 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
365 353
366 STACK_CHECK_START_REL(L, 0); 354 STACK_CHECK_START_REL(L, 0);
367 // first, raise an error if the function is already known 355 // first, raise an error if the function is already known
@@ -374,7 +362,7 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State*
374 ++ _depth; 362 ++ _depth;
375 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name? 363 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name?
376 // generate name 364 // generate name
377 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n" 365 DEBUGSPEW_OR_NOT(newName, std::ignore) = luaG_pushFQN(L, fqn, _depth, &newNameLength);// ... {bfc} k o name? "f.q.n"
378 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order 366 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order
379 // on different VMs even when the tables are populated the exact same way. 367 // on different VMs even when the tables are populated the exact same way.
380 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), 368 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL),
@@ -420,8 +408,8 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State*
420 lua_rawseti( L, fqn, _depth); // ... {bfc} k 408 lua_rawseti( L, fqn, _depth); // ... {bfc} k
421 } 409 }
422 -- _depth; 410 -- _depth;
423 STACK_CHECK( L, -1); 411 STACK_CHECK(L, -1);
424 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 412 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
425} 413}
426 414
427// ################################################################################################# 415// #################################################################################################
@@ -435,8 +423,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
435 int const cache = _ctx_base + 2; 423 int const cache = _ctx_base + 2;
436 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) 424 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search)
437 int const breadth_first_cache = lua_gettop( L) + 1; 425 int const breadth_first_cache = lua_gettop( L) + 1;
438 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END)); 426 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END));
439 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 427 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
440 428
441 STACK_GROW( L, 6); 429 STACK_GROW( L, 6);
442 // slot _i contains a table where we search for functions (or a full userdata with a metatable) 430 // slot _i contains a table where we search for functions (or a full userdata with a metatable)
@@ -457,8 +445,8 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
457 STACK_CHECK( L, 0); 445 STACK_CHECK( L, 0);
458 if( visit_count > 0) 446 if( visit_count > 0)
459 { 447 {
460 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); 448 DEBUGSPEW_CODE(fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END));
461 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 449 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
462 return; 450 return;
463 } 451 }
464 452
@@ -513,7 +501,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
513 { 501 {
514 DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); 502 DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string");
515 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); 503 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key));
516 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 504 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
517 // un-visit this table in case we do need to process it 505 // un-visit this table in case we do need to process it
518 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} 506 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
519 lua_rawget( L, cache); // ... {_i} {bfc} k {} n 507 lua_rawget( L, cache); // ... {_i} {bfc} k {} n
@@ -536,7 +524,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
536 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); 524 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth);
537 lua_pop( L, 1); // ... {_i} {bfc} k 525 lua_pop( L, 1); // ... {_i} {bfc} k
538 STACK_CHECK( L, 2); 526 STACK_CHECK( L, 2);
539 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 527 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
540 } 528 }
541 // remove table name from fqn stack 529 // remove table name from fqn stack
542 lua_pushnil( L); // ... {_i} {bfc} nil 530 lua_pushnil( L); // ... {_i} {bfc} nil
@@ -546,7 +534,7 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
546 lua_pop( L, 1); // ... {_i} 534 lua_pop( L, 1); // ... {_i}
547 STACK_CHECK( L, 0); 535 STACK_CHECK( L, 0);
548 // we are done // ... {_i} {bfc} 536 // we are done // ... {_i} {bfc}
549 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 537 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
550} 538}
551 539
552// ################################################################################################# 540// #################################################################################################
@@ -554,14 +542,14 @@ static void populate_func_lookup_table_recur(DEBUGSPEW_PARAM_COMMA(Universe* U)
554/* 542/*
555 * create a "fully.qualified.name" <-> function equivalence database 543 * create a "fully.qualified.name" <-> function equivalence database
556 */ 544 */
557void populate_func_lookup_table( lua_State* L, int _i, char const* name_) 545void populate_func_lookup_table(lua_State* L, int i_, char const* name_)
558{ 546{
559 int const ctx_base = lua_gettop( L) + 1; 547 int const ctx_base = lua_gettop(L) + 1;
560 int const in_base = lua_absindex( L, _i); 548 int const in_base = lua_absindex(L, i_);
561 int start_depth = 0; 549 int start_depth = 0;
562 DEBUGSPEW_CODE( Universe* U = universe_get( L)); 550 DEBUGSPEW_CODE( Universe* U = universe_get( L));
563 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); 551 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr"));
564 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 552 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
565 STACK_GROW( L, 3); 553 STACK_GROW( L, 3);
566 STACK_CHECK_START_REL(L, 0); 554 STACK_CHECK_START_REL(L, 0);
567 LOOKUP_REGKEY.pushValue(L); // {} 555 LOOKUP_REGKEY.pushValue(L); // {}
@@ -612,7 +600,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
612 (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); 600 (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base)));
613 } 601 }
614 STACK_CHECK( L, 0); 602 STACK_CHECK( L, 0);
615 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 603 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
616} 604}
617 605
618// ################################################################################################# 606// #################################################################################################
@@ -625,7 +613,7 @@ static constexpr UniqueKey REG_MTID{ 0x2e68f9b4751584dcull };
625/* 613/*
626* Get a unique ID for metatable at [i]. 614* Get a unique ID for metatable at [i].
627*/ 615*/
628static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) 616[[nodiscard]] static lua_Integer get_mt_id(Universe* U, lua_State* L, int i)
629{ 617{
630 lua_Integer id; 618 lua_Integer id;
631 619
@@ -666,25 +654,25 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i)
666// ################################################################################################# 654// #################################################################################################
667 655
668// function sentinel used to transfer native functions from/to keeper states 656// function sentinel used to transfer native functions from/to keeper states
669static int func_lookup_sentinel( lua_State* L) 657[[nodiscard]] static int func_lookup_sentinel(lua_State* L)
670{ 658{
671 return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 659 return luaL_error(L, "function lookup sentinel for %s, should never be called", lua_tostring(L, lua_upvalueindex(1)));
672} 660}
673 661
674// ################################################################################################# 662// #################################################################################################
675 663
676// function sentinel used to transfer native table from/to keeper states 664// function sentinel used to transfer native table from/to keeper states
677static int table_lookup_sentinel( lua_State* L) 665[[nodiscard]] static int table_lookup_sentinel(lua_State* L)
678{ 666{
679 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 667 return luaL_error(L, "table lookup sentinel for %s, should never be called", lua_tostring(L, lua_upvalueindex(1)));
680} 668}
681 669
682// ################################################################################################# 670// #################################################################################################
683 671
684// function sentinel used to transfer cloned full userdata from/to keeper states 672// function sentinel used to transfer cloned full userdata from/to keeper states
685static int userdata_clone_sentinel( lua_State* L) 673[[nodiscard]] static int userdata_clone_sentinel(lua_State* L)
686{ 674{
687 return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); 675 return luaL_error(L, "userdata clone sentinel for %s, should never be called", lua_tostring(L, lua_upvalueindex(1)));
688} 676}
689 677
690// ################################################################################################# 678// #################################################################################################
@@ -692,7 +680,7 @@ static int userdata_clone_sentinel( lua_State* L)
692/* 680/*
693 * retrieve the name of a function/table in the lookup database 681 * retrieve the name of a function/table in the lookup database
694 */ 682 */
695static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char const* upName_, size_t* len_) 683[[nodiscard]] static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char const* upName_, size_t* len_)
696{ 684{
697 DEBUGSPEW_CODE( Universe* const U = universe_get( L)); 685 DEBUGSPEW_CODE( Universe* const U = universe_get( L));
698 char const* fqn; 686 char const* fqn;
@@ -765,7 +753,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char
765/* 753/*
766 * Push a looked-up table, or nothing if we found nothing 754 * Push a looked-up table, or nothing if we found nothing
767 */ 755 */
768static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, char const* upName_) 756[[nodiscard]] static bool lookup_table(Dest L2, Source L, int i, LookupMode mode_, char const* upName_)
769{ 757{
770 // get the name of the table we want to send 758 // get the name of the table we want to send
771 size_t len; 759 size_t len;
@@ -775,7 +763,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c
775 return false; 763 return false;
776 } 764 }
777 // push the equivalent table in the destination's stack, retrieved from the lookup table 765 // push the equivalent table in the destination's stack, retrieved from the lookup table
778 STACK_CHECK_START_REL(L2, 0); // L // L2 766 STACK_CHECK_START_REL(L2, 0); // L // L2
779 STACK_GROW( L2, 3); // up to 3 slots are necessary on error 767 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
780 switch( mode_) 768 switch( mode_)
781 { 769 {
@@ -785,34 +773,34 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c
785 773
786 case LookupMode::ToKeeper: 774 case LookupMode::ToKeeper:
787 // push a sentinel closure that holds the lookup name as upvalue 775 // push a sentinel closure that holds the lookup name as upvalue
788 lua_pushlstring( L2, fqn, len); // "f.q.n" 776 lua_pushlstring(L2, fqn, len); // "f.q.n"
789 lua_pushcclosure( L2, table_lookup_sentinel, 1); // f 777 lua_pushcclosure(L2, table_lookup_sentinel, 1); // f
790 break; 778 break;
791 779
792 case LookupMode::LaneBody: 780 case LookupMode::LaneBody:
793 case LookupMode::FromKeeper: 781 case LookupMode::FromKeeper:
794 LOOKUP_REGKEY.pushValue(L2); // {} 782 LOOKUP_REGKEY.pushValue(L2); // {}
795 STACK_CHECK( L2, 1); 783 STACK_CHECK(L2, 1);
796 ASSERT_L( lua_istable( L2, -1)); 784 ASSERT_L(lua_istable(L2, -1));
797 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 785 lua_pushlstring(L2, fqn, len); // {} "f.q.n"
798 lua_rawget( L2, -2); // {} t 786 lua_rawget(L2, -2); // {} t
799 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) 787 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead)
800 // but not when we extract something out of a keeper, as there is nothing to clone! 788 // but not when we extract something out of a keeper, as there is nothing to clone!
801 if (lua_isnil(L2, -1) && mode_ == LookupMode::LaneBody) 789 if (lua_isnil(L2, -1) && mode_ == LookupMode::LaneBody)
802 { 790 {
803 lua_pop( L2, 2); // 791 lua_pop(L2, 2); //
804 STACK_CHECK( L2, 0); 792 STACK_CHECK(L2, 0);
805 return false; 793 return false;
806 } 794 }
807 else if( !lua_istable( L2, -1)) 795 else if( !lua_istable(L2, -1))
808 { 796 {
809 char const* from, *to; 797 char const* from, *to;
810 lua_getglobal( L, "decoda_name"); // ... t ... decoda_name 798 lua_getglobal(L, "decoda_name"); // ... t ... decoda_name
811 from = lua_tostring( L, -1); 799 from = lua_tostring(L, -1);
812 lua_pop( L, 1); // ... t ... 800 lua_pop(L, 1); // ... t ...
813 lua_getglobal( L2, "decoda_name"); // {} t decoda_name 801 lua_getglobal(L2, "decoda_name"); // {} t decoda_name
814 to = lua_tostring( L2, -1); 802 to = lua_tostring( L2, -1);
815 lua_pop( L2, 1); // {} t 803 lua_pop(L2, 1); // {} t
816 // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 804 // when mode_ == LookupMode::FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
817 (void) luaL_error( 805 (void) luaL_error(
818 (mode_ == LookupMode::FromKeeper) ? L2 : L 806 (mode_ == LookupMode::FromKeeper) ? L2 : L
@@ -823,7 +811,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c
823 ); 811 );
824 return false; 812 return false;
825 } 813 }
826 lua_remove( L2, -2); // t 814 lua_remove(L2, -2); // t
827 break; 815 break;
828 } 816 }
829 STACK_CHECK( L2, 1); 817 STACK_CHECK( L2, 1);
@@ -842,13 +830,12 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c
842 * Returns true if the table was cached (no need to fill it!); false if 830 * Returns true if the table was cached (no need to fill it!); false if
843 * it's a virgin. 831 * it's a virgin.
844 */ 832 */
845static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i) 833[[nodiscard]] static bool push_cached_table(Dest L2, int L2_cache_i, Source L, int i)
846{ 834{
847 bool not_found_in_cache; // L2
848 void const* p{ lua_topointer(L, i) }; 835 void const* p{ lua_topointer(L, i) };
849 836
850 ASSERT_L( L2_cache_i != 0); 837 ASSERT_L( L2_cache_i != 0);
851 STACK_GROW( L2, 3); 838 STACK_GROW( L2, 3); // L2
852 STACK_CHECK_START_REL(L2, 0); 839 STACK_CHECK_START_REL(L2, 0);
853 840
854 // We don't need to use the from state ('L') in ID since the life span 841 // We don't need to use the from state ('L') in ID since the life span
@@ -859,7 +846,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i
859 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); 846 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
860 847
861 lua_rawget( L2, L2_cache_i); // ... {cached|nil} 848 lua_rawget( L2, L2_cache_i); // ... {cached|nil}
862 not_found_in_cache = lua_isnil( L2, -1); 849 bool const not_found_in_cache{ lua_isnil(L2, -1) };
863 if( not_found_in_cache) 850 if( not_found_in_cache)
864 { 851 {
865 lua_pop( L2, 1); // ... 852 lua_pop( L2, 1); // ...
@@ -878,83 +865,83 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i
878/* 865/*
879 * Return some name helping to identify an object 866 * Return some name helping to identify an object
880 */ 867 */
881static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) 868[[nodiscard]] static int discover_object_name_recur(lua_State* L, int shortest_, int depth_)
882{ 869{
883 int const what = 1; // o "r" {c} {fqn} ... {?} 870 int const what = 1; // o "r" {c} {fqn} ... {?}
884 int const result = 2; 871 int const result = 2;
885 int const cache = 3; 872 int const cache = 3;
886 int const fqn = 4; 873 int const fqn = 4;
887 // no need to scan this table if the name we will discover is longer than one we already know 874 // no need to scan this table if the name we will discover is longer than one we already know
888 if( shortest_ <= depth_ + 1) 875 if (shortest_ <= depth_ + 1)
889 { 876 {
890 return shortest_; 877 return shortest_;
891 } 878 }
892 STACK_GROW( L, 3); 879 STACK_GROW(L, 3);
893 STACK_CHECK_START_REL(L, 0); 880 STACK_CHECK_START_REL(L, 0);
894 // stack top contains the table to search in 881 // stack top contains the table to search in
895 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 882 lua_pushvalue(L, -1); // o "r" {c} {fqn} ... {?} {?}
896 lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 883 lua_rawget(L, cache); // o "r" {c} {fqn} ... {?} nil/1
897 // if table is already visited, we are done 884 // if table is already visited, we are done
898 if( !lua_isnil( L, -1)) 885 if( !lua_isnil(L, -1))
899 { 886 {
900 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} 887 lua_pop(L, 1); // o "r" {c} {fqn} ... {?}
901 return shortest_; 888 return shortest_;
902 } 889 }
903 // examined table is not in the cache, add it now 890 // examined table is not in the cache, add it now
904 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} 891 lua_pop(L, 1); // o "r" {c} {fqn} ... {?}
905 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 892 lua_pushvalue(L, -1); // o "r" {c} {fqn} ... {?} {?}
906 lua_pushinteger( L, 1); // o "r" {c} {fqn} ... {?} {?} 1 893 lua_pushinteger(L, 1); // o "r" {c} {fqn} ... {?} {?} 1
907 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} 894 lua_rawset(L, cache); // o "r" {c} {fqn} ... {?}
908 // scan table contents 895 // scan table contents
909 lua_pushnil( L); // o "r" {c} {fqn} ... {?} nil 896 lua_pushnil(L); // o "r" {c} {fqn} ... {?} nil
910 while( lua_next( L, -2)) // o "r" {c} {fqn} ... {?} k v 897 while (lua_next(L, -2)) // o "r" {c} {fqn} ... {?} k v
911 { 898 {
912 //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : nullptr; // only for debugging 899 //char const *const strKey = (lua_type(L, -2) == LUA_TSTRING) ? lua_tostring(L, -2) : nullptr; // only for debugging
913 //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging 900 //lua_Number const numKey = (lua_type(L, -2) == LUA_TNUMBER) ? lua_tonumber(L, -2) : -6666; // only for debugging
914 STACK_CHECK( L, 2); 901 STACK_CHECK(L, 2);
915 // append key name to fqn stack 902 // append key name to fqn stack
916 ++ depth_; 903 ++ depth_;
917 lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k 904 lua_pushvalue(L, -2); // o "r" {c} {fqn} ... {?} k v k
918 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v 905 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v
919 if( lua_rawequal( L, -1, what)) // is it what we are looking for? 906 if (lua_rawequal(L, -1, what)) // is it what we are looking for?
920 { 907 {
921 STACK_CHECK( L, 2); 908 STACK_CHECK(L, 2);
922 // update shortest name 909 // update shortest name
923 if( depth_ < shortest_) 910 if( depth_ < shortest_)
924 { 911 {
925 shortest_ = depth_; 912 shortest_ = depth_;
926 luaG_pushFQN( L, fqn, depth_, nullptr); // o "r" {c} {fqn} ... {?} k v "fqn" 913 std::ignore = luaG_pushFQN(L, fqn, depth_, nullptr); // o "r" {c} {fqn} ... {?} k v "fqn"
927 lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v 914 lua_replace(L, result); // o "r" {c} {fqn} ... {?} k v
928 } 915 }
929 // no need to search further at this level 916 // no need to search further at this level
930 lua_pop( L, 2); // o "r" {c} {fqn} ... {?} 917 lua_pop(L, 2); // o "r" {c} {fqn} ... {?}
931 STACK_CHECK( L, 0); 918 STACK_CHECK(L, 0);
932 break; 919 break;
933 } 920 }
934 switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v 921 switch (lua_type(L, -1)) // o "r" {c} {fqn} ... {?} k v
935 { 922 {
936 default: // nil, boolean, light userdata, number and string aren't identifiable 923 default: // nil, boolean, light userdata, number and string aren't identifiable
937 break; 924 break;
938 925
939 case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {} 926 case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {}
940 STACK_CHECK( L, 2); 927 STACK_CHECK(L, 2);
941 shortest_ = discover_object_name_recur( L, shortest_, depth_); 928 shortest_ = discover_object_name_recur(L, shortest_, depth_);
942 // search in the table's metatable too 929 // search in the table's metatable too
943 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} 930 if (lua_getmetatable(L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt}
944 { 931 {
945 if( lua_istable( L, -1)) 932 if( lua_istable(L, -1))
946 { 933 {
947 ++ depth_; 934 ++ depth_;
948 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable" 935 lua_pushliteral(L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable"
949 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt} 936 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
950 shortest_ = discover_object_name_recur( L, shortest_, depth_); 937 shortest_ = discover_object_name_recur(L, shortest_, depth_);
951 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k {} {mt} nil 938 lua_pushnil(L); // o "r" {c} {fqn} ... {?} k {} {mt} nil
952 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt} 939 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
953 -- depth_; 940 -- depth_;
954 } 941 }
955 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {} 942 lua_pop(L, 1); // o "r" {c} {fqn} ... {?} k {}
956 } 943 }
957 STACK_CHECK( L, 2); 944 STACK_CHECK(L, 2);
958 break; 945 break;
959 946
960 case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T 947 case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T
@@ -962,61 +949,61 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
962 break; 949 break;
963 950
964 case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U 951 case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U
965 STACK_CHECK( L, 2); 952 STACK_CHECK(L, 2);
966 // search in the object's metatable (some modules are built that way) 953 // search in the object's metatable (some modules are built that way)
967 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt} 954 if (lua_getmetatable(L, -1)) // o "r" {c} {fqn} ... {?} k U {mt}
968 { 955 {
969 if( lua_istable( L, -1)) 956 if (lua_istable(L, -1))
970 { 957 {
971 ++ depth_; 958 ++ depth_;
972 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k U {mt} "__metatable" 959 lua_pushliteral(L, "__metatable"); // o "r" {c} {fqn} ... {?} k U {mt} "__metatable"
973 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt} 960 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
974 shortest_ = discover_object_name_recur( L, shortest_, depth_); 961 shortest_ = discover_object_name_recur(L, shortest_, depth_);
975 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k U {mt} nil 962 lua_pushnil(L); // o "r" {c} {fqn} ... {?} k U {mt} nil
976 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt} 963 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
977 -- depth_; 964 -- depth_;
978 } 965 }
979 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 966 lua_pop(L, 1); // o "r" {c} {fqn} ... {?} k U
980 } 967 }
981 STACK_CHECK( L, 2); 968 STACK_CHECK(L, 2);
982 // search in the object's uservalues 969 // search in the object's uservalues
983 { 970 {
984 int uvi = 1; 971 int uvi = 1;
985 while( lua_getiuservalue( L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u} 972 while (lua_getiuservalue(L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u}
986 { 973 {
987 if( lua_istable( L, -1)) // if it is a table, look inside 974 if( lua_istable(L, -1)) // if it is a table, look inside
988 { 975 {
989 ++ depth_; 976 ++ depth_;
990 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue" 977 lua_pushliteral(L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue"
991 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 978 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
992 shortest_ = discover_object_name_recur( L, shortest_, depth_); 979 shortest_ = discover_object_name_recur(L, shortest_, depth_);
993 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil 980 lua_pushnil(L); // o "r" {c} {fqn} ... {?} k v {u} nil
994 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 981 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
995 -- depth_; 982 -- depth_;
996 } 983 }
997 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 984 lua_pop(L, 1); // o "r" {c} {fqn} ... {?} k U
998 ++ uvi; 985 ++ uvi;
999 } 986 }
1000 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 987 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1001 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 988 lua_pop(L, 1); // o "r" {c} {fqn} ... {?} k U
1002 } 989 }
1003 STACK_CHECK( L, 2); 990 STACK_CHECK(L, 2);
1004 break; 991 break;
1005 } 992 }
1006 // make ready for next iteration 993 // make ready for next iteration
1007 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k 994 lua_pop(L, 1); // o "r" {c} {fqn} ... {?} k
1008 // remove name from fqn stack 995 // remove name from fqn stack
1009 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil 996 lua_pushnil(L); // o "r" {c} {fqn} ... {?} k nil
1010 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k 997 lua_rawseti(L, fqn, depth_); // o "r" {c} {fqn} ... {?} k
1011 STACK_CHECK( L, 1); 998 STACK_CHECK(L, 1);
1012 -- depth_; 999 -- depth_;
1013 } // o "r" {c} {fqn} ... {?} 1000 } // o "r" {c} {fqn} ... {?}
1014 STACK_CHECK( L, 0); 1001 STACK_CHECK(L, 0);
1015 // remove the visited table from the cache, in case a shorter path to the searched object exists 1002 // remove the visited table from the cache, in case a shorter path to the searched object exists
1016 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} 1003 lua_pushvalue(L, -1); // o "r" {c} {fqn} ... {?} {?}
1017 lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil 1004 lua_pushnil(L); // o "r" {c} {fqn} ... {?} {?} nil
1018 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} 1005 lua_rawset(L, cache); // o "r" {c} {fqn} ... {?}
1019 STACK_CHECK( L, 0); 1006 STACK_CHECK(L, 0);
1020 return shortest_; 1007 return shortest_;
1021} 1008}
1022 1009
@@ -1181,7 +1168,7 @@ static char const* vt_names[] =
1181// we have to do it that way because we can't unbalance the stack between buffer operations 1168// we have to do it that way because we can't unbalance the stack between buffer operations
1182// namely, this means we can't push a function on top of the stack *after* we initialize the buffer! 1169// namely, this means we can't push a function on top of the stack *after* we initialize the buffer!
1183// luckily, this also works with earlier Lua versions 1170// luckily, this also works with earlier Lua versions
1184static int buf_writer( lua_State* L, void const* b, size_t size, void* ud) 1171[[nodiscard]] static int buf_writer(lua_State* L, void const* b, size_t size, void* ud)
1185{ 1172{
1186 luaL_Buffer* B = (luaL_Buffer*) ud; 1173 luaL_Buffer* B = (luaL_Buffer*) ud;
1187 if( !B->L) 1174 if( !B->L)
@@ -1194,7 +1181,7 @@ static int buf_writer( lua_State* L, void const* b, size_t size, void* ud)
1194 1181
1195// ################################################################################################# 1182// #################################################################################################
1196 1183
1197static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) 1184static void copy_func(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode mode_, char const* upName_)
1198{ 1185{
1199 int n, needToPush; 1186 int n, needToPush;
1200 luaL_Buffer B; 1187 luaL_Buffer B;
@@ -1348,10 +1335,10 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L,
1348 * 1335 *
1349 * Always pushes a function to 'L2'. 1336 * Always pushes a function to 'L2'.
1350 */ 1337 */
1351static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) 1338static void copy_cached_func(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode mode_, char const* upName_)
1352{ 1339{
1353 FuncSubType funcSubType; 1340 FuncSubType funcSubType;
1354 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // nullptr for LuaJIT-fast && bytecode functions 1341 std::ignore = luaG_tocfunction(L, i, &funcSubType); // nullptr for LuaJIT-fast && bytecode functions
1355 if( funcSubType == FST_Bytecode) 1342 if( funcSubType == FST_Bytecode)
1356 { 1343 {
1357 void* const aspointer = (void*)lua_topointer( L, i); 1344 void* const aspointer = (void*)lua_topointer( L, i);
@@ -1403,64 +1390,63 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta
1403 1390
1404// ################################################################################################# 1391// #################################################################################################
1405 1392
1406static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) 1393[[nodiscard]] static bool push_cached_metatable(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode mode_, char const* upName_)
1407{ 1394{
1408 STACK_CHECK_START_REL(L, 0); 1395 STACK_CHECK_START_REL(L, 0);
1409 if( lua_getmetatable( L, i)) // ... mt 1396 if (!lua_getmetatable(L, i)) // ... mt
1410 { 1397 {
1411 lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable 1398 STACK_CHECK( L, 0);
1399 return false;
1400 }
1401 STACK_CHECK(L, 1);
1412 1402
1413 STACK_CHECK_START_REL(L2, 0); 1403 lua_Integer const mt_id{ get_mt_id(U, L, -1) }; // Unique id for the metatable
1414 STACK_GROW( L2, 4); 1404
1415 // do we already know this metatable? 1405 STACK_CHECK_START_REL(L2, 0);
1416 push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] 1406 STACK_GROW(L2, 4);
1417 lua_pushinteger( L2, mt_id); // _R[REG_MTID] id 1407 // do we already know this metatable?
1418 lua_rawget( L2, -2); // _R[REG_MTID] mt? 1408 push_registry_subtable(L2, REG_MTID); // _R[REG_MTID]
1419 1409 lua_pushinteger(L2, mt_id); // _R[REG_MTID] id
1420 STACK_CHECK( L2, 2); 1410 lua_rawget(L2, -2); // _R[REG_MTID] mt|nil
1421 1411 STACK_CHECK(L2, 2);
1422 if( lua_isnil( L2, -1)) 1412
1423 { // L2 did not know the metatable 1413 if (lua_isnil(L2, -1))
1424 lua_pop( L2, 1); // _R[REG_MTID] 1414 { // L2 did not know the metatable
1425 if (inter_copy_one(U, L2, L2_cache_i, L, lua_gettop( L), VT::METATABLE, mode_, upName_)) // _R[REG_MTID] mt 1415 lua_pop(L2, 1); // _R[REG_MTID]
1426 { 1416 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_gettop(L), VT::METATABLE, mode_, upName_)) // _R[REG_MTID] mt?
1427 STACK_CHECK( L2, 2); 1417 {
1428 // mt_id -> metatable 1418 luaL_error(L, "Error copying a metatable"); // doesn't return
1429 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id
1430 lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt
1431 lua_rawset( L2, -4); // _R[REG_MTID] mt
1432
1433 // metatable -> mt_id
1434 lua_pushvalue( L2, -1); // _R[REG_MTID] mt mt
1435 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt mt id
1436 lua_rawset( L2, -4); // _R[REG_MTID] mt
1437 }
1438 else
1439 {
1440 (void) luaL_error( L, "Error copying a metatable");
1441 }
1442 STACK_CHECK( L2, 2);
1443 } 1419 }
1444 lua_remove( L2, -2); // mt
1445 1420
1446 lua_pop( L, 1); // ... 1421 STACK_CHECK(L2, 2); // _R[REG_MTID] mt
1447 STACK_CHECK( L2, 1); 1422 // mt_id -> metatable
1448 STACK_CHECK( L, 0); 1423 lua_pushinteger(L2, mt_id); // _R[REG_MTID] mt id
1449 return true; 1424 lua_pushvalue(L2, -2); // _R[REG_MTID] mt id mt
1425 lua_rawset(L2, -4); // _R[REG_MTID] mt
1426
1427 // metatable -> mt_id
1428 lua_pushvalue(L2, -1); // _R[REG_MTID] mt mt
1429 lua_pushinteger(L2, mt_id); // _R[REG_MTID] mt mt id
1430 lua_rawset(L2, -4); // _R[REG_MTID] mt
1431 STACK_CHECK(L2, 2);
1450 } 1432 }
1451 STACK_CHECK( L, 0); 1433 lua_remove(L2, -2); // mt
1452 return false; 1434
1435 lua_pop(L, 1); // ...
1436 STACK_CHECK(L2, 1);
1437 STACK_CHECK(L, 0);
1438 return true;
1453} 1439}
1454 1440
1455// ################################################################################################# 1441// #################################################################################################
1456 1442
1457static void inter_copy_keyvaluepair(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, VT vt_, LookupMode mode_, char const* upName_) 1443[[nodiscard]] static void inter_copy_keyvaluepair(Universe* U, Dest L2, int L2_cache_i, Source L, VT vt_, LookupMode mode_, char const* upName_)
1458{ 1444{
1459 int val_i = lua_gettop(L); 1445 int val_i = lua_gettop(L);
1460 int key_i = val_i - 1; 1446 int key_i = val_i - 1;
1461 1447
1462 // Only basic key types are copied over; others ignored 1448 // Only basic key types are copied over; others ignored
1463 if (inter_copy_one(U, L2, 0 /*key*/, L, key_i, VT::KEY, mode_, upName_)) 1449 if (inter_copy_one(U, L2, L2_cache_i, L, key_i, VT::KEY, mode_, upName_))
1464 { 1450 {
1465 char* valPath = (char*) upName_; 1451 char* valPath = (char*) upName_;
1466 if( U->verboseErrors) 1452 if( U->verboseErrors)
@@ -1526,7 +1512,7 @@ static void inter_copy_keyvaluepair(Universe* U, lua_State* L2, int L2_cache_i,
1526*/ 1512*/
1527static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull }; 1513static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1528 1514
1529static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int source_i_, LookupMode mode_, char const* upName_) 1515[[nodiscard]] static bool copyclone(Universe* U, Dest L2, int L2_cache_i, Source L, int source_i_, LookupMode mode_, char const* upName_)
1530{ 1516{
1531 void* const source = lua_touserdata( L, source_i_); 1517 void* const source = lua_touserdata( L, source_i_);
1532 source_i_ = lua_absindex( L, source_i_); 1518 source_i_ = lua_absindex( L, source_i_);
@@ -1612,7 +1598,10 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L,
1612 // assign uservalues 1598 // assign uservalues
1613 while( uvi > 0) 1599 while( uvi > 0)
1614 { 1600 {
1615 inter_copy_one(U, L2, L2_cache_i, L, lua_absindex( L, -1), VT::NORMAL, mode_, upName_); // ... u uv 1601 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), VT::NORMAL, mode_, upName_)) // ... u uv
1602 {
1603 luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1)); // doesn't return
1604 }
1616 lua_pop( L, 1); // ... mt __lanesclone [uv]* 1605 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1617 // this pops the value from the stack 1606 // this pops the value from the stack
1618 lua_setiuservalue( L2, -2, uvi); // ... u 1607 lua_setiuservalue( L2, -2, uvi); // ... u
@@ -1641,7 +1630,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L,
1641 1630
1642// ################################################################################################# 1631// #################################################################################################
1643 1632
1644static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) 1633[[nodiscard]] static bool inter_copy_userdata(Universe* U, Dest L2, int L2_cache_i, Source L, int i, VT vt_, LookupMode mode_, char const* upName_)
1645{ 1634{
1646 STACK_CHECK_START_REL(L, 0); 1635 STACK_CHECK_START_REL(L, 0);
1647 STACK_CHECK_START_REL(L2, 0); 1636 STACK_CHECK_START_REL(L2, 0);
@@ -1653,140 +1642,141 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_
1653 // try clonable userdata first 1642 // try clonable userdata first
1654 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) 1643 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_))
1655 { 1644 {
1656 STACK_CHECK( L, 0); 1645 STACK_CHECK(L, 0);
1657 STACK_CHECK( L2, 1); 1646 STACK_CHECK(L2, 1);
1658 return true; 1647 return true;
1659 } 1648 }
1660 1649
1661 STACK_CHECK( L, 0); 1650 STACK_CHECK(L, 0);
1662 STACK_CHECK( L2, 0); 1651 STACK_CHECK(L2, 0);
1663 1652
1664 // Allow only deep userdata entities to be copied across 1653 // Allow only deep userdata entities to be copied across
1665 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); 1654 DEBUGSPEW_CODE(fprintf(stderr, "USERDATA\n"));
1666 if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) 1655 if (copydeep(U, L2, L2_cache_i, L, i, mode_, upName_))
1667 { 1656 {
1668 STACK_CHECK( L, 0); 1657 STACK_CHECK(L, 0);
1669 STACK_CHECK( L2, 1); 1658 STACK_CHECK(L2, 1);
1670 return true; 1659 return true;
1671 } 1660 }
1672 1661
1673 STACK_CHECK( L, 0); 1662 STACK_CHECK(L, 0);
1674 STACK_CHECK( L2, 0); 1663 STACK_CHECK(L2, 0);
1675 1664
1676 // Not a deep or clonable full userdata 1665 // Not a deep or clonable full userdata
1677 if( U->demoteFullUserdata) // attempt demotion to light userdata 1666 if (U->demoteFullUserdata) // attempt demotion to light userdata
1678 { 1667 {
1679 void* lud = lua_touserdata( L, i); 1668 void* lud = lua_touserdata(L, i);
1680 lua_pushlightuserdata( L2, lud); 1669 lua_pushlightuserdata(L2, lud);
1681 } 1670 }
1682 else // raise an error 1671 else // raise an error
1683 { 1672 {
1684 (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); 1673 luaL_error(L, "can't copy non-deep full userdata across lanes"); // doesn't return
1685 } 1674 }
1686 1675
1687 STACK_CHECK( L2, 1); 1676 STACK_CHECK(L2, 1);
1688 STACK_CHECK( L, 0); 1677 STACK_CHECK(L, 0);
1689 return true; 1678 return true;
1690} 1679}
1691 1680
1692// ################################################################################################# 1681// #################################################################################################
1693 1682
1694static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int source_i_, VT vt_, LookupMode mode_, char const* upName_) 1683[[nodiscard]] static bool inter_copy_function(Universe* U, Dest L2, int L2_cache_i, Source L, int source_i_, VT vt_, LookupMode mode_, char const* upName_)
1695{ 1684{
1696 if (vt_ == VT::KEY) 1685 if (vt_ == VT::KEY)
1697 { 1686 {
1698 return false; 1687 return false;
1699 } 1688 }
1700 1689
1701 STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) 1690 STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination)
1702 STACK_CHECK_START_REL(L2, 0); 1691 STACK_CHECK_START_REL(L2, 0);
1703 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1692 DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", upName_));
1704 1693
1705 if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper 1694 if (lua_tocfunction(L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper
1706 { 1695 {
1707 // clone the full userdata again 1696 // clone the full userdata again
1708 size_t userdata_size = 0;
1709 void* source;
1710 void* clone;
1711 1697
1712 // let's see if we already restored this userdata 1698 // let's see if we already restored this userdata
1713 lua_getupvalue( L, source_i_, 2); // ... u 1699 lua_getupvalue(L, source_i_, 2); // ... u
1714 source = lua_touserdata( L, -1); 1700 void* source = lua_touserdata(L, -1);
1715 lua_pushlightuserdata( L2, source); // ... source 1701 lua_pushlightuserdata(L2, source); // ... source
1716 lua_rawget( L2, L2_cache_i); // ... u? 1702 lua_rawget(L2, L2_cache_i); // ... u?
1717 if( !lua_isnil( L2, -1)) 1703 if (!lua_isnil(L2, -1))
1718 { 1704 {
1719 lua_pop( L, 1); // ... 1705 lua_pop(L, 1); // ...
1720 STACK_CHECK( L, 0); 1706 STACK_CHECK(L, 0);
1721 STACK_CHECK( L2, 1); 1707 STACK_CHECK(L2, 1);
1722 return true; 1708 return true;
1723 } 1709 }
1724 lua_pop( L2, 1); // ... 1710 lua_pop(L2, 1); // ...
1725 1711
1726 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself 1712 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1727 lookup_table( L2, L, source_i_, mode_, upName_); // ... mt 1713 std::ignore = lookup_table(L2, L, source_i_, mode_, upName_); // ... mt
1728 // originally 'source_i_' slot was the proxy closure, but from now on it indexes the actual userdata we extracted from it 1714 // originally 'source_i_' slot was the proxy closure, but from now on it indexes the actual userdata we extracted from it
1729 source_i_ = lua_gettop( L); 1715 source_i_ = lua_gettop(L);
1730 source = lua_touserdata( L, -1); 1716 source = lua_touserdata(L, -1);
1717 void* clone{ nullptr };
1731 // get the number of bytes to allocate for the clone 1718 // get the number of bytes to allocate for the clone
1732 userdata_size = (size_t) lua_rawlen( L, -1); 1719 size_t const userdata_size{ lua_rawlen(L, -1) };
1733 { 1720 {
1734 // extract uservalues (don't transfer them yet) 1721 // extract uservalues (don't transfer them yet)
1735 int uvi = 0; 1722 int uvi = 0;
1736 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... u uv 1723 while (lua_getiuservalue(L, source_i_, ++uvi) != LUA_TNONE) {} // ... u uv
1737 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 1724 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1738 lua_pop( L, 1); // ... u [uv]* 1725 lua_pop(L, 1); // ... u [uv]*
1739 -- uvi; 1726 --uvi;
1740 STACK_CHECK( L, uvi + 1); 1727 STACK_CHECK(L, uvi + 1);
1741 // create the clone userdata with the required number of uservalue slots 1728 // create the clone userdata with the required number of uservalue slots
1742 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u 1729 clone = lua_newuserdatauv(L2, userdata_size, uvi); // ... mt u
1743 // add it in the cache 1730 // add it in the cache
1744 lua_pushlightuserdata( L2, source); // ... mt u source 1731 lua_pushlightuserdata(L2, source); // ... mt u source
1745 lua_pushvalue( L2, -2); // ... mt u source u 1732 lua_pushvalue(L2, -2); // ... mt u source u
1746 lua_rawset( L2, L2_cache_i); // ... mt u 1733 lua_rawset(L2, L2_cache_i); // ... mt u
1747 // set metatable 1734 // set metatable
1748 lua_pushvalue( L2, -2); // ... mt u mt 1735 lua_pushvalue(L2, -2); // ... mt u mt
1749 lua_setmetatable( L2, -2); // ... mt u 1736 lua_setmetatable(L2, -2); // ... mt u
1750 // transfer and assign uservalues 1737 // transfer and assign uservalues
1751 while( uvi > 0) 1738 while (uvi > 0)
1752 { 1739 {
1753 inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), vt_, mode_, upName_); // ... mt u uv 1740 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), vt_, mode_, upName_)) // ... mt u uv
1754 lua_pop( L, 1); // ... u [uv]* 1741 {
1742 luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1)); // doesn't return
1743 }
1744 lua_pop(L, 1); // ... u [uv]*
1755 // this pops the value from the stack 1745 // this pops the value from the stack
1756 lua_setiuservalue( L2, -2, uvi); // ... mt u 1746 lua_setiuservalue(L2, -2, uvi); // ... mt u
1757 -- uvi; 1747 -- uvi;
1758 } 1748 }
1759 // when we are done, all uservalues are popped from the stack, we can pop the source as well 1749 // when we are done, all uservalues are popped from the stack, we can pop the source as well
1760 lua_pop( L, 1); // ... 1750 lua_pop(L, 1); // ...
1761 STACK_CHECK( L, 0); 1751 STACK_CHECK(L, 0);
1762 STACK_CHECK( L2, 2); // ... mt u 1752 STACK_CHECK(L2, 2); // ... mt u
1763 } 1753 }
1764 // perform the custom cloning part 1754 // perform the custom cloning part
1765 lua_insert( L2, -2); // ... u mt 1755 lua_insert(L2, -2); // ... u mt
1766 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with 1756 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
1767 lua_getfield(L2, -1, "__lanesclone"); // ... u mt __lanesclone 1757 lua_getfield(L2, -1, "__lanesclone"); // ... u mt __lanesclone
1768 lua_remove( L2, -2); // ... u __lanesclone 1758 lua_remove(L2, -2); // ... u __lanesclone
1769 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone 1759 lua_pushlightuserdata(L2, clone); // ... u __lanesclone clone
1770 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source 1760 lua_pushlightuserdata(L2, source); // ... u __lanesclone clone source
1771 lua_pushinteger( L2, userdata_size); // ... u __lanesclone clone source size 1761 lua_pushinteger(L2, userdata_size); // ... u __lanesclone clone source size
1772 // clone:__lanesclone(dest, source, size) 1762 // clone:__lanesclone(dest, source, size)
1773 lua_call( L2, 3, 0); // ... u 1763 lua_call(L2, 3, 0); // ... u
1774 } 1764 }
1775 else // regular function 1765 else // regular function
1776 { 1766 {
1777 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1767 DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", upName_));
1778 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1768 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
1779 copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f 1769 copy_cached_func(U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f
1780 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1770 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
1781 } 1771 }
1782 STACK_CHECK( L2, 1); 1772 STACK_CHECK(L2, 1);
1783 STACK_CHECK( L, 0); 1773 STACK_CHECK(L, 0);
1784 return true; 1774 return true;
1785} 1775}
1786 1776
1787// ################################################################################################# 1777// #################################################################################################
1788 1778
1789static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) 1779[[nodiscard]] static bool inter_copy_table(Universe* U, Dest L2, int L2_cache_i, Source L, int i, VT vt_, LookupMode mode_, char const* upName_)
1790{ 1780{
1791 if (vt_ == VT::KEY) 1781 if (vt_ == VT::KEY)
1792 { 1782 {
@@ -1795,15 +1785,15 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta
1795 1785
1796 STACK_CHECK_START_REL(L, 0); 1786 STACK_CHECK_START_REL(L, 0);
1797 STACK_CHECK_START_REL(L2, 0); 1787 STACK_CHECK_START_REL(L2, 0);
1798 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); 1788 DEBUGSPEW_CODE(fprintf(stderr, "TABLE %s\n", upName_));
1799 1789
1800 /* 1790 /*
1801 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) 1791 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?)
1802 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism 1792 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism
1803 */ 1793 */
1804 if( lookup_table( L2, L, i, mode_, upName_)) 1794 if (lookup_table(L2, L, i, mode_, upName_))
1805 { 1795 {
1806 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know 1796 ASSERT_L(lua_istable(L2, -1) || (lua_tocfunction(L2, -1) == table_lookup_sentinel)); // from lookup data. can also be table_lookup_sentinel if this is a table we know
1807 return true; 1797 return true;
1808 } 1798 }
1809 1799
@@ -1816,33 +1806,33 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta
1816 * Note: Even metatables need to go through this test; to detect 1806 * Note: Even metatables need to go through this test; to detect
1817 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes) 1807 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
1818 */ 1808 */
1819 if( push_cached_table( L2, L2_cache_i, L, i)) 1809 if (push_cached_table(L2, L2_cache_i, L, i))
1820 { 1810 {
1821 ASSERT_L( lua_istable( L2, -1)); // from cache 1811 ASSERT_L(lua_istable(L2, -1)); // from cache
1822 return true; 1812 return true;
1823 } 1813 }
1824 ASSERT_L( lua_istable( L2, -1)); 1814 ASSERT_L(lua_istable(L2, -1));
1825 1815
1826 STACK_GROW( L, 2); 1816 STACK_GROW(L, 2);
1827 STACK_GROW( L2, 2); 1817 STACK_GROW(L2, 2);
1828 1818
1829 lua_pushnil( L); // start iteration 1819 lua_pushnil(L); // start iteration
1830 while( lua_next( L, i)) 1820 while (lua_next(L, i))
1831 { 1821 {
1832 // need a function to prevent overflowing the stack with verboseErrors-induced alloca() 1822 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
1833 inter_copy_keyvaluepair(U, L2, L2_cache_i, L, vt_, mode_, upName_); 1823 inter_copy_keyvaluepair(U, L2, L2_cache_i, L, vt_, mode_, upName_);
1834 lua_pop( L, 1); // pop value (next round) 1824 lua_pop(L, 1); // pop value (next round)
1835 } 1825 }
1836 STACK_CHECK( L, 0); 1826 STACK_CHECK(L, 0);
1837 STACK_CHECK( L2, 1); 1827 STACK_CHECK(L2, 1);
1838 1828
1839 // Metatables are expected to be immutable, and copied only once. 1829 // Metatables are expected to be immutable, and copied only once.
1840 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt? 1830 if (push_cached_metatable(U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt?
1841 { 1831 {
1842 lua_setmetatable( L2, -2); // ... t 1832 lua_setmetatable(L2, -2); // ... t
1843 } 1833 }
1844 STACK_CHECK( L2, 1); 1834 STACK_CHECK(L2, 1);
1845 STACK_CHECK( L, 0); 1835 STACK_CHECK(L, 0);
1846 return true; 1836 return true;
1847} 1837}
1848 1838
@@ -1858,21 +1848,21 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta
1858* 1848*
1859* Returns true if value was pushed, false if its type is non-supported. 1849* Returns true if value was pushed, false if its type is non-supported.
1860*/ 1850*/
1861bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, VT vt_, LookupMode mode_, char const* upName_) 1851[[nodiscard]] bool inter_copy_one(Universe* U, Dest L2, int L2_cache_i, Source L, int i, VT vt_, LookupMode mode_, char const* upName_)
1862{ 1852{
1863 bool ret{ true }; 1853 bool ret{ true };
1864 int val_type = lua_type( L, i); 1854 LuaType val_type{ lua_type_as_enum(L, i) };
1865 static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); 1855 static constexpr int pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
1866 STACK_GROW( L2, 1); 1856 STACK_GROW( L2, 1);
1867 STACK_CHECK_START_REL(L, 0); // L // L2 1857 STACK_CHECK_START_REL(L, 0); // L // L2
1868 STACK_CHECK_START_REL(L2, 0); // L // L2 1858 STACK_CHECK_START_REL(L2, 0); // L // L2
1869 1859
1870 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); 1860 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END));
1871 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1861 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
1872 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)])); 1862 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[static_cast<int>(vt_)]));
1873 1863
1874 // Non-POD can be skipped if its metatable contains { __lanesignore = true } 1864 // Non-POD can be skipped if its metatable contains { __lanesignore = true }
1875 if( ((1 << val_type) & pod_mask) == 0) 1865 if( ((1 << static_cast<int>(val_type)) & pod_mask) == 0)
1876 { 1866 {
1877 if( lua_getmetatable( L, i)) // ... mt 1867 if( lua_getmetatable( L, i)) // ... mt
1878 { 1868 {
@@ -1880,7 +1870,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1880 if( lua_isboolean( L, -1) && lua_toboolean( L, -1)) 1870 if( lua_isboolean( L, -1) && lua_toboolean( L, -1))
1881 { 1871 {
1882 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END)); 1872 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END));
1883 val_type = LUA_TNIL; 1873 val_type = LuaType::NIL;
1884 } 1874 }
1885 lua_pop( L, 2); // ... 1875 lua_pop( L, 2); // ...
1886 } 1876 }
@@ -1892,7 +1882,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1892 { 1882 {
1893 /* Basic types allowed both as values, and as table keys */ 1883 /* Basic types allowed both as values, and as table keys */
1894 1884
1895 case LUA_TBOOLEAN: 1885 case LuaType::BOOLEAN:
1896 { 1886 {
1897 int const v{ lua_toboolean(L, i) }; 1887 int const v{ lua_toboolean(L, i) };
1898 DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false")); 1888 DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false"));
@@ -1900,7 +1890,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1900 } 1890 }
1901 break; 1891 break;
1902 1892
1903 case LUA_TNUMBER: 1893 case LuaType::NUMBER:
1904 /* LNUM patch support (keeping integer accuracy) */ 1894 /* LNUM patch support (keeping integer accuracy) */
1905#if defined LUA_LNUM || LUA_VERSION_NUM >= 503 1895#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1906 if( lua_isinteger( L, i)) 1896 if( lua_isinteger( L, i))
@@ -1919,7 +1909,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1919 } 1909 }
1920 break; 1910 break;
1921 1911
1922 case LUA_TSTRING: 1912 case LuaType::STRING:
1923 { 1913 {
1924 size_t len; 1914 size_t len;
1925 char const* s = lua_tolstring( L, i, &len); 1915 char const* s = lua_tolstring( L, i, &len);
@@ -1928,7 +1918,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1928 } 1918 }
1929 break; 1919 break;
1930 1920
1931 case LUA_TLIGHTUSERDATA: 1921 case LuaType::LIGHTUSERDATA:
1932 { 1922 {
1933 void* p = lua_touserdata( L, i); 1923 void* p = lua_touserdata( L, i);
1934 DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p)); 1924 DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p));
@@ -1938,11 +1928,11 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1938 1928
1939 /* The following types are not allowed as table keys */ 1929 /* The following types are not allowed as table keys */
1940 1930
1941 case LUA_TUSERDATA: 1931 case LuaType::USERDATA:
1942 ret = inter_copy_userdata(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); 1932 ret = inter_copy_userdata(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
1943 break; 1933 break;
1944 1934
1945 case LUA_TNIL: 1935 case LuaType::NIL:
1946 if (vt_ == VT::KEY) 1936 if (vt_ == VT::KEY)
1947 { 1937 {
1948 ret = false; 1938 ret = false;
@@ -1951,29 +1941,31 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1951 lua_pushnil( L2); 1941 lua_pushnil( L2);
1952 break; 1942 break;
1953 1943
1954 case LUA_TFUNCTION: 1944 case LuaType::FUNCTION:
1955 ret = inter_copy_function(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); 1945 ret = inter_copy_function(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
1956 break; 1946 break;
1957 1947
1958 case LUA_TTABLE: 1948 case LuaType::TABLE:
1959 ret = inter_copy_table(U, L2, L2_cache_i, L, i, vt_, mode_, upName_); 1949 ret = inter_copy_table(U, L2, L2_cache_i, L, i, vt_, mode_, upName_);
1960 break; 1950 break;
1961 1951
1962 /* The following types cannot be copied */ 1952 /* The following types cannot be copied */
1963 1953
1964 case 10: // LuaJIT CDATA 1954 case LuaType::CDATA:
1965 case LUA_TTHREAD: 1955 case LuaType::THREAD:
1966 ret = false; 1956 ret = false;
1967 break; 1957 break;
1968 } 1958 }
1969 1959
1970 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1960 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
1971 1961
1972 STACK_CHECK( L2, ret ? 1 : 0); 1962 STACK_CHECK( L2, ret ? 1 : 0);
1973 STACK_CHECK( L, 0); 1963 STACK_CHECK( L, 0);
1974 return ret; 1964 return ret;
1975} 1965}
1976 1966
1967// #################################################################################################
1968
1977/* 1969/*
1978* Akin to 'lua_xmove' but copies values between _any_ Lua states. 1970* Akin to 'lua_xmove' but copies values between _any_ Lua states.
1979* 1971*
@@ -1981,124 +1973,137 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in
1981* 1973*
1982* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. 1974* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
1983*/ 1975*/
1984int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode mode_) 1976[[nodiscard]] InterCopyResult luaG_inter_copy(Universe* U, Source L, Dest L2, int n, LookupMode mode_)
1985{ 1977{
1986 int top_L = lua_gettop(L); // ... {}n 1978 int const top_L{ lua_gettop(L) }; // ... {}n
1987 int top_L2 = lua_gettop(L2); // ... 1979 int const top_L2{ lua_gettop(L2) }; // ...
1988 int i, j;
1989 char tmpBuf[16]; 1980 char tmpBuf[16];
1990 char const* pBuf = U->verboseErrors ? tmpBuf : "?"; 1981 char const* pBuf{ U->verboseErrors ? tmpBuf : "?" };
1991 bool copyok{ true };
1992 1982
1993 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END)); 1983 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END));
1994 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1984 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
1995 1985
1996 if( n > top_L) 1986 if (n > top_L)
1997 { 1987 {
1998 // requesting to copy more than is available? 1988 // requesting to copy more than is available?
1999 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END)); 1989 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END));
2000 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1990 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
2001 return -1; 1991 return InterCopyResult::NotEnoughValues;
2002 } 1992 }
2003 1993
2004 STACK_CHECK_START_REL(L2, 0); 1994 STACK_CHECK_START_REL(L2, 0);
2005 STACK_GROW( L2, n + 1); 1995 STACK_GROW(L2, n + 1);
2006 1996
2007 /* 1997 /*
2008 * Make a cache table for the duration of this copy. Collects tables and 1998 * Make a cache table for the duration of this copy. Collects tables and
2009 * function entries, avoiding the same entries to be passed on as multiple 1999 * function entries, avoiding the same entries to be passed on as multiple
2010 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner! 2000 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner!
2011 */ 2001 */
2012 lua_newtable( L2); // ... cache 2002 lua_newtable(L2); // ... cache
2013 2003
2014 STACK_CHECK_START_REL(L, 0); 2004 STACK_CHECK_START_REL(L, 0);
2015 for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) 2005 bool copyok{ true };
2006 for (int i = top_L - n + 1, j = 1; i <= top_L; ++i, ++j)
2016 { 2007 {
2017 if( U->verboseErrors) 2008 if (U->verboseErrors)
2018 { 2009 {
2019 sprintf( tmpBuf, "arg_%d", j); 2010 sprintf(tmpBuf, "arg_%d", j);
2020 } 2011 }
2021 copyok = inter_copy_one(U, L2, top_L2 + 1, L, i, VT::NORMAL, mode_, pBuf); // ... cache {}n 2012 copyok = inter_copy_one(U, L2, top_L2 + 1, L, i, VT::NORMAL, mode_, pBuf); // ... cache {}n
2022 if( !copyok) 2013 if (!copyok)
2023 { 2014 {
2024 break; 2015 break;
2025 } 2016 }
2026 } 2017 }
2027 STACK_CHECK( L, 0); 2018 STACK_CHECK(L, 0);
2028 2019
2029 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 2020 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
2030 2021
2031 if( copyok) 2022 if (copyok)
2032 { 2023 {
2033 STACK_CHECK( L2, n + 1); 2024 STACK_CHECK(L2, n + 1);
2034 // Remove the cache table. Persistent caching would cause i.e. multiple 2025 // Remove the cache table. Persistent caching would cause i.e. multiple
2035 // messages passed in the same table to use the same table also in receiving end. 2026 // messages passed in the same table to use the same table also in receiving end.
2036 lua_remove( L2, top_L2 + 1); 2027 lua_remove(L2, top_L2 + 1);
2037 return 0; 2028 return InterCopyResult::Success;
2038 } 2029 }
2039 2030
2040 // error -> pop everything from the target state stack 2031 // error -> pop everything from the target state stack
2041 lua_settop( L2, top_L2); 2032 lua_settop(L2, top_L2);
2042 STACK_CHECK( L2, 0); 2033 STACK_CHECK(L2, 0);
2043 return -2; 2034 return InterCopyResult::Error;
2044} 2035}
2045 2036
2037// #################################################################################################
2046 2038
2047int luaG_inter_move(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode mode_) 2039[[nodiscard]] InterCopyResult luaG_inter_move(Universe* U, Source L, Dest L2, int n_, LookupMode mode_)
2048{ 2040{
2049 int ret = luaG_inter_copy( U, L, L2, n, mode_); 2041 InterCopyResult const ret{ luaG_inter_copy(U, L, L2, n_, mode_) };
2050 lua_pop( L, (int) n); 2042 lua_pop( L, n_);
2051 return ret; 2043 return ret;
2052} 2044}
2053 2045
2054int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_) 2046// #################################################################################################
2047
2048// transfers stuff from L->_G["package"] to L2->_G["package"]
2049// returns InterCopyResult::Success if everything is fine
2050// returns InterCopyResult::Error if pushed an error message in L
2051// else raise an error in L
2052[[nodiscard]] InterCopyResult luaG_inter_copy_package(Universe* U, Source L, Dest L2, int package_idx_, LookupMode mode_)
2055{ 2053{
2056 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); 2054 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END));
2057 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 2055 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
2058 // package 2056 // package
2059 STACK_CHECK_START_REL(L, 0); 2057 STACK_CHECK_START_REL(L, 0);
2060 STACK_CHECK_START_REL(L2, 0); 2058 STACK_CHECK_START_REL(L2, 0);
2061 package_idx_ = lua_absindex( L, package_idx_); 2059 package_idx_ = lua_absindex(L, package_idx_);
2062 if( lua_type( L, package_idx_) != LUA_TTABLE) 2060 if (lua_type(L, package_idx_) != LUA_TTABLE)
2063 { 2061 {
2064 lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); 2062 lua_pushfstring(L, "expected package as table, got %s", luaL_typename(L, package_idx_));
2065 STACK_CHECK( L, 1); 2063 STACK_CHECK(L, 1);
2066 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later 2064 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later
2067 return (mode_ == LookupMode::LaneBody) ? lua_error(L) : 1; 2065 if (mode_ == LookupMode::LaneBody)
2066 {
2067 lua_error(L); // doesn't return
2068 }
2069 return InterCopyResult::Error;
2068 } 2070 }
2069 lua_getglobal( L2, "package"); 2071 lua_getglobal(L2, "package");
2070 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing 2072 if (!lua_isnil(L2, -1)) // package library not loaded: do nothing
2071 { 2073 {
2072 int i;
2073 // package.loaders is renamed package.searchers in Lua 5.2 2074 // package.loaders is renamed package.searchers in Lua 5.2
2074 // but don't copy it anyway, as the function names change depending on the slot index! 2075 // but don't copy it anyway, as the function names change depending on the slot index!
2075 // users should provide an on_state_create function to setup custom loaders instead 2076 // users should provide an on_state_create function to setup custom loaders instead
2076 // don't copy package.preload in keeper states (they don't know how to translate functions) 2077 // don't copy package.preload in keeper states (they don't know how to translate functions)
2077 char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr }; 2078 char const* entries[] = { "path", "cpath", (mode_ == LookupMode::LaneBody) ? "preload" : nullptr /*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, nullptr };
2078 for( i = 0; entries[i]; ++ i) 2079 for (char const* const entry : entries)
2079 { 2080 {
2080 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i])); 2081 if (!entry)
2081 lua_getfield( L, package_idx_, entries[i]);
2082 if( lua_isnil( L, -1))
2083 { 2082 {
2084 lua_pop( L, 1); 2083 continue;
2084 }
2085 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entry));
2086 lua_getfield(L, package_idx_, entry);
2087 if (lua_isnil(L, -1))
2088 {
2089 lua_pop(L, 1);
2085 } 2090 }
2086 else 2091 else
2087 { 2092 {
2088 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 2093 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
2089 luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2 2094 std::ignore = luaG_inter_move(U, L, L2, 1, mode_); // moves the entry to L2
2090 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 2095 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
2091 lua_setfield( L2, -2, entries[i]); // set package[entries[i]] 2096 lua_setfield(L2, -2, entry); // set package[entry]
2092 } 2097 }
2093 } 2098 }
2094 } 2099 }
2095 else 2100 else
2096 { 2101 {
2097 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); 2102 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END));
2098 } 2103 }
2099 lua_pop( L2, 1); 2104 lua_pop(L2, 1);
2100 STACK_CHECK( L2, 0); 2105 STACK_CHECK(L2, 0);
2101 STACK_CHECK( L, 0); 2106 STACK_CHECK(L, 0);
2102 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 2107 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
2103 return 0; 2108 return InterCopyResult::Success;
2104} 2109}