diff options
Diffstat (limited to 'src/tools.cpp')
-rw-r--r-- | src/tools.cpp | 251 |
1 files changed, 124 insertions, 127 deletions
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 | ||