diff options
-rw-r--r-- | src/cancel.cpp | 13 | ||||
-rw-r--r-- | src/compat.cpp | 9 | ||||
-rw-r--r-- | src/deep.cpp | 15 | ||||
-rw-r--r-- | src/keeper.cpp | 6 | ||||
-rw-r--r-- | src/lanes.cpp | 14 | ||||
-rw-r--r-- | src/lanes_private.h | 2 | ||||
-rw-r--r-- | src/tools.cpp | 251 |
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) | 18 | static 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. | ||
97 | int lua_setiuservalue(lua_State* L, int idx, int n) | 98 | int 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 | ||
1377 | int push_thread_status(lua_State* L, Lane* lane_) | 1377 | void 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); | 106 | void 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 | ||