aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cancel.cpp13
-rw-r--r--src/compat.cpp9
-rw-r--r--src/deep.cpp15
-rw-r--r--src/keeper.cpp6
-rw-r--r--src/lanes.cpp14
-rw-r--r--src/lanes_private.h2
-rw-r--r--src/tools.cpp251
7 files changed, 154 insertions, 156 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp
index 2f3c22e..3a01ac2 100644
--- a/src/cancel.cpp
+++ b/src/cancel.cpp
@@ -213,7 +213,7 @@ CancelOp which_cancel_op(char const* op_string_)
213 lua_remove(L, idx_); // argument is processed, remove it 213 lua_remove(L, idx_); // argument is processed, remove it
214 if (op == CancelOp::Invalid) 214 if (op == CancelOp::Invalid)
215 { 215 {
216 std::ignore = luaL_error(L, "invalid hook option %s", str); 216 std::ignore = luaL_error(L, "invalid hook option %s", str); // doesn't return
217 } 217 }
218 return op; 218 return op;
219 } 219 }
@@ -260,6 +260,7 @@ LUAG_FUNC(thread_cancel)
260 wake_lane = lua_toboolean(L, 2); 260 wake_lane = lua_toboolean(L, 2);
261 lua_remove(L, 2); // argument is processed, remove it 261 lua_remove(L, 2); // argument is processed, remove it
262 } 262 }
263 STACK_CHECK_START_REL(L, 0);
263 switch (thread_cancel(lane, op, hook_count, wait_timeout, wake_lane)) 264 switch (thread_cancel(lane, op, hook_count, wait_timeout, wake_lane))
264 { 265 {
265 default: // should never happen unless we added a case and forgot to handle it 266 default: // should never happen unless we added a case and forgot to handle it
@@ -267,15 +268,15 @@ LUAG_FUNC(thread_cancel)
267 break; 268 break;
268 269
269 case CancelResult::Timeout: 270 case CancelResult::Timeout:
270 lua_pushboolean(L, 0); 271 lua_pushboolean(L, 0); // false
271 lua_pushstring(L, "timeout"); 272 lua_pushstring(L, "timeout"); // false "timeout"
272 break; 273 break;
273 274
274 case CancelResult::Cancelled: 275 case CancelResult::Cancelled:
275 lua_pushboolean(L, 1); 276 lua_pushboolean(L, 1); // true
276 std::ignore = push_thread_status(L, lane); 277 push_thread_status(L, lane); // true status
277 break; 278 break;
278 } 279 }
279 // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value" 280 STACK_CHECK(L, 2);
280 return 2; 281 return 2;
281} 282}
diff --git a/src/compat.cpp b/src/compat.cpp
index 9807390..73d0f6b 100644
--- a/src/compat.cpp
+++ b/src/compat.cpp
@@ -15,7 +15,7 @@
15// ################################################################################################ 15// ################################################################################################
16// ################################################################################################ 16// ################################################################################################
17 17
18[[nodiscard]] static int luaL_getsubtable(lua_State* L, int idx, const char* fname) 18static int luaL_getsubtable(lua_State* L, int idx, const char* fname)
19{ 19{
20 lua_getfield(L, idx, fname); 20 lua_getfield(L, idx, fname);
21 if (lua_istable(L, -1)) 21 if (lua_istable(L, -1))
@@ -38,7 +38,7 @@ void luaL_requiref(lua_State *L, const char *modname, lua_CFunction openf, int g
38 lua_pushcfunction(L, openf); 38 lua_pushcfunction(L, openf);
39 lua_pushstring(L, modname); /* argument to open function */ 39 lua_pushstring(L, modname); /* argument to open function */
40 lua_call(L, 1, 1); /* open module */ 40 lua_call(L, 1, 1); /* open module */
41 std::ignore = luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); 41 luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
42 lua_pushvalue(L, -2); /* make copy of module (call result) */ 42 lua_pushvalue(L, -2); /* make copy of module (call result) */
43 lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ 43 lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
44 lua_pop(L, 1); /* remove _LOADED table */ 44 lua_pop(L, 1); /* remove _LOADED table */
@@ -93,7 +93,8 @@ int lua_getiuservalue(lua_State* L, int idx, int n)
93 93
94// ################################################################################################ 94// ################################################################################################
95 95
96// pop stack top, sets it a uservalue #n of full userdata at idx 96// Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index.
97// Returns 0 if the userdata does not have that value.
97int lua_setiuservalue(lua_State* L, int idx, int n) 98int lua_setiuservalue(lua_State* L, int idx, int n)
98{ 99{
99 if( n > 1 100 if( n > 1
@@ -106,7 +107,7 @@ int lua_setiuservalue(lua_State* L, int idx, int n)
106 return 0; 107 return 0;
107 } 108 }
108 109
109 std::ignore = lua_setuservalue(L, idx); 110 lua_setuservalue(L, idx);
110 return 1; // I guess anything non-0 is ok 111 return 1; // I guess anything non-0 is ok
111} 112}
112 113
diff --git a/src/deep.cpp b/src/deep.cpp
index a3806aa..418724e 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -470,11 +470,10 @@ bool copydeep(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode
470 int const clone_i = lua_gettop( L2); 470 int const clone_i = lua_gettop( L2);
471 while( nuv) 471 while( nuv)
472 { 472 {
473 std::ignore = inter_copy_one(U 473 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), VT::NORMAL, mode_, upName_)) // u uv
474 , L2, L2_cache_i 474 {
475 , L, lua_absindex( L, -1) 475 return luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1));
476 , VT::NORMAL, mode_, upName_ 476 }
477 ); // u uv
478 lua_pop( L, 1); // ... u [uv]* 477 lua_pop( L, 1); // ... u [uv]*
479 // this pops the value from the stack 478 // this pops the value from the stack
480 lua_setiuservalue(L2, clone_i, nuv); // u 479 lua_setiuservalue(L2, clone_i, nuv); // u
@@ -482,14 +481,14 @@ bool copydeep(Universe* U, Dest L2, int L2_cache_i, Source L, int i, LookupMode
482 } 481 }
483 } 482 }
484 483
485 STACK_CHECK( L2, 1); 484 STACK_CHECK(L2, 1);
486 STACK_CHECK( L, 0); 485 STACK_CHECK(L, 0);
487 486
488 if (errmsg != nullptr) 487 if (errmsg != nullptr)
489 { 488 {
490 // raise the error in the proper state (not the keeper) 489 // raise the error in the proper state (not the keeper)
491 lua_State* const errL{ (mode_ == LookupMode::FromKeeper) ? L2 : L }; 490 lua_State* const errL{ (mode_ == LookupMode::FromKeeper) ? L2 : L };
492 std::ignore = luaL_error(errL, errmsg); 491 std::ignore = luaL_error(errL, errmsg); // doesn't return
493 } 492 }
494 return true; 493 return true;
495} \ No newline at end of file 494} \ No newline at end of file
diff --git a/src/keeper.cpp b/src/keeper.cpp
index 19fbd06..37fcba5 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -656,7 +656,7 @@ void init_keepers(Universe* U, lua_State* L)
656 lua_pop(L, 1); // 656 lua_pop(L, 1); //
657 if (nb_keepers < 1) 657 if (nb_keepers < 1)
658 { 658 {
659 std::ignore = luaL_error(L, "Bad number of keepers (%d)", nb_keepers); 659 std::ignore = luaL_error(L, "Bad number of keepers (%d)", nb_keepers); // doesn't return
660 } 660 }
661 STACK_CHECK(L, 0); 661 STACK_CHECK(L, 0);
662 662
@@ -671,7 +671,7 @@ void init_keepers(Universe* U, lua_State* L)
671 U->keepers = static_cast<Keepers*>(U->internal_allocator.alloc(bytes)); 671 U->keepers = static_cast<Keepers*>(U->internal_allocator.alloc(bytes));
672 if (U->keepers == nullptr) 672 if (U->keepers == nullptr)
673 { 673 {
674 std::ignore = luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); 674 std::ignore = luaL_error(L, "init_keepers() failed while creating keeper array; out of memory"); // doesn't return
675 } 675 }
676 U->keepers->Keepers::Keepers(); 676 U->keepers->Keepers::Keepers();
677 U->keepers->gc_threshold = keepers_gc_threshold; 677 U->keepers->gc_threshold = keepers_gc_threshold;
@@ -688,7 +688,7 @@ void init_keepers(Universe* U, lua_State* L)
688 lua_State* const K{ create_state(U, L) }; 688 lua_State* const K{ create_state(U, L) };
689 if (K == nullptr) 689 if (K == nullptr)
690 { 690 {
691 std::ignore = luaL_error(L, "init_keepers() failed while creating keeper states; out of memory"); 691 std::ignore = luaL_error(L, "init_keepers() failed while creating keeper states; out of memory"); // doesn't return
692 } 692 }
693 693
694 U->keepers->keeper_array[i].L = K; 694 U->keepers->keeper_array[i].L = K;
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 2a5ebfd..f549359 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -540,7 +540,7 @@ static void selfdestruct_add(Lane* lane_)
540 if (lane != SELFDESTRUCT_END) 540 if (lane != SELFDESTRUCT_END)
541 { 541 {
542 // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it) 542 // this causes a leak because we don't call U's destructor (which could be bad if the still running lanes are accessing it)
543 std::ignore = luaL_error(L, "Zombie thread %s refuses to die!", lane->debug_name); 543 std::ignore = luaL_error(L, "Zombie thread %s refuses to die!", lane->debug_name); // doesn't return
544 } 544 }
545 } 545 }
546 546
@@ -1374,13 +1374,12 @@ LUAG_FUNC(lane_new)
1374 1374
1375// ################################################################################################# 1375// #################################################################################################
1376 1376
1377int push_thread_status(lua_State* L, Lane* lane_) 1377void push_thread_status(lua_State* L, Lane* lane_)
1378{ 1378{
1379 char const* const str{ thread_status_string(lane_) }; 1379 char const* const str{ thread_status_string(lane_) };
1380 ASSERT_L(str); 1380 ASSERT_L(str);
1381 1381
1382 lua_pushstring(L, str); 1382 std::ignore = lua_pushstring(L, str);
1383 return 1;
1384} 1383}
1385 1384
1386// ################################################################################################# 1385// #################################################################################################
@@ -1583,11 +1582,12 @@ LUAG_FUNC(thread_index)
1583 } 1582 }
1584 if (lua_type(L, KEY) == LUA_TSTRING) 1583 if (lua_type(L, KEY) == LUA_TSTRING)
1585 { 1584 {
1586 char const * const keystr = lua_tostring(L, KEY); 1585 char const* const keystr{ lua_tostring(L, KEY) };
1587 lua_settop(L, 2); // keep only our original arguments on the stack 1586 lua_settop(L, 2); // keep only our original arguments on the stack
1588 if (strcmp( keystr, "status") == 0) 1587 if (strcmp( keystr, "status") == 0)
1589 { 1588 {
1590 return push_thread_status(L, lane); // push the string representing the status 1589 push_thread_status(L, lane); // push the string representing the status
1590 return 1;
1591 } 1591 }
1592 // return UD.metatable[key] 1592 // return UD.metatable[key]
1593 lua_getmetatable(L, UD); // UD KEY mt 1593 lua_getmetatable(L, UD); // UD KEY mt
@@ -1634,7 +1634,7 @@ LUAG_FUNC(threads)
1634 lua_newtable(L); // {} {} 1634 lua_newtable(L); // {} {}
1635 lua_pushstring(L, lane->debug_name); // {} {} "name" 1635 lua_pushstring(L, lane->debug_name); // {} {} "name"
1636 lua_setfield(L, -2, "name"); // {} {} 1636 lua_setfield(L, -2, "name"); // {} {}
1637 std::ignore = push_thread_status(L, lane); // {} {} "status" 1637 push_thread_status(L, lane); // {} {} "status"
1638 lua_setfield(L, -2, "status"); // {} {} 1638 lua_setfield(L, -2, "status"); // {} {}
1639 lua_rawseti(L, -2, ++index); // {} 1639 lua_rawseti(L, -2, ++index); // {}
1640 lane = lane->tracking_next; 1640 lane = lane->tracking_next;
diff --git a/src/lanes_private.h b/src/lanes_private.h
index ba40e44..18e55fd 100644
--- a/src/lanes_private.h
+++ b/src/lanes_private.h
@@ -103,4 +103,4 @@ static constexpr UniqueKey LANE_POINTER_REGKEY{ 0xB3022205633743BCull }; // used
103 return *(static_cast<Lane**>(luaL_checkudata(L, i_, "Lane"))); 103 return *(static_cast<Lane**>(luaL_checkudata(L, i_, "Lane")));
104} 104}
105 105
106[[nodiscard]] int push_thread_status(lua_State* L, Lane* s); 106void push_thread_status(lua_State* L, Lane* lane_);
diff --git a/src/tools.cpp b/src/tools.cpp
index 4083a57..9207df6 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -1393,50 +1393,49 @@ static void copy_cached_func(Universe* U, Dest L2, int L2_cache_i, Source L, int
1393[[nodiscard]] static bool push_cached_metatable(Universe* U, Dest L2, int L2_cache_i, Source 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_)
1394{ 1394{
1395 STACK_CHECK_START_REL(L, 0); 1395 STACK_CHECK_START_REL(L, 0);
1396 if( lua_getmetatable( L, i)) // ... mt 1396 if (!lua_getmetatable(L, i)) // ... mt
1397 { 1397 {
1398 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);
1399 1402
1400 STACK_CHECK_START_REL(L2, 0); 1403 lua_Integer const mt_id{ get_mt_id(U, L, -1) }; // Unique id for the metatable
1401 STACK_GROW( L2, 4); 1404
1402 // do we already know this metatable? 1405 STACK_CHECK_START_REL(L2, 0);
1403 push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] 1406 STACK_GROW(L2, 4);
1404 lua_pushinteger( L2, mt_id); // _R[REG_MTID] id 1407 // do we already know this metatable?
1405 lua_rawget( L2, -2); // _R[REG_MTID] mt? 1408 push_registry_subtable(L2, REG_MTID); // _R[REG_MTID]
1406 1409 lua_pushinteger(L2, mt_id); // _R[REG_MTID] id
1407 STACK_CHECK( L2, 2); 1410 lua_rawget(L2, -2); // _R[REG_MTID] mt|nil
1408 1411 STACK_CHECK(L2, 2);
1409 if( lua_isnil( L2, -1)) 1412
1410 { // L2 did not know the metatable 1413 if (lua_isnil(L2, -1))
1411 lua_pop( L2, 1); // _R[REG_MTID] 1414 { // L2 did not know the metatable
1412 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]
1413 { 1416 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_gettop(L), VT::METATABLE, mode_, upName_)) // _R[REG_MTID] mt?
1414 STACK_CHECK( L2, 2); 1417 {
1415 // mt_id -> metatable 1418 std::ignore = luaL_error(L, "Error copying a metatable"); // doesn't return
1416 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id
1417 lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt
1418 lua_rawset( L2, -4); // _R[REG_MTID] mt
1419
1420 // metatable -> mt_id
1421 lua_pushvalue( L2, -1); // _R[REG_MTID] mt mt
1422 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt mt id
1423 lua_rawset( L2, -4); // _R[REG_MTID] mt
1424 }
1425 else
1426 {
1427 (void) luaL_error( L, "Error copying a metatable");
1428 }
1429 STACK_CHECK( L2, 2);
1430 } 1419 }
1431 lua_remove( L2, -2); // mt
1432 1420
1433 lua_pop( L, 1); // ... 1421 STACK_CHECK(L2, 2); // _R[REG_MTID] mt
1434 STACK_CHECK( L2, 1); 1422 // mt_id -> metatable
1435 STACK_CHECK( L, 0); 1423 lua_pushinteger(L2, mt_id); // _R[REG_MTID] mt id
1436 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);
1437 } 1432 }
1438 STACK_CHECK( L, 0); 1433 lua_remove(L2, -2); // mt
1439 return false; 1434
1435 lua_pop(L, 1); // ...
1436 STACK_CHECK(L2, 1);
1437 STACK_CHECK(L, 0);
1438 return true;
1440} 1439}
1441 1440
1442// ################################################################################################# 1441// #################################################################################################
@@ -1599,11 +1598,10 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1599 // assign uservalues 1598 // assign uservalues
1600 while( uvi > 0) 1599 while( uvi > 0)
1601 { 1600 {
1602 std::ignore = inter_copy_one(U 1601 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), VT::NORMAL, mode_, upName_)) // ... u uv
1603 , L2, L2_cache_i 1602 {
1604 , L, lua_absindex(L, -1) 1603 std::ignore = luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1)); // doesn't return
1605 , VT::NORMAL, mode_, upName_ 1604 }
1606 ); // ... u uv
1607 lua_pop( L, 1); // ... mt __lanesclone [uv]* 1605 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1608 // this pops the value from the stack 1606 // this pops the value from the stack
1609 lua_setiuservalue( L2, -2, uvi); // ... u 1607 lua_setiuservalue( L2, -2, uvi); // ... u
@@ -1644,39 +1642,39 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1644 // try clonable userdata first 1642 // try clonable userdata first
1645 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) 1643 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_))
1646 { 1644 {
1647 STACK_CHECK( L, 0); 1645 STACK_CHECK(L, 0);
1648 STACK_CHECK( L2, 1); 1646 STACK_CHECK(L2, 1);
1649 return true; 1647 return true;
1650 } 1648 }
1651 1649
1652 STACK_CHECK( L, 0); 1650 STACK_CHECK(L, 0);
1653 STACK_CHECK( L2, 0); 1651 STACK_CHECK(L2, 0);
1654 1652
1655 // Allow only deep userdata entities to be copied across 1653 // Allow only deep userdata entities to be copied across
1656 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); 1654 DEBUGSPEW_CODE(fprintf(stderr, "USERDATA\n"));
1657 if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) 1655 if (copydeep(U, L2, L2_cache_i, L, i, mode_, upName_))
1658 { 1656 {
1659 STACK_CHECK( L, 0); 1657 STACK_CHECK(L, 0);
1660 STACK_CHECK( L2, 1); 1658 STACK_CHECK(L2, 1);
1661 return true; 1659 return true;
1662 } 1660 }
1663 1661
1664 STACK_CHECK( L, 0); 1662 STACK_CHECK(L, 0);
1665 STACK_CHECK( L2, 0); 1663 STACK_CHECK(L2, 0);
1666 1664
1667 // Not a deep or clonable full userdata 1665 // Not a deep or clonable full userdata
1668 if( U->demoteFullUserdata) // attempt demotion to light userdata 1666 if (U->demoteFullUserdata) // attempt demotion to light userdata
1669 { 1667 {
1670 void* lud = lua_touserdata( L, i); 1668 void* lud = lua_touserdata(L, i);
1671 lua_pushlightuserdata( L2, lud); 1669 lua_pushlightuserdata(L2, lud);
1672 } 1670 }
1673 else // raise an error 1671 else // raise an error
1674 { 1672 {
1675 (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); 1673 std::ignore = luaL_error(L, "can't copy non-deep full userdata across lanes"); // doesn't return
1676 } 1674 }
1677 1675
1678 STACK_CHECK( L2, 1); 1676 STACK_CHECK(L2, 1);
1679 STACK_CHECK( L, 0); 1677 STACK_CHECK(L, 0);
1680 return true; 1678 return true;
1681} 1679}
1682 1680
@@ -1689,91 +1687,90 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1689 return false; 1687 return false;
1690 } 1688 }
1691 1689
1692 STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) 1690 STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination)
1693 STACK_CHECK_START_REL(L2, 0); 1691 STACK_CHECK_START_REL(L2, 0);
1694 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1692 DEBUGSPEW_CODE(fprintf(stderr, "FUNCTION %s\n", upName_));
1695 1693
1696 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
1697 { 1695 {
1698 // clone the full userdata again 1696 // clone the full userdata again
1699 1697
1700 // let's see if we already restored this userdata 1698 // let's see if we already restored this userdata
1701 lua_getupvalue( L, source_i_, 2); // ... u 1699 lua_getupvalue(L, source_i_, 2); // ... u
1702 void* source = lua_touserdata( L, -1); 1700 void* source = lua_touserdata(L, -1);
1703 lua_pushlightuserdata( L2, source); // ... source 1701 lua_pushlightuserdata(L2, source); // ... source
1704 lua_rawget( L2, L2_cache_i); // ... u? 1702 lua_rawget(L2, L2_cache_i); // ... u?
1705 if( !lua_isnil( L2, -1)) 1703 if (!lua_isnil(L2, -1))
1706 { 1704 {
1707 lua_pop( L, 1); // ... 1705 lua_pop(L, 1); // ...
1708 STACK_CHECK( L, 0); 1706 STACK_CHECK(L, 0);
1709 STACK_CHECK( L2, 1); 1707 STACK_CHECK(L2, 1);
1710 return true; 1708 return true;
1711 } 1709 }
1712 lua_pop( L2, 1); // ... 1710 lua_pop(L2, 1); // ...
1713 1711
1714 // 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
1715 std::ignore = lookup_table( L2, L, source_i_, mode_, upName_); // ... mt 1713 std::ignore = lookup_table(L2, L, source_i_, mode_, upName_); // ... mt
1716 // 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
1717 source_i_ = lua_gettop( L); 1715 source_i_ = lua_gettop(L);
1718 source = lua_touserdata( L, -1); 1716 source = lua_touserdata(L, -1);
1719 void* clone{ nullptr }; 1717 void* clone{ nullptr };
1720 // get the number of bytes to allocate for the clone 1718 // get the number of bytes to allocate for the clone
1721 size_t const userdata_size { lua_rawlen(L, -1) }; 1719 size_t const userdata_size{ lua_rawlen(L, -1) };
1722 { 1720 {
1723 // extract uservalues (don't transfer them yet) 1721 // extract uservalues (don't transfer them yet)
1724 int uvi = 0; 1722 int uvi = 0;
1725 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... u uv 1723 while (lua_getiuservalue(L, source_i_, ++uvi) != LUA_TNONE) {} // ... u uv
1726 // 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
1727 lua_pop( L, 1); // ... u [uv]* 1725 lua_pop(L, 1); // ... u [uv]*
1728 -- uvi; 1726 --uvi;
1729 STACK_CHECK( L, uvi + 1); 1727 STACK_CHECK(L, uvi + 1);
1730 // create the clone userdata with the required number of uservalue slots 1728 // create the clone userdata with the required number of uservalue slots
1731 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u 1729 clone = lua_newuserdatauv(L2, userdata_size, uvi); // ... mt u
1732 // add it in the cache 1730 // add it in the cache
1733 lua_pushlightuserdata( L2, source); // ... mt u source 1731 lua_pushlightuserdata(L2, source); // ... mt u source
1734 lua_pushvalue( L2, -2); // ... mt u source u 1732 lua_pushvalue(L2, -2); // ... mt u source u
1735 lua_rawset( L2, L2_cache_i); // ... mt u 1733 lua_rawset(L2, L2_cache_i); // ... mt u
1736 // set metatable 1734 // set metatable
1737 lua_pushvalue( L2, -2); // ... mt u mt 1735 lua_pushvalue(L2, -2); // ... mt u mt
1738 lua_setmetatable( L2, -2); // ... mt u 1736 lua_setmetatable(L2, -2); // ... mt u
1739 // transfer and assign uservalues 1737 // transfer and assign uservalues
1740 while( uvi > 0) 1738 while (uvi > 0)
1741 { 1739 {
1742 std::ignore = inter_copy_one(U 1740 if (!inter_copy_one(U, L2, L2_cache_i, L, lua_absindex(L, -1), vt_, mode_, upName_)) // ... mt u uv
1743 , L2, L2_cache_i 1741 {
1744 , L, lua_absindex(L, -1) 1742 std::ignore = luaL_error(L, "Cannot copy upvalue type '%s'", luaL_typename(L, -1)); // doesn't return
1745 , vt_, mode_, upName_ 1743 }
1746 ); // ... mt u uv 1744 lua_pop(L, 1); // ... u [uv]*
1747 lua_pop( L, 1); // ... u [uv]*
1748 // this pops the value from the stack 1745 // this pops the value from the stack
1749 lua_setiuservalue( L2, -2, uvi); // ... mt u 1746 lua_setiuservalue(L2, -2, uvi); // ... mt u
1750 -- uvi; 1747 -- uvi;
1751 } 1748 }
1752 // 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
1753 lua_pop( L, 1); // ... 1750 lua_pop(L, 1); // ...
1754 STACK_CHECK( L, 0); 1751 STACK_CHECK(L, 0);
1755 STACK_CHECK( L2, 2); // ... mt u 1752 STACK_CHECK(L2, 2); // ... mt u
1756 } 1753 }
1757 // perform the custom cloning part 1754 // perform the custom cloning part
1758 lua_insert( L2, -2); // ... u mt 1755 lua_insert(L2, -2); // ... u mt
1759 // __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
1760 lua_getfield(L2, -1, "__lanesclone"); // ... u mt __lanesclone 1757 lua_getfield(L2, -1, "__lanesclone"); // ... u mt __lanesclone
1761 lua_remove( L2, -2); // ... u __lanesclone 1758 lua_remove(L2, -2); // ... u __lanesclone
1762 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone 1759 lua_pushlightuserdata(L2, clone); // ... u __lanesclone clone
1763 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source 1760 lua_pushlightuserdata(L2, source); // ... u __lanesclone clone source
1764 lua_pushinteger( L2, userdata_size); // ... u __lanesclone clone source size 1761 lua_pushinteger(L2, userdata_size); // ... u __lanesclone clone source size
1765 // clone:__lanesclone(dest, source, size) 1762 // clone:__lanesclone(dest, source, size)
1766 lua_call( L2, 3, 0); // ... u 1763 lua_call(L2, 3, 0); // ... u
1767 } 1764 }
1768 else // regular function 1765 else // regular function
1769 { 1766 {
1770 DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", upName_)); 1767 DEBUGSPEW_CODE(fprintf( stderr, "FUNCTION %s\n", upName_));
1771 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed)); 1768 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_add(1, std::memory_order_relaxed));
1772 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
1773 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed)); 1770 DEBUGSPEW_CODE(U->debugspew_indent_depth.fetch_sub(1, std::memory_order_relaxed));
1774 } 1771 }
1775 STACK_CHECK( L2, 1); 1772 STACK_CHECK(L2, 1);
1776 STACK_CHECK( L, 0); 1773 STACK_CHECK(L, 0);
1777 return true; 1774 return true;
1778} 1775}
1779 1776
@@ -1788,15 +1785,15 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1788 1785
1789 STACK_CHECK_START_REL(L, 0); 1786 STACK_CHECK_START_REL(L, 0);
1790 STACK_CHECK_START_REL(L2, 0); 1787 STACK_CHECK_START_REL(L2, 0);
1791 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); 1788 DEBUGSPEW_CODE(fprintf(stderr, "TABLE %s\n", upName_));
1792 1789
1793 /* 1790 /*
1794 * 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?)
1795 * 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
1796 */ 1793 */
1797 if( lookup_table( L2, L, i, mode_, upName_)) 1794 if (lookup_table(L2, L, i, mode_, upName_))
1798 { 1795 {
1799 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
1800 return true; 1797 return true;
1801 } 1798 }
1802 1799
@@ -1809,33 +1806,33 @@ static constexpr UniqueKey CLONABLES_CACHE_KEY{ 0xD04EE018B3DEE8F5ull };
1809 * Note: Even metatables need to go through this test; to detect 1806 * Note: Even metatables need to go through this test; to detect
1810 * 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)
1811 */ 1808 */
1812 if( push_cached_table( L2, L2_cache_i, L, i)) 1809 if (push_cached_table(L2, L2_cache_i, L, i))
1813 { 1810 {
1814 ASSERT_L( lua_istable( L2, -1)); // from cache 1811 ASSERT_L(lua_istable(L2, -1)); // from cache
1815 return true; 1812 return true;
1816 } 1813 }
1817 ASSERT_L( lua_istable( L2, -1)); 1814 ASSERT_L(lua_istable(L2, -1));
1818 1815
1819 STACK_GROW( L, 2); 1816 STACK_GROW(L, 2);
1820 STACK_GROW( L2, 2); 1817 STACK_GROW(L2, 2);
1821 1818
1822 lua_pushnil( L); // start iteration 1819 lua_pushnil(L); // start iteration
1823 while( lua_next( L, i)) 1820 while (lua_next(L, i))
1824 { 1821 {
1825 // 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()
1826 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_);
1827 lua_pop( L, 1); // pop value (next round) 1824 lua_pop(L, 1); // pop value (next round)
1828 } 1825 }
1829 STACK_CHECK( L, 0); 1826 STACK_CHECK(L, 0);
1830 STACK_CHECK( L2, 1); 1827 STACK_CHECK(L2, 1);
1831 1828
1832 // Metatables are expected to be immutable, and copied only once. 1829 // Metatables are expected to be immutable, and copied only once.
1833 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?
1834 { 1831 {
1835 lua_setmetatable( L2, -2); // ... t 1832 lua_setmetatable(L2, -2); // ... t
1836 } 1833 }
1837 STACK_CHECK( L2, 1); 1834 STACK_CHECK(L2, 1);
1838 STACK_CHECK( L, 0); 1835 STACK_CHECK(L, 0);
1839 return true; 1836 return true;
1840} 1837}
1841 1838